Fix "paint brush" mode for custom brushes (fix #1587)

This commit is contained in:
David Capello 2017-10-05 17:29:19 -03:00
parent 9c6f6f3114
commit babe23adc8
6 changed files with 36 additions and 20 deletions

View File

@ -91,11 +91,13 @@ namespace app {
// to a shape (e.g. pen shape) with various scanlines.
virtual void inkHline(int x1, int y, int x2, ToolLoop* loop) = 0;
// Returns true in case that the ink needs to update something
// depending on the specific stroke points (e.g. for color
// gradients)
virtual bool dependsOnStroke() const { return false; }
virtual void updateInk(ToolLoop* loop, Strokes& strokes) { }
// Called when we have to start using the ink for a new set of
// strokes (e.g. color gradients is adjusted depending on the
// first/last stroke points).
virtual void prepareForStrokes(ToolLoop* loop, Strokes& strokes) { }
// Called for each point shape.
virtual void prepareForPointShape(ToolLoop* loop, int x, int y) { }
};

View File

@ -34,14 +34,15 @@ namespace {
class BaseInkProcessing {
public:
virtual ~BaseInkProcessing() { }
virtual void hline(int x1, int y, int x2, ToolLoop* loop) = 0;
virtual void updateInk(ToolLoop* loop, Strokes& strokes) { }
virtual void processScanline(int x1, int y, int x2, ToolLoop* loop) = 0;
virtual void prepareForStrokes(ToolLoop* loop, Strokes& strokes) { }
virtual void prepareForPointShape(ToolLoop* loop, int x, int y) { }
};
template<typename Derived>
class InkProcessing : public BaseInkProcessing {
public:
void hline(int x1, int y, int x2, ToolLoop* loop) override {
void processScanline(int x1, int y, int x2, ToolLoop* loop) override {
int x;
// Use mask
@ -926,12 +927,12 @@ public:
{
}
void hline(int x1, int y, int x2, ToolLoop* loop) override {
void processScanline(int x1, int y, int x2, ToolLoop* loop) override {
m_tmpAddress = (RgbTraits::address_t)m_tmpImage->getPixelAddress(x1, y);
base::hline(x1, y, x2, loop);
base::processScanline(x1, y, x2, loop);
}
void updateInk(ToolLoop* loop, Strokes& strokes) override {
void prepareForStrokes(ToolLoop* loop, Strokes& strokes) override {
// Do nothing
}
@ -948,7 +949,7 @@ private:
};
template<>
void GradientInkProcessing<RgbTraits>::updateInk(ToolLoop* loop, Strokes& strokes)
void GradientInkProcessing<RgbTraits>::prepareForStrokes(ToolLoop* loop, Strokes& strokes)
{
color_t c0 = loop->getPrimaryColor();
color_t c1 = loop->getSecondaryColor();
@ -966,7 +967,7 @@ void GradientInkProcessing<RgbTraits>::processPixel(int x, int y)
}
template<>
void GradientInkProcessing<GrayscaleTraits>::updateInk(ToolLoop* loop, Strokes& strokes)
void GradientInkProcessing<GrayscaleTraits>::prepareForStrokes(ToolLoop* loop, Strokes& strokes)
{
color_t c0 = loop->getPrimaryColor();
color_t c1 = loop->getSecondaryColor();
@ -994,7 +995,7 @@ void GradientInkProcessing<GrayscaleTraits>::processPixel(int x, int y)
}
template<>
void GradientInkProcessing<IndexedTraits>::updateInk(ToolLoop* loop, Strokes& strokes)
void GradientInkProcessing<IndexedTraits>::prepareForStrokes(ToolLoop* loop, Strokes& strokes)
{
color_t c0 = m_palette->getEntry(loop->getPrimaryColor());
color_t c1 = m_palette->getEntry(loop->getSecondaryColor());
@ -1094,6 +1095,13 @@ public:
m_v = (m_brush->patternOrigin().y - loop->getCelOrigin().y) % m_height;
}
void prepareForPointShape(ToolLoop* loop, int x, int y) override {
if (m_brush->pattern() == BrushPattern::PAINT_BRUSH) {
m_u = (m_brush->patternOrigin().x - loop->getCelOrigin().x) % m_width;
m_v = (m_brush->patternOrigin().y - loop->getCelOrigin().y) % m_height;
}
}
void processPixel(int x, int y) {
// Do nothing
}

View File

@ -26,7 +26,12 @@ public:
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
ASSERT(m_proc);
m_proc->hline(x1, y, x2, loop);
m_proc->processScanline(x1, y, x2, loop);
}
void prepareForPointShape(ToolLoop* loop, int x, int y) override {
ASSERT(m_proc);
m_proc->prepareForPointShape(loop, x, y);
}
protected:
@ -143,15 +148,14 @@ public:
bool isPaint() const override { return true; }
bool isEffect() const override { return true; }
bool dependsOnStroke() const override { return true; }
bool withDitheringOptions() const override { return true; }
void prepareInk(ToolLoop* loop) override {
setProc(get_ink_proc<GradientInkProcessing>(loop));
}
void updateInk(ToolLoop* loop, Strokes& strokes) override {
proc()->updateInk(loop, strokes);
void prepareForStrokes(ToolLoop* loop, Strokes& strokes) override {
proc()->prepareForStrokes(loop, strokes);
}
};

View File

@ -66,6 +66,8 @@ public:
}
}
loop->getInk()->prepareForPointShape(loop, x, y);
for (auto scanline : *m_compressedImage) {
int u = x+scanline.x;
doInkHline(u, y+scanline.y, u+scanline.w-1, loop);

View File

@ -175,8 +175,7 @@ void ToolLoopManager::doLoopStep(bool last_step)
m_toolLoop->validateSrcImage(m_dirtyArea);
}
if (m_toolLoop->getInk()->dependsOnStroke())
m_toolLoop->getInk()->updateInk(m_toolLoop, strokes);
m_toolLoop->getInk()->prepareForStrokes(m_toolLoop, strokes);
// Invalidate destionation image areas.
if (m_toolLoop->getTracePolicy() == TracePolicy::Last) {

View File

@ -223,6 +223,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
brushBounds.origin()));
if (loop) {
loop->getInk()->prepareInk(loop);
loop->getController()->prepareController(loop);
loop->getIntertwine()->prepareIntertwine();
loop->getPointShape()->preparePointShape(loop);
loop->getPointShape()->transformPoint(