184 lines
5.9 KiB
Diff
184 lines
5.9 KiB
Diff
diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c
|
|
index 869d535..44652bc 100644
|
|
--- a/gdk/gdkdraw.c
|
|
+++ b/gdk/gdkdraw.c
|
|
@@ -752,9 +752,6 @@ gdk_draw_image (GdkDrawable *drawable,
|
|
* On older X servers, rendering pixbufs with an alpha channel involves round
|
|
* trips to the X server, and may be somewhat slow.
|
|
*
|
|
- * The clip mask of @gc is ignored, but clip rectangles and clip regions work
|
|
- * fine.
|
|
- *
|
|
* If GDK is built with the Sun mediaLib library, the gdk_draw_pixbuf
|
|
* function is accelerated using mediaLib, which provides hardware
|
|
* acceleration on Intel, AMD, and Sparc chipsets. If desired, mediaLib
|
|
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
|
|
index b4c6f81..699cebf 100644
|
|
--- a/gdk/gdkgc.c
|
|
+++ b/gdk/gdkgc.c
|
|
@@ -646,24 +646,49 @@ _gdk_gc_add_drawable_clip (GdkGC *gc,
|
|
GdkPixmap *new_mask;
|
|
GdkGC *tmp_gc;
|
|
GdkColor black = {0, 0, 0, 0};
|
|
+ GdkRectangle r;
|
|
+ GdkOverlapType overlap;
|
|
|
|
- priv->old_clip_mask = g_object_ref (priv->clip_mask);
|
|
- gdk_drawable_get_size (priv->old_clip_mask, &w, &h);
|
|
-
|
|
- new_mask = gdk_pixmap_new (priv->old_clip_mask, w, h, -1);
|
|
- tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)new_mask, FALSE);
|
|
-
|
|
- gdk_gc_set_foreground (tmp_gc, &black);
|
|
- gdk_draw_rectangle (new_mask, tmp_gc, TRUE, 0, 0, -1, -1);
|
|
- _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE); /* Takes ownership of region */
|
|
- gdk_draw_drawable (new_mask,
|
|
- tmp_gc,
|
|
- priv->old_clip_mask,
|
|
- 0, 0,
|
|
- 0, 0,
|
|
- -1, -1);
|
|
- gdk_gc_set_clip_region (tmp_gc, NULL);
|
|
- gdk_gc_set_clip_mask (gc, new_mask);
|
|
+ gdk_drawable_get_size (priv->clip_mask, &w, &h);
|
|
+
|
|
+ r.x = 0;
|
|
+ r.y = 0;
|
|
+ r.width = w;
|
|
+ r.height = h;
|
|
+
|
|
+ /* Its quite common to expose areas that are completely in or outside
|
|
+ * the region, so we try to avoid allocating bitmaps that are just fully
|
|
+ * set or completely unset.
|
|
+ */
|
|
+ overlap = gdk_region_rect_in (region, &r);
|
|
+ if (overlap == GDK_OVERLAP_RECTANGLE_PART)
|
|
+ {
|
|
+ /* The region and the mask intersect, create a new clip mask that
|
|
+ includes both areas */
|
|
+ priv->old_clip_mask = g_object_ref (priv->clip_mask);
|
|
+ new_mask = gdk_pixmap_new (priv->old_clip_mask, w, h, -1);
|
|
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)new_mask, FALSE);
|
|
+
|
|
+ gdk_gc_set_foreground (tmp_gc, &black);
|
|
+ gdk_draw_rectangle (new_mask, tmp_gc, TRUE, 0, 0, -1, -1);
|
|
+ _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE); /* Takes ownership of region */
|
|
+ gdk_draw_drawable (new_mask,
|
|
+ tmp_gc,
|
|
+ priv->old_clip_mask,
|
|
+ 0, 0,
|
|
+ 0, 0,
|
|
+ -1, -1);
|
|
+ gdk_gc_set_clip_region (tmp_gc, NULL);
|
|
+ gdk_gc_set_clip_mask (gc, new_mask);
|
|
+ }
|
|
+ else if (overlap == GDK_OVERLAP_RECTANGLE_OUT)
|
|
+ {
|
|
+ GdkRegion *empty = gdk_region_new ();
|
|
+
|
|
+ priv->old_clip_mask = g_object_ref (priv->clip_mask);
|
|
+ _gdk_windowing_gc_set_clip_region (gc, empty, FALSE);
|
|
+ gdk_region_destroy (empty);
|
|
+ }
|
|
}
|
|
else
|
|
{
|
|
@@ -775,6 +800,24 @@ _gdk_gc_get_clip_region (GdkGC *gc)
|
|
}
|
|
|
|
/**
|
|
+ * _gdk_gc_get_clip_mask:
|
|
+ * @gc: a #GdkGC
|
|
+ *
|
|
+ * Gets the current clip mask for @gc, if any.
|
|
+ *
|
|
+ * Return value: the clip mask for the GC, or %NULL.
|
|
+ * (if a clip region is set, the return will be %NULL)
|
|
+ * This value is owned by the GC and must not be freed.
|
|
+ **/
|
|
+GdkBitmap *
|
|
+_gdk_gc_get_clip_mask (GdkGC *gc)
|
|
+{
|
|
+ g_return_val_if_fail (GDK_IS_GC (gc), NULL);
|
|
+
|
|
+ return GDK_GC_GET_PRIVATE (gc)->clip_mask;
|
|
+}
|
|
+
|
|
+/**
|
|
* _gdk_gc_get_fill:
|
|
* @gc: a #GdkGC
|
|
*
|
|
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
|
|
index 946c3f9..c984386 100644
|
|
--- a/gdk/gdkinternals.h
|
|
+++ b/gdk/gdkinternals.h
|
|
@@ -399,6 +399,7 @@ void _gdk_gc_init (GdkGC *gc,
|
|
GdkGCValuesMask values_mask);
|
|
|
|
GdkRegion *_gdk_gc_get_clip_region (GdkGC *gc);
|
|
+GdkBitmap *_gdk_gc_get_clip_mask (GdkGC *gc);
|
|
gboolean _gdk_gc_get_exposures (GdkGC *gc);
|
|
GdkFill _gdk_gc_get_fill (GdkGC *gc);
|
|
GdkPixmap *_gdk_gc_get_tile (GdkGC *gc);
|
|
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
|
|
index 6e72cab..d9b1e5b 100644
|
|
--- a/gdk/gdkwindow.c
|
|
+++ b/gdk/gdkwindow.c
|
|
@@ -639,7 +639,12 @@ remove_child_area (GdkWindowObject *private,
|
|
child_region = gdk_region_rectangle (&r);
|
|
|
|
if (child->shape)
|
|
- gdk_region_intersect (child_region, child->shape);
|
|
+ {
|
|
+ /* Adjust shape region to parent window coords */
|
|
+ gdk_region_offset (child->shape, child->x, child->y);
|
|
+ gdk_region_intersect (child_region, child->shape);
|
|
+ gdk_region_offset (child->shape, -child->x, -child->y);
|
|
+ }
|
|
else if (private->window_type == GDK_WINDOW_FOREIGN)
|
|
{
|
|
shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
|
|
@@ -4660,7 +4665,12 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
|
|
|
|
child_region = gdk_region_rectangle (&r);
|
|
if (child->shape)
|
|
- gdk_region_intersect (child_region, child->shape);
|
|
+ {
|
|
+ /* Adjust shape region to parent window coords */
|
|
+ gdk_region_offset (child->shape, child->x, child->y);
|
|
+ gdk_region_intersect (child_region, child->shape);
|
|
+ gdk_region_offset (child->shape, -child->x, -child->y);
|
|
+ }
|
|
|
|
if (child->impl == private->impl)
|
|
{
|
|
diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c
|
|
index 537a47e..b2cac29 100644
|
|
--- a/gdk/x11/gdkdrawable-x11.c
|
|
+++ b/gdk/x11/gdkdrawable-x11.c
|
|
@@ -388,9 +388,22 @@ gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
|
|
else
|
|
{
|
|
XRenderPictureAttributes pa;
|
|
- pa.clip_mask = None;
|
|
+ GdkBitmap *mask;
|
|
+ gulong pa_mask;
|
|
+
|
|
+ pa_mask = CPClipMask;
|
|
+ if (gc && (mask = _gdk_gc_get_clip_mask (gc)))
|
|
+ {
|
|
+ pa.clip_mask = GDK_PIXMAP_XID (mask);
|
|
+ pa.clip_x_origin = gc->clip_x_origin;
|
|
+ pa.clip_y_origin = gc->clip_y_origin;
|
|
+ pa_mask |= CPClipXOrigin | CPClipYOrigin;
|
|
+ }
|
|
+ else
|
|
+ pa.clip_mask = None;
|
|
+
|
|
XRenderChangePicture (xdisplay, picture,
|
|
- CPClipMask, &pa);
|
|
+ pa_mask, &pa);
|
|
}
|
|
}
|
|
|