+ GdkGCValues gcValues;
+ gcValues.foreground.pixel = 0;
+ GdkGC* gc = gdk_gc_new_with_values(mask, &gcValues, GDK_GC_FOREGROUND);
+ GdkPixmap* pixmap = gdk_pixmap_new(mask, w, h, 1);
+ // clear new mask, so clipped areas will be masked
+ gdk_draw_rectangle(pixmap, gc, true, 0, 0, w, h);
+ gdk_gc_set_clip_region(gc, clipRegion);
+ gdk_gc_set_clip_origin(gc, -dst_x, -dst_y);
+ // draw old mask onto new one, with clip
+ gdk_draw_drawable(pixmap, gc, mask, x, y, 0, 0, w, h);
+ g_object_unref(gc);
+ return pixmap;
+}
+
+// make a color pixmap from part of a mono one, using text fg/bg colors
+GdkPixmap*
+wxWindowDCImpl::MonoToColor(GdkPixmap* monoPixmap, int x, int y, int w, int h) const
+{
+ GdkPixmap* pixmap = gdk_pixmap_new(m_gdkwindow, w, h, -1);
+ GdkGCValues gcValues;
+ gcValues.foreground.pixel = m_textForegroundColour.GetColor()->pixel;
+ gcValues.background.pixel = m_textBackgroundColour.GetColor()->pixel;
+ gcValues.stipple = monoPixmap;
+ gcValues.fill = GDK_OPAQUE_STIPPLED;
+ gcValues.ts_x_origin = -x;
+ gcValues.ts_y_origin = -y;
+ GdkGC* gc = gdk_gc_new_with_values(pixmap, &gcValues, GdkGCValuesMask(
+ GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_STIPPLE | GDK_GC_FILL |
+ GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN));
+ gdk_draw_rectangle(pixmap, gc, true, 0, 0, w, h);
+ g_object_unref(gc);
+ return pixmap;
+}
+
+void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap,
+ wxCoord x, wxCoord y,
+ bool useMask )
+{
+ 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);
+ }