Fix creating wxCairoBitmapData from wxBitmap under wxGTK2
wxAlphaPixelData can be only used to access pixel data in 32 bpp bitmaps. Also, because bitmaps can have both alpha values and mask, the mask should be applied to the created surface even if alpha channel exists. Masked pixels become fully transparent and unmasked pixels should retain original alpha values. Closes #18570.
This commit is contained in:
@@ -1489,22 +1489,14 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
// Create a surface object and copy the bitmap pixel data to it. if the
|
// Create a surface object and copy the bitmap pixel data to it. if the
|
||||||
// image has alpha (or a mask represented as alpha) then we'll use a
|
// image has alpha (or a mask represented as alpha) then we'll use a
|
||||||
// different format and iterator than if it doesn't...
|
// different format and iterator than if it doesn't...
|
||||||
const bool isSrcBpp32 =
|
const bool isSrcBpp32 = bmp.GetDepth() == 32;
|
||||||
#if defined(__WXGTK__) && !defined(__WXGTK3__)
|
|
||||||
bmp.GetDepth() == 32 || bmp.GetMask() != NULL;
|
|
||||||
#else
|
|
||||||
bmp.GetDepth() == 32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cairo_format_t bufferFormat =
|
cairo_format_t bufferFormat =
|
||||||
#if defined(__WXGTK__) && !defined(__WXGTK3__)
|
// Under MSW and OSX we can have 32 bpp xRGB bitmaps (without alpha).
|
||||||
isSrcBpp32
|
#if defined(__WXMSW__) || defined(__WXOSX__)
|
||||||
#elif defined(__WXGTK3__)
|
|
||||||
isSrcBpp32 || bmp.GetMask() != NULL
|
|
||||||
#elif defined(__WXMSW__) || defined(__WXOSX__)
|
|
||||||
(isSrcBpp32 && bmp.HasAlpha()) || bmp.GetMask() != NULL
|
(isSrcBpp32 && bmp.HasAlpha()) || bmp.GetMask() != NULL
|
||||||
#else
|
#else
|
||||||
isSrcBpp32
|
isSrcBpp32 || bmp.GetMask() != NULL
|
||||||
#endif
|
#endif
|
||||||
? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
|
? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
|
||||||
|
|
||||||
@@ -1515,12 +1507,12 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
|
|
||||||
if ( isSrcBpp32 )
|
if ( isSrcBpp32 )
|
||||||
{
|
{
|
||||||
// Using wxAlphaPixelData sets (on wxMSW and wxOSX) the internal
|
|
||||||
// "has alpha" flag but we want to leave it unchanged, so we need
|
|
||||||
// to save its current value now and restore it afterwards.
|
|
||||||
#if defined(__WXMSW__) || defined(__WXOSX__)
|
#if defined(__WXMSW__) || defined(__WXOSX__)
|
||||||
|
// Under MSW and OSX we can have 32 bpp xRGB bitmaps (without alpha).
|
||||||
const bool hasAlpha = bmpSource.HasAlpha();
|
const bool hasAlpha = bmpSource.HasAlpha();
|
||||||
#endif // __WXMSW__ || __WXOSX__
|
#else
|
||||||
|
const bool hasAlpha = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
// use the bitmap's alpha
|
// use the bitmap's alpha
|
||||||
@@ -1538,7 +1530,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
// with alpha in the upper 8 bits, then red, then green, then
|
// with alpha in the upper 8 bits, then red, then green, then
|
||||||
// blue. The 32-bit quantities are stored native-endian.
|
// blue. The 32-bit quantities are stored native-endian.
|
||||||
// Pre-multiplied alpha is used.
|
// Pre-multiplied alpha is used.
|
||||||
unsigned char alpha = (bufferFormat == CAIRO_FORMAT_ARGB32) ? p.Alpha() : 255;
|
unsigned char alpha = (bufferFormat == CAIRO_FORMAT_ARGB32 && hasAlpha) ? p.Alpha() : 255;
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
// MSW bitmap pixel bits are already premultiplied.
|
// MSW bitmap pixel bits are already premultiplied.
|
||||||
*data = (alpha << 24 | p.Red() << 16 | p.Green() << 8 | p.Blue());
|
*data = (alpha << 24 | p.Red() << 16 | p.Green() << 8 | p.Blue());
|
||||||
@@ -1562,7 +1554,9 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__WXMSW__) || defined(__WXOSX__)
|
#if defined(__WXMSW__) || defined(__WXOSX__)
|
||||||
// Reset "has alpha" flag back.
|
// Using wxAlphaPixelData sets (on wxMSW and wxOSX) the internal
|
||||||
|
// "has alpha" flag but we want to leave it unchanged, so we need
|
||||||
|
// to reset "has alpha" flag back.
|
||||||
// (wxBitmap::UseAlpha() is used only on wxMSW and wxOSX.)
|
// (wxBitmap::UseAlpha() is used only on wxMSW and wxOSX.)
|
||||||
bmpSource.UseAlpha(hasAlpha);
|
bmpSource.UseAlpha(hasAlpha);
|
||||||
#endif // __WXMSW__ || __WXOSX__
|
#endif // __WXMSW__ || __WXOSX__
|
||||||
@@ -1594,14 +1588,9 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__WXMSW__) || defined(__WXGTK3__) || defined(__WXOSX__)
|
|
||||||
// if there is a mask, set the alpha bytes in the target buffer to
|
// if there is a mask, set the alpha bytes in the target buffer to
|
||||||
// fully transparent or fully opaque
|
// fully transparent or retain original value
|
||||||
#if defined(__WXMSW__)
|
|
||||||
if (bmp.GetMask() != NULL && !bmp.HasAlpha())
|
|
||||||
#else // __WXGTK3__
|
|
||||||
if (bmp.GetMask() != NULL)
|
if (bmp.GetMask() != NULL)
|
||||||
#endif // __WXMSW__ / __WXGTK3__
|
|
||||||
{
|
{
|
||||||
wxBitmap bmpMask = bmp.GetMask()->GetBitmap();
|
wxBitmap bmpMask = bmp.GetMask()->GetBitmap();
|
||||||
data = (wxUint32*)m_buffer;
|
data = (wxUint32*)m_buffer;
|
||||||
@@ -1622,8 +1611,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
if (p.Red()+p.Green()+p.Blue() == 0)
|
if (p.Red()+p.Green()+p.Blue() == 0)
|
||||||
#endif
|
#endif
|
||||||
*data = 0;
|
*data = 0;
|
||||||
else
|
|
||||||
*data = (wxALPHA_OPAQUE << 24) | (*data & 0x00FFFFFF);
|
|
||||||
++data;
|
++data;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
@@ -1633,7 +1621,6 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
p.OffsetY(pixData, 1);
|
p.OffsetY(pixData, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __WXMSW__ || __WXGTK3__
|
|
||||||
|
|
||||||
InitSurface(bufferFormat, stride);
|
InitSurface(bufferFormat, stride);
|
||||||
#endif // wxHAS_RAW_BITMAP
|
#endif // wxHAS_RAW_BITMAP
|
||||||
|
Reference in New Issue
Block a user