From 1b9f7fcd29bbe86da8a2153827425e80826bb9d5 Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Sun, 10 Nov 2019 15:02:00 +0100 Subject: [PATCH] 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. --- src/generic/graphicc.cpp | 41 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 60c09fa4da..a3e6d1221c 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -1489,22 +1489,14 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm // 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 // different format and iterator than if it doesn't... - const bool isSrcBpp32 = -#if defined(__WXGTK__) && !defined(__WXGTK3__) - bmp.GetDepth() == 32 || bmp.GetMask() != NULL; -#else - bmp.GetDepth() == 32; -#endif + const bool isSrcBpp32 = bmp.GetDepth() == 32; cairo_format_t bufferFormat = -#if defined(__WXGTK__) && !defined(__WXGTK3__) - isSrcBpp32 -#elif defined(__WXGTK3__) - isSrcBpp32 || bmp.GetMask() != NULL -#elif defined(__WXMSW__) || defined(__WXOSX__) + // Under MSW and OSX we can have 32 bpp xRGB bitmaps (without alpha). +#if defined(__WXMSW__) || defined(__WXOSX__) (isSrcBpp32 && bmp.HasAlpha()) || bmp.GetMask() != NULL #else - isSrcBpp32 + isSrcBpp32 || bmp.GetMask() != NULL #endif ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24; @@ -1515,12 +1507,12 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm 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__) + // Under MSW and OSX we can have 32 bpp xRGB bitmaps (without alpha). const bool hasAlpha = bmpSource.HasAlpha(); -#endif // __WXMSW__ || __WXOSX__ +#else + const bool hasAlpha = true; +#endif { // 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 // blue. The 32-bit quantities are stored native-endian. // 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__ // MSW bitmap pixel bits are already premultiplied. *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__) - // 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.) bmpSource.UseAlpha(hasAlpha); #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 - // fully transparent or fully opaque -#if defined(__WXMSW__) - if (bmp.GetMask() != NULL && !bmp.HasAlpha()) -#else // __WXGTK3__ + // fully transparent or retain original value if (bmp.GetMask() != NULL) -#endif // __WXMSW__ / __WXGTK3__ { wxBitmap bmpMask = bmp.GetMask()->GetBitmap(); data = (wxUint32*)m_buffer; @@ -1622,8 +1611,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm if (p.Red()+p.Green()+p.Blue() == 0) #endif *data = 0; - else - *data = (wxALPHA_OPAQUE << 24) | (*data & 0x00FFFFFF); + ++data; ++p; } @@ -1633,7 +1621,6 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm p.OffsetY(pixData, 1); } } -#endif // __WXMSW__ || __WXGTK3__ InitSurface(bufferFormat, stride); #endif // wxHAS_RAW_BITMAP