+ wxCHECK_RET( IsOk(), wxT("invalid window dc") );
+ wxCHECK_RET( bitmap.IsOk(), wxT("invalid bitmap") );
+
+ if (!m_gdkwindow) return;
+
+ const int w = bitmap.GetWidth();
+ const int h = bitmap.GetHeight();
+
+ // notice that as the bitmap is not drawn upside down (or right to left)
+ // even if the corresponding axis direction is inversed, we need to take it
+ // into account when calculating its bounding box
+ CalcBoundingBox(x, y);
+ CalcBoundingBox(x + m_signX*w, y + m_signY*h);
+
+ // device coords
+ int xx = LogicalToDeviceX(x);
+ const int yy = LogicalToDeviceY(y);
+ const int ww = LogicalToDeviceXRel(w);
+ const int hh = LogicalToDeviceYRel(h);
+
+ if (m_window && m_window->GetLayoutDirection() == wxLayout_RightToLeft)
+ xx -= ww;
+
+ GdkRegion* const clipRegion = m_currentClippingRegion.GetRegion();
+ // determine clip region overlap
+ int overlap = wxInRegion;
+ if (clipRegion)
+ {
+ overlap = m_currentClippingRegion.Contains(xx, yy, ww, hh);
+ if (overlap == wxOutRegion)
+ return;
+ }
+
+ const bool isScaled = ww != w || hh != h;
+ const bool hasAlpha = bitmap.HasAlpha();
+ GdkGC* const use_gc = m_penGC;
+
+ GdkPixmap* mask = NULL;
+ // mask does not work when drawing a pixbuf with alpha
+ if (useMask && !hasAlpha)
+ {
+ wxMask* m = bitmap.GetMask();
+ if (m)
+ mask = *m;
+ }
+
+ GdkPixmap* mask_new = NULL;
+ if (mask)
+ {
+ if (isScaled)
+ {
+ mask = ScaleMask(mask, 0, 0, w, h, ww, hh, m_scaleX, m_scaleY);
+ mask_new = mask;
+ }
+ if (overlap == wxPartRegion)
+ {
+ // need a new mask that also masks the clipped area,
+ // because gc can't have both a mask and a clip region
+ mask = ClipMask(mask, clipRegion, 0, 0, xx, yy, ww, hh);
+ if (mask_new)
+ g_object_unref(mask_new);
+ mask_new = mask;
+ }
+ gdk_gc_set_clip_mask(use_gc, mask);
+ gdk_gc_set_clip_origin(use_gc, xx, yy);
+ }
+
+ // determine whether to use pixmap or pixbuf
+ GdkPixmap* pixmap = NULL;
+ GdkPixmap* pixmap_new = NULL;
+ GdkPixbuf* pixbuf = NULL;
+ GdkPixbuf* pixbuf_new = NULL;
+ if (bitmap.HasPixmap())
+ pixmap = bitmap.GetPixmap();
+ if (pixmap && gdk_drawable_get_depth(pixmap) == 1)
+ {
+ if (gdk_drawable_get_depth(m_gdkwindow) != 1)
+ {
+ // convert mono pixmap to color using text fg/bg colors
+ pixmap = MonoToColor(pixmap, 0, 0, w, h);
+ pixmap_new = pixmap;
+ }
+ }
+ else if (hasAlpha || pixmap == NULL)
+ pixbuf = bitmap.GetPixbuf();
+
+ if (isScaled)
+ {
+ if (pixbuf)
+ pixbuf = Scale(pixbuf, ww, hh, m_scaleX, m_scaleY);
+ else
+ pixbuf = Scale(pixmap, 0, 0, w, h, ww, hh, m_scaleX, m_scaleY);
+
+ pixbuf_new = pixbuf;
+ }
+
+ if (pixbuf)
+ {
+ gdk_draw_pixbuf(m_gdkwindow, use_gc, pixbuf,
+ 0, 0, xx, yy, ww, hh, GDK_RGB_DITHER_NORMAL, 0, 0);
+ }
+ else
+ {
+ gdk_draw_drawable(m_gdkwindow, use_gc, pixmap, 0, 0, xx, yy, ww, hh);
+ }
+
+ if (pixbuf_new)
+ g_object_unref(pixbuf_new);
+ if (pixmap_new)
+ g_object_unref(pixmap_new);
+ if (mask)
+ {
+ gdk_gc_set_clip_region(use_gc, clipRegion);
+
+ // Notice that we can only release the mask now, we can't do it before
+ // the calls to gdk_draw_xxx() above as they crash with X error with
+ // GTK+ up to 2.20.1 (i.e. it works with 2.20 but is known to not work
+ // with 2.16.1 and below).
+ if (mask_new)
+ g_object_unref(mask_new);
+ }
+}
+
+bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest,
+ wxCoord width, wxCoord height,
+ wxDC *source,
+ wxCoord xsrc, wxCoord ysrc,
+ wxRasterOperationMode logical_func,
+ bool useMask,
+ wxCoord xsrcMask, wxCoord ysrcMask )
+{
+ wxCHECK_MSG( IsOk(), false, wxT("invalid window dc") );
+ wxCHECK_MSG( source, false, wxT("invalid source dc") );
+
+ if (!m_gdkwindow) return false;
+
+ GdkDrawable* srcDrawable = NULL;
+ GdkPixmap* mask = NULL;
+ wxMemoryDC* memDC = wxDynamicCast(source, wxMemoryDC);
+ if (memDC)
+ {
+ const wxBitmap& bitmap = memDC->GetSelectedBitmap();
+ if (!bitmap.IsOk())
+ return false;
+ srcDrawable = bitmap.GetPixmap();
+ if (useMask)
+ {
+ wxMask* m = bitmap.GetMask();
+ if (m)
+ mask = *m;
+ }