Use wxAlphaPixelData if the source bitmap depth is 32 or if on wxGTK and there is a mask. Add a separate pass on MSW if there is a mask to adjust the cairo surface's alpha to match the mask.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69253 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2011-09-30 23:40:02 +00:00
parent 54c730a94f
commit 75ded4d173

View File

@@ -1089,20 +1089,18 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
wxBitmap bmpSource = bmp; // we need a non-const instance wxBitmap bmpSource = bmp; // we need a non-const instance
m_buffer = new unsigned char[bw*bh*4]; m_buffer = new unsigned char[bw*bh*4];
wxUint32* data = (wxUint32*)m_buffer; wxUint32* data = (wxUint32*)m_buffer;
cairo_format_t bufferFormat;
// 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...
if (bmpSource.HasAlpha() || (bmpSource.GetMask() if (bmpSource.GetDepth() == 32
#ifdef __WXMSW__ #ifdef __WXGTK__
// this check is needed under wxMSW, but adding this condition to wxGTK || bmpSource.GetMask()
// causes an assert when getting alpha pixel data, not sure about Mac.
&& bmpSource.GetDepth() == 32
#endif #endif
)) )
{ { // use the bitmap's alpha
m_surface = cairo_image_surface_create_for_data( bufferFormat = CAIRO_FORMAT_ARGB32;
m_buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh)); wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data.")); wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
@@ -1133,8 +1131,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
} }
else // no alpha else // no alpha
{ {
m_surface = cairo_image_surface_create_for_data( bufferFormat = CAIRO_FORMAT_RGB24;
m_buffer, CAIRO_FORMAT_RGB24, bw, bh, bw*4);
wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh)); wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data.")); wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
@@ -1156,6 +1153,38 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
p.OffsetY(pixData, 1); p.OffsetY(pixData, 1);
} }
} }
#ifdef __WXMSW__
// if there is a mask, set the alpha bytes in the target buffer to
// fully transparent or fully opaque
if (bmpSource.GetMask())
{
wxBitmap bmpMask = bmpSource.GetMaskBitmap();
bufferFormat = CAIRO_FORMAT_ARGB32;
data = (wxUint32*)m_buffer;
wxNativePixelData pixData(bmpMask, wxPoint(0,0), wxSize(bw, bh));
wxCHECK_RET( pixData, wxT("Failed to gain raw access to mask bitmap data."));
wxNativePixelData::Iterator p(pixData);
for (int y=0; y<bh; y++)
{
wxNativePixelData::Iterator rowStart = p;
for (int x=0; x<bw; x++)
{
if (p.Red()+p.Green()+p.Blue() == 0)
*data = 0;
else
*data = (wxALPHA_OPAQUE << 24) | (*data & 0x00FFFFFF);
++data;
++p;
}
p = rowStart;
p.OffsetY(pixData, 1);
}
}
#endif
m_surface = cairo_image_surface_create_for_data(
m_buffer, bufferFormat, bw, bh, bw*4);
m_pattern = cairo_pattern_create_for_surface(m_surface); m_pattern = cairo_pattern_create_for_surface(m_surface);
#endif // wxHAS_RAW_BITMAP #endif // wxHAS_RAW_BITMAP
} }