Skip to content

Commit

Permalink
Fix custom brushes + Pen + Shading Ink breaks pattern alignment (fix a…
Browse files Browse the repository at this point in the history
  • Loading branch information
Gasparoken committed Oct 7, 2019
1 parent 8eed8b8 commit bd32cb6
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 4 deletions.
208 changes: 205 additions & 3 deletions src/app/tools/ink_processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ class ShadingInkProcessing<RgbTraits> : public DoubleInkProcessing<ShadingInkPro

*m_dstAddress = m_palette->getEntry(i);
}

private:
const Palette* m_palette;
const RgbMap* m_rgbmap;
Expand Down Expand Up @@ -814,7 +814,7 @@ class ShadingInkProcessing<GrayscaleTraits> : public DoubleInkProcessing<Shading
rgba_getb(rgba))).value()),
rgba_geta(rgba));
}

private:
const Palette* m_palette;
const RgbMap* m_rgbmap;
Expand Down Expand Up @@ -1125,7 +1125,7 @@ class BrushInkProcessingBase : public DoubleInkProcessing<BrushInkProcessingBase

color_t getTransparentColor() { return m_transparentColor; }

private:
protected:
void alignPixelPoint(int& x, int& y) {
x = (x - m_u) % m_width;
y = (y - m_v) % m_height;
Expand Down Expand Up @@ -1363,6 +1363,208 @@ void BrushLockAlphaInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
*m_dstAddress = graya(graya_getv(c), graya_geta(*m_srcAddress));
}

//////////////////////////////////////////////////////////////////////
// Brush Ink - Shading ink type
//////////////////////////////////////////////////////////////////////

template<typename ImageTraits>
class BrushShadingInkProcessing : public BrushInkProcessingBase<ImageTraits> {
public:
BrushShadingInkProcessing(ToolLoop* loop) :
BrushInkProcessingBase<ImageTraits>(loop),
m_rgbmap(loop->getRgbMap()),
m_remap(loop->getShadingRemap()),
m_left(loop->getMouseButton() == ToolLoop::Left) {
}

typename ImageTraits::pixel_t shadingProcessPixel(int iDst, int iBrush, color_t initialDst) {
// We cannot use the m_rgbmap->mapColor() function because RgbMaps
// are created with findBestfit(), and findBestfit() limits the
// returned indexes to [0,255] range (it's mainly used for RGBA ->
// Indexed image conversion).

// If we didn't find the exact match.
if (iDst < 0 || iBrush < 0) {
return initialDst;
}

if (m_remap) {
iDst = (*(m_remap))[iDst];
}
else {
if (m_left) {
--iDst;
if (iDst < 0)
iDst = BrushInkProcessingBase<ImageTraits>::m_palette->size()-1;
}
else {
++iDst;
if (iDst >= BrushInkProcessingBase<ImageTraits>::m_palette->size())
iDst = 0;
}
}
return BrushInkProcessingBase<ImageTraits>::m_palette->getEntry(iDst);
}

void processPixel(int x, int y) override {
//Do nothing
}

private:
const RgbMap* m_rgbmap;
const Remap* m_remap;
bool m_left;
};

template <>
void BrushShadingInkProcessing<RgbTraits>::processPixel(int x, int y) {
alignPixelPoint(x, y);
if (m_brushMask && !get_pixel_fast<BitmapTraits>(m_brushMask, x, y))
return;

color_t c;
int iDst = m_palette->findExactMatch(rgba_getr(*m_dstAddress),
rgba_getg(*m_dstAddress),
rgba_getb(*m_dstAddress),
rgba_geta(*m_dstAddress),
-1);
int iBrush = 1;
switch (m_brushImage->pixelFormat()) {
case IMAGE_RGB: {
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
iBrush = m_palette->findExactMatch(rgba_getr(c),
rgba_getg(c),
rgba_getb(c),
rgba_geta(c),
-1);
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
break;
}
case IMAGE_INDEXED: {
// TODO m_palette->getEntry(c) does not work because the m_palette member is
// loaded the Graya Palette, NOT the original Indexed Palette from where m_brushImage belongs.
// This conversion can be possible if we load the palette pointer in m_brush when
// is created the custom brush in the Indexed Sprite.

c = get_pixel_fast<IndexedTraits>(m_brushImage, x, y);
if (m_transparentColor != c) {
iBrush = 1;
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
}
break;
}
case IMAGE_GRAYSCALE: {
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
if (graya_geta(c) != 0) {
iBrush = 1;
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
}
break;
}
default:
ASSERT(false);
return;
}
};

template <>
void BrushShadingInkProcessing<IndexedTraits>::processPixel(int x, int y) {
alignPixelPoint(x, y);
if (m_brushMask && !get_pixel_fast<BitmapTraits>(m_brushMask, x, y))
return;

color_t c;
int iBrush = 1;
int iDst = *m_dstAddress;
switch (m_brushImage->pixelFormat()) {
case IMAGE_RGB: {
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
iBrush = m_palette->findExactMatch(rgba_getr(c),
rgba_getg(c),
rgba_getb(c),
rgba_geta(c),
-1);
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
break;
}
case IMAGE_INDEXED: {
// TODO m_palette->getEntry(c) does not work because the m_palette member is
// loaded the Graya Palette, NOT the original Indexed Palette from where m_brushImage belongs.
// This conversion can be possible if we load the palette pointer in m_brush when
// is created the custom brush in the Indexed Sprite.

c = get_pixel_fast<IndexedTraits>(m_brushImage, x, y);
if (m_transparentColor != c) {
iBrush = 1;
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
}
break;
}
case IMAGE_GRAYSCALE: {
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
if (graya_geta(c) != 0) {
iBrush = 1;
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
}
break;
}
default:
ASSERT(false);
return;
}
};

template <>
void BrushShadingInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
alignPixelPoint(x, y);
if (m_brushMask && !get_pixel_fast<BitmapTraits>(m_brushMask, x, y))
return;

color_t c;
int iBrush = 1;
color_t greyValue = graya_getv(*m_dstAddress);
int iDst = m_palette->findExactMatch(greyValue,
greyValue,
greyValue,
graya_geta(*m_dstAddress),
-1);
switch (m_brushImage->pixelFormat()) {
case IMAGE_RGB: {
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
iBrush = m_palette->findExactMatch(rgba_getr(c),
rgba_getg(c),
rgba_getb(c),
rgba_geta(c),
-1);
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
break;
}
case IMAGE_INDEXED: {
// TODO m_palette->getEntry(c) does not work because the m_palette member is
// loaded the Graya Palette, NOT the original Indexed Palette from where m_brushImage belongs.
// This conversion can be possible if we load the palette pointer in m_brush when
// is created the custom brush in the Indexed Sprite.

c = get_pixel_fast<IndexedTraits>(m_brushImage, x, y);
if (m_transparentColor != c) {
iBrush = 1;
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
}
break;
}
case IMAGE_GRAYSCALE: {
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
if (graya_geta(c) != 0) {
iBrush = 1;
*m_dstAddress = shadingProcessPixel(iDst, iBrush, *m_dstAddress);
}
break;
}
default:
ASSERT(false);
return;
}
};
//////////////////////////////////////////////////////////////////////

template<template<typename> class T>
Expand Down
7 changes: 6 additions & 1 deletion src/app/tools/inks.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ class ShadingInk : public PaintInk {

void prepareInk(ToolLoop* loop) override {
if (loop->getShadingRemap()) {
setProc(get_ink_proc<ShadingInkProcessing>(loop));
if (loop->getBrush()->type() == doc::kImageBrushType) {
setProc(get_ink_proc<BrushShadingInkProcessing>(loop));
}
else {
setProc(get_ink_proc<ShadingInkProcessing>(loop));
}
}
else {
PaintInk::prepareInk(loop);
Expand Down

0 comments on commit bd32cb6

Please sign in to comment.