[gimp] Bug 795081 - Crash when using a brush combined with a dynamics



commit f5cb1fed85341a9d0a46fb1391b19fa9ea3ccb42
Author: Ell <ell_se yahoo com>
Date:   Mon Apr 9 14:25:57 2018 -0400

    Bug 795081 - Crash when using a brush combined with a dynamics
    
    In GimpPaintTool, brush outline generation took place during
    gimp_paint_tool_draw() even while painting.  This function is run
    concurrently with the paint thread.  When using dynamics, this
    introduced a race conidition between updating the brush mask in the
    paint thread, and updating the brush boundary in the main thread.
    
    Move brush outline generation during painting to
    gimppainttool-paint.c, and perform it in the display-update
    timeout, while the main thread and the paint thread are
    synchronized.

 app/core/gimpdrawable.c         |    8 ++++++
 app/core/gimpdrawable.h         |    1 +
 app/tools/gimppainttool-paint.c |   47 ++++++++++++++++++++++++++++++++++++--
 app/tools/gimppainttool.c       |   28 +++++++++++++++-------
 app/tools/gimppainttool.h       |   32 ++++++++++++++------------
 5 files changed, 89 insertions(+), 27 deletions(-)
---
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 39c470b..cc41116 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -1669,3 +1669,11 @@ gimp_drawable_flush_paint (GimpDrawable *drawable)
 
   return FALSE;
 }
+
+gboolean
+gimp_drawable_is_painting (GimpDrawable *drawable)
+{
+  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
+
+  return drawable->private->paint_count > 0;
+}
diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h
index 0d69aef..c4b6c2e 100644
--- a/app/core/gimpdrawable.h
+++ b/app/core/gimpdrawable.h
@@ -231,6 +231,7 @@ const guchar    * gimp_drawable_get_colormap         (GimpDrawable    *drawable)
 void              gimp_drawable_start_paint          (GimpDrawable    *drawable);
 gboolean          gimp_drawable_end_paint            (GimpDrawable    *drawable);
 gboolean          gimp_drawable_flush_paint          (GimpDrawable    *drawable);
+gboolean          gimp_drawable_is_painting          (GimpDrawable    *drawable);
 
 
 #endif /* __GIMP_DRAWABLE_H__ */
diff --git a/app/tools/gimppainttool-paint.c b/app/tools/gimppainttool-paint.c
index d357ce4..72614e6 100644
--- a/app/tools/gimppainttool-paint.c
+++ b/app/tools/gimppainttool-paint.c
@@ -68,10 +68,12 @@ typedef struct
 
 /*  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_update_outline (GimpPaintTool *paint_tool);
 
 
 /*  static variables  */
@@ -180,6 +182,9 @@ gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool)
 
   update = gimp_drawable_flush_paint (drawable);
 
+  if (update)
+    gimp_paint_tool_paint_update_outline (paint_tool);
+
   paint_timeout_pending = FALSE;
   g_cond_signal (&paint_cond);
 
@@ -202,6 +207,36 @@ gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool)
   return G_SOURCE_CONTINUE;
 }
 
+static void
+gimp_paint_tool_paint_update_outline (GimpPaintTool *paint_tool)
+{
+  if (gimp_paint_tool_paint_use_thread (paint_tool))
+    {
+      gimp_paint_tool_set_draw_fallback (paint_tool, FALSE, 0.0);
+
+      if (paint_tool->draw_brush)
+        {
+          GimpPaintCore *core     = paint_tool->core;
+          GimpDisplay   *display  = paint_tool->display;
+          GimpDrawable  *drawable = paint_tool->drawable;
+          gint           off_x, off_y;
+          gdouble        x, y;
+
+          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
+
+          x = core->cur_coords.x + off_x;
+          y = core->cur_coords.y + off_y;
+
+          if (paint_tool->outline)
+            g_object_unref (paint_tool->outline);
+
+          paint_tool->outline =
+            GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline (paint_tool,
+                                                                 display, x, y);
+        }
+    }
+}
+
 
 /*  public functions  */
 
@@ -303,6 +338,9 @@ gimp_paint_tool_paint_start (GimpPaintTool     *paint_tool,
                              GIMP_PAINT_STATE_MOTION, time);
     }
 
+  /*  Update the brush outline  */
+  gimp_paint_tool_paint_update_outline (paint_tool);
+
   gimp_projection_flush_now (gimp_image_get_projection (image));
   gimp_display_flush_now (display);
 
@@ -384,6 +422,9 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool,
   else
     gimp_paint_core_finish (core, drawable, TRUE);
 
+  /*  Clear the brush outline  */
+  g_clear_object (&paint_tool->outline);
+
   /*  Exit paint mode  */
   if (gimp_paint_tool_paint_use_thread (paint_tool))
     gimp_drawable_end_paint (drawable);
diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c
index 77ef265..626a0d8 100644
--- a/app/tools/gimppainttool.c
+++ b/app/tools/gimppainttool.c
@@ -672,12 +672,9 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
           line_drawn = TRUE;
         }
 
-      gimp_paint_tool_set_draw_fallback (paint_tool, FALSE, 0.0);
-
-      if (paint_tool->draw_brush)
-        outline = gimp_paint_tool_get_outline (paint_tool,
-                                               draw_tool->display,
-                                               cur_x, cur_y);
+      outline = gimp_paint_tool_get_outline (paint_tool,
+                                             draw_tool->display,
+                                             cur_x, cur_y);
 
       if (outline)
         {
@@ -770,9 +767,22 @@ gimp_paint_tool_get_outline (GimpPaintTool *paint_tool,
                              gdouble        x,
                              gdouble        y)
 {
-  if (GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline)
-    return GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline (paint_tool,
-                                                                display, x, y);
+  if (paint_tool->drawable && gimp_drawable_is_painting (paint_tool->drawable))
+    {
+      if (paint_tool->outline)
+        return g_object_ref (paint_tool->outline);
+    }
+  else
+    {
+      gimp_paint_tool_set_draw_fallback (paint_tool, FALSE, 0.0);
+
+      if (paint_tool->draw_brush &&
+          GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline)
+        {
+          return GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline (
+            paint_tool, display, x, y);
+        }
+    }
 
   return NULL;
 }
diff --git a/app/tools/gimppainttool.h b/app/tools/gimppainttool.h
index d2eff14..1164009 100644
--- a/app/tools/gimppainttool.h
+++ b/app/tools/gimppainttool.h
@@ -39,26 +39,28 @@ typedef struct _GimpPaintToolClass GimpPaintToolClass;
 
 struct _GimpPaintTool
 {
-  GimpColorTool  parent_instance;
+  GimpColorTool   parent_instance;
 
-  gboolean       pick_colors;  /*  pick color if ctrl is pressed   */
-  gboolean       draw_line;
+  gboolean        pick_colors;  /*  pick color if ctrl is pressed   */
+  gboolean        draw_line;
 
-  gboolean       show_cursor;
-  gboolean       draw_brush;
-  gboolean       draw_fallback;
-  gint           fallback_size;
-  gboolean       draw_circle;
-  gint           circle_size;
+  gboolean        show_cursor;
+  gboolean        draw_brush;
+  gboolean        draw_fallback;
+  gint            fallback_size;
+  gboolean        draw_circle;
+  gint            circle_size;
 
-  const gchar   *status;       /* status message */
-  const gchar   *status_line;  /* status message when drawing a line */
-  const gchar   *status_ctrl;  /* additional message for the ctrl modifier */
+  const gchar    *status;       /* status message */
+  const gchar    *status_line;  /* status message when drawing a line */
+  const gchar    *status_ctrl;  /* additional message for the ctrl modifier */
 
-  GimpPaintCore *core;
+  GimpPaintCore  *core;
 
-  GimpDisplay   *display;
-  GimpDrawable  *drawable;
+  GimpDisplay    *display;
+  GimpDrawable   *drawable;
+
+  GimpCanvasItem *outline;
 };
 
 struct _GimpPaintToolClass


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