[gimp] app: add an infrastructure that allows to stroke multiple items at once



commit e6ce564de45a8fbc14a384412da10df186a4516f
Author: Michael Natterer <mitch gimp org>
Date:   Sun Sep 26 14:12:54 2010 +0200

    app: add an infrastructure that allows to stroke multiple items at once
    
    In order to avoid visually overlapping lines:
    
    - GimpCanvasItem got a "suspend_stroking" API that allows to skip
      stroking and instead starts a new sub-path
    - GimpCanvasGroup got a "group_stroking" API that sets suspend_stroking
      on all its children and does one stroke after calling all items'
      draw().

 app/display/gimpcanvasgroup.c |   58 ++++++++++++++++++++++++++++++++++++++---
 app/display/gimpcanvasgroup.h |   13 ++++++---
 app/display/gimpcanvasitem.c  |   53 ++++++++++++++++++++++++++++++++-----
 app/display/gimpcanvasitem.h  |   31 ++++++++++++----------
 4 files changed, 126 insertions(+), 29 deletions(-)
---
diff --git a/app/display/gimpcanvasgroup.c b/app/display/gimpcanvasgroup.c
index 6b4d465..95b50a8 100644
--- a/app/display/gimpcanvasgroup.c
+++ b/app/display/gimpcanvasgroup.c
@@ -35,7 +35,8 @@
 
 enum
 {
-  PROP_0
+  PROP_0,
+  PROP_GROUP_STROKING
 };
 
 
@@ -43,7 +44,8 @@ typedef struct _GimpCanvasGroupPrivate GimpCanvasGroupPrivate;
 
 struct _GimpCanvasGroupPrivate
 {
-  GList *items;
+  GList    *items;
+  gboolean  group_stroking;
 };
 
 #define GET_PRIVATE(group) \
@@ -88,6 +90,12 @@ gimp_canvas_group_class_init (GimpCanvasGroupClass *klass)
   item_class->draw           = gimp_canvas_group_draw;
   item_class->get_extents    = gimp_canvas_group_get_extents;
 
+  g_object_class_install_property (object_class, PROP_GROUP_STROKING,
+                                   g_param_spec_boolean ("group-stroking",
+                                                         NULL, NULL,
+                                                         FALSE,
+                                                         GIMP_PARAM_READWRITE));
+
   g_type_class_add_private (klass, sizeof (GimpCanvasGroupPrivate));
 }
 
@@ -117,10 +125,14 @@ gimp_canvas_group_set_property (GObject      *object,
                                 const GValue *value,
                                 GParamSpec   *pspec)
 {
-  /* GimpCanvasGroupPrivate *private = GET_PRIVATE (object); */
+  GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
 
   switch (property_id)
     {
+    case PROP_GROUP_STROKING:
+      private->group_stroking = g_value_get_boolean (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -133,10 +145,14 @@ gimp_canvas_group_get_property (GObject    *object,
                                 GValue     *value,
                                 GParamSpec *pspec)
 {
-  /* GimpCanvasGroupPrivate *private = GET_PRIVATE (object); */
+  GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
 
   switch (property_id)
     {
+    case PROP_GROUP_STROKING:
+      g_value_set_boolean (value, private->group_stroking);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -157,6 +173,9 @@ gimp_canvas_group_draw (GimpCanvasItem   *item,
 
       gimp_canvas_item_draw (sub_item, shell, cr);
     }
+
+  if (private->group_stroking)
+    _gimp_canvas_item_stroke (item, shell, cr);
 }
 
 static GdkRegion *
@@ -205,5 +224,36 @@ gimp_canvas_group_add_item (GimpCanvasGroup *group,
 
   private = GET_PRIVATE (group);
 
+  if (private->group_stroking)
+    gimp_canvas_item_suspend_stroking (item);
+
   private->items = g_list_append (private->items, g_object_ref (item));
 }
+
+void
+gimp_canvas_group_remove_item (GimpCanvasGroup *group,
+                               GimpCanvasItem  *item)
+{
+  GimpCanvasGroupPrivate *private;
+
+  g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
+  g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+  private = GET_PRIVATE (group);
+
+  g_return_if_fail (g_list_find (private->items, item));
+
+  private->items = g_list_remove (private->items, item);
+  g_object_unref (item);
+}
+
+void
+gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
+                                      gboolean         group_stroking)
+{
+  g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
+
+  g_object_set (group,
+                "group-stroking", group_stroking ? TRUE : FALSE,
+                NULL);
+}
diff --git a/app/display/gimpcanvasgroup.h b/app/display/gimpcanvasgroup.h
index 150bb54..f0d10a4 100644
--- a/app/display/gimpcanvasgroup.h
+++ b/app/display/gimpcanvasgroup.h
@@ -47,12 +47,17 @@ struct _GimpCanvasGroupClass
 };
 
 
-GType            gimp_canvas_group_get_type (void) G_GNUC_CONST;
+GType            gimp_canvas_group_get_type           (void) G_GNUC_CONST;
 
-GimpCanvasItem * gimp_canvas_group_new      (void);
+GimpCanvasItem * gimp_canvas_group_new                (void);
 
-void             gimp_canvas_group_add_item (GimpCanvasGroup *group,
-                                             GimpCanvasItem  *item);
+void             gimp_canvas_group_add_item           (GimpCanvasGroup *group,
+                                                       GimpCanvasItem  *item);
+void             gimp_canvas_group_remove_item        (GimpCanvasGroup *group,
+                                                       GimpCanvasItem  *item);
+
+void             gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
+                                                       gboolean         group_stroking);
 
 
 #endif /* __GIMP_CANVAS_GROUP_H__ */
diff --git a/app/display/gimpcanvasitem.c b/app/display/gimpcanvasitem.c
index b6aeaee..2bdf056 100644
--- a/app/display/gimpcanvasitem.c
+++ b/app/display/gimpcanvasitem.c
@@ -37,6 +37,7 @@ typedef struct _GimpCanvasItemPrivate GimpCanvasItemPrivate;
 struct _GimpCanvasItemPrivate
 {
   gboolean highlight;
+  gint     suspend_stroking;
 };
 
 #define GET_PRIVATE(item) \
@@ -122,15 +123,43 @@ void
 gimp_canvas_item_set_highlight (GimpCanvasItem *item,
                                 gboolean        highlight)
 {
-  GimpCanvasItemPrivate *private = GET_PRIVATE (item);
+  GimpCanvasItemPrivate *private;
 
   g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
 
+  private = GET_PRIVATE (item);
+
   private->highlight = highlight ? TRUE : FALSE;
 }
 
+void
+gimp_canvas_item_suspend_stroking (GimpCanvasItem *item)
+{
+  GimpCanvasItemPrivate *private;
+
+  g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+  private = GET_PRIVATE (item);
+
+  private->suspend_stroking++;
+}
+
+void
+gimp_canvas_item_resume_stroking (GimpCanvasItem *item)
+{
+  GimpCanvasItemPrivate *private;
+
+  g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+
+  private = GET_PRIVATE (item);
+
+  g_return_if_fail (private->suspend_stroking > 0);
+
+  private->suspend_stroking--;
+}
+
 
-/*  protexted functions  */
+/*  protected functions  */
 
 void
 _gimp_canvas_item_stroke (GimpCanvasItem   *item,
@@ -139,11 +168,18 @@ _gimp_canvas_item_stroke (GimpCanvasItem   *item,
 {
   GimpCanvasItemPrivate *private = GET_PRIVATE (item);
 
-  gimp_display_shell_set_tool_bg_style (shell, cr);
-  cairo_stroke_preserve (cr);
-
-  gimp_display_shell_set_tool_fg_style (shell, cr, private->highlight);
-  cairo_stroke (cr);
+  if (private->suspend_stroking == 0)
+    {
+      gimp_display_shell_set_tool_bg_style (shell, cr);
+      cairo_stroke_preserve (cr);
+
+      gimp_display_shell_set_tool_fg_style (shell, cr, private->highlight);
+      cairo_stroke (cr);
+    }
+  else
+    {
+      cairo_new_sub_path (cr);
+    }
 }
 
 void
@@ -153,6 +189,9 @@ _gimp_canvas_item_fill (GimpCanvasItem   *item,
 {
   GimpCanvasItemPrivate *private = GET_PRIVATE (item);
 
+  if (private->suspend_stroking > 0)
+    g_warning ("_gimp_canvas_item_fill() on an item that is in a stroking group");
+
   gimp_display_shell_set_tool_bg_style (shell, cr);
   cairo_set_line_width (cr, 2.0);
   cairo_stroke_preserve (cr);
diff --git a/app/display/gimpcanvasitem.h b/app/display/gimpcanvasitem.h
index 876d996..fa14af6 100644
--- a/app/display/gimpcanvasitem.h
+++ b/app/display/gimpcanvasitem.h
@@ -52,26 +52,29 @@ struct _GimpCanvasItemClass
 };
 
 
-GType       gimp_canvas_item_get_type     (void) G_GNUC_CONST;
+GType       gimp_canvas_item_get_type         (void) G_GNUC_CONST;
 
-void        gimp_canvas_item_draw         (GimpCanvasItem   *item,
-                                           GimpDisplayShell *shell,
-                                           cairo_t          *cr);
-GdkRegion * gimp_canvas_item_get_extents  (GimpCanvasItem   *item,
-                                           GimpDisplayShell *shell);
+void        gimp_canvas_item_draw             (GimpCanvasItem   *item,
+                                               GimpDisplayShell *shell,
+                                               cairo_t          *cr);
+GdkRegion * gimp_canvas_item_get_extents      (GimpCanvasItem   *item,
+                                               GimpDisplayShell *shell);
 
-void        gimp_canvas_item_set_highlight(GimpCanvasItem   *item,
-                                           gboolean          highlight);
+void        gimp_canvas_item_set_highlight    (GimpCanvasItem   *item,
+                                               gboolean          highlight);
+
+void        gimp_canvas_item_suspend_stroking (GimpCanvasItem   *item);
+void        gimp_canvas_item_resume_stroking  (GimpCanvasItem   *item);
 
 
 /*  protected  */
 
-void        _gimp_canvas_item_stroke      (GimpCanvasItem   *item,
-                                           GimpDisplayShell *shell,
-                                           cairo_t          *cr);
-void        _gimp_canvas_item_fill        (GimpCanvasItem   *item,
-                                           GimpDisplayShell *shell,
-                                           cairo_t          *cr);
+void        _gimp_canvas_item_stroke          (GimpCanvasItem   *item,
+                                               GimpDisplayShell *shell,
+                                               cairo_t          *cr);
+void        _gimp_canvas_item_fill            (GimpCanvasItem   *item,
+                                               GimpDisplayShell *shell,
+                                               cairo_t          *cr);
 
 
 #endif /* __GIMP_CANVAS_ITEM_H__ */



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