* All drawing modes except for B_OP_COPY should respect transparent pixels in
source bitmaps. The destination is preserved now when encountering such transparent pixels in the source bitmaps. * B_OP_ERASE is supposed to replace with the low color whereever a source bitmap has a non-transparent pixel. * The B_OP_MIN and B_OP_MAX drawing modes are supposed to select either the source or destination pixel based on their brightness, not combine the two pixels' color components into a new pixel. The brightness_for() function is taken from ColorConversion.cpp in the interface kit. Probably a simpler algorithm would do as well. * Handle B_TRANSPARENT_MAGIC_* in all cases when drawing bitmaps with non-alpha source bitmaps, as all modes except B_OP_COPY are sensitive to transparency. This should make all drawing modes behave as documented in the BeBook. Except for B_OP_SELECT, which seems broken under R5, the results compare nicely now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26075 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
3d75dfbb4a
commit
61ed28ee13
@ -1363,12 +1363,13 @@ Painter::_DrawBitmap(agg::rendering_buffer& srcBuffer, color_space format,
|
||||
}
|
||||
}
|
||||
|
||||
if (format != B_RGB32 || fDrawingMode != B_OP_OVER) {
|
||||
if (format == B_RGBA32 || fDrawingMode == B_OP_COPY) {
|
||||
_DrawBitmapGeneric32(srcBuffer, xOffset, yOffset,
|
||||
xScale, yScale, viewRect);
|
||||
break;
|
||||
}
|
||||
// otherwise fall through to get B_OP_OVER handling for B_RGB32
|
||||
// otherwise fall through to get proper transparency handling for
|
||||
// B_RGB32 where a B_TRANSPARENT_MAGIC might be set on pixels
|
||||
}
|
||||
default: {
|
||||
if (format == B_CMAP8 && xScale == 1.0 && yScale == 1.0) {
|
||||
@ -1396,33 +1397,31 @@ Painter::_DrawBitmap(agg::rendering_buffer& srcBuffer, color_space format,
|
||||
0, format);
|
||||
|
||||
if (err >= B_OK) {
|
||||
if (fDrawingMode == B_OP_OVER) {
|
||||
// the original bitmap might have had some of the
|
||||
// transaparent magic colors set that we now need to
|
||||
// make transparent in our RGBA32 bitmap again.
|
||||
switch (format) {
|
||||
case B_RGB32:
|
||||
_TransparentMagicToAlpha((uint32 *)srcBuffer.buf(),
|
||||
srcBuffer.width(), srcBuffer.height(),
|
||||
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA32,
|
||||
&temp);
|
||||
break;
|
||||
// the original bitmap might have had some of the
|
||||
// transaparent magic colors set that we now need to
|
||||
// make transparent in our RGBA32 bitmap again.
|
||||
switch (format) {
|
||||
case B_RGB32:
|
||||
_TransparentMagicToAlpha((uint32 *)srcBuffer.buf(),
|
||||
srcBuffer.width(), srcBuffer.height(),
|
||||
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA32,
|
||||
&temp);
|
||||
break;
|
||||
|
||||
// TODO: not sure if this applies to B_RGBA15 too. It
|
||||
// should not because B_RGBA15 actually has an alpha
|
||||
// channel itself and it should have been preserved
|
||||
// when importing the bitmap. Maybe it applies to
|
||||
// B_RGB16 though?
|
||||
case B_RGB15:
|
||||
_TransparentMagicToAlpha((uint16 *)srcBuffer.buf(),
|
||||
srcBuffer.width(), srcBuffer.height(),
|
||||
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA15,
|
||||
&temp);
|
||||
break;
|
||||
// TODO: not sure if this applies to B_RGBA15 too. It
|
||||
// should not because B_RGBA15 actually has an alpha
|
||||
// channel itself and it should have been preserved
|
||||
// when importing the bitmap. Maybe it applies to
|
||||
// B_RGB16 though?
|
||||
case B_RGB15:
|
||||
_TransparentMagicToAlpha((uint16 *)srcBuffer.buf(),
|
||||
srcBuffer.width(), srcBuffer.height(),
|
||||
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA15,
|
||||
&temp);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
agg::rendering_buffer convertedBuffer;
|
||||
|
@ -111,5 +111,16 @@ typedef PixelFormat::agg_buffer agg_buffer;
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
uint8
|
||||
brightness_for(uint8 red, uint8 green, uint8 blue)
|
||||
{
|
||||
// brightness = 0.301 * red + 0.586 * green + 0.113 * blue
|
||||
// we use for performance reasons:
|
||||
// brightness = (308 * red + 600 * green + 116 * blue) / 1024
|
||||
return uint8((308 * red + 600 * green + 116 * blue) / 1024);
|
||||
}
|
||||
|
||||
|
||||
#endif // DRAWING_MODE_H
|
||||
|
||||
|
@ -135,7 +135,7 @@ blend_color_hspan_add(int x, int y, unsigned len,
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
if (*covers) {
|
||||
if (*covers && colors->a > 0) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_ADD(p, colors->r, colors->g, colors->b);
|
||||
} else {
|
||||
@ -150,14 +150,18 @@ blend_color_hspan_add(int x, int y, unsigned len,
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
ASSIGN_ADD(p, colors->r, colors->g, colors->b);
|
||||
if (colors->a > 0) {
|
||||
ASSIGN_ADD(p, colors->r, colors->g, colors->b);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_ADD(p, colors->r, colors->g, colors->b, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_ADD(p, colors->r, colors->g, colors->b, cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
|
@ -134,16 +134,18 @@ blend_color_hspan_erase(int x, int y, unsigned len,
|
||||
const uint8* covers, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
// TODO: compare this with BView
|
||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||
rgb_color lowColor = pattern->LowColor();
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
if(*covers) {
|
||||
if(*covers == 255) {
|
||||
ASSIGN_ERASE(p, colors->r, colors->g, colors->b);
|
||||
if (*covers && colors->a > 0) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_ERASE(p, lowColor.red, lowColor.green,
|
||||
lowColor.blue);
|
||||
} else {
|
||||
BLEND_ERASE(p, colors->r, colors->g, colors->b, *covers);
|
||||
BLEND_ERASE(p, lowColor.red, lowColor.green, lowColor.blue,
|
||||
*covers);
|
||||
}
|
||||
}
|
||||
covers++;
|
||||
@ -154,14 +156,20 @@ blend_color_hspan_erase(int x, int y, unsigned len,
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
ASSIGN_ERASE(p, colors->r, colors->g, colors->b);
|
||||
if (colors->a > 0) {
|
||||
ASSIGN_ERASE(p, lowColor.red, lowColor.green,
|
||||
lowColor.blue);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_ERASE(p, colors->r, colors->g, colors->b, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_ERASE(p, lowColor.red, lowColor.green, lowColor.blue,
|
||||
cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
|
@ -157,8 +157,11 @@ blend_color_hspan_invert(int x, int y, unsigned len,
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_INVERT(p, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_INVERT(p, cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,10 @@
|
||||
{ \
|
||||
pixel32 _p; \
|
||||
_p.data32 = *(uint32*)d; \
|
||||
uint8 rt = max_c(_p.data8[2], (r)); \
|
||||
uint8 gt = max_c(_p.data8[1], (g)); \
|
||||
uint8 bt = max_c(_p.data8[0], (b)); \
|
||||
BLEND(d, rt, gt, bt, a); \
|
||||
if (brightness_for((r), (g), (b)) \
|
||||
> brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||
BLEND(d, (r), (g), (b), a); \
|
||||
} \
|
||||
}
|
||||
|
||||
// ASSIGN_MAX
|
||||
@ -28,10 +28,13 @@
|
||||
{ \
|
||||
pixel32 _p; \
|
||||
_p.data32 = *(uint32*)d; \
|
||||
d[0] = max_c(_p.data8[0], (b)); \
|
||||
d[1] = max_c(_p.data8[1], (g)); \
|
||||
d[2] = max_c(_p.data8[2], (r)); \
|
||||
d[3] = 255; \
|
||||
if (brightness_for((r), (g), (b)) \
|
||||
> brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||
d[0] = (b); \
|
||||
d[1] = (g); \
|
||||
d[2] = (r); \
|
||||
d[3] = 255; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
@ -135,7 +138,7 @@ blend_color_hspan_max(int x, int y, unsigned len,
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
if (*covers) {
|
||||
if (*covers && colors->a > 0) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_MAX(p, colors->r, colors->g, colors->b);
|
||||
} else {
|
||||
@ -150,14 +153,18 @@ blend_color_hspan_max(int x, int y, unsigned len,
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
ASSIGN_MAX(p, colors->r, colors->g, colors->b);
|
||||
if (colors->a > 0) {
|
||||
ASSIGN_MAX(p, colors->r, colors->g, colors->b);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_MAX(p, colors->r, colors->g, colors->b, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_MAX(p, colors->r, colors->g, colors->b, cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
|
@ -11,10 +11,10 @@
|
||||
{ \
|
||||
pixel32 _p; \
|
||||
_p.data32 = *(uint32*)d; \
|
||||
uint8 rt = min_c(_p.data8[2], (r)); \
|
||||
uint8 gt = min_c(_p.data8[1], (g)); \
|
||||
uint8 bt = min_c(_p.data8[0], (b)); \
|
||||
BLEND(d, rt, gt, bt, a); \
|
||||
if (brightness_for((r), (g), (b)) \
|
||||
< brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||
BLEND(d, (r), (g), (b), a); \
|
||||
} \
|
||||
}
|
||||
|
||||
// ASSIGN_MIN
|
||||
@ -22,10 +22,13 @@
|
||||
{ \
|
||||
pixel32 _p; \
|
||||
_p.data32 = *(uint32*)d; \
|
||||
d[0] = min_c(_p.data8[0], (b)); \
|
||||
d[1] = min_c(_p.data8[1], (g)); \
|
||||
d[2] = min_c(_p.data8[2], (r)); \
|
||||
d[3] = 255; \
|
||||
if (brightness_for((r), (g), (b)) \
|
||||
< brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||
d[0] = (b); \
|
||||
d[1] = (g); \
|
||||
d[2] = (r); \
|
||||
d[3] = 255; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
@ -129,7 +132,7 @@ blend_color_hspan_min(int x, int y, unsigned len,
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
if (*covers) {
|
||||
if (*covers && colors->a > 0) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_MIN(p, colors->r, colors->g, colors->b);
|
||||
} else {
|
||||
@ -144,14 +147,18 @@ blend_color_hspan_min(int x, int y, unsigned len,
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
ASSIGN_MIN(p, colors->r, colors->g, colors->b);
|
||||
if (colors->a > 0) {
|
||||
ASSIGN_MIN(p, colors->r, colors->g, colors->b);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_MIN(p, colors->r, colors->g, colors->b, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_MIN(p, colors->r, colors->g, colors->b, cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
|
@ -138,8 +138,7 @@ blend_color_hspan_over(int x, int y, unsigned len,
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
// if (*covers) {
|
||||
if (*covers && (colors->a & 0xff)) {
|
||||
if (*covers && colors->a > 0) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
||||
} else {
|
||||
@ -154,16 +153,18 @@ if (*covers && (colors->a & 0xff)) {
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
if (colors->a & 0xff) {
|
||||
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
||||
}
|
||||
if (colors->a > 0) {
|
||||
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_OVER(p, colors->r, colors->g, colors->b, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_OVER(p, colors->r, colors->g, colors->b, cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
|
@ -169,7 +169,7 @@ blend_color_hspan_select(int x, int y, unsigned len,
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
if (*covers && compare(p, high, low, &color)) {
|
||||
if (*covers && colors->a > 0 && compare(p, high, low, &color)) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_SELECT(p, color.red, color.green, color.blue);
|
||||
} else {
|
||||
@ -184,7 +184,7 @@ blend_color_hspan_select(int x, int y, unsigned len,
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
if (compare(p, high, low, &color)) {
|
||||
if (colors->a > 0 && compare(p, high, low, &color)) {
|
||||
ASSIGN_SELECT(p, color.red, color.green, color.blue);
|
||||
}
|
||||
p += 4;
|
||||
@ -193,7 +193,7 @@ blend_color_hspan_select(int x, int y, unsigned len,
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
if (compare(p, high, low, &color)) {
|
||||
if (colors->a > 0 && compare(p, high, low, &color)) {
|
||||
BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
|
||||
}
|
||||
p += 4;
|
||||
|
@ -137,7 +137,7 @@ blend_color_hspan_subtract(int x, int y, unsigned len,
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
if (*covers) {
|
||||
if (*covers && colors->a > 0) {
|
||||
if (*covers == 255) {
|
||||
ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
|
||||
} else {
|
||||
@ -152,14 +152,18 @@ blend_color_hspan_subtract(int x, int y, unsigned len,
|
||||
// solid full opcacity
|
||||
if (cover == 255) {
|
||||
do {
|
||||
ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
|
||||
if (colors->a > 0) {
|
||||
ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (cover) {
|
||||
do {
|
||||
BLEND_SUBTRACT(p, colors->r, colors->g, colors->b, cover);
|
||||
if (colors->a > 0) {
|
||||
BLEND_SUBTRACT(p, colors->r, colors->g, colors->b, cover);
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
|
Loading…
Reference in New Issue
Block a user