diff --git a/src/app/tools/ink_processing.h b/src/app/tools/ink_processing.h index a08ccfe8f..541f7442b 100644 --- a/src/app/tools/ink_processing.h +++ b/src/app/tools/ink_processing.h @@ -1124,6 +1124,14 @@ private: // Brush Ink - Base ////////////////////////////////////////////////////////////////////// +// TODO In all cases where we get the brush index and use that index +// in m_palette->getEntry(index), the color is converted to the +// sprite palette or to the grayscale palette (for grayscale +// sprites), we might want to save the original palette in the +// brush to use that one in these cases (not sure if this does +// applies when we select a new foreground/background color in +// the color bar and the brush color changes, or if this should +// be a new optional flag/parameter to save on each brush) template class BrushInkProcessingBase : public DoubleInkProcessing, ImageTraits> { public: @@ -1141,7 +1149,15 @@ public: m_height = m_brush->bounds().h; m_u = (m_brush->patternOrigin().x - loop->getCelOrigin().x) % m_width; m_v = (m_brush->patternOrigin().y - loop->getCelOrigin().y) % m_height; - m_transparentColor = loop->sprite()->transparentColor(); + + if (loop->sprite()->colorMode() == ColorMode::INDEXED) { + if (loop->getLayer()->isTransparent()) + m_transparentColor = loop->sprite()->transparentColor(); + else + m_transparentColor = -1; + } + else + m_transparentColor = 0; } void prepareForPointShape(ToolLoop* loop, bool firstPoint, int x, int y) override { @@ -1264,10 +1280,6 @@ bool BrushInkProcessingBase::preProcessPixel(int x, int y, color_t* r 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(m_brushImage, x, y); if (m_transparentColor == c) c = 0; @@ -1310,12 +1322,6 @@ bool BrushInkProcessingBase::preProcessPixel(int x, int y, colo 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(m_brushImage, x, y); if (m_transparentColor == c) c = 0; @@ -1353,19 +1359,43 @@ bool BrushInkProcessingBase::preProcessPixel(int x, int y, color_ switch (m_brushImage->pixelFormat()) { case IMAGE_RGB: { c = get_pixel_fast(m_brushImage, x, y); - c = m_palette->findBestfit(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c), 0); + color_t d = m_palette->getEntry(*m_dstAddress); + c = rgba_blender_normal(d, c, m_opacity); + c = m_palette->findBestfit(rgba_getr(c), + rgba_getg(c), + rgba_getb(c), + rgba_geta(c), m_transparentColor); break; } case IMAGE_INDEXED: { c = get_pixel_fast(m_brushImage, x, y); + if (c == m_transparentColor) + return false; + + color_t f = m_palette->getEntry(c); + + // Keep original index in special opaque case + if (rgba_geta(f) == 255 && m_opacity == 255) + break; + + color_t b = m_palette->getEntry(*m_dstAddress); + c = rgba_blender_normal(b, f, m_opacity); + c = m_palette->findBestfit(rgba_getr(c), + rgba_getg(c), + rgba_getb(c), + rgba_geta(c), m_transparentColor); break; } case IMAGE_GRAYSCALE: { c = get_pixel_fast(m_brushImage, x, y); + color_t b = m_palette->getEntry(*m_dstAddress); + b = graya(rgba_luma(b), + rgba_geta(b)); + c = graya_blender_normal(b, c, m_opacity); c = m_palette->findBestfit(graya_getv(c), graya_getv(c), graya_getv(c), - graya_geta(c), 0); + graya_geta(c), m_transparentColor); break; } case IMAGE_BITMAP: { @@ -1495,12 +1525,6 @@ void BrushEraserInkProcessing::processPixel(int x, int y) { if (m_transparentColor == c) c = 0; else - // TODO m_palette->getEntry(c) does not work because the - // m_palette member is loaded the Rgba 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 = m_palette->getEntry(c); int t; c = doc::rgba(rgba_getr(*m_srcAddress), @@ -1549,14 +1573,9 @@ void BrushEraserInkProcessing::processPixel(int x, int y) { c = get_pixel_fast(m_brushImage, x, y); if (m_transparentColor == c) c = 0; - else - // 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. + else { c = m_palette->getEntry(c); + } int t; c = graya(graya_getv(*m_srcAddress), MUL_UN8(graya_geta(*m_dstAddress), 255 - rgba_geta(c), t)); @@ -1606,7 +1625,7 @@ void BrushEraserInkProcessing::processPixel(int x, int y) { c = m_palette->findBestfit(graya_getv(c), graya_getv(c), graya_getv(c), - graya_geta(c), 0); + graya_geta(c), m_transparentColor); break; } case IMAGE_BITMAP: { @@ -1731,10 +1750,6 @@ void BrushShadingInkProcessing::processPixel(int x, int y) { 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. auto c = get_pixel_fast(m_brushImage, x, y); if (m_transparentColor != c) *m_dstAddress = m_shading(*m_srcAddress); @@ -1781,10 +1796,6 @@ void BrushCopyInkProcessing::processPixel(int x, int y) { 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(m_brushImage, x, y); if (c == m_transparentColor) { *m_dstAddress = *m_srcAddress; @@ -1824,7 +1835,10 @@ void BrushCopyInkProcessing::processPixel(int x, int y) { c = get_pixel_fast(m_brushImage, x, y); if (rgba_geta(c) == 0) return; - c = m_palette->findBestfit(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c), 0); + c = m_palette->findBestfit(rgba_getr(c), + rgba_getg(c), + rgba_getb(c), + rgba_geta(c), m_transparentColor); if (c == 0) c = *m_srcAddress; break; @@ -1842,7 +1856,7 @@ void BrushCopyInkProcessing::processPixel(int x, int y) { c = m_palette->findBestfit(graya_getv(c), graya_getv(c), graya_getv(c), - graya_geta(c), 0); + graya_geta(c), m_transparentColor); break; } case IMAGE_BITMAP: { @@ -1873,12 +1887,6 @@ void BrushCopyInkProcessing::processPixel(int x, int y) { 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(m_brushImage, x, y); if (c == m_transparentColor) { *m_dstAddress = *m_srcAddress;