diff --git a/include/wx/gtk/bitmap.h b/include/wx/gtk/bitmap.h index 714fbf3a61..993c71dbae 100644 --- a/include/wx/gtk/bitmap.h +++ b/include/wx/gtk/bitmap.h @@ -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 diff --git a/src/gtk/bitmap.cpp b/src/gtk/bitmap.cpp index cfd87549d9..609ab479d0 100644 --- a/src/gtk/bitmap.cpp +++ b/src/gtk/bitmap.cpp @@ -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();