mirror of
https://github.com/aseprite/aseprite.git
synced 2024-12-29 18:20:44 +00:00
Fix the ink processing to draw brushes w/alpha compositing on indexed sprites
This commit is contained in:
parent
83b2038de1
commit
d4b4dfd36d
@ -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<typename ImageTraits>
|
||||
class BrushInkProcessingBase : public DoubleInkProcessing<BrushInkProcessingBase<ImageTraits>, 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<RgbTraits>::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<IndexedTraits>(m_brushImage, x, y);
|
||||
if (m_transparentColor == c)
|
||||
c = 0;
|
||||
@ -1310,12 +1322,6 @@ bool BrushInkProcessingBase<GrayscaleTraits>::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<IndexedTraits>(m_brushImage, x, y);
|
||||
if (m_transparentColor == c)
|
||||
c = 0;
|
||||
@ -1353,19 +1359,43 @@ bool BrushInkProcessingBase<IndexedTraits>::preProcessPixel(int x, int y, color_
|
||||
switch (m_brushImage->pixelFormat()) {
|
||||
case IMAGE_RGB: {
|
||||
c = get_pixel_fast<RgbTraits>(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<IndexedTraits>(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<GrayscaleTraits>(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<RgbTraits>::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<GrayscaleTraits>::processPixel(int x, int y) {
|
||||
c = get_pixel_fast<IndexedTraits>(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<IndexedTraits>::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<GrayscaleTraits>::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<IndexedTraits>(m_brushImage, x, y);
|
||||
if (m_transparentColor != c)
|
||||
*m_dstAddress = m_shading(*m_srcAddress);
|
||||
@ -1781,10 +1796,6 @@ void BrushCopyInkProcessing<RgbTraits>::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<IndexedTraits>(m_brushImage, x, y);
|
||||
if (c == m_transparentColor) {
|
||||
*m_dstAddress = *m_srcAddress;
|
||||
@ -1824,7 +1835,10 @@ void BrushCopyInkProcessing<IndexedTraits>::processPixel(int x, int y) {
|
||||
c = get_pixel_fast<RgbTraits>(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<IndexedTraits>::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<GrayscaleTraits>::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<IndexedTraits>(m_brushImage, x, y);
|
||||
if (c == m_transparentColor) {
|
||||
*m_dstAddress = *m_srcAddress;
|
||||
|
Loading…
Reference in New Issue
Block a user