app: reorganize gimppainttool-paint, to allow use by subclasses

We'd like subclasses of GimpPaintTool to be able to issue paint
commands to the tool's paint-core (in particular, see the next
commit.)  Since paint commands should be executed on the paint
thread, the subclasses must not call the paint-core functions
directly, but should rather let gimppainttool-paint issue the
commands on their behalf.

Reorgainze gimppainttool-paint to make it usable for this purpose
by subclasses.  In particular, add
gimp_paint_tool_paint_core_paint() and
gimp_paint_tool_paint_core_interpolate(), which call the
corresponding paint-core functions on the paint thread.

Additionally, rename the {start,end,flush}_paint() virtual
functions of GimpPaintTool to paint_{start,end,flush}(), and rename
gimp_paint_tool_is_painting() to gimp_paint_tool_paint_is_active(),
so that all the gimppainttool-paint-related stuff are grouped under
the same namespace.
This commit is contained in:
Ell 2018-04-16 09:36:35 -04:00
parent 3f4995d3d7
commit e02a339e01
5 changed files with 163 additions and 59 deletions

View File

@ -43,6 +43,7 @@
#include "display/gimpdisplayshell.h"
#include "gimpbrushtool.h"
#include "gimppainttool-paint.h"
#include "gimptoolcontrol.h"
@ -61,9 +62,9 @@ static void gimp_brush_tool_options_notify (GimpTool *tool,
GimpToolOptions *options,
const GParamSpec *pspec);
static void gimp_brush_tool_start_paint (GimpPaintTool *paint_tool);
static void gimp_brush_tool_end_paint (GimpPaintTool *paint_tool);
static void gimp_brush_tool_flush_paint (GimpPaintTool *paint_tool);
static void gimp_brush_tool_paint_start (GimpPaintTool *paint_tool);
static void gimp_brush_tool_paint_end (GimpPaintTool *paint_tool);
static void gimp_brush_tool_paint_flush (GimpPaintTool *paint_tool);
static GimpCanvasItem *
gimp_brush_tool_get_outline (GimpPaintTool *paint_tool,
GimpDisplay *display,
@ -101,9 +102,9 @@ gimp_brush_tool_class_init (GimpBrushToolClass *klass)
tool_class->cursor_update = gimp_brush_tool_cursor_update;
tool_class->options_notify = gimp_brush_tool_options_notify;
paint_tool_class->start_paint = gimp_brush_tool_start_paint;
paint_tool_class->end_paint = gimp_brush_tool_end_paint;
paint_tool_class->flush_paint = gimp_brush_tool_flush_paint;
paint_tool_class->paint_start = gimp_brush_tool_paint_start;
paint_tool_class->paint_end = gimp_brush_tool_paint_end;
paint_tool_class->paint_flush = gimp_brush_tool_paint_flush;
paint_tool_class->get_outline = gimp_brush_tool_get_outline;
}
@ -233,14 +234,14 @@ gimp_brush_tool_options_notify (GimpTool *tool,
}
static void
gimp_brush_tool_start_paint (GimpPaintTool *paint_tool)
gimp_brush_tool_paint_start (GimpPaintTool *paint_tool)
{
GimpBrushTool *brush_tool = GIMP_BRUSH_TOOL (paint_tool);
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_tool->core);
const GimpBezierDesc *boundary;
if (GIMP_PAINT_TOOL_CLASS (parent_class)->start_paint)
GIMP_PAINT_TOOL_CLASS (parent_class)->start_paint (paint_tool);
if (GIMP_PAINT_TOOL_CLASS (parent_class)->paint_start)
GIMP_PAINT_TOOL_CLASS (parent_class)->paint_start (paint_tool);
boundary = gimp_brush_tool_get_boundary (brush_tool,
&brush_tool->boundary_width,
@ -257,25 +258,25 @@ gimp_brush_tool_start_paint (GimpPaintTool *paint_tool)
}
static void
gimp_brush_tool_end_paint (GimpPaintTool *paint_tool)
gimp_brush_tool_paint_end (GimpPaintTool *paint_tool)
{
GimpBrushTool *brush_tool = GIMP_BRUSH_TOOL (paint_tool);
g_clear_pointer (&brush_tool->boundary, gimp_bezier_desc_free);
if (GIMP_PAINT_TOOL_CLASS (parent_class)->end_paint)
GIMP_PAINT_TOOL_CLASS (parent_class)->end_paint (paint_tool);
if (GIMP_PAINT_TOOL_CLASS (parent_class)->paint_end)
GIMP_PAINT_TOOL_CLASS (parent_class)->paint_end (paint_tool);
}
static void
gimp_brush_tool_flush_paint (GimpPaintTool *paint_tool)
gimp_brush_tool_paint_flush (GimpPaintTool *paint_tool)
{
GimpBrushTool *brush_tool = GIMP_BRUSH_TOOL (paint_tool);
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_tool->core);
const GimpBezierDesc *boundary;
if (GIMP_PAINT_TOOL_CLASS (parent_class)->flush_paint)
GIMP_PAINT_TOOL_CLASS (parent_class)->flush_paint (paint_tool);
if (GIMP_PAINT_TOOL_CLASS (parent_class)->paint_flush)
GIMP_PAINT_TOOL_CLASS (parent_class)->paint_flush (paint_tool);
if (brush_tool->boundary_scale != brush_core->scale ||
brush_tool->boundary_aspect_ratio != brush_core->aspect_ratio ||
@ -347,7 +348,7 @@ gimp_brush_tool_create_outline (GimpBrushTool *brush_tool,
g_return_val_if_fail (GIMP_IS_BRUSH_TOOL (brush_tool), NULL);
g_return_val_if_fail (GIMP_IS_DISPLAY (display), NULL);
if (gimp_paint_tool_is_painting (GIMP_PAINT_TOOL (brush_tool)))
if (gimp_paint_tool_paint_is_active (GIMP_PAINT_TOOL (brush_tool)))
{
boundary = brush_tool->boundary;
width = brush_tool->boundary_width;

View File

@ -43,25 +43,32 @@
typedef enum
{
PAINT_ITEM_TYPE_INTERPOLATE,
PAINT_ITEM_TYPE_CORE_PAINT,
PAINT_ITEM_TYPE_CORE_INTERPOLATE,
PAINT_ITEM_TYPE_FINISH
} PaintItemType;
typedef struct
{
PaintItemType type;
PaintItemType type;
union
{
struct
{
GimpPaintTool *paint_tool;
GimpCoords coords;
guint32 time;
GimpPaintTool *paint_tool;
union
{
GimpPaintState state;
GimpCoords coords;
};
guint32 time;
};
gboolean *finished;
gboolean *finished;
};
} PaintItem;
@ -131,7 +138,28 @@ gimp_paint_tool_paint_thread (gpointer data)
switch (item->type)
{
case PAINT_ITEM_TYPE_INTERPOLATE:
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);
@ -180,8 +208,8 @@ gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool)
update = gimp_drawable_flush_paint (drawable);
if (update && GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->flush_paint)
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->flush_paint (paint_tool);
if (update && GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_flush)
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_flush (paint_tool);
paint_timeout_pending = FALSE;
g_cond_signal (&paint_cond);
@ -292,9 +320,9 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool,
/* Notify subclasses */
if (gimp_paint_tool_paint_use_thread (paint_tool) &&
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->start_paint)
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_start)
{
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->start_paint (paint_tool);
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_start (paint_tool);
}
/* Let the specific painting function initialize itself */
@ -396,9 +424,9 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool,
/* Notify subclasses */
if (gimp_paint_tool_paint_use_thread (paint_tool) &&
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->end_paint)
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_end)
{
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->end_paint (paint_tool);
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_end (paint_tool);
}
/* Exit paint mode */
@ -409,6 +437,16 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool,
paint_tool->drawable = NULL;
}
gboolean
gimp_paint_tool_paint_is_active (GimpPaintTool *paint_tool)
{
g_return_val_if_fail (GIMP_IS_PAINT_TOOL (paint_tool), FALSE);
return paint_tool->drawable != NULL &&
gimp_drawable_is_painting (paint_tool->drawable);
}
void
gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool,
const GimpCoords *coords,
@ -445,6 +483,16 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool,
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)
{
g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool));
if (gimp_paint_tool_paint_use_thread (paint_tool))
{
PaintItem *item;
@ -453,9 +501,9 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool,
item = g_slice_new (PaintItem);
item->type = PAINT_ITEM_TYPE_INTERPOLATE;
item->type = PAINT_ITEM_TYPE_CORE_PAINT;
item->paint_tool = paint_tool;
item->coords = curr_coords;
item->state = state;
item->time = time;
g_mutex_lock (&paint_queue_mutex);
@ -467,16 +515,70 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool,
}
else
{
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (paint_tool);
GimpDisplay *display = paint_tool->display;
GimpImage *image = gimp_display_get_image (display);
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_interpolate (core,
drawable, paint_options, &curr_coords, time);
gimp_paint_core_paint (core,
drawable, paint_options, state, time);
gimp_projection_flush_now (gimp_image_get_projection (image));
gimp_display_flush_now (display);
gimp_draw_tool_resume (draw_tool);
}
}
void
gimp_paint_tool_paint_core_interpolate (GimpPaintTool *paint_tool,
const GimpCoords *coords,
guint32 time)
{
g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool));
g_return_if_fail (coords != NULL);
if (gimp_paint_tool_paint_use_thread (paint_tool))
{
PaintItem *item;
/* Push an item to the queue, to be processed by the paint thread */
item = g_slice_new (PaintItem);
item->type = PAINT_ITEM_TYPE_CORE_INTERPOLATE;
item->paint_tool = paint_tool;
item->coords = *coords;
item->time = time;
g_mutex_lock (&paint_queue_mutex);
g_queue_push_tail (&paint_queue, item);
g_cond_signal (&paint_queue_cond);
g_mutex_unlock (&paint_queue_mutex);
}
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;
/* Paint directly */
gimp_draw_tool_pause (draw_tool);
gimp_paint_core_interpolate (core,
drawable, paint_options, coords, time);
gimp_projection_flush_now (gimp_image_get_projection (image));
gimp_display_flush_now (display);

View File

@ -19,19 +19,28 @@
#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_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);
void gimp_paint_tool_paint_motion (GimpPaintTool *tool,
const GimpCoords *coords,
guint32 time);
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);
#endif /* __GIMP_PAINT_TOOL_PAINT_H__ */

View File

@ -843,9 +843,3 @@ gimp_paint_tool_set_draw_circle (GimpPaintTool *tool,
tool->draw_circle = draw_circle;
tool->circle_size = circle_size;
}
gboolean
gimp_paint_tool_is_painting (GimpPaintTool *tool)
{
return tool->drawable != NULL && gimp_drawable_is_painting (tool->drawable);
}

View File

@ -65,9 +65,9 @@ struct _GimpPaintToolClass
{
GimpColorToolClass parent_class;
void (* start_paint) (GimpPaintTool *paint_tool);
void (* end_paint) (GimpPaintTool *paint_tool);
void (* flush_paint) (GimpPaintTool *paint_tool);
void (* paint_start) (GimpPaintTool *paint_tool);
void (* paint_end) (GimpPaintTool *paint_tool);
void (* paint_flush) (GimpPaintTool *paint_tool);
GimpCanvasItem * (* get_outline) (GimpPaintTool *paint_tool,
GimpDisplay *display,
@ -89,7 +89,5 @@ void gimp_paint_tool_set_draw_circle (GimpPaintTool *tool,
gboolean draw_circle,
gint circle_size);
gboolean gimp_paint_tool_is_painting (GimpPaintTool *tool);
#endif /* __GIMP_PAINT_TOOL_H__ */