+ wxCHECK_MSG( IsOk(), NULL, wxT("invalid bitmap") );
+
+ return M_BMPDATA->m_mask;
+}
+
+void wxBitmap::SetMask( wxMask *mask )
+{
+ wxCHECK_RET( IsOk(), wxT("invalid bitmap") );
+
+ AllocExclusive();
+ delete M_BMPDATA->m_mask;
+ M_BMPDATA->m_mask = mask;
+}
+
+wxBitmap wxBitmap::GetMaskBitmap() const
+{
+ wxBitmap bitmap;
+ wxBitmapRefData* bmpData = M_BMPDATA;
+#ifdef __WXGTK3__
+ cairo_surface_t* mask = NULL;
+ if (bmpData && bmpData->m_mask)
+ mask = bmpData->m_mask->GetBitmap();
+ if (mask)
+ {
+ const int w = cairo_image_surface_get_width(mask);
+ const int h = cairo_image_surface_get_height(mask);
+ GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, w, h);
+ const guchar* src = cairo_image_surface_get_data(mask);
+ guchar* dst = gdk_pixbuf_get_pixels(pixbuf);
+ const int stride_src = cairo_image_surface_get_stride(mask);
+ const int stride_dst = gdk_pixbuf_get_rowstride(pixbuf);
+ for (int j = 0; j < h; j++, src += stride_src, dst += stride_dst)
+ {
+ guchar* d = dst;
+ for (int i = 0; i < w; i++, d += 3)
+ {
+ d[0] = src[i];
+ d[1] = src[i];
+ d[2] = src[i];
+ }
+ }
+ bitmap = wxBitmap(pixbuf);
+ }
+#else
+ GdkPixmap* mask = NULL;
+ if (bmpData && bmpData->m_mask)
+ mask = bmpData->m_mask->GetBitmap();
+ if (mask)
+ {
+ int w, h;
+ gdk_drawable_get_size(mask, &w, &h);
+ GdkPixbuf* pixbuf = gdk_pixbuf_get_from_drawable(
+ NULL, mask, NULL, 0, 0, 0, 0, w, h);
+ bitmap = wxBitmap(pixbuf);
+ }
+#endif
+ return bitmap;
+}
+
+bool wxBitmap::CopyFromIcon(const wxIcon& icon)
+{
+ *this = icon;
+ return IsOk();
+}
+
+#ifdef __WXGTK3__
+static cairo_surface_t* GetSubSurface(cairo_surface_t* surface, const wxRect& rect)
+{
+ cairo_surface_flush(surface);
+ const cairo_format_t format = cairo_image_surface_get_format(surface);
+ int x = rect.x;
+ if (format != CAIRO_FORMAT_A8)
+ x *= 4;
+ cairo_surface_t* subSurface = cairo_image_surface_create(format, rect.width, rect.height);
+ const int srcStride = cairo_image_surface_get_stride(surface);
+ const int dstStride = cairo_image_surface_get_stride(subSurface);
+ const guchar* src = cairo_image_surface_get_data(surface) + rect.y * srcStride + x;
+ guchar* dst = cairo_image_surface_get_data(subSurface);
+ for (int j = 0; j < rect.height; j++, src += srcStride, dst += dstStride)
+ memcpy(dst, src, dstStride);
+ cairo_surface_mark_dirty(subSurface);
+ return subSurface;
+}
+#endif
+
+wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
+{
+ wxBitmap ret;
+
+ wxCHECK_MSG(IsOk(), ret, wxT("invalid bitmap"));
+
+ const int w = rect.width;
+ const int h = rect.height;
+ const wxBitmapRefData* bmpData = M_BMPDATA;
+
+ wxCHECK_MSG(rect.x >= 0 && rect.y >= 0 &&
+ rect.x + w <= bmpData->m_width &&
+ rect.y + h <= bmpData->m_height,
+ ret, wxT("invalid bitmap region"));
+
+ wxBitmapRefData * const newRef = new wxBitmapRefData(w, h, bmpData->m_bpp);
+ ret.m_refData = newRef;
+
+#ifdef __WXGTK3__
+ if (bmpData->m_pixbufNoMask)
+ {
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_subpixbuf(bmpData->m_pixbufNoMask, rect.x, rect.y, w, h);
+ newRef->m_pixbufNoMask = gdk_pixbuf_copy(pixbuf);
+ wxASSERT(newRef->m_bpp == 32 || !gdk_pixbuf_get_has_alpha(newRef->m_pixbufNoMask));
+ g_object_unref(pixbuf);
+ }
+ else if (bmpData->m_surface)
+ newRef->m_surface = GetSubSurface(bmpData->m_surface, rect);
+
+ cairo_surface_t* maskSurf = NULL;
+ if (bmpData->m_mask)
+ maskSurf = bmpData->m_mask->GetBitmap();
+ if (maskSurf)
+ {
+ newRef->m_mask = new wxMask(GetSubSurface(maskSurf, rect));
+ }
+#else
+ if (bmpData->m_pixbuf)
+ {
+ GdkPixbuf* pixbuf =
+ gdk_pixbuf_new_subpixbuf(bmpData->m_pixbuf, rect.x, rect.y, w, h);
+ newRef->m_pixbuf = gdk_pixbuf_copy(pixbuf);
+ g_object_unref(pixbuf);
+ }
+ if (bmpData->m_pixmap)
+ {
+ newRef->m_pixmap = gdk_pixmap_new(bmpData->m_pixmap, w, h, -1);
+ GdkGC* gc = gdk_gc_new(newRef->m_pixmap);
+ gdk_draw_drawable(
+ newRef->m_pixmap, gc, bmpData->m_pixmap, rect.x, rect.y, 0, 0, w, h);
+ g_object_unref(gc);
+ }
+ GdkPixmap* mask = NULL;
+ if (bmpData->m_mask)
+ mask = bmpData->m_mask->GetBitmap();
+ if (mask)
+ {
+ GdkPixmap* sub_mask = gdk_pixmap_new(mask, w, h, 1);
+ newRef->m_mask = new wxMask(sub_mask);
+ GdkGC* gc = gdk_gc_new(sub_mask);
+ gdk_draw_drawable(
+ sub_mask, gc, mask, rect.x, rect.y, 0, 0, w, h);
+ g_object_unref(gc);
+ }
+#endif
+
+ return ret;
+}
+
+bool wxBitmap::SaveFile( const wxString &name, wxBitmapType type, const wxPalette *WXUNUSED(palette) ) const
+{
+ wxCHECK_MSG( IsOk(), false, wxT("invalid bitmap") );
+
+#if wxUSE_IMAGE
+ wxImage image = ConvertToImage();
+ if (image.IsOk() && image.SaveFile(name, type))
+ return true;
+#endif
+ const char* type_name = NULL;
+ switch (type)
+ {
+ case wxBITMAP_TYPE_BMP: type_name = "bmp"; break;
+ case wxBITMAP_TYPE_ICO: type_name = "ico"; break;
+ case wxBITMAP_TYPE_JPEG: type_name = "jpeg"; break;
+ case wxBITMAP_TYPE_PNG: type_name = "png"; break;
+ default: break;
+ }
+ return type_name &&
+ gdk_pixbuf_save(GetPixbuf(), wxGTK_CONV_FN(name), type_name, NULL, NULL);
+}
+
+bool wxBitmap::LoadFile( const wxString &name, wxBitmapType type )
+{
+#if wxUSE_IMAGE
+ wxImage image;
+ if (image.LoadFile(name, type) && image.IsOk())
+ *this = wxBitmap(image);
+ else
+#endif
+ {
+ wxUnusedVar(type); // The type is detected automatically by GDK.
+
+ *this = wxBitmap(gdk_pixbuf_new_from_file(wxGTK_CONV_FN(name), NULL));
+ }
+
+ return IsOk();
+}
+
+#if wxUSE_PALETTE
+wxPalette *wxBitmap::GetPalette() const
+{
+ return NULL;
+}
+
+void wxBitmap::SetPalette(const wxPalette& WXUNUSED(palette))
+{
+ // TODO
+}
+#endif // wxUSE_PALETTE