Fix creating wxCairoBitmapData from wxImage with mask

If source wxImage has a mask we need to create ARGB32 Cairo surface (even
for RGB image) and based on the mask values set the alpha values to fully
transparent or retain original values.
This commit is contained in:
Artur Wieczorek
2021-02-08 23:54:14 +01:00
parent c7667c16f8
commit 279ee715fd

View File

@@ -1712,7 +1712,7 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer,
const wxImage& image)
: wxGraphicsBitmapData(renderer)
{
const cairo_format_t bufferFormat = image.HasAlpha()
const cairo_format_t bufferFormat = image.HasAlpha() || image.HasMask()
? CAIRO_FORMAT_ARGB32
: CAIRO_FORMAT_RGB24;
@@ -1734,13 +1734,16 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer,
for ( int x = 0; x < m_width; x++ )
{
const unsigned char a = *alpha++;
const unsigned char a = alpha ? *alpha : wxALPHA_OPAQUE;
*dst++ = a << 24 |
Premultiply(a, src[0]) << 16 |
Premultiply(a, src[1]) << 8 |
Premultiply(a, src[2]);
*dst++ = a << 24 |
((a * src[0]) / 255) << 16 |
((a * src[1]) / 255) << 8 |
((a * src[2]) / 255);
src += 3;
if ( alpha )
alpha++;
}
dst = rowStartDst + stride / 4;
@@ -1764,6 +1767,37 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer,
}
}
// if there is a mask, set the alpha bytes in the target buffer to
// fully transparent or retain original value
if ( image.HasMask() )
{
unsigned char mr = image.GetMaskRed();
unsigned char mg = image.GetMaskGreen();
unsigned char mb = image.GetMaskBlue();
dst = reinterpret_cast<wxUint32*>(m_buffer);
src = image.GetData();
if ( bufferFormat == CAIRO_FORMAT_ARGB32 )
{
for ( int y = 0; y < m_height; y++ )
{
wxUint32* const rowStartDst = dst;
for ( int x = 0; x < m_width; x++ )
{
if ( src[0] == mr && src[1] == mg && src[2] == mb )
*dst = 0;
dst++;
src += 3;
}
dst = rowStartDst + stride / 4;
}
}
}
InitSurface(bufferFormat, stride);
}