[gimp] app: fix airbrush periodic stamp behavior



commit 542a04735be9df70377dd4d5020370d2e4437e59
Author: Ell <ell_se yahoo com>
Date:   Wed Apr 18 13:35:28 2018 -0400

    app: fix airbrush periodic stamp behavior
    
    Commit ddfc7715cbcd8d165520902bc0abfff3c09b88f4 changed the
    airbrush periodic stamp behavior, so that instead of using the main
    brush, it issued a full MOTION event, potentially using a different
    brush when using a GIH brush.
    
    Fix this, by renaming the "timeout" signal of GimpAirbrush to
    "stamp", and by adding a new gimp_airbrush_stamp() function, which
    should be used for painting the periodic airbrush dab in response,
    instead of calling gimp_paint_core_paint() directly, and which
    calls gimp_airbrush_paint() instead, as the old code did.
    
    In order to call this function from the paint thread, we replace
    the various gimp_paint_tool_paint_core_foo() functions, introduced
    in the above commit, with a generic gimp_paint_tool_paint_push()
    function, which takes a callback (and a data pointer) to run on the
    paint thread, and queues it for execution (when not using the paint
    thread, the function is called directly from the calling thread.)

 app/paint/gimpairbrush.c        |   37 +++++-
 app/paint/gimpairbrush.h        |   12 ++-
 app/tools/gimpairbrushtool.c    |   37 ++++--
 app/tools/gimppainttool-paint.c |  258 ++++++++++++++-------------------------
 app/tools/gimppainttool-paint.h |   46 ++++----
 5 files changed, 186 insertions(+), 204 deletions(-)
---
diff --git a/app/paint/gimpairbrush.c b/app/paint/gimpairbrush.c
index 042cb2b..c30cc24 100644
--- a/app/paint/gimpairbrush.c
+++ b/app/paint/gimpairbrush.c
@@ -38,7 +38,7 @@
 
 enum
 {
-  TIMEOUT,
+  STAMP,
   LAST_SIGNAL
 };
 
@@ -88,11 +88,11 @@ gimp_airbrush_class_init (GimpAirbrushClass *klass)
 
   paint_core_class->paint = gimp_airbrush_paint;
 
-  airbrush_signals[TIMEOUT] =
-    g_signal_new ("timeout",
+  airbrush_signals[STAMP] =
+    g_signal_new ("stamp",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (GimpAirbrushClass, timeout),
+                  G_STRUCT_OFFSET (GimpAirbrushClass, stamp),
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -114,6 +114,8 @@ gimp_airbrush_finalize (GObject *object)
       airbrush->timeout_id = 0;
     }
 
+  g_clear_object (&airbrush->sym);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -158,6 +160,13 @@ gimp_airbrush_paint (GimpPaintCore    *paint_core,
           fade_point = gimp_paint_options_get_fade (paint_options, image,
                                                     paint_core->pixel_dist);
 
+          airbrush->drawable      = drawable;
+          airbrush->paint_options = paint_options;
+
+          if (airbrush->sym)
+            g_object_unref (airbrush->sym);
+          airbrush->sym = g_object_ref (sym);
+
           /* Base our timeout on the original stroke. */
           coords = gimp_symmetry_get_origin (sym);
 
@@ -180,6 +189,8 @@ gimp_airbrush_paint (GimpPaintCore    *paint_core,
                                                    paint_options,
                                                    sym,
                                                    paint_state, time);
+
+      g_clear_object (&airbrush->sym);
       break;
     }
 }
@@ -221,7 +232,23 @@ gimp_airbrush_timeout (gpointer data)
 
   airbrush->timeout_id = 0;
 
-  g_signal_emit (airbrush, airbrush_signals[TIMEOUT], 0);
+  g_signal_emit (airbrush, airbrush_signals[STAMP], 0);
 
   return G_SOURCE_REMOVE;
 }
+
+
+/*  public functions  */
+
+
+void
+gimp_airbrush_stamp (GimpAirbrush *airbrush)
+{
+  g_return_if_fail (GIMP_IS_AIRBRUSH (airbrush));
+
+  gimp_airbrush_paint (GIMP_PAINT_CORE (airbrush),
+                       airbrush->drawable,
+                       airbrush->paint_options,
+                       airbrush->sym,
+                       GIMP_PAINT_STATE_MOTION, 0);
+}
diff --git a/app/paint/gimpairbrush.h b/app/paint/gimpairbrush.h
index 7aa802c..4efb8d7 100644
--- a/app/paint/gimpairbrush.h
+++ b/app/paint/gimpairbrush.h
@@ -34,9 +34,13 @@ typedef struct _GimpAirbrushClass GimpAirbrushClass;
 
 struct _GimpAirbrush
 {
-  GimpPaintbrush  parent_instance;
+  GimpPaintbrush    parent_instance;
 
-  guint           timeout_id;
+  guint             timeout_id;
+
+  GimpSymmetry     *sym;
+  GimpDrawable     *drawable;
+  GimpPaintOptions *paint_options;
 };
 
 struct _GimpAirbrushClass
@@ -44,7 +48,7 @@ struct _GimpAirbrushClass
   GimpPaintbrushClass  parent_class;
 
   /*  signals  */
-  void (* timeout) (GimpAirbrush *airbrush);
+  void (* stamp) (GimpAirbrush *airbrush);
 };
 
 
@@ -53,5 +57,7 @@ void    gimp_airbrush_register (Gimp                      *gimp,
 
 GType   gimp_airbrush_get_type (void) G_GNUC_CONST;
 
+void    gimp_airbrush_stamp    (GimpAirbrush              *airbrush);
+
 
 #endif  /*  __GIMP_AIRBRUSH_H__  */
diff --git a/app/tools/gimpairbrushtool.c b/app/tools/gimpairbrushtool.c
index 2374a37..a315bb7 100644
--- a/app/tools/gimpairbrushtool.c
+++ b/app/tools/gimpairbrushtool.c
@@ -24,6 +24,7 @@
 
 #include "tools-types.h"
 
+#include "paint/gimpairbrush.h"
 #include "paint/gimpairbrushoptions.h"
 
 #include "widgets/gimphelp-ids.h"
@@ -37,12 +38,15 @@
 #include "gimp-intl.h"
 
 
-static void        gimp_airbrush_tool_constructed      (GObject          *object);
+static void        gimp_airbrush_tool_constructed    (GObject          *object);
 
-static void        gimp_airbrush_tool_airbrush_timeout (GimpAirbrush     *airbrush,
-                                                        GimpAirbrushTool *airbrush_tool);
+static void        gimp_airbrush_tool_airbrush_stamp (GimpAirbrush     *airbrush,
+                                                      GimpAirbrushTool *airbrush_tool);
 
-static GtkWidget * gimp_airbrush_options_gui           (GimpToolOptions  *tool_options);
+static void        gimp_airbrush_tool_stamp          (GimpAirbrushTool *airbrush_tool,
+                                                      gpointer          data);
+
+static GtkWidget * gimp_airbrush_options_gui         (GimpToolOptions  *tool_options);
 
 
 G_DEFINE_TYPE (GimpAirbrushTool, gimp_airbrush_tool, GIMP_TYPE_PAINTBRUSH_TOOL)
@@ -91,17 +95,30 @@ gimp_airbrush_tool_constructed (GObject *object)
 
   G_OBJECT_CLASS (parent_class)->constructed (object);
 
-  g_signal_connect_object (paint_tool->core, "timeout",
-                           G_CALLBACK (gimp_airbrush_tool_airbrush_timeout),
+  g_signal_connect_object (paint_tool->core, "stamp",
+                           G_CALLBACK (gimp_airbrush_tool_airbrush_stamp),
                            object, 0);
 }
 
 static void
-gimp_airbrush_tool_airbrush_timeout (GimpAirbrush     *airbrush,
-                                     GimpAirbrushTool *airbrush_tool)
+gimp_airbrush_tool_airbrush_stamp (GimpAirbrush     *airbrush,
+                                   GimpAirbrushTool *airbrush_tool)
 {
-  gimp_paint_tool_paint_core_paint (GIMP_PAINT_TOOL (airbrush_tool),
-                                    GIMP_PAINT_STATE_MOTION, 0);
+  GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (airbrush_tool);
+
+  gimp_paint_tool_paint_push (
+    paint_tool,
+    (GimpPaintToolPaintFunc) gimp_airbrush_tool_stamp,
+    NULL);
+}
+
+static void
+gimp_airbrush_tool_stamp (GimpAirbrushTool *airbrush_tool,
+                          gpointer          data)
+{
+  GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (airbrush_tool);
+
+  gimp_airbrush_stamp (GIMP_AIRBRUSH (paint_tool->core));
 }
 
 
diff --git a/app/tools/gimppainttool-paint.c b/app/tools/gimppainttool-paint.c
index 869c2d6..cf64b8d 100644
--- a/app/tools/gimppainttool-paint.c
+++ b/app/tools/gimppainttool-paint.c
@@ -41,44 +41,36 @@
 #define DISPLAY_UPDATE_INTERVAL 10000 /* microseconds */
 
 
-typedef enum
-{
-  PAINT_ITEM_TYPE_CORE_PAINT,
-  PAINT_ITEM_TYPE_CORE_INTERPOLATE,
-  PAINT_ITEM_TYPE_FINISH
-} PaintItemType;
+#define PAINT_FINISH            NULL
 
 
 typedef struct
 {
-  PaintItemType         type;
-
+  GimpPaintTool          *paint_tool;
+  GimpPaintToolPaintFunc  func;
   union
-  {
-    struct
     {
-      GimpPaintTool    *paint_tool;
-
-      union
-      {
-        GimpPaintState  state;
-        GimpCoords      coords;
-      };
-
-      guint32           time;
+      gpointer            data;
+      gboolean           *finished;
     };
-
-    gboolean           *finished;
-  };
 } PaintItem;
 
+typedef struct
+{
+  GimpCoords coords;
+  guint32    time;
+} InterpolateData;
+
 
 /*  local function prototypes  */
 
-static gboolean   gimp_paint_tool_paint_use_thread (GimpPaintTool *paint_tool);
-static gpointer   gimp_paint_tool_paint_thread     (gpointer       data);
+static gboolean   gimp_paint_tool_paint_use_thread  (GimpPaintTool   *paint_tool);
+static gpointer   gimp_paint_tool_paint_thread      (gpointer         data);
+
+static gboolean   gimp_paint_tool_paint_timeout     (GimpPaintTool   *paint_tool);
 
-static gboolean   gimp_paint_tool_paint_timeout    (GimpPaintTool *paint_tool);
+static void       gimp_paint_tool_paint_interpolate (GimpPaintTool   *paint_tool,
+                                                     InterpolateData *data);
 
 
 /*  static variables  */
@@ -136,56 +128,23 @@ gimp_paint_tool_paint_thread (gpointer data)
       while (! (item = g_queue_pop_head (&paint_queue)))
         g_cond_wait (&paint_queue_cond, &paint_queue_mutex);
 
-      switch (item->type)
+      if (item->func == PAINT_FINISH)
         {
-        case PAINT_ITEM_TYPE_CORE_PAINT:
-          {
-            GimpPaintTool    *paint_tool    = item->paint_tool;
-            GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
-            GimpPaintCore    *core          = paint_tool->core;
-            GimpDrawable     *drawable      = paint_tool->drawable;
-
-            g_mutex_unlock (&paint_queue_mutex);
-            g_mutex_lock (&paint_mutex);
-
-            while (paint_timeout_pending)
-              g_cond_wait (&paint_cond, &paint_mutex);
-
-            gimp_paint_core_paint (core, drawable, paint_options,
-                                   item->state, item->time);
-
-            g_mutex_unlock (&paint_mutex);
-            g_mutex_lock (&paint_queue_mutex);
-          }
-          break;
-
-        case PAINT_ITEM_TYPE_CORE_INTERPOLATE:
-          {
-            GimpPaintTool    *paint_tool    = item->paint_tool;
-            GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
-            GimpPaintCore    *core          = paint_tool->core;
-            GimpDrawable     *drawable      = paint_tool->drawable;
-
-            g_mutex_unlock (&paint_queue_mutex);
-            g_mutex_lock (&paint_mutex);
-
-            while (paint_timeout_pending)
-              g_cond_wait (&paint_cond, &paint_mutex);
-
-            gimp_paint_core_interpolate (core, drawable, paint_options,
-                                         &item->coords, item->time);
-
-            g_mutex_unlock (&paint_mutex);
-            g_mutex_lock (&paint_queue_mutex);
-          }
-          break;
-
-        case PAINT_ITEM_TYPE_FINISH:
-          {
-            *item->finished = TRUE;
-            g_cond_signal (&paint_queue_cond);
-          }
-          break;
+          *item->finished = TRUE;
+          g_cond_signal (&paint_queue_cond);
+        }
+      else
+        {
+          g_mutex_unlock (&paint_queue_mutex);
+          g_mutex_lock (&paint_mutex);
+
+          while (paint_timeout_pending)
+            g_cond_wait (&paint_cond, &paint_mutex);
+
+          item->func (item->paint_tool, item->data);
+
+          g_mutex_unlock (&paint_mutex);
+          g_mutex_lock (&paint_queue_mutex);
         }
 
       g_slice_free (PaintItem, item);
@@ -233,6 +192,20 @@ gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool)
   return G_SOURCE_CONTINUE;
 }
 
+static void
+gimp_paint_tool_paint_interpolate (GimpPaintTool   *paint_tool,
+                                   InterpolateData *data)
+{
+  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
+  GimpPaintCore    *core          = paint_tool->core;
+  GimpDrawable     *drawable      = paint_tool->drawable;
+
+  gimp_paint_core_interpolate (core, drawable, paint_options,
+                               &data->coords, data->time);
+
+  g_slice_free (InterpolateData, data);
+}
+
 
 /*  public functions  */
 
@@ -380,13 +353,16 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool,
       gboolean   finished = FALSE;
       guint64    end_time;
 
+      g_return_if_fail (gimp_paint_tool_paint_is_active (paint_tool));
+
       g_source_remove (paint_timeout_id);
       paint_timeout_id = 0;
 
       item = g_slice_new (PaintItem);
 
-      item->type     = PAINT_ITEM_TYPE_FINISH;
-      item->finished = &finished;
+      item->paint_tool = paint_tool;
+      item->func       = PAINT_FINISH;
+      item->finished   = &finished;
 
       g_mutex_lock (&paint_queue_mutex);
 
@@ -446,65 +422,27 @@ gimp_paint_tool_paint_is_active (GimpPaintTool *paint_tool)
          gimp_drawable_is_painting (paint_tool->drawable);
 }
 
-
 void
-gimp_paint_tool_paint_motion (GimpPaintTool    *paint_tool,
-                              const GimpCoords *coords,
-                              guint32           time)
-{
-  GimpPaintOptions *paint_options;
-  GimpPaintCore    *core;
-  GimpDrawable     *drawable;
-  GimpCoords        curr_coords;
-  gint              off_x, off_y;
-
-  g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool));
-  g_return_if_fail (coords != NULL);
-  g_return_if_fail (paint_tool->display != NULL);
-
-  paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
-  core          = paint_tool->core;
-  drawable      = paint_tool->drawable;
-
-  curr_coords = *coords;
-
-  gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
-
-  curr_coords.x -= off_x;
-  curr_coords.y -= off_y;
-
-  gimp_paint_core_smooth_coords (core, paint_options, &curr_coords);
-
-  /*  Don't paint while the Shift key is pressed for line drawing  */
-  if (paint_tool->draw_line)
-    {
-      gimp_paint_core_set_current_coords (core, &curr_coords);
-
-      return;
-    }
-
-  gimp_paint_tool_paint_core_interpolate (paint_tool, &curr_coords, time);
-}
-
-void
-gimp_paint_tool_paint_core_paint (GimpPaintTool  *paint_tool,
-                                  GimpPaintState  state,
-                                  guint32         time)
+gimp_paint_tool_paint_push (GimpPaintTool          *paint_tool,
+                            GimpPaintToolPaintFunc  func,
+                            gpointer                data)
 {
   g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool));
+  g_return_if_fail (func != NULL);
 
   if (gimp_paint_tool_paint_use_thread (paint_tool))
     {
       PaintItem *item;
 
+      g_return_if_fail (gimp_paint_tool_paint_is_active (paint_tool));
+
       /*  Push an item to the queue, to be processed by the paint thread  */
 
       item = g_slice_new (PaintItem);
 
-      item->type       = PAINT_ITEM_TYPE_CORE_PAINT;
       item->paint_tool = paint_tool;
-      item->state      = state;
-      item->time       = time;
+      item->func       = func;
+      item->data       = data;
 
       g_mutex_lock (&paint_queue_mutex);
 
@@ -515,19 +453,15 @@ gimp_paint_tool_paint_core_paint (GimpPaintTool  *paint_tool,
     }
   else
     {
-      GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (paint_tool);
-      GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
-      GimpPaintCore    *core          = paint_tool->core;
-      GimpDisplay      *display       = paint_tool->display;
-      GimpImage        *image         = gimp_display_get_image (display);
-      GimpDrawable     *drawable      = paint_tool->drawable;
+      GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (paint_tool);
+      GimpDisplay  *display   = paint_tool->display;
+      GimpImage    *image     = gimp_display_get_image (display);
 
       /*  Paint directly  */
 
       gimp_draw_tool_pause (draw_tool);
 
-      gimp_paint_core_paint (core,
-                             drawable, paint_options, state, time);
+      func (paint_tool, data);
 
       gimp_projection_flush_now (gimp_image_get_projection (image));
       gimp_display_flush_now (display);
@@ -537,52 +471,48 @@ gimp_paint_tool_paint_core_paint (GimpPaintTool  *paint_tool,
 }
 
 void
-gimp_paint_tool_paint_core_interpolate (GimpPaintTool    *paint_tool,
-                                        const GimpCoords *coords,
-                                        guint32           time)
+gimp_paint_tool_paint_motion (GimpPaintTool    *paint_tool,
+                              const GimpCoords *coords,
+                              guint32           time)
 {
+  GimpPaintOptions *paint_options;
+  GimpPaintCore    *core;
+  GimpDrawable     *drawable;
+  InterpolateData  *data;
+  gint              off_x, off_y;
+
   g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool));
   g_return_if_fail (coords != NULL);
+  g_return_if_fail (paint_tool->display != NULL);
 
-  if (gimp_paint_tool_paint_use_thread (paint_tool))
-    {
-      PaintItem *item;
+  paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
+  core          = paint_tool->core;
+  drawable      = paint_tool->drawable;
 
-      /*  Push an item to the queue, to be processed by the paint thread  */
+  data = g_slice_new (InterpolateData);
 
-      item = g_slice_new (PaintItem);
+  data->coords = *coords;
+  data->time   = time;
 
-      item->type       = PAINT_ITEM_TYPE_CORE_INTERPOLATE;
-      item->paint_tool = paint_tool;
-      item->coords     = *coords;
-      item->time       = time;
+  gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
 
-      g_mutex_lock (&paint_queue_mutex);
+  data->coords.x -= off_x;
+  data->coords.y -= off_y;
 
-      g_queue_push_tail (&paint_queue, item);
-      g_cond_signal (&paint_queue_cond);
+  gimp_paint_core_smooth_coords (core, paint_options, &data->coords);
 
-      g_mutex_unlock (&paint_queue_mutex);
-    }
-  else
+  /*  Don't paint while the Shift key is pressed for line drawing  */
+  if (paint_tool->draw_line)
     {
-      GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (paint_tool);
-      GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool);
-      GimpPaintCore    *core          = paint_tool->core;
-      GimpDisplay      *display       = paint_tool->display;
-      GimpImage        *image         = gimp_display_get_image (display);
-      GimpDrawable     *drawable      = paint_tool->drawable;
-
-      /*  Paint directly  */
-
-      gimp_draw_tool_pause (draw_tool);
+      gimp_paint_core_set_current_coords (core, &data->coords);
 
-      gimp_paint_core_interpolate (core,
-                                   drawable, paint_options, coords, time);
+      g_slice_free (InterpolateData, data);
 
-      gimp_projection_flush_now (gimp_image_get_projection (image));
-      gimp_display_flush_now (display);
-
-      gimp_draw_tool_resume (draw_tool);
+      return;
     }
+
+  gimp_paint_tool_paint_push (
+    paint_tool,
+    (GimpPaintToolPaintFunc) gimp_paint_tool_paint_interpolate,
+    data);
 }
diff --git a/app/tools/gimppainttool-paint.h b/app/tools/gimppainttool-paint.h
index 8dcc056..23d13b3 100644
--- a/app/tools/gimppainttool-paint.h
+++ b/app/tools/gimppainttool-paint.h
@@ -19,28 +19,30 @@
 #define __GIMP_PAINT_TOOL_PAINT_H__
 
 
-gboolean   gimp_paint_tool_paint_start            (GimpPaintTool     *tool,
-                                                   GimpDisplay       *display,
-                                                   const GimpCoords  *coords,
-                                                   guint32            time,
-                                                   gboolean           constrain,
-                                                   GError           **error);
-void       gimp_paint_tool_paint_end              (GimpPaintTool     *tool,
-                                                   guint32            time,
-                                                   gboolean           cancel);
-
-gboolean   gimp_paint_tool_paint_is_active        (GimpPaintTool     *tool);
-
-void       gimp_paint_tool_paint_motion           (GimpPaintTool    *tool,
-                                                   const GimpCoords *coords,
-                                                   guint32           time);
-
-void       gimp_paint_tool_paint_core_paint       (GimpPaintTool     *tool,
-                                                   GimpPaintState     state,
-                                                   guint32            time);
-void       gimp_paint_tool_paint_core_interpolate (GimpPaintTool     *tool,
-                                                   const GimpCoords  *coords,
-                                                   guint32            time);
+typedef void (* GimpPaintToolPaintFunc) (GimpPaintTool *tool,
+                                         gpointer       data);
+
+
+
+gboolean   gimp_paint_tool_paint_start     (GimpPaintTool           *tool,
+                                            GimpDisplay             *display,
+                                            const GimpCoords        *coords,
+                                            guint32                  time,
+                                            gboolean                 constrain,
+                                            GError                 **error);
+void       gimp_paint_tool_paint_end       (GimpPaintTool           *tool,
+                                            guint32                  time,
+                                            gboolean                 cancel);
+
+gboolean   gimp_paint_tool_paint_is_active (GimpPaintTool           *tool);
+
+void       gimp_paint_tool_paint_push      (GimpPaintTool           *tool,
+                                            GimpPaintToolPaintFunc   func,
+                                            gpointer                 data);
+
+void       gimp_paint_tool_paint_motion    (GimpPaintTool           *tool,
+                                            const GimpCoords        *coords,
+                                            guint32                  time);
 
 
 #endif  /*  __GIMP_PAINT_TOOL_PAINT_H__  */


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