Fixed creating Cairo bitmap from wxBitmap (wxMSW).
Fixed creating wxCairoBitmapData from 32bpp wxBitmap (with and without alpha channel). This also fixes wxCairoRenderer::CreateBitmap method. 1. 32bpp bitmap can represent under MSW either ARGB or RGB bitmap so there is necessary to examine its real contents with wxBitmap::HasAlpha function. 2. ARGB bitmaps are premultiplied and there is not necessary to premultiply them again.
This commit is contained in:
@@ -97,6 +97,22 @@ using namespace std;
|
|||||||
#include <cairo-atsui.h>
|
#include <cairo-atsui.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Helper functions for dealing with alpha pre-multiplication.
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
inline unsigned char Premultiply(unsigned char alpha, unsigned char data)
|
||||||
|
{
|
||||||
|
return alpha ? (data * alpha) / 0xff : data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned char Unpremultiply(unsigned char alpha, unsigned char data)
|
||||||
|
{
|
||||||
|
return alpha ? (data * 0xff) / alpha : data;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
class WXDLLIMPEXP_CORE wxCairoPathData : public wxGraphicsPathData
|
class WXDLLIMPEXP_CORE wxCairoPathData : public wxGraphicsPathData
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
@@ -1370,19 +1386,31 @@ 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...
|
||||||
cairo_format_t bufferFormat = bmp.GetDepth() == 32
|
const bool isSrcBpp32 =
|
||||||
#if defined(__WXGTK__) && !defined(__WXGTK3__)
|
#if defined(__WXGTK__) && !defined(__WXGTK3__)
|
||||||
|| bmp.GetMask()
|
bmp.GetDepth() == 32 || bmp.GetMask() != NULL;
|
||||||
|
#else
|
||||||
|
bmp.GetDepth() == 32;
|
||||||
#endif
|
#endif
|
||||||
? CAIRO_FORMAT_ARGB32
|
|
||||||
: CAIRO_FORMAT_RGB24;
|
cairo_format_t bufferFormat =
|
||||||
|
#if defined(__WXGTK__) && !defined(__WXGTK3__)
|
||||||
|
isSrcBpp32
|
||||||
|
#elif defined(__WXGTK3__)
|
||||||
|
isSrcBpp32 || bmp.GetMask() != NULL
|
||||||
|
#elif defined(__WXMSW__)
|
||||||
|
(isSrcBpp32 && bmp.HasAlpha()) || bmp.GetMask() != NULL
|
||||||
|
#else
|
||||||
|
isSrcBpp32
|
||||||
|
#endif
|
||||||
|
? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
|
||||||
|
|
||||||
int stride = InitBuffer(bmp.GetWidth(), bmp.GetHeight(), bufferFormat);
|
int stride = InitBuffer(bmp.GetWidth(), bmp.GetHeight(), bufferFormat);
|
||||||
|
|
||||||
wxBitmap bmpSource = bmp; // we need a non-const instance
|
wxBitmap bmpSource = bmp; // we need a non-const instance
|
||||||
wxUint32* data = (wxUint32*)m_buffer;
|
wxUint32* data = (wxUint32*)m_buffer;
|
||||||
|
|
||||||
if ( bufferFormat == CAIRO_FORMAT_ARGB32 )
|
if ( isSrcBpp32 )
|
||||||
{
|
{
|
||||||
// use the bitmap's alpha
|
// use the bitmap's alpha
|
||||||
wxAlphaPixelData
|
wxAlphaPixelData
|
||||||
@@ -1400,14 +1428,19 @@ 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 = p.Alpha();
|
unsigned char alpha = (bufferFormat == CAIRO_FORMAT_ARGB32) ? p.Alpha() : 255;
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
// MSW bitmap pixel bits are already premultiplied.
|
||||||
|
*data = (alpha << 24 | p.Red() << 16 | p.Green() << 8 | p.Blue());
|
||||||
|
#else // !__WXMSW__
|
||||||
if (alpha == 0)
|
if (alpha == 0)
|
||||||
*data = 0;
|
*data = 0;
|
||||||
else
|
else
|
||||||
*data = (alpha << 24
|
*data = (alpha << 24
|
||||||
| (p.Red() * alpha/255) << 16
|
| Premultiply(alpha, p.Red()) << 16
|
||||||
| (p.Green() * alpha/255) << 8
|
| Premultiply(alpha, p.Green()) << 8
|
||||||
| (p.Blue() * alpha/255) );
|
| Premultiply(alpha, p.Blue()));
|
||||||
|
#endif // __WXMSW__ / !__WXMSW__
|
||||||
++data;
|
++data;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
@@ -1434,7 +1467,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
// the upper 8 bits unused. Red, Green, and Blue are stored in
|
// the upper 8 bits unused. Red, Green, and Blue are stored in
|
||||||
// the remaining 24 bits in that order. The 32-bit quantities
|
// the remaining 24 bits in that order. The 32-bit quantities
|
||||||
// are stored native-endian.
|
// are stored native-endian.
|
||||||
*data = ( p.Red() << 16 | p.Green() << 8 | p.Blue() );
|
*data = (wxALPHA_OPAQUE << 24 | p.Red() << 16 | p.Green() << 8 | p.Blue() );
|
||||||
++data;
|
++data;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
@@ -1444,13 +1477,17 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
p.OffsetY(pixData, 1);
|
p.OffsetY(pixData, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__WXMSW__) || defined(__WXGTK3__)
|
#if defined(__WXMSW__) || defined(__WXGTK3__)
|
||||||
// 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 fully opaque
|
||||||
if (bmpSource.GetMask())
|
#if defined(__WXMSW__)
|
||||||
|
if (bmp.GetMask() != NULL && !bmp.HasAlpha())
|
||||||
|
#else // __WXGTK3__
|
||||||
|
if (bmp.GetMask() != NULL)
|
||||||
|
#endif // __WXMSW__ / __WXGTK3__
|
||||||
{
|
{
|
||||||
wxBitmap bmpMask = bmpSource.GetMask()->GetBitmap();
|
wxBitmap bmpMask = bmp.GetMask()->GetBitmap();
|
||||||
bufferFormat = CAIRO_FORMAT_ARGB32;
|
|
||||||
data = (wxUint32*)m_buffer;
|
data = (wxUint32*)m_buffer;
|
||||||
wxNativePixelData
|
wxNativePixelData
|
||||||
pixData(bmpMask, wxPoint(0, 0), wxSize(m_width, m_height));
|
pixData(bmpMask, wxPoint(0, 0), wxSize(m_width, m_height));
|
||||||
@@ -1476,7 +1513,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
p.OffsetY(pixData, 1);
|
p.OffsetY(pixData, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // __WXMSW__ || __WXGTK3__
|
||||||
|
|
||||||
InitSurface(bufferFormat, stride);
|
InitSurface(bufferFormat, stride);
|
||||||
#endif // wxHAS_RAW_BITMAP
|
#endif // wxHAS_RAW_BITMAP
|
||||||
@@ -1484,22 +1521,6 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||||||
|
|
||||||
#if wxUSE_IMAGE
|
#if wxUSE_IMAGE
|
||||||
|
|
||||||
// Helper functions for dealing with alpha pre-multiplication.
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
inline unsigned char Premultiply(unsigned char alpha, unsigned char data)
|
|
||||||
{
|
|
||||||
return alpha ? (data * alpha)/0xff : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned char Unpremultiply(unsigned char alpha, unsigned char data)
|
|
||||||
{
|
|
||||||
return alpha ? (data * 0xff)/alpha : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer,
|
wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer,
|
||||||
const wxImage& image)
|
const wxImage& image)
|
||||||
: wxGraphicsBitmapData(renderer)
|
: wxGraphicsBitmapData(renderer)
|
||||||
|
Reference in New Issue
Block a user