+ wxDCImpl* impl = source->GetImpl();
+ wxWindowDCImpl* gtk_impl = wxDynamicCast(impl, wxWindowDCImpl);
+ if (gtk_impl)
+ srcDrawable = gtk_impl->GetGDKWindow();
+ if (srcDrawable == NULL)
+ return false;
+ }
+
+ CalcBoundingBox(xdest, ydest);
+ CalcBoundingBox(xdest + width, ydest + height);
+
+ // source device coords
+ int src_x = source->LogicalToDeviceX(xsrc);
+ int src_y = source->LogicalToDeviceY(ysrc);
+ int src_w = source->LogicalToDeviceXRel(width);
+ int src_h = source->LogicalToDeviceYRel(height);
+
+ // Clip source rect to source dc.
+ // Only necessary when scaling, to avoid GDK errors when
+ // converting to pixbuf, but no harm in always doing it.
+ // If source rect changes, it also changes the dest rect.
+ wxRect clip;
+ gdk_drawable_get_size(srcDrawable, &clip.width, &clip.height);
+ clip.Intersect(wxRect(src_x, src_y, src_w, src_h));
+ if (src_w != clip.width || src_h != clip.height)
+ {
+ if (clip.width == 0)
+ return true;
+
+ src_w = clip.width;
+ src_h = clip.height;
+ width = source->DeviceToLogicalXRel(src_w);
+ height = source->DeviceToLogicalYRel(src_h);
+ if (src_x != clip.x || src_y != clip.y)
+ {
+ xdest += source->DeviceToLogicalXRel(clip.x - src_x);
+ ydest += source->DeviceToLogicalYRel(clip.y - src_y);
+ src_x = clip.x;
+ src_y = clip.y;
+ }
+ }
+
+ // destination device coords
+ const int dst_x = LogicalToDeviceX(xdest);
+ const int dst_y = LogicalToDeviceY(ydest);
+ const int dst_w = LogicalToDeviceXRel(width);
+ const int dst_h = LogicalToDeviceYRel(height);
+
+ GdkRegion* const clipRegion = m_currentClippingRegion.GetRegion();
+ // determine dest clip region overlap
+ int overlap = wxInRegion;
+ if (clipRegion)
+ {
+ overlap = m_currentClippingRegion.Contains(dst_x, dst_y, dst_w, dst_h);
+ if (overlap == wxOutRegion)
+ return true;
+ }
+
+ const bool isScaled = src_w != dst_w || src_h != dst_h;
+ double scale_x = 0;
+ double scale_y = 0;
+ if (isScaled)
+ {
+ // get source to dest scale
+ double usx, usy, lsx, lsy;
+ source->GetUserScale(&usx, &usy);
+ source->GetLogicalScale(&lsx, &lsy);
+ scale_x = m_scaleX / (usx * lsx);
+ scale_y = m_scaleY / (usy * lsy);
+ }
+
+ GdkGC* const use_gc = m_penGC;
+
+ if (mask)
+ {
+ g_object_ref(mask);
+ int srcMask_x = src_x;
+ int srcMask_y = src_y;
+ if (xsrcMask != -1 || ysrcMask != -1)
+ {
+ srcMask_x = source->LogicalToDeviceX(xsrcMask);
+ srcMask_y = source->LogicalToDeviceY(ysrcMask);
+ }
+ if (isScaled)
+ {
+ mask = ScaleMask(mask, srcMask_x, srcMask_y,
+ src_w, src_h, dst_w, dst_h, scale_x, scale_y);
+ srcMask_x = 0;
+ srcMask_y = 0;
+ }
+ 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,
+ srcMask_x, srcMask_y, dst_x, dst_y, dst_w, dst_h);
+ srcMask_x = 0;
+ srcMask_y = 0;
+ }
+ gdk_gc_set_clip_mask(use_gc, mask);
+ gdk_gc_set_clip_origin(use_gc, dst_x - srcMask_x, dst_y - srcMask_y);