+ 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;