* 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:
@@ -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,
|
_DrawBitmapGeneric32(srcBuffer, xOffset, yOffset,
|
||||||
xScale, yScale, viewRect);
|
xScale, yScale, viewRect);
|
||||||
break;
|
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: {
|
default: {
|
||||||
if (format == B_CMAP8 && xScale == 1.0 && yScale == 1.0) {
|
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);
|
0, format);
|
||||||
|
|
||||||
if (err >= B_OK) {
|
if (err >= B_OK) {
|
||||||
if (fDrawingMode == B_OP_OVER) {
|
// the original bitmap might have had some of the
|
||||||
// the original bitmap might have had some of the
|
// transaparent magic colors set that we now need to
|
||||||
// transaparent magic colors set that we now need to
|
// make transparent in our RGBA32 bitmap again.
|
||||||
// make transparent in our RGBA32 bitmap again.
|
switch (format) {
|
||||||
switch (format) {
|
case B_RGB32:
|
||||||
case B_RGB32:
|
_TransparentMagicToAlpha((uint32 *)srcBuffer.buf(),
|
||||||
_TransparentMagicToAlpha((uint32 *)srcBuffer.buf(),
|
srcBuffer.width(), srcBuffer.height(),
|
||||||
srcBuffer.width(), srcBuffer.height(),
|
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA32,
|
||||||
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA32,
|
&temp);
|
||||||
&temp);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO: not sure if this applies to B_RGBA15 too. It
|
// TODO: not sure if this applies to B_RGBA15 too. It
|
||||||
// should not because B_RGBA15 actually has an alpha
|
// should not because B_RGBA15 actually has an alpha
|
||||||
// channel itself and it should have been preserved
|
// channel itself and it should have been preserved
|
||||||
// when importing the bitmap. Maybe it applies to
|
// when importing the bitmap. Maybe it applies to
|
||||||
// B_RGB16 though?
|
// B_RGB16 though?
|
||||||
case B_RGB15:
|
case B_RGB15:
|
||||||
_TransparentMagicToAlpha((uint16 *)srcBuffer.buf(),
|
_TransparentMagicToAlpha((uint16 *)srcBuffer.buf(),
|
||||||
srcBuffer.width(), srcBuffer.height(),
|
srcBuffer.width(), srcBuffer.height(),
|
||||||
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA15,
|
srcBuffer.stride(), B_TRANSPARENT_MAGIC_RGBA15,
|
||||||
&temp);
|
&temp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
agg::rendering_buffer convertedBuffer;
|
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
|
#endif // DRAWING_MODE_H
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ blend_color_hspan_add(int x, int y, unsigned len,
|
|||||||
if (covers) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
if (*covers) {
|
if (*covers && colors->a > 0) {
|
||||||
if (*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_ADD(p, colors->r, colors->g, colors->b);
|
ASSIGN_ADD(p, colors->r, colors->g, colors->b);
|
||||||
} else {
|
} else {
|
||||||
@@ -150,14 +150,18 @@ blend_color_hspan_add(int x, int y, unsigned len,
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
|
|||||||
@@ -134,16 +134,18 @@ blend_color_hspan_erase(int x, int y, unsigned len,
|
|||||||
const uint8* covers, uint8 cover,
|
const uint8* covers, uint8 cover,
|
||||||
agg_buffer* buffer, const PatternHandler* pattern)
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
{
|
{
|
||||||
// TODO: compare this with BView
|
|
||||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||||
|
rgb_color lowColor = pattern->LowColor();
|
||||||
if (covers) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
if(*covers) {
|
if (*covers && colors->a > 0) {
|
||||||
if(*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_ERASE(p, colors->r, colors->g, colors->b);
|
ASSIGN_ERASE(p, lowColor.red, lowColor.green,
|
||||||
|
lowColor.blue);
|
||||||
} else {
|
} else {
|
||||||
BLEND_ERASE(p, colors->r, colors->g, colors->b, *covers);
|
BLEND_ERASE(p, lowColor.red, lowColor.green, lowColor.blue,
|
||||||
|
*covers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
covers++;
|
covers++;
|
||||||
@@ -154,14 +156,20 @@ blend_color_hspan_erase(int x, int y, unsigned len,
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
|
|||||||
@@ -157,8 +157,11 @@ blend_color_hspan_invert(int x, int y, unsigned len,
|
|||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
do {
|
||||||
BLEND_INVERT(p, cover);
|
if (colors->a > 0) {
|
||||||
|
BLEND_INVERT(p, cover);
|
||||||
|
}
|
||||||
p += 4;
|
p += 4;
|
||||||
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
{ \
|
{ \
|
||||||
pixel32 _p; \
|
pixel32 _p; \
|
||||||
_p.data32 = *(uint32*)d; \
|
_p.data32 = *(uint32*)d; \
|
||||||
uint8 rt = max_c(_p.data8[2], (r)); \
|
if (brightness_for((r), (g), (b)) \
|
||||||
uint8 gt = max_c(_p.data8[1], (g)); \
|
> brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||||
uint8 bt = max_c(_p.data8[0], (b)); \
|
BLEND(d, (r), (g), (b), a); \
|
||||||
BLEND(d, rt, gt, bt, a); \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASSIGN_MAX
|
// ASSIGN_MAX
|
||||||
@@ -28,10 +28,13 @@
|
|||||||
{ \
|
{ \
|
||||||
pixel32 _p; \
|
pixel32 _p; \
|
||||||
_p.data32 = *(uint32*)d; \
|
_p.data32 = *(uint32*)d; \
|
||||||
d[0] = max_c(_p.data8[0], (b)); \
|
if (brightness_for((r), (g), (b)) \
|
||||||
d[1] = max_c(_p.data8[1], (g)); \
|
> brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||||
d[2] = max_c(_p.data8[2], (r)); \
|
d[0] = (b); \
|
||||||
d[3] = 255; \
|
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) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
if (*covers) {
|
if (*covers && colors->a > 0) {
|
||||||
if (*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_MAX(p, colors->r, colors->g, colors->b);
|
ASSIGN_MAX(p, colors->r, colors->g, colors->b);
|
||||||
} else {
|
} else {
|
||||||
@@ -150,14 +153,18 @@ blend_color_hspan_max(int x, int y, unsigned len,
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
{ \
|
{ \
|
||||||
pixel32 _p; \
|
pixel32 _p; \
|
||||||
_p.data32 = *(uint32*)d; \
|
_p.data32 = *(uint32*)d; \
|
||||||
uint8 rt = min_c(_p.data8[2], (r)); \
|
if (brightness_for((r), (g), (b)) \
|
||||||
uint8 gt = min_c(_p.data8[1], (g)); \
|
< brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||||
uint8 bt = min_c(_p.data8[0], (b)); \
|
BLEND(d, (r), (g), (b), a); \
|
||||||
BLEND(d, rt, gt, bt, a); \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASSIGN_MIN
|
// ASSIGN_MIN
|
||||||
@@ -22,10 +22,13 @@
|
|||||||
{ \
|
{ \
|
||||||
pixel32 _p; \
|
pixel32 _p; \
|
||||||
_p.data32 = *(uint32*)d; \
|
_p.data32 = *(uint32*)d; \
|
||||||
d[0] = min_c(_p.data8[0], (b)); \
|
if (brightness_for((r), (g), (b)) \
|
||||||
d[1] = min_c(_p.data8[1], (g)); \
|
< brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \
|
||||||
d[2] = min_c(_p.data8[2], (r)); \
|
d[0] = (b); \
|
||||||
d[3] = 255; \
|
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) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
if (*covers) {
|
if (*covers && colors->a > 0) {
|
||||||
if (*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_MIN(p, colors->r, colors->g, colors->b);
|
ASSIGN_MIN(p, colors->r, colors->g, colors->b);
|
||||||
} else {
|
} else {
|
||||||
@@ -144,14 +147,18 @@ blend_color_hspan_min(int x, int y, unsigned len,
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
|
|||||||
@@ -138,8 +138,7 @@ blend_color_hspan_over(int x, int y, unsigned len,
|
|||||||
if (covers) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
// if (*covers) {
|
if (*covers && colors->a > 0) {
|
||||||
if (*covers && (colors->a & 0xff)) {
|
|
||||||
if (*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
||||||
} else {
|
} else {
|
||||||
@@ -154,16 +153,18 @@ if (*covers && (colors->a & 0xff)) {
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
do {
|
||||||
if (colors->a & 0xff) {
|
if (colors->a > 0) {
|
||||||
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
ASSIGN_OVER(p, colors->r, colors->g, colors->b);
|
||||||
}
|
}
|
||||||
p += 4;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ blend_color_hspan_select(int x, int y, unsigned len,
|
|||||||
if (covers) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
if (*covers && compare(p, high, low, &color)) {
|
if (*covers && colors->a > 0 && compare(p, high, low, &color)) {
|
||||||
if (*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_SELECT(p, color.red, color.green, color.blue);
|
ASSIGN_SELECT(p, color.red, color.green, color.blue);
|
||||||
} else {
|
} else {
|
||||||
@@ -184,7 +184,7 @@ blend_color_hspan_select(int x, int y, unsigned len,
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
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);
|
ASSIGN_SELECT(p, color.red, color.green, color.blue);
|
||||||
}
|
}
|
||||||
p += 4;
|
p += 4;
|
||||||
@@ -193,7 +193,7 @@ blend_color_hspan_select(int x, int y, unsigned len,
|
|||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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);
|
BLEND_SELECT(p, color.red, color.green, color.blue, *covers);
|
||||||
}
|
}
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ blend_color_hspan_subtract(int x, int y, unsigned len,
|
|||||||
if (covers) {
|
if (covers) {
|
||||||
// non-solid opacity
|
// non-solid opacity
|
||||||
do {
|
do {
|
||||||
if (*covers) {
|
if (*covers && colors->a > 0) {
|
||||||
if (*covers == 255) {
|
if (*covers == 255) {
|
||||||
ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
|
ASSIGN_SUBTRACT(p, colors->r, colors->g, colors->b);
|
||||||
} else {
|
} else {
|
||||||
@@ -152,14 +152,18 @@ blend_color_hspan_subtract(int x, int y, unsigned len,
|
|||||||
// solid full opcacity
|
// solid full opcacity
|
||||||
if (cover == 255) {
|
if (cover == 255) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
// solid partial opacity
|
// solid partial opacity
|
||||||
} else if (cover) {
|
} else if (cover) {
|
||||||
do {
|
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;
|
p += 4;
|
||||||
++colors;
|
++colors;
|
||||||
} while(--len);
|
} while(--len);
|
||||||
|
|||||||
Reference in New Issue
Block a user