[gimp/gimp-2-10] app: better handle drawable and image update for line art computation.



commit 4c3fcdb6bbd2a38bb369efae9399119afe2dbffc
Author: Jehan <jehan girinstud io>
Date:   Mon Nov 19 14:13:03 2018 +0100

    app: better handle drawable and image update for line art computation.
    
    The "update" signal on drawable or projection can actually be emitted
    many times for a single painting event. Just add new signals ("painted"
    on GimpDrawable and "rendered" on GimpProjection) which are emitted once
    for a single update (from user point of view), at the end, after actual
    rendering is done (i.e. after the various "update" signals).
    
    Also better support the sample merge vs current drawable paths for
    bucket fill.
    
    (cherry picked from commit 047265333cff7e13db173db8d0bddc6279e9e318)

 app/core/gimpdrawable.c        | 30 +++++++++++++++++++++++
 app/core/gimpdrawable.h        |  1 +
 app/core/gimpprojection.c      | 11 +++++++++
 app/core/gimpprojection.h      | 13 +++++-----
 app/tools/gimpbucketfilltool.c | 54 +++++++++++++++++++++++++++++-------------
 5 files changed, 86 insertions(+), 23 deletions(-)
---
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 262d67ea5c..8b93c4eaac 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -68,6 +68,7 @@
 enum
 {
   UPDATE,
+  PAINTED,
   ALPHA_CHANGED,
   LAST_SIGNAL
 };
@@ -220,6 +221,16 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
   GimpFilterClass   *filter_class      = GIMP_FILTER_CLASS (klass);
   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
 
+  /**
+   * GimpDrawable::update:
+   * @drawable: the object which received the signal.
+   * @x:
+   * @y:
+   * @width:
+   * @height:
+   *
+   * This signal is emitted when a region of the drawable is updated.
+   **/
   gimp_drawable_signals[UPDATE] =
     g_signal_new ("update",
                   G_TYPE_FROM_CLASS (klass),
@@ -233,6 +244,24 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
                   G_TYPE_INT,
                   G_TYPE_INT);
 
+  /**
+   * GimpDrawable::painted:
+   * @drawable: the object which received the signal.
+   *
+   * This signal is emitted when the drawable has been painted. Unlike
+   * the "update" signal, it will be emitted once for a single paint
+   * event (whereas several "update" signals could be emitted
+   * sequentially for various regions of the drawable).
+   **/
+  gimp_drawable_signals[PAINTED] =
+    g_signal_new ("painted",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpDrawableClass, painted),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
   gimp_drawable_signals[ALPHA_CHANGED] =
     g_signal_new ("alpha-changed",
                   G_TYPE_FROM_CLASS (klass),
@@ -1018,6 +1047,7 @@ gimp_drawable_update (GimpDrawable *drawable,
     {
       g_signal_emit (drawable, gimp_drawable_signals[UPDATE], 0,
                      x, y, width, height);
+      g_signal_emit (drawable, gimp_drawable_signals[PAINTED], 0);
     }
   else
     {
diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h
index a36f001c17..0239ab0880 100644
--- a/app/core/gimpdrawable.h
+++ b/app/core/gimpdrawable.h
@@ -50,6 +50,7 @@ struct _GimpDrawableClass
                                            gint                  y,
                                            gint                  width,
                                            gint                  height);
+  void          (* painted)               (GimpDrawable         *drawable);
   void          (* alpha_changed)         (GimpDrawable         *drawable);
 
   /*  virtual functions  */
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index b7b2c26a3d..9d9765e3bb 100644
--- a/app/core/gimpprojection.c
+++ b/app/core/gimpprojection.c
@@ -81,6 +81,7 @@ static gdouble GIMP_PROJECTION_CHUNK_TIME = 0.0666;
 enum
 {
   UPDATE,
+  RENDERED,
   LAST_SIGNAL
 };
 
@@ -258,6 +259,15 @@ gimp_projection_class_init (GimpProjectionClass *klass)
                   G_TYPE_INT,
                   G_TYPE_INT);
 
+  projection_signals[RENDERED] =
+    g_signal_new ("rendered",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GimpProjectionClass, rendered),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
   object_class->finalize         = gimp_projection_finalize;
   object_class->set_property     = gimp_projection_set_property;
   object_class->get_property     = gimp_projection_get_property;
@@ -842,6 +852,7 @@ gimp_projection_chunk_render_stop (GimpProjection *proj)
 
   g_source_remove (proj->priv->chunk_render.idle_id);
   proj->priv->chunk_render.idle_id = 0;
+  g_signal_emit (proj, projection_signals[RENDERED], 0);
 }
 
 static gboolean
diff --git a/app/core/gimpprojection.h b/app/core/gimpprojection.h
index 8c9baf69e6..36d76d076c 100644
--- a/app/core/gimpprojection.h
+++ b/app/core/gimpprojection.h
@@ -44,12 +44,13 @@ struct _GimpProjectionClass
 {
   GimpObjectClass  parent_class;
 
-  void (* update) (GimpProjection *proj,
-                   gboolean        now,
-                   gint            x,
-                   gint            y,
-                   gint            width,
-                   gint            height);
+  void (* update)   (GimpProjection *proj,
+                     gboolean        now,
+                     gint            x,
+                     gint            y,
+                     gint            width,
+                     gint            height);
+  void (* rendered) (GimpProjection *proj);
 };
 
 
diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c
index 60d05accf0..a4f6639e53 100644
--- a/app/tools/gimpbucketfilltool.c
+++ b/app/tools/gimpbucketfilltool.c
@@ -138,11 +138,9 @@ static void     gimp_bucket_fill_tool_image_changed    (GimpContext           *c
                                                         GimpBucketFillTool    *tool);
 static void     gimp_bucket_fill_tool_drawable_changed (GimpImage            *image,
                                                         GimpBucketFillTool   *tool);
-static void     gimp_bucket_fill_tool_drawable_update  (GimpDrawable         *drawable,
-                                                        gint                  x,
-                                                        gint                  y,
-                                                        gint                  width,
-                                                        gint                  height,
+static void  gimp_bucket_fill_tool_projection_rendered (GimpProjection     *proj,
+                                                        GimpBucketFillTool *tool);
+static void     gimp_bucket_fill_tool_drawable_painted (GimpDrawable         *drawable,
                                                         GimpBucketFillTool   *tool);
 
 
@@ -240,6 +238,8 @@ gimp_bucket_fill_tool_finalize (GObject *object)
   if (image)
     {
       g_signal_handlers_disconnect_by_data (image, tool);
+      g_signal_handlers_disconnect_by_data (gimp_image_get_projection (image),
+                                            tool);
       g_object_unref (image);
     }
   if (drawable)
@@ -406,10 +406,14 @@ gimp_bucket_fill_tool_preview (GimpBucketFillTool *tool,
 static void
 gimp_bucket_fill_tool_commit (GimpBucketFillTool *tool)
 {
-  tool->priv->fill_in_progress = FALSE;
-
   if (tool->priv->filter)
     {
+      GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+
+      /* Make sure the drawable will signal being painted. */
+      if (! options->sample_merged)
+        tool->priv->fill_in_progress = FALSE;
+
       gimp_drawable_filter_commit (tool->priv->filter,
                                    GIMP_PROGRESS (tool), FALSE);
       gimp_image_flush (gimp_display_get_image (GIMP_TOOL (tool)->display));
@@ -849,7 +853,11 @@ gimp_bucket_fill_tool_image_changed (GimpContext        *context,
       g_clear_object (&tool->priv->line_art);
 
       if (prev_image)
-        g_signal_handlers_disconnect_by_data (prev_image, tool);
+        {
+          g_signal_handlers_disconnect_by_data (prev_image, tool);
+          g_signal_handlers_disconnect_by_data (gimp_image_get_projection (prev_image),
+                                                tool);
+        }
       if (prev_drawable)
         {
           g_signal_handlers_disconnect_by_data (prev_drawable, tool);
@@ -866,6 +874,9 @@ gimp_bucket_fill_tool_image_changed (GimpContext        *context,
           g_signal_connect (image, "active-channel-changed",
                             G_CALLBACK (gimp_bucket_fill_tool_drawable_changed),
                             tool);
+          g_signal_connect (gimp_image_get_projection (image), "rendered",
+                            G_CALLBACK (gimp_bucket_fill_tool_projection_rendered),
+                            tool);
           gimp_bucket_fill_tool_drawable_changed (image, tool);
         }
     }
@@ -887,8 +898,8 @@ gimp_bucket_fill_tool_drawable_changed (GimpImage          *image,
 
       g_weak_ref_set (&tool->priv->cached_drawable, drawable ? drawable : NULL);
       if (drawable)
-        g_signal_connect (drawable, "update",
-                          G_CALLBACK (gimp_bucket_fill_tool_drawable_update),
+        g_signal_connect (drawable, "painted",
+                          G_CALLBACK (gimp_bucket_fill_tool_drawable_painted),
                           tool);
 
       gimp_bucket_fill_compute_line_art (tool);
@@ -898,12 +909,21 @@ gimp_bucket_fill_tool_drawable_changed (GimpImage          *image,
 }
 
 static void
-gimp_bucket_fill_tool_drawable_update (GimpDrawable       *drawable,
-                                       gint                x,
-                                       gint                y,
-                                       gint                width,
-                                       gint                height,
-                                       GimpBucketFillTool *tool)
+gimp_bucket_fill_tool_projection_rendered (GimpProjection     *proj,
+                                           GimpBucketFillTool *tool)
+{
+  GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+
+  if (options->sample_merged)
+    gimp_bucket_fill_compute_line_art (tool);
+}
+
+static void
+gimp_bucket_fill_tool_drawable_painted (GimpDrawable       *drawable,
+                                        GimpBucketFillTool *tool)
 {
-  gimp_bucket_fill_compute_line_art (tool);
+  GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+
+  if (! options->sample_merged)
+    gimp_bucket_fill_compute_line_art (tool);
 }


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