]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkgc.c
GtkWindow: Add gtk_window_has_group()
[~andy/gtk] / gdk / gdkgc.c
index f3ac9682026c6b65146be4216ae596f9b876874a..fbdfb6d5ed23f751802aba09318fa872cf2b9bd7 100644 (file)
@@ -46,20 +46,21 @@ struct _GdkGCPrivate
   guint32 region_tag_applied;
   int region_tag_offset_x;
   int region_tag_offset_y;
-  
+
   GdkRegion *old_clip_region;
   GdkPixmap *old_clip_mask;
-  
-  GdkSubwindowMode subwindow_mode;
-  
-  GdkFill fill;
+
   GdkBitmap *stipple;
   GdkPixmap *tile;
 
   GdkPixmap *clip_mask;
-  
+
   guint32 fg_pixel;
   guint32 bg_pixel;
+
+  guint subwindow_mode : 1;
+  guint fill : 2;
+  guint exposures : 2;
 };
 
 #define GDK_GC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_GC, GdkGCPrivate))
@@ -187,6 +188,10 @@ _gdk_gc_init (GdkGC           *gc,
     priv->bg_pixel = values->background.pixel;
   if (values_mask & GDK_GC_SUBWINDOW)
     priv->subwindow_mode = values->subwindow_mode;
+  if (values_mask & GDK_GC_EXPOSURES)
+    priv->exposures = values->graphics_exposures;
+  else
+    priv->exposures = TRUE;
 
   gc->colormap = gdk_drawable_get_colormap (drawable);
   if (gc->colormap)
@@ -217,34 +222,6 @@ gdk_gc_finalize (GObject *object)
   G_OBJECT_CLASS (gdk_gc_parent_class)->finalize (object);
 }
 
-/**
- * gdk_gc_ref:
- * @gc: a #GdkGC
- *
- * Deprecated function; use g_object_ref() instead.
- *
- * Return value: the gc.
- **/
-GdkGC *
-gdk_gc_ref (GdkGC *gc)
-{
-  return (GdkGC *) g_object_ref (gc);
-}
-
-/**
- * gdk_gc_unref:
- * @gc: a #GdkGC
- *
- * Decrement the reference count of @gc.
- *
- * Deprecated: Use g_object_unref() instead.
- **/
-void
-gdk_gc_unref (GdkGC *gc)
-{
-  g_object_unref (gc);
-}
-
 /**
  * gdk_gc_get_values:
  * @gc:  a #GdkGC.
@@ -350,6 +327,8 @@ gdk_gc_set_values (GdkGC           *gc,
     priv->bg_pixel = values->background.pixel;
   if (values_mask & GDK_GC_SUBWINDOW)
     priv->subwindow_mode = values->subwindow_mode;
+  if (values_mask & GDK_GC_EXPOSURES)
+    priv->exposures = values->graphics_exposures;
   
   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
 }
@@ -400,29 +379,6 @@ gdk_gc_set_background (GdkGC             *gc,
   gdk_gc_set_values (gc, &values, GDK_GC_BACKGROUND);
 }
 
-/**
- * gdk_gc_set_font:
- * @gc: a #GdkGC.
- * @font: the new font. 
- * 
- * Sets the font for a graphics context. (Note that
- * all text-drawing functions in GDK take a @font
- * argument; the value set here is used when that
- * argument is %NULL.)
- **/
-void
-gdk_gc_set_font (GdkGC  *gc,
-                GdkFont *font)
-{
-  GdkGCValues values;
-
-  g_return_if_fail (GDK_IS_GC (gc));
-  g_return_if_fail (font != NULL);
-
-  values.font = font;
-  gdk_gc_set_values (gc, &values, GDK_GC_FONT);
-}
-
 /**
  * gdk_gc_set_function:
  * @gc: a #GdkGC.
@@ -612,7 +568,6 @@ _gdk_gc_set_clip_region_internal (GdkGC     *gc,
 }
 
 
-/* returns old clip region */
 void
 _gdk_gc_add_drawable_clip (GdkGC     *gc,
                           guint32    region_tag,
@@ -640,24 +595,58 @@ _gdk_gc_add_drawable_clip (GdkGC     *gc,
       GdkPixmap *new_mask;
       GdkGC *tmp_gc;
       GdkColor black = {0, 0, 0, 0};
-      
-      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);
+      GdkRectangle r;
+      GdkOverlapType overlap;
+
+      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);
+         g_object_unref (new_mask);
+       }
+      else if (overlap == GDK_OVERLAP_RECTANGLE_OUT)
+       {
+         /* No intersection, set empty clip region */
+         GdkRegion *empty = gdk_region_new ();
+
+         gdk_region_destroy (region);
+         priv->old_clip_mask = g_object_ref (priv->clip_mask);
+         priv->clip_region = empty;
+         _gdk_windowing_gc_set_clip_region (gc, empty, FALSE);
+       }
+      else
+       {
+         /* Completely inside region, don't set unnecessary clip */
+         gdk_region_destroy (region);
+         return;
+       }
     }
   else
     {
@@ -665,7 +654,7 @@ _gdk_gc_add_drawable_clip (GdkGC     *gc,
       priv->clip_region = region;
       if (priv->old_clip_region)
        gdk_region_intersect (region, priv->old_clip_region);
-      
+
       _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
     }
 
@@ -687,6 +676,12 @@ _gdk_gc_remove_drawable_clip (GdkGC *gc)
          gdk_gc_set_clip_mask (gc, priv->old_clip_mask);
          g_object_unref (priv->old_clip_mask);
          priv->old_clip_mask = NULL;
+
+         if (priv->clip_region)
+           {
+             g_object_unref (priv->clip_region);
+             priv->clip_region = NULL;
+           }
        }
       else
        {
@@ -768,6 +763,24 @@ _gdk_gc_get_clip_region (GdkGC *gc)
   return GDK_GC_GET_PRIVATE (gc)->clip_region;
 }
 
+/**
+ * _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
@@ -784,6 +797,14 @@ _gdk_gc_get_fill (GdkGC *gc)
   return GDK_GC_GET_PRIVATE (gc)->fill;
 }
 
+gboolean
+_gdk_gc_get_exposures (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), FALSE);
+
+  return GDK_GC_GET_PRIVATE (gc)->exposures;
+}
+
 /**
  * _gdk_gc_get_tile:
  * @gc: a #GdkGC
@@ -1086,6 +1107,7 @@ gdk_gc_copy (GdkGC *dst_gc,
   dst_priv->fg_pixel = src_priv->fg_pixel;
   dst_priv->bg_pixel = src_priv->bg_pixel;
   dst_priv->subwindow_mode = src_priv->subwindow_mode;
+  dst_priv->exposures = src_priv->exposures;
 }
 
 /**
@@ -1324,6 +1346,8 @@ _gdk_gc_update_context (GdkGC          *gc,
 
   priv = GDK_GC_GET_PRIVATE (gc);
 
+  _gdk_gc_remove_drawable_clip (gc);
+
   fill = priv->fill;
   if (override_stipple && fill != GDK_OPAQUE_STIPPLED)
     fill = GDK_STIPPLED;
@@ -1414,6 +1438,10 @@ _gdk_gc_update_context (GdkGC          *gc,
     return;
 
   cairo_reset_clip (cr);
+  /* The reset above resets the window clip rect, so we want to re-set that */
+  if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
+
   if (priv->clip_region)
     {
       cairo_save (cr);
@@ -1429,9 +1457,6 @@ _gdk_gc_update_context (GdkGC          *gc,
       cairo_clip (cr);
     }
 
-  /* The reset above resets the window clip rect, so we want to re-set that */
-  if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
-    GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
 }