[gtk+/client-side-windows: 21/284] Move drawable clip tracking into GdkGC



commit e9ee842db1cec299f6b67ecfa9eb23985d60aad3
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Dec 4 20:18:02 2008 +0100

    Move drawable clip tracking into GdkGC
---
 gdk/gdkgc.c        |   91 ++++++++++++++++++++++++++++++++++++++--------------
 gdk/gdkinternals.h |   11 +++---
 gdk/gdkwindow.c    |   71 +++++++++++++++++++++-------------------
 gdk/gdkwindow.h    |    1 +
 4 files changed, 112 insertions(+), 62 deletions(-)

diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
index 6bc3a99..355a346 100644
--- a/gdk/gdkgc.c
+++ b/gdk/gdkgc.c
@@ -43,6 +43,10 @@ struct _GdkGCPrivate
 {
   GdkRegion *clip_region;
 
+  guint32 region_tag_applied;
+  
+  GdkRegion *old_clip_region;
+  
   GdkSubwindowMode subwindow_mode;
   
   GdkFill fill;
@@ -190,6 +194,8 @@ gdk_gc_finalize (GObject *object)
 
   if (priv->clip_region)
     gdk_region_destroy (priv->clip_region);
+  if (priv->old_clip_region)
+    gdk_region_destroy (priv->old_clip_region);
   if (gc->colormap)
     g_object_unref (gc->colormap);
   if (priv->tile)
@@ -273,6 +279,12 @@ gdk_gc_set_values (GdkGC           *gc,
 
   priv = GDK_GC_GET_PRIVATE (gc);
 
+  if ((values_mask & GDK_GC_CLIP_X_ORIGIN) ||
+      (values_mask & GDK_GC_CLIP_Y_ORIGIN) ||
+      (values_mask & GDK_GC_CLIP_MASK) ||
+      (values_mask & GDK_GC_SUBWINDOW))
+    _gdk_gc_remove_drawable_clip (gc);
+  
   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
     gc->clip_x_origin = values->clip_x_origin;
   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
@@ -549,10 +561,10 @@ gdk_gc_set_clip_mask (GdkGC	*gc,
 }
 
 /* Takes ownership of passed in region */
-void
-_gdk_gc_set_clip_region_internal (GdkGC     *gc,
-				  GdkRegion *region,
-				  gboolean reset_origin)
+static void
+_gdk_gc_set_clip_region_real (GdkGC     *gc,
+			      GdkRegion *region,
+			      gboolean reset_origin)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
@@ -564,37 +576,54 @@ _gdk_gc_set_clip_region_internal (GdkGC     *gc,
   _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
 }
 
+/* Doesn't copy region, allows not to reset origin */
+void
+_gdk_gc_set_clip_region_internal (GdkGC     *gc,
+				  GdkRegion *region,
+				  gboolean reset_origin)
+{
+  _gdk_gc_remove_drawable_clip (gc);
+  _gdk_gc_set_clip_region_real (gc, region, reset_origin);
+}
+
+
 /* returns old clip region */
 void
-_gdk_gc_intersect_clip_region (GdkGC     *gc,
-			       GdkRegion *region,
-			       int        offset_x,
-			       int        offset_y,
-			       GdkRegion **old_clip_region)
+_gdk_gc_add_drawable_clip (GdkGC     *gc,
+			   guint32    region_tag,
+			   GdkRegion *region,
+			   int        offset_x,
+			   int        offset_y)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-  GdkRegion *old_clip;
-  gboolean free;
 
-  old_clip = priv->clip_region;
+  g_assert (priv->old_clip_region == NULL);
+  
+  priv->region_tag_applied = region_tag;
+  priv->old_clip_region = priv->clip_region;
 
   region = gdk_region_copy (region);
-
   if (offset_x != 0 || offset_y != 0)
     gdk_region_offset (region, offset_x, offset_y);
   
   priv->clip_region = region;
-  if (old_clip)
-    gdk_region_intersect (region, old_clip);
+  if (priv->old_clip_region)
+    gdk_region_intersect (region, priv->old_clip_region);
 
-  if (old_clip_region)
-    *old_clip_region = old_clip;
-  else
-    gdk_region_destroy (old_clip);
-  
   _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
-  
-  return old_clip;
+}
+
+void
+_gdk_gc_remove_drawable_clip (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  if (priv->region_tag_applied)
+    {
+      _gdk_gc_set_clip_region_real (gc, priv->old_clip_region, FALSE);
+      priv->old_clip_region = NULL;
+      priv->region_tag_applied = 0;
+    }
 }
 
 /**
@@ -614,12 +643,14 @@ gdk_gc_set_clip_rectangle (GdkGC              *gc,
   
   g_return_if_fail (GDK_IS_GC (gc));
 
+  _gdk_gc_remove_drawable_clip (gc);
+  
   if (rectangle)
     region = gdk_region_rectangle (rectangle);
   else
     region = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, region, TRUE);
+  _gdk_gc_set_clip_region_real (gc, region, TRUE);
 }
 
 /**
@@ -639,12 +670,14 @@ gdk_gc_set_clip_region (GdkGC           *gc,
 
   g_return_if_fail (GDK_IS_GC (gc));
 
+  _gdk_gc_remove_drawable_clip (gc);
+  
   if (region)
     copy = gdk_region_copy (region);
   else
     copy = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, copy, TRUE);
+  _gdk_gc_set_clip_region_real (gc, copy, TRUE);
 }
 
 /**
@@ -945,6 +978,16 @@ gdk_gc_copy (GdkGC *dst_gc,
     dst_priv->clip_region = gdk_region_copy (src_priv->clip_region);
   else
     dst_priv->clip_region = NULL;
+
+  dst_priv->region_tag_applied = src_priv->region_tag_applied;
+  
+  if (dst_priv->old_clip_region)
+    gdk_region_destroy (dst_priv->old_clip_region);
+
+  if (src_priv->old_clip_region)
+    dst_priv->old_clip_region = gdk_region_copy (src_priv->old_clip_region);
+  else
+    dst_priv->old_clip_region = NULL;
   
   dst_priv->fill = src_priv->fill;
   
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 995f3bf..c9d5378 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -293,11 +293,12 @@ GdkPixmap *_gdk_gc_get_tile        (GdkGC *gc);
 GdkBitmap *_gdk_gc_get_stipple     (GdkGC *gc);
 guint32    _gdk_gc_get_fg_pixel    (GdkGC *gc);
 guint32    _gdk_gc_get_bg_pixel    (GdkGC *gc);
-void      _gdk_gc_intersect_clip_region     (GdkGC     *gc,
-					     GdkRegion *region,
-					     int        offset_x,
-					     int        offset_y,
-					     GdkRegion **old_region);
+void      _gdk_gc_add_drawable_clip     (GdkGC     *gc,
+					 guint32    region_tag,
+					 GdkRegion *region,
+					 int        offset_x,
+					 int        offset_y);
+void      _gdk_gc_remove_drawable_clip  (GdkGC     *gc);
 void       _gdk_gc_set_clip_region_internal (GdkGC     *gc,
 					     GdkRegion *region,
 					     gboolean reset_origin);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 5d9b812..7043b83 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -69,6 +69,7 @@ struct _GdkWindowPaint
   gint y_offset;
   cairo_surface_t *surface;
   guint uses_implicit : 1;
+  guint32 region_tag;
 };
 
 /* Global info */
@@ -234,6 +235,14 @@ static gpointer parent_class = NULL;
 
 static const cairo_user_data_key_t gdk_window_cairo_key;
 
+static guint32
+new_region_tag (void)
+{
+  static guint32 tag = 0;
+
+  return ++tag;
+}
+
 GType
 gdk_window_object_get_type (void)
 {
@@ -509,6 +518,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
       if (private->clip_region)
 	gdk_region_destroy (private->clip_region);
       private->clip_region = new_clip;
+      private->clip_tag = new_region_tag ();
 
       private->clip_region_with_children = gdk_region_copy (private->clip_region);
       remove_child_area (private, NULL, private->clip_region_with_children);
@@ -1925,17 +1935,19 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   implicit_paint = impl_window->implicit_paint;
 
   paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_copy (region);
+  paint->region_tag = new_region_tag ();
+      
   if (implicit_paint)
     {
       int width, height;
-
+      
       paint->uses_implicit = TRUE;
       paint->pixmap = g_object_ref (implicit_paint->pixmap);
       paint->x_offset = -private->abs_x + implicit_paint->x_offset;
       paint->y_offset = -private->abs_y + implicit_paint->y_offset;
-      paint->region = gdk_region_copy (region);
       gdk_region_intersect (paint->region, private->clip_region_with_children);
-
+      
       /* It would be nice if we had some cairo support here so we
 	 could set the clip rect on the cairo surface */
       width = private->abs_x + private->width;
@@ -1943,9 +1955,6 @@ gdk_window_begin_paint_region (GdkWindow       *window,
       
       paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
 							    width, height);
-      if (paint->surface)
-	cairo_surface_set_device_offset (paint->surface,
-					 - paint->x_offset, - paint->y_offset);
 
       /* Mark the region as valid on the implicit paint */
       gdk_region_offset (paint->region, private->abs_x, private->abs_y); 
@@ -1955,19 +1964,18 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   else
     {
       paint->uses_implicit = FALSE;
-      paint->region = gdk_region_copy (region);
       paint->x_offset = clip_box.x;
       paint->y_offset = clip_box.y;
       paint->pixmap =
 	gdk_pixmap_new (window,
 			MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
-
       paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
-      cairo_surface_set_device_offset (paint->surface,
-				       - paint->x_offset, - paint->y_offset);
     }
+ 
+  if (paint->surface)
+    cairo_surface_set_device_offset (paint->surface,
+				     -paint->x_offset, -paint->y_offset);
   
-      
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *tmp_paint = list->data;
@@ -2264,8 +2272,7 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
 static void
 setup_clip_for_draw (GdkDrawable *drawable,
 		     GdkGC *gc,
-		     int old_clip_x, int old_clip_y,
-		     GdkRegion **old_clip_region)
+		     int old_clip_x, int old_clip_y)
 {
   GdkWindowObject *private = (GdkWindowObject *)drawable;
   GdkRegion *clip;
@@ -2275,27 +2282,27 @@ setup_clip_for_draw (GdkDrawable *drawable,
   else
     clip = private->clip_region;
     
-  _gdk_gc_intersect_clip_region (gc, clip,
-				 /* If there was a clip origin set appart from the
-				  * window offset, need to take that into consideration */
-				 -old_clip_x, -old_clip_y,
-				 old_clip_region);
+  _gdk_gc_add_drawable_clip (gc,
+			     private->clip_tag,
+			     clip,
+			     /* If there was a clip origin set appart from the
+			      * window offset, need to take that into consideration */
+			     -old_clip_x, -old_clip_y);
 }
 
 static void
 setup_clip_for_paint (GdkDrawable *drawable,
 		      GdkWindowPaint *paint,
 		      GdkGC *gc,
-		      int old_clip_x, int old_clip_y,
-		      GdkRegion **old_clip_region)
+		      int old_clip_x, int old_clip_y)
 {
-  _gdk_gc_intersect_clip_region (gc,
-				 /* This includes the window clip */
-				 paint->region,
-				 /* If there was a clip origin set appart from the
-				  * window offset, need to take that into consideration */
-				 -old_clip_x, -old_clip_y,
-				 old_clip_region);
+  _gdk_gc_add_drawable_clip (gc,
+			     paint->region_tag,
+			     /* This includes the window clip */
+			     paint->region,
+			     /* If there was a clip origin set appart from the
+			      * window offset, need to take that into consideration */
+			     -old_clip_x, -old_clip_y);
 }
 
 
@@ -2322,23 +2329,21 @@ setup_clip_for_paint (GdkDrawable *drawable,
      }
 
 #define SETUP_PAINT_GC_CLIP(gc)                             \
-      GdkRegion *old_clip_region;                           \
       if (paint->uses_implicit)        			    \
 	setup_clip_for_paint (drawable, paint, gc, old_clip_x,	\
-                              old_clip_y, &old_clip_region);
+                              old_clip_y);
 
 #define RESTORE_PAINT_GC_CLIP(gc)                          \
       if (paint->uses_implicit)    			   \
-        _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+        _gdk_gc_remove_drawable_clip (gc);
 
 
 #define SETUP_DIRECT_GC_CLIP(gc)                            \
-      GdkRegion *old_clip_region;                           \
       gdk_window_flush_implicit_paint ((GdkWindow *)drawable);\
-      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y, &old_clip_region);
+      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
 
 #define RESTORE_DIRECT_GC_CLIP(gc)                                 \
-      _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+      _gdk_gc_remove_drawable_clip (gc);
 
 static GdkGC *
 gdk_window_create_gc (GdkDrawable     *drawable,
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index ec3f67a..7a628b5 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -328,6 +328,7 @@ struct _GdkWindowObject
 
   int abs_x, abs_y; /* Absolute offset in impl */
   gint width, height;
+  guint32 clip_tag;
   GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
   GdkRegion *clip_region_with_children; /* Clip region in window coords */
   GdkColormap *colormap;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]