[gimp] Bug 795081 - Crash when using a brush combined with a dynamics
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 795081 - Crash when using a brush combined with a dynamics
- Date: Mon, 9 Apr 2018 18:28:32 +0000 (UTC)
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]