diff --git a/app/paint/gimpairbrush.c b/app/paint/gimpairbrush.c index 042cb2b33b..c30cc248be 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 7aa802cc53..4efb8d73f7 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 2374a372c5..a315bb7d18 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 869c2d6142..cf64b8d766 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; + *item->finished = TRUE; + g_cond_signal (&paint_queue_cond); + } + else + { + g_mutex_unlock (&paint_queue_mutex); + g_mutex_lock (&paint_mutex); - g_mutex_unlock (&paint_queue_mutex); - g_mutex_lock (&paint_mutex); + while (paint_timeout_pending) + g_cond_wait (&paint_cond, &paint_mutex); - while (paint_timeout_pending) - g_cond_wait (&paint_cond, &paint_mutex); + item->func (item->paint_tool, item->data); - 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; + 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,6 +422,53 @@ gimp_paint_tool_paint_is_active (GimpPaintTool *paint_tool) gimp_drawable_is_painting (paint_tool->drawable); } +void +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->paint_tool = paint_tool; + item->func = func; + item->data = data; + + 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); + GimpDisplay *display = paint_tool->display; + GimpImage *image = gimp_display_get_image (display); + + /* Paint directly */ + + gimp_draw_tool_pause (draw_tool); + + func (paint_tool, data); + + 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_motion (GimpPaintTool *paint_tool, @@ -455,7 +478,7 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool, GimpPaintOptions *paint_options; GimpPaintCore *core; GimpDrawable *drawable; - GimpCoords curr_coords; + InterpolateData *data; gint off_x, off_y; g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool)); @@ -466,123 +489,30 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool, core = paint_tool->core; drawable = paint_tool->drawable; - curr_coords = *coords; + data = g_slice_new (InterpolateData); + + data->coords = *coords; + data->time = time; gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); - curr_coords.x -= off_x; - curr_coords.y -= off_y; + data->coords.x -= off_x; + data->coords.y -= off_y; - gimp_paint_core_smooth_coords (core, paint_options, &curr_coords); + gimp_paint_core_smooth_coords (core, paint_options, &data->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); + gimp_paint_core_set_current_coords (core, &data->coords); + + g_slice_free (InterpolateData, data); 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; - - /* 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; - - 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_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); - - gimp_draw_tool_resume (draw_tool); - } + 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 8dcc056867..23d13b3451 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); +typedef void (* GimpPaintToolPaintFunc) (GimpPaintTool *tool, + gpointer data); -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); +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__ */