+ wxBitmap bmp;
+
+ wxCHECK_MSG(Ok(), bmp, wxT("invalid bitmap"));
+
+ width = wxMax(width, 1);
+ height = wxMax(height, 1);
+
+ const double scale_x = double(width) / clipwidth;
+ const double scale_y = double(height) / clipheight;
+
+ // Converting to pixbuf, scaling with gdk_pixbuf_scale, and converting
+ // back, is faster than scaling pixmap ourselves.
+
+ // use pixbuf if already available,
+ // otherwise create temporary pixbuf from pixmap
+ GdkPixbuf* pixbuf = M_BMPDATA->m_pixbuf;
+ if (pixbuf)
+ g_object_ref(pixbuf);
+ else
+ pixbuf = gdk_pixbuf_get_from_drawable(
+ NULL, M_BMPDATA->m_pixmap, NULL,
+ 0, 0, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height);
+
+ // new pixbuf for scaled wxBitmap
+ GdkPixbuf* pixbuf_scaled = gdk_pixbuf_new(
+ GDK_COLORSPACE_RGB, gdk_pixbuf_get_has_alpha(pixbuf), 8, width, height);
+
+ // GDK_INTERP_NEAREST is the lowest-quality method for continuous-tone
+ // images, but the only one which preserves sharp edges
+ gdk_pixbuf_scale(
+ pixbuf, pixbuf_scaled,
+ 0, 0, width, height, -clipx*scale_x, -clipy*scale_y, scale_x, scale_y,
+ GDK_INTERP_NEAREST);
+
+ g_object_unref(pixbuf);
+ bmp.SetPixbuf(pixbuf_scaled, M_BMPDATA->m_bpp);
+
+ if (M_BMPDATA->m_mask)
+ {
+ pixbuf = gdk_pixbuf_get_from_drawable(
+ NULL, M_BMPDATA->m_mask->m_bitmap, NULL,
+ 0, 0, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height);
+
+ pixbuf_scaled = gdk_pixbuf_new(
+ GDK_COLORSPACE_RGB, false, 8, width, height);
+
+ gdk_pixbuf_scale(
+ pixbuf, pixbuf_scaled,
+ 0, 0, width, height, -clipx, -clipy, scale_x, scale_y,
+ GDK_INTERP_NEAREST);
+
+ g_object_unref(pixbuf);
+
+ // use existing functionality to create mask from scaled pixbuf
+ wxBitmap maskbmp;
+ maskbmp.SetPixbuf(pixbuf_scaled);
+ bmp.SetMask(new wxMask(maskbmp, *wxBLACK));
+ }
+ return bmp;