diff options
author | Alexander Larsson <alexl@redhat.com> | 2009-07-07 15:14:16 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2009-07-07 17:10:49 +0200 |
commit | 52e3d2cf0e848d8956a6091c68b6d382cbbf4eb6 (patch) | |
tree | 3f784637c9f9dbd80b4f01e6d90236771683ef33 | |
parent | 2678a454e5447ba28cf1aa7c316a1e73b7b30018 (diff) | |
download | gdk-pixbuf-52e3d2cf0e848d8956a6091c68b6d382cbbf4eb6.tar.gz |
Optimize clip-to-window with clipmask case when fully visible or obscured
This avoids creating alot of bitmaps in common trivial cases.
-rw-r--r-- | gdk/gdkgc.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c index 43e2a5f32..699cebfc2 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 { |