app: in GimpPaintTool, sync brush-outline coords while painting

Add GimpPaintTool::paint_[xy] members, and periodically assign the
paint core's current coords to them in
gimp_paint_tool_paint_timeout(), while the main thread and the
paint thread are synchronized, during painting.

In gimp_paint_tool_draw(), fetch the current coords for the brush
outline from the above members during painting, instead of directly
from the paint core, to avoid a race condition with the paint
thread, so that we always use the correct coordinates at the time
the paint buffer was flushed back to the drawable.
This commit is contained in:
Ell 2018-06-08 03:14:17 -04:00
parent 0a4fa44528
commit 5c17d2a43b
3 changed files with 49 additions and 30 deletions

View File

@ -158,13 +158,17 @@ gimp_paint_tool_paint_thread (gpointer data)
static gboolean
gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool)
{
GimpDrawable *drawable = paint_tool->drawable;
gboolean update;
GimpPaintCore *core = paint_tool->core;
GimpDrawable *drawable = paint_tool->drawable;
gboolean update;
paint_timeout_pending = TRUE;
g_mutex_lock (&paint_mutex);
paint_tool->paint_x = core->cur_coords.x;
paint_tool->paint_y = core->cur_coords.y;
update = gimp_drawable_flush_paint (drawable);
if (update && GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_flush)
@ -248,6 +252,9 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool,
curr_coords.x -= off_x;
curr_coords.y -= off_y;
paint_tool->paint_x = curr_coords.x;
paint_tool->paint_y = curr_coords.y;
/* If we use a separate paint thread, enter paint mode before starting the
* paint core
*/

View File

@ -643,46 +643,55 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
GimpCanvasItem *outline = NULL;
gboolean line_drawn = FALSE;
gdouble last_x, last_y;
gdouble cur_x, cur_y;
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
last_x = core->last_coords.x + off_x;
last_y = core->last_coords.y + off_y;
cur_x = core->cur_coords.x + off_x;
cur_y = core->cur_coords.y + off_y;
if (paint_tool->draw_line &&
! gimp_tool_control_is_active (GIMP_TOOL (draw_tool)->control))
if (gimp_paint_tool_paint_is_active (paint_tool))
{
GimpCanvasGroup *group;
cur_x = paint_tool->paint_x + off_x;
cur_y = paint_tool->paint_y + off_y;
}
else
{
cur_x = core->cur_coords.x + off_x;
cur_y = core->cur_coords.y + off_y;
group = gimp_draw_tool_add_stroke_group (draw_tool);
gimp_draw_tool_push_group (draw_tool, group);
if (paint_tool->draw_line &&
! gimp_tool_control_is_active (GIMP_TOOL (draw_tool)->control))
{
GimpCanvasGroup *group;
gdouble last_x, last_y;
gimp_draw_tool_add_handle (draw_tool,
GIMP_HANDLE_CIRCLE,
last_x, last_y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_HANDLE_ANCHOR_CENTER);
last_x = core->last_coords.x + off_x;
last_y = core->last_coords.y + off_y;
gimp_draw_tool_add_line (draw_tool,
last_x, last_y,
cur_x, cur_y);
group = gimp_draw_tool_add_stroke_group (draw_tool);
gimp_draw_tool_push_group (draw_tool, group);
gimp_draw_tool_add_handle (draw_tool,
GIMP_HANDLE_CIRCLE,
cur_x, cur_y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_HANDLE_ANCHOR_CENTER);
gimp_draw_tool_add_handle (draw_tool,
GIMP_HANDLE_CIRCLE,
last_x, last_y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_HANDLE_ANCHOR_CENTER);
gimp_draw_tool_pop_group (draw_tool);
gimp_draw_tool_add_line (draw_tool,
last_x, last_y,
cur_x, cur_y);
line_drawn = TRUE;
gimp_draw_tool_add_handle (draw_tool,
GIMP_HANDLE_CIRCLE,
cur_x, cur_y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_TOOL_HANDLE_SIZE_CIRCLE,
GIMP_HANDLE_ANCHOR_CENTER);
gimp_draw_tool_pop_group (draw_tool);
line_drawn = TRUE;
}
}
gimp_paint_tool_set_draw_fallback (paint_tool, FALSE, 0.0);

View File

@ -59,6 +59,9 @@ struct _GimpPaintTool
GimpDisplay *display;
GimpDrawable *drawable;
gdouble paint_x;
gdouble paint_y;
};
struct _GimpPaintToolClass