Fix storing wxBitmap data in GdkPixbuf
Under wxGTK+2 bitmap data with mask and without it (raw) should be stored in the separate GdkPixbuf buffers - just like it's done in wxGTK+3. These two buffers are necessary because only GdkPixbuf with raw bitmap data (original, non-masked) should be copied when wxBitmapRefData instance is cloned e.g. in SetMask(). GdkPixbuf with masked data is not copied and is created on first use in wxBitmap::GetPixbuf(). Closes #18508. See #18498.
This commit is contained in:
@@ -133,7 +133,6 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
GdkPixbuf* GetPixbufNoMask() const;
|
||||
cairo_t* CairoCreate() const;
|
||||
void Draw(cairo_t* cr, int x, int y, bool useMask = true, const wxColour* fg = NULL, const wxColour* bg = NULL) const;
|
||||
void SetSourceSurface(cairo_t* cr, int x, int y, const wxColour* fg = NULL, const wxColour* bg = NULL) const;
|
||||
@@ -143,6 +142,7 @@ public:
|
||||
bool HasPixbuf() const;
|
||||
wxBitmap(GdkPixmap* pixmap);
|
||||
#endif
|
||||
GdkPixbuf* GetPixbufNoMask() const;
|
||||
GdkPixbuf *GetPixbuf() const;
|
||||
|
||||
// raw bitmap access support functions
|
||||
|
@@ -58,7 +58,6 @@ static void MaskToAlpha(GdkPixmap* mask, GdkPixbuf* pixbuf, int w, int h)
|
||||
{
|
||||
for (int x = w; x; x--, p += 4, mask_data += 3)
|
||||
{
|
||||
*p = 255;
|
||||
// no need to test all 3 components,
|
||||
// pixels are either (0,0,0) or (0xff,0xff,0xff)
|
||||
if (mask_data[0] == 0)
|
||||
@@ -208,7 +207,7 @@ bool wxMask::InitFromColour(const wxBitmap& bitmap, const wxColour& colour)
|
||||
const wxByte r_mask = colour.Red();
|
||||
const wxByte g_mask = colour.Green();
|
||||
const wxByte b_mask = colour.Blue();
|
||||
GdkPixbuf* pixbuf = bitmap.GetPixbuf();
|
||||
GdkPixbuf* pixbuf = bitmap.GetPixbufNoMask();
|
||||
const wxByte* in = gdk_pixbuf_get_pixels(pixbuf);
|
||||
const int inc = 3 + int(gdk_pixbuf_get_has_alpha(pixbuf) != 0);
|
||||
const int rowpadding = gdk_pixbuf_get_rowstride(pixbuf) - inc * w;
|
||||
@@ -333,7 +332,6 @@ public:
|
||||
virtual bool IsOk() const wxOVERRIDE;
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
GdkPixbuf* m_pixbufMask;
|
||||
GdkPixbuf* m_pixbufNoMask;
|
||||
cairo_surface_t* m_surface;
|
||||
double m_scaleFactor;
|
||||
@@ -341,6 +339,7 @@ public:
|
||||
GdkPixmap *m_pixmap;
|
||||
GdkPixbuf *m_pixbuf;
|
||||
#endif
|
||||
GdkPixbuf *m_pixbufMask;
|
||||
wxMask *m_mask;
|
||||
int m_width;
|
||||
int m_height;
|
||||
@@ -359,7 +358,6 @@ public:
|
||||
wxBitmapRefData::wxBitmapRefData(int width, int height, int depth)
|
||||
{
|
||||
#ifdef __WXGTK3__
|
||||
m_pixbufMask = NULL;
|
||||
m_pixbufNoMask = NULL;
|
||||
m_surface = NULL;
|
||||
m_scaleFactor = 1;
|
||||
@@ -367,6 +365,7 @@ wxBitmapRefData::wxBitmapRefData(int width, int height, int depth)
|
||||
m_pixmap = NULL;
|
||||
m_pixbuf = NULL;
|
||||
#endif
|
||||
m_pixbufMask = NULL;
|
||||
m_mask = NULL;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
@@ -384,13 +383,13 @@ wxBitmapRefData::wxBitmapRefData(int width, int height, int depth)
|
||||
wxBitmapRefData::~wxBitmapRefData()
|
||||
{
|
||||
#ifdef __WXGTK3__
|
||||
if (m_pixbufMask)
|
||||
g_object_unref(m_pixbufMask);
|
||||
if (m_pixbufNoMask)
|
||||
g_object_unref(m_pixbufNoMask);
|
||||
if (m_surface)
|
||||
cairo_surface_destroy(m_surface);
|
||||
#else
|
||||
if (m_pixbufMask)
|
||||
g_object_unref(m_pixbufMask);
|
||||
if (m_pixmap)
|
||||
g_object_unref (m_pixmap);
|
||||
if (m_pixbuf)
|
||||
@@ -542,7 +541,6 @@ bool wxBitmap::Create( int width, int height, int depth )
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
static void CopyImageData(
|
||||
guchar* dst, int dstChannels, int dstStride,
|
||||
const guchar* src, int srcChannels, int srcStride,
|
||||
@@ -587,7 +585,6 @@ static void CopyImageData(
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
#ifdef __WXGTK3__
|
||||
@@ -1365,6 +1362,26 @@ void wxBitmap::Draw(cairo_t* cr, int x, int y, bool useMask, const wxColour* fg,
|
||||
else
|
||||
cairo_paint(cr);
|
||||
}
|
||||
#else
|
||||
GdkPixbuf* wxBitmap::GetPixbufNoMask() const
|
||||
{
|
||||
wxCHECK_MSG(IsOk(), NULL, "invalid bitmap");
|
||||
|
||||
wxBitmapRefData* bmpData = M_BMPDATA;
|
||||
GdkPixbuf* pixbuf = bmpData->m_pixbuf;
|
||||
if (pixbuf)
|
||||
return pixbuf;
|
||||
|
||||
const int w = bmpData->m_width;
|
||||
const int h = bmpData->m_height;
|
||||
|
||||
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, bmpData->m_alphaRequested, 8, w, h);
|
||||
if ( bmpData->m_pixmap )
|
||||
PixmapToPixbuf(bmpData->m_pixmap, pixbuf, w, h);
|
||||
|
||||
bmpData->m_pixbuf = pixbuf;
|
||||
return pixbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
GdkPixbuf *wxBitmap::GetPixbuf() const
|
||||
@@ -1405,21 +1422,31 @@ GdkPixbuf *wxBitmap::GetPixbuf() const
|
||||
|
||||
return bmpData->m_pixbufMask;
|
||||
#else
|
||||
if (bmpData->m_pixbuf)
|
||||
return bmpData->m_pixbuf;
|
||||
if ( bmpData->m_pixbufMask )
|
||||
return bmpData->m_pixbufMask;
|
||||
|
||||
const int w = bmpData->m_width;
|
||||
const int h = bmpData->m_height;
|
||||
if ( !bmpData->m_pixbuf )
|
||||
GetPixbufNoMask();
|
||||
|
||||
GdkPixmap* mask = NULL;
|
||||
if (bmpData->m_mask)
|
||||
mask = *bmpData->m_mask;
|
||||
const bool useAlpha = bmpData->m_alphaRequested || mask;
|
||||
bmpData->m_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, useAlpha, 8, w, h);
|
||||
if (bmpData->m_pixmap)
|
||||
PixmapToPixbuf(bmpData->m_pixmap, bmpData->m_pixbuf, w, h);
|
||||
if (mask)
|
||||
MaskToAlpha(mask, bmpData->m_pixbuf, w, h);
|
||||
return bmpData->m_pixbuf;
|
||||
|
||||
if ( !mask )
|
||||
return bmpData->m_pixbuf;
|
||||
|
||||
bmpData->m_pixbufMask = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, w, h);
|
||||
guchar* dst = gdk_pixbuf_get_pixels(bmpData->m_pixbufMask);
|
||||
guchar* src = gdk_pixbuf_get_pixels(bmpData->m_pixbuf);
|
||||
const int dstStride = gdk_pixbuf_get_rowstride(bmpData->m_pixbufMask);
|
||||
const int srcStride = gdk_pixbuf_get_rowstride(bmpData->m_pixbuf);
|
||||
CopyImageData(dst, 4, dstStride,
|
||||
src, gdk_pixbuf_get_n_channels(bmpData->m_pixbuf), srcStride,
|
||||
w, h);
|
||||
MaskToAlpha(mask, bmpData->m_pixbufMask, w, h);
|
||||
return bmpData->m_pixbufMask;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1471,11 +1498,17 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
|
||||
}
|
||||
}
|
||||
#else
|
||||
GdkPixbuf *pixbuf = GetPixbuf();
|
||||
GdkPixbuf *pixbuf = GetPixbufNoMask();
|
||||
|
||||
// Pixmap will get out of date when our pixbuf is accessed directly, so
|
||||
// ensure we don't keep the old data in it.
|
||||
PurgeOtherRepresentations(Pixbuf);
|
||||
// Pixbuf with masked data will get out of date too
|
||||
if ( M_BMPDATA->m_pixbufMask )
|
||||
{
|
||||
g_object_unref(M_BMPDATA->m_pixbufMask);
|
||||
M_BMPDATA->m_pixbufMask = NULL;
|
||||
}
|
||||
|
||||
const bool hasAlpha = HasAlpha();
|
||||
|
||||
|
Reference in New Issue
Block a user