diff --git a/app/paint/gimpairbrush.c b/app/paint/gimpairbrush.c index 6bd9fb2806..fc61409e14 100644 --- a/app/paint/gimpairbrush.c +++ b/app/paint/gimpairbrush.c @@ -49,7 +49,7 @@ enum static void gimp_airbrush_finalize (GObject *object); static void gimp_airbrush_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -123,7 +123,7 @@ gimp_airbrush_finalize (GObject *object) static void gimp_airbrush_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -133,6 +133,8 @@ gimp_airbrush_paint (GimpPaintCore *paint_core, GimpAirbrushOptions *options = GIMP_AIRBRUSH_OPTIONS (paint_options); GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics; + g_return_if_fail (g_list_length (drawables) == 1); + if (airbrush->timeout_id) { g_source_remove (airbrush->timeout_id); @@ -142,18 +144,18 @@ gimp_airbrush_paint (GimpPaintCore *paint_core, switch (paint_state) { case GIMP_PAINT_STATE_INIT: - GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable, + GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawables, paint_options, sym, paint_state, time); break; case GIMP_PAINT_STATE_MOTION: - gimp_airbrush_motion (paint_core, drawable, paint_options, sym); + gimp_airbrush_motion (paint_core, drawables->data, paint_options, sym); if ((options->rate != 0.0) && ! options->motion_only) { - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawables->data)); gdouble fade_point; gdouble dynamic_rate; gint timeout; @@ -162,7 +164,7 @@ gimp_airbrush_paint (GimpPaintCore *paint_core, fade_point = gimp_paint_options_get_fade (paint_options, image, paint_core->pixel_dist); - airbrush->drawable = drawable; + airbrush->drawable = drawables->data; airbrush->paint_options = paint_options; if (airbrush->sym) @@ -191,7 +193,7 @@ gimp_airbrush_paint (GimpPaintCore *paint_core, break; case GIMP_PAINT_STATE_FINISH: - GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable, + GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawables, paint_options, sym, paint_state, time); @@ -250,16 +252,20 @@ gimp_airbrush_timeout (gpointer data) void gimp_airbrush_stamp (GimpAirbrush *airbrush) { + GList *drawables; + g_return_if_fail (GIMP_IS_AIRBRUSH (airbrush)); gimp_symmetry_set_origin (airbrush->sym, airbrush->drawable, &airbrush->coords); + drawables = g_list_prepend (NULL, airbrush->drawable), gimp_airbrush_paint (GIMP_PAINT_CORE (airbrush), - airbrush->drawable, + drawables, airbrush->paint_options, airbrush->sym, GIMP_PAINT_STATE_MOTION, 0); + g_list_free (drawables); gimp_symmetry_clear_origin (airbrush->sym); } diff --git a/app/paint/gimpbrushcore.c b/app/paint/gimpbrushcore.c index 4b1e8cd3a8..d9796ae489 100644 --- a/app/paint/gimpbrushcore.c +++ b/app/paint/gimpbrushcore.c @@ -65,22 +65,22 @@ enum static void gimp_brush_core_finalize (GObject *object); static gboolean gimp_brush_core_start (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); static gboolean gimp_brush_core_pre_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time); static void gimp_brush_core_post_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time); static void gimp_brush_core_interpolate (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, guint32 time); @@ -249,7 +249,7 @@ gimp_brush_core_finalize (GObject *object) static gboolean gimp_brush_core_pre_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time) @@ -281,7 +281,7 @@ gimp_brush_core_pre_paint (GimpPaintCore *paint_core, /*No drawing anything if the scale is too small*/ if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_transforming_brush) { - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawables->data)); gdouble fade_point; if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_dynamic_transforming_brush) @@ -337,7 +337,7 @@ gimp_brush_core_pre_paint (GimpPaintCore *paint_core, static void gimp_brush_core_post_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time) @@ -352,13 +352,16 @@ gimp_brush_core_post_paint (GimpPaintCore *paint_core, static gboolean gimp_brush_core_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) { GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core); GimpContext *context = GIMP_CONTEXT (paint_options); + GimpImage *image = NULL; + + g_return_val_if_fail (drawables != NULL, FALSE); gimp_brush_core_set_brush (core, gimp_context_get_brush (context)); @@ -378,10 +381,17 @@ gimp_brush_core_start (GimpPaintCore *paint_core, return FALSE; } + for (GList *iter = drawables; iter; iter = iter->next) + if (image == NULL) + image = gimp_item_get_image (GIMP_ITEM (iter->data)); + else + g_return_val_if_fail (image == gimp_item_get_image (GIMP_ITEM (iter->data)), + FALSE); + if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_transforming_brush) { gimp_brush_core_eval_transform_dynamics (core, - drawable, + image, paint_options, coords); @@ -393,8 +403,7 @@ gimp_brush_core_start (GimpPaintCore *paint_core, core->brush = core->main_brush; core->jitter = - gimp_paint_options_get_jitter (paint_options, - gimp_item_get_image (GIMP_ITEM (drawable))); + gimp_paint_options_get_jitter (paint_options, image); return TRUE; } @@ -427,12 +436,12 @@ gimp_avoid_exact_integer (gdouble *x) static void gimp_brush_core_interpolate (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, guint32 time) { GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core); - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawables->data)); GimpDynamicsOutput *spacing_output; GimpCoords last_coords; GimpCoords current_coords; @@ -496,7 +505,7 @@ gimp_brush_core_interpolate (GimpPaintCore *paint_core, { gimp_paint_core_set_last_coords (paint_core, ¤t_coords); - gimp_paint_core_paint (paint_core, drawable, paint_options, + gimp_paint_core_paint (paint_core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, time); paint_core->pixel_dist = pixel_initial + pixel_dist; /* Don't forget to update pixel distance*/ @@ -757,7 +766,7 @@ gimp_brush_core_interpolate (GimpPaintCore *paint_core, paint_core->distance = initial + t * dist; paint_core->pixel_dist = pixel_initial + t * pixel_dist; - gimp_paint_core_paint (paint_core, drawable, paint_options, + gimp_paint_core_paint (paint_core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, time); } @@ -1140,7 +1149,7 @@ gimp_brush_core_get_brush_pixmap (GimpBrushCore *core) void gimp_brush_core_eval_transform_dynamics (GimpBrushCore *core, - GimpDrawable *drawable, + GimpImage *image, GimpPaintOptions *paint_options, const GimpCoords *coords) { @@ -1186,9 +1195,8 @@ gimp_brush_core_eval_transform_dynamics (GimpBrushCore *core, { gdouble fade_point = 1.0; - if (drawable) + if (image) { - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); GimpPaintCore *paint_core = GIMP_PAINT_CORE (core); fade_point = gimp_paint_options_get_fade (paint_options, image, diff --git a/app/paint/gimpbrushcore.h b/app/paint/gimpbrushcore.h index 3ba4a41984..a6ab08bdd6 100644 --- a/app/paint/gimpbrushcore.h +++ b/app/paint/gimpbrushcore.h @@ -140,7 +140,7 @@ const GimpTempBuf * gimp_brush_core_get_brush_pixmap void gimp_brush_core_eval_transform_dynamics (GimpBrushCore *core, - GimpDrawable *drawable, + GimpImage *image, GimpPaintOptions *paint_options, const GimpCoords *coords); void gimp_brush_core_eval_transform_symmetry diff --git a/app/paint/gimpclone.c b/app/paint/gimpclone.c index 9c807f43ff..fa6daaaeef 100644 --- a/app/paint/gimpclone.c +++ b/app/paint/gimpclone.c @@ -46,7 +46,7 @@ static gboolean gimp_clone_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); @@ -110,14 +110,14 @@ gimp_clone_init (GimpClone *clone) static gboolean gimp_clone_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) { GimpCloneOptions *options = GIMP_CLONE_OPTIONS (paint_options); - if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawable, + if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawables, paint_options, coords, error)) { diff --git a/app/paint/gimpconvolve.c b/app/paint/gimpconvolve.c index f2eea47cb6..347c8487e4 100644 --- a/app/paint/gimpconvolve.c +++ b/app/paint/gimpconvolve.c @@ -47,7 +47,7 @@ static void gimp_convolve_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -101,16 +101,19 @@ gimp_convolve_init (GimpConvolve *convolve) static void gimp_convolve_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, guint32 time) { + g_return_if_fail (g_list_length (drawables) == 1); + switch (paint_state) { case GIMP_PAINT_STATE_MOTION: - gimp_convolve_motion (paint_core, drawable, paint_options, sym); + for (GList *iter = drawables; iter; iter = iter->next) + gimp_convolve_motion (paint_core, iter->data, paint_options, sym); break; default: @@ -156,7 +159,7 @@ gimp_convolve_motion (GimpPaintCore *paint_core, return; gimp_brush_core_eval_transform_dynamics (GIMP_BRUSH_CORE (paint_core), - drawable, + image, paint_options, coords); n_strokes = gimp_symmetry_get_size (sym); diff --git a/app/paint/gimpdodgeburn.c b/app/paint/gimpdodgeburn.c index cdfc176443..e803970018 100644 --- a/app/paint/gimpdodgeburn.c +++ b/app/paint/gimpdodgeburn.c @@ -40,7 +40,7 @@ static void gimp_dodge_burn_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -86,19 +86,22 @@ gimp_dodge_burn_init (GimpDodgeBurn *dodgeburn) static void gimp_dodge_burn_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, guint32 time) { + g_return_if_fail (g_list_length (drawables) == 1); + switch (paint_state) { case GIMP_PAINT_STATE_INIT: break; case GIMP_PAINT_STATE_MOTION: - gimp_dodge_burn_motion (paint_core, drawable, paint_options, sym); + for (GList *iter = drawables; iter; iter = iter->next) + gimp_dodge_burn_motion (paint_core, iter->data, paint_options, sym); break; case GIMP_PAINT_STATE_FINISH: @@ -142,12 +145,12 @@ gimp_dodge_burn_motion (GimpPaintCore *paint_core, return; if (paint_options->application_mode == GIMP_PAINT_CONSTANT) - src_buffer = gimp_paint_core_get_orig_image (paint_core); + src_buffer = gimp_paint_core_get_orig_image (paint_core, drawable); else src_buffer = gimp_drawable_get_buffer (drawable); gimp_brush_core_eval_transform_dynamics (brush_core, - drawable, + image, paint_options, coords); n_strokes = gimp_symmetry_get_size (sym); diff --git a/app/paint/gimpheal.c b/app/paint/gimpheal.c index 814fd26a78..625444fa5b 100644 --- a/app/paint/gimpheal.c +++ b/app/paint/gimpheal.c @@ -68,7 +68,7 @@ */ static gboolean gimp_heal_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); @@ -138,21 +138,21 @@ gimp_heal_init (GimpHeal *heal) static gboolean gimp_heal_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) { GimpSourceCore *source_core = GIMP_SOURCE_CORE (paint_core); - if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawable, + if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawables, paint_options, coords, error)) { return FALSE; } - if (! source_core->set_source && gimp_drawable_is_indexed (drawable)) + if (! source_core->set_source && gimp_drawable_is_indexed (drawables->data)) { g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("Healing does not operate on indexed layers.")); diff --git a/app/paint/gimpink.c b/app/paint/gimpink.c index 10e528c6ba..9814309693 100644 --- a/app/paint/gimpink.c +++ b/app/paint/gimpink.c @@ -54,7 +54,7 @@ static void gimp_ink_finalize (GObject *object); static void gimp_ink_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -149,7 +149,7 @@ gimp_ink_finalize (GObject *object) static void gimp_ink_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -159,6 +159,8 @@ gimp_ink_paint (GimpPaintCore *paint_core, GimpCoords *cur_coords; GimpCoords last_coords; + g_return_if_fail (g_list_length (drawables) == 1); + gimp_paint_core_get_last_coords (paint_core, &last_coords); cur_coords = gimp_symmetry_get_origin (sym); @@ -215,7 +217,8 @@ gimp_ink_paint (GimpPaintCore *paint_core, break; case GIMP_PAINT_STATE_MOTION: - gimp_ink_motion (paint_core, drawable, paint_options, sym, time); + for (GList *iter = drawables; iter; iter = iter->next) + gimp_ink_motion (paint_core, iter->data, paint_options, sym, time); break; case GIMP_PAINT_STATE_FINISH: diff --git a/app/paint/gimpmybrushcore.c b/app/paint/gimpmybrushcore.c index b0771a61af..fe54a24f22 100644 --- a/app/paint/gimpmybrushcore.c +++ b/app/paint/gimpmybrushcore.c @@ -62,16 +62,16 @@ struct _GimpMybrushCorePrivate static void gimp_mybrush_core_finalize (GObject *object); static gboolean gimp_mybrush_core_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); static void gimp_mybrush_core_interpolate (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, guint32 time); static void gimp_mybrush_core_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -141,7 +141,7 @@ gimp_mybrush_core_finalize (GObject *object) static gboolean gimp_mybrush_core_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) @@ -163,7 +163,7 @@ gimp_mybrush_core_start (GimpPaintCore *paint_core, static void gimp_mybrush_core_interpolate (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, guint32 time) { @@ -180,13 +180,13 @@ gimp_mybrush_core_interpolate (GimpPaintCore *paint_core, mybrush->private->synthetic = TRUE; - gimp_paint_core_paint (paint_core, drawable, paint_options, + gimp_paint_core_paint (paint_core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, time); paint_core->cur_coords = saved_coords; } - gimp_paint_core_paint (paint_core, drawable, paint_options, + gimp_paint_core_paint (paint_core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, time); paint_core->last_coords = paint_core->cur_coords; @@ -194,7 +194,7 @@ gimp_mybrush_core_interpolate (GimpPaintCore *paint_core, static void gimp_mybrush_core_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -204,6 +204,8 @@ gimp_mybrush_core_paint (GimpPaintCore *paint_core, GimpContext *context = GIMP_CONTEXT (paint_options); GimpRGB fg; + g_return_if_fail (g_list_length (drawables) == 1); + switch (paint_state) { case GIMP_PAINT_STATE_INIT: @@ -212,21 +214,21 @@ gimp_mybrush_core_paint (GimpPaintCore *paint_core, gimp_symmetry_set_stateful (sym, TRUE); mybrush->private->surface = - gimp_mypaint_surface_new (gimp_drawable_get_buffer (drawable), - gimp_drawable_get_active_mask (drawable), + gimp_mypaint_surface_new (gimp_drawable_get_buffer (drawables->data), + gimp_drawable_get_active_mask (drawables->data), paint_core->mask_buffer, paint_core->mask_x_offset, paint_core->mask_y_offset, GIMP_MYBRUSH_OPTIONS (paint_options)); - gimp_mybrush_core_create_brushes (mybrush, drawable, paint_options, sym); + gimp_mybrush_core_create_brushes (mybrush, drawables->data, paint_options, sym); mybrush->private->last_time = -1; mybrush->private->synthetic = FALSE; break; case GIMP_PAINT_STATE_MOTION: - gimp_mybrush_core_motion (paint_core, drawable, paint_options, + gimp_mybrush_core_motion (paint_core, drawables->data, paint_options, sym, time); break; diff --git a/app/paint/gimppaintbrush.c b/app/paint/gimppaintbrush.c index 410b02504a..25940af5cf 100644 --- a/app/paint/gimppaintbrush.c +++ b/app/paint/gimppaintbrush.c @@ -47,7 +47,7 @@ static void gimp_paintbrush_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -104,7 +104,7 @@ gimp_paintbrush_init (GimpPaintbrush *paintbrush) static void gimp_paintbrush_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -112,26 +112,32 @@ gimp_paintbrush_paint (GimpPaintCore *paint_core, { GimpPaintbrush *paintbrush = GIMP_PAINTBRUSH (paint_core); + g_return_if_fail (g_list_length (drawables) == 1); + switch (paint_state) { case GIMP_PAINT_STATE_INIT: { GimpRGB color; - if (GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_color_history_color && - GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_color_history_color ( - paintbrush, drawable, paint_options, &color)) - { - GimpContext *context = GIMP_CONTEXT (paint_options); + for (GList *iter = drawables; iter; iter = iter->next) + if (GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_color_history_color && + GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_color_history_color (paintbrush, + iter->data, + paint_options, + &color)) + { + GimpContext *context = GIMP_CONTEXT (paint_options); - gimp_palettes_add_color_history (context->gimp, &color); - } + gimp_palettes_add_color_history (context->gimp, &color); + } } break; case GIMP_PAINT_STATE_MOTION: - _gimp_paintbrush_motion (paint_core, drawable, paint_options, - sym, GIMP_OPACITY_OPAQUE); + for (GList *iter = drawables; iter; iter = iter->next) + _gimp_paintbrush_motion (paint_core, iter->data, paint_options, + sym, GIMP_OPACITY_OPAQUE); break; case GIMP_PAINT_STATE_FINISH: @@ -258,7 +264,7 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core, if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush) { gimp_brush_core_eval_transform_dynamics (brush_core, - drawable, + image, paint_options, coords); } diff --git a/app/paint/gimppaintcore-stroke.c b/app/paint/gimppaintcore-stroke.c index 3beac93dba..ab73977404 100644 --- a/app/paint/gimppaintcore-stroke.c +++ b/app/paint/gimppaintcore-stroke.c @@ -55,6 +55,9 @@ gimp_paint_core_stroke (GimpPaintCore *core, gboolean push_undo, GError **error) { + GList *drawables; + gboolean success = FALSE; + g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); @@ -63,36 +66,40 @@ gimp_paint_core_stroke (GimpPaintCore *core, g_return_val_if_fail (n_strokes > 0, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - if (gimp_paint_core_start (core, drawable, paint_options, &strokes[0], + drawables = g_list_prepend (NULL, drawable); + + if (gimp_paint_core_start (core, drawables, paint_options, &strokes[0], error)) { gint i; core->last_coords = strokes[0]; - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_INIT, 0); - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, 0); for (i = 1; i < n_strokes; i++) { - gimp_paint_core_interpolate (core, drawable, paint_options, + gimp_paint_core_interpolate (core, drawables, paint_options, &strokes[i], 0); } - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_FINISH, 0); - gimp_paint_core_finish (core, drawable, push_undo); + gimp_paint_core_finish (core, drawables, push_undo); gimp_paint_core_cleanup (core); - return TRUE; + success = TRUE; } - return FALSE; + g_list_free (drawables); + + return success; } gboolean @@ -107,6 +114,7 @@ gimp_paint_core_stroke_boundary (GimpPaintCore *core, gboolean push_undo, GError **error) { + GList *drawables; GimpBoundSeg *stroke_segs; gint n_stroke_segs; gint off_x; @@ -148,6 +156,8 @@ gimp_paint_core_stroke_boundary (GimpPaintCore *core, n_coords++; + drawables = g_list_prepend (NULL, drawable); + for (s = 0; s < n_stroke_segs; s++) { while (stroke_segs[seg].x1 != -1 || @@ -172,7 +182,7 @@ gimp_paint_core_stroke_boundary (GimpPaintCore *core, gimp_paint_core_stroke_emulate_dynamics (coords, n_coords); if (initialized || - gimp_paint_core_start (core, drawable, paint_options, &coords[0], + gimp_paint_core_start (core, drawables, paint_options, &coords[0], error)) { gint i; @@ -182,19 +192,19 @@ gimp_paint_core_stroke_boundary (GimpPaintCore *core, core->cur_coords = coords[0]; core->last_coords = coords[0]; - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_INIT, 0); - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, 0); for (i = 1; i < n_coords; i++) { - gimp_paint_core_interpolate (core, drawable, paint_options, + gimp_paint_core_interpolate (core, drawables, paint_options, &coords[i], 0); } - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_FINISH, 0); } else @@ -214,11 +224,12 @@ gimp_paint_core_stroke_boundary (GimpPaintCore *core, if (initialized) { - gimp_paint_core_finish (core, drawable, push_undo); + gimp_paint_core_finish (core, drawables, push_undo); gimp_paint_core_cleanup (core); } + g_list_free (drawables); g_free (coords); g_free (stroke_segs); @@ -234,6 +245,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, gboolean push_undo, GError **error) { + GList *drawables; GList *stroke; gboolean initialized = FALSE; gboolean due_to_lack_of_points = FALSE; @@ -253,6 +265,8 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, off_x -= vectors_off_x; off_y -= vectors_off_y; + drawables = g_list_prepend (NULL, drawable); + for (stroke = vectors->strokes->head; stroke; stroke = stroke->next) @@ -278,7 +292,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, coords->len); if (initialized || - gimp_paint_core_start (core, drawable, paint_options, + gimp_paint_core_start (core, drawables, paint_options, &g_array_index (coords, GimpCoords, 0), error)) { @@ -287,20 +301,20 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, core->cur_coords = g_array_index (coords, GimpCoords, 0); core->last_coords = g_array_index (coords, GimpCoords, 0); - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_INIT, 0); - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, 0); for (i = 1; i < coords->len; i++) { - gimp_paint_core_interpolate (core, drawable, paint_options, + gimp_paint_core_interpolate (core, drawables, paint_options, &g_array_index (coords, GimpCoords, i), 0); } - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_FINISH, 0); } else @@ -322,7 +336,7 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, if (initialized) { - gimp_paint_core_finish (core, drawable, push_undo); + gimp_paint_core_finish (core, drawables, push_undo); gimp_paint_core_cleanup (core); } @@ -333,6 +347,8 @@ gimp_paint_core_stroke_vectors (GimpPaintCore *core, _("Not enough points to stroke")); } + g_list_free (drawables); + return initialized; } diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c index ebf7b03ef9..14b3470701 100644 --- a/app/paint/gimppaintcore.c +++ b/app/paint/gimppaintcore.c @@ -80,28 +80,28 @@ static void gimp_paint_core_get_property (GObject *object, GParamSpec *pspec); static gboolean gimp_paint_core_real_start (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); static gboolean gimp_paint_core_real_pre_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *options, GimpPaintState paint_state, guint32 time); static void gimp_paint_core_real_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *options, GimpSymmetry *sym, GimpPaintState paint_state, guint32 time); static void gimp_paint_core_real_post_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *options, GimpPaintState paint_state, guint32 time); static void gimp_paint_core_real_interpolate (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *options, guint32 time); static GeglBuffer * @@ -154,6 +154,7 @@ static void gimp_paint_core_init (GimpPaintCore *core) { core->ID = global_core_ID++; + core->undo_buffers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); } static void @@ -164,6 +165,7 @@ gimp_paint_core_finalize (GObject *object) gimp_paint_core_cleanup (core); g_clear_pointer (&core->undo_desc, g_free); + g_hash_table_unref (core->undo_buffers); if (core->stroke_buffer) { @@ -217,7 +219,7 @@ gimp_paint_core_get_property (GObject *object, static gboolean gimp_paint_core_real_start (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) @@ -227,7 +229,7 @@ gimp_paint_core_real_start (GimpPaintCore *core, static gboolean gimp_paint_core_real_pre_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time) @@ -237,7 +239,7 @@ gimp_paint_core_real_pre_paint (GimpPaintCore *core, static void gimp_paint_core_real_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -247,7 +249,7 @@ gimp_paint_core_real_paint (GimpPaintCore *core, static void gimp_paint_core_real_post_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time) @@ -256,11 +258,11 @@ gimp_paint_core_real_post_paint (GimpPaintCore *core, static void gimp_paint_core_real_interpolate (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, guint32 time) { - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, time); core->last_coords = core->cur_coords; @@ -297,7 +299,7 @@ gimp_paint_core_real_push_undo (GimpPaintCore *core, void gimp_paint_core_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time) @@ -305,22 +307,19 @@ gimp_paint_core_paint (GimpPaintCore *core, GimpPaintCoreClass *core_class; g_return_if_fail (GIMP_IS_PAINT_CORE (core)); - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); + g_return_if_fail (drawables != NULL); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options)); core_class = GIMP_PAINT_CORE_GET_CLASS (core); - if (core_class->pre_paint (core, drawable, + if (core_class->pre_paint (core, drawables, paint_options, paint_state, time)) { GimpSymmetry *sym; GimpImage *image; - GimpItem *item; - item = GIMP_ITEM (drawable); - image = gimp_item_get_image (item); + image = gimp_item_get_image (GIMP_ITEM (drawables->data)); if (paint_state == GIMP_PAINT_STATE_MOTION) { @@ -330,16 +329,16 @@ gimp_paint_core_paint (GimpPaintCore *core, } sym = g_object_ref (gimp_image_get_active_symmetry (image)); - gimp_symmetry_set_origin (sym, drawable, &core->cur_coords); + gimp_symmetry_set_origin (sym, drawables->data, &core->cur_coords); - core_class->paint (core, drawable, + core_class->paint (core, drawables, paint_options, sym, paint_state, time); gimp_symmetry_clear_origin (sym); g_object_unref (sym); - core_class->post_paint (core, drawable, + core_class->post_paint (core, drawables, paint_options, paint_state, time); } @@ -347,24 +346,24 @@ gimp_paint_core_paint (GimpPaintCore *core, gboolean gimp_paint_core_start (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) { GimpImage *image; - GimpItem *item; GimpChannel *mask; g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE); - g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); - g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); + g_return_val_if_fail (g_list_length (drawables) > 0, FALSE); g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE); g_return_val_if_fail (coords != NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - item = GIMP_ITEM (drawable); - image = gimp_item_get_image (item); + for (GList *iter = drawables; iter; iter = iter->next) + g_return_val_if_fail (gimp_item_is_attached (iter->data), FALSE); + + image = gimp_item_get_image (GIMP_ITEM (drawables->data)); if (core->stroke_buffer) { @@ -378,22 +377,15 @@ gimp_paint_core_start (GimpPaintCore *core, /* remember the last stroke's endpoint for later undo */ core->start_coords = core->last_coords; + core->cur_coords = *coords; - core->cur_coords = *coords; - - if (! GIMP_PAINT_CORE_GET_CLASS (core)->start (core, drawable, + if (! GIMP_PAINT_CORE_GET_CLASS (core)->start (core, drawables, paint_options, coords, error)) { return FALSE; } - /* Allocate the undo structure */ - if (core->undo_buffer) - g_object_unref (core->undo_buffer); - - core->undo_buffer = gimp_gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); - /* Set the image pickable */ if (! core->show_all) core->image_pickable = GIMP_PICKABLE (image); @@ -410,80 +402,86 @@ gimp_paint_core_start (GimpPaintCore *core, core->saved_proj_buffer = gimp_gegl_buffer_dup (buffer); } - /* Allocate the canvas blocks structure */ - if (core->canvas_buffer) - g_object_unref (core->canvas_buffer); - - core->canvas_buffer = - gegl_buffer_new (GEGL_RECTANGLE (0, 0, - gimp_item_get_width (item), - gimp_item_get_height (item)), - babl_format ("Y float")); - - /* Get the initial undo extents */ - - core->x1 = core->x2 = core->cur_coords.x; - core->y1 = core->y2 = core->cur_coords.y; - - core->last_paint.x = -1e6; - core->last_paint.y = -1e6; - - mask = gimp_image_get_mask (image); - - /* don't apply the mask to itself and don't apply an empty mask */ - if (GIMP_DRAWABLE (mask) != drawable && ! gimp_channel_is_empty (mask)) + for (GList *iter = drawables; iter; iter = iter->next) { - GeglBuffer *mask_buffer; - gint offset_x; - gint offset_y; + /* Allocate the undo structures */ + g_hash_table_insert (core->undo_buffers, iter->data, + gimp_gegl_buffer_dup (gimp_drawable_get_buffer (iter->data))); - mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); - gimp_item_get_offset (item, &offset_x, &offset_y); + /* Allocate the canvas blocks structure */ + if (core->canvas_buffer) + g_object_unref (core->canvas_buffer); - core->mask_buffer = g_object_ref (mask_buffer); - core->mask_x_offset = -offset_x; - core->mask_y_offset = -offset_y; - } - else - { - core->mask_buffer = NULL; - } + core->canvas_buffer = + gegl_buffer_new (GEGL_RECTANGLE (0, 0, + gimp_item_get_width (iter->data), + gimp_item_get_height (iter->data)), + babl_format ("Y float")); - if (paint_options->use_applicator) - { - core->applicator = gimp_applicator_new (NULL); + /* Get the initial undo extents */ - if (core->mask_buffer) + core->x1 = core->x2 = core->cur_coords.x; + core->y1 = core->y2 = core->cur_coords.y; + + core->last_paint.x = -1e6; + core->last_paint.y = -1e6; + + mask = gimp_image_get_mask (image); + + /* don't apply the mask to itself and don't apply an empty mask */ + if (GIMP_DRAWABLE (mask) != iter->data && ! gimp_channel_is_empty (mask)) { - gimp_applicator_set_mask_buffer (core->applicator, - core->mask_buffer); - gimp_applicator_set_mask_offset (core->applicator, - core->mask_x_offset, - core->mask_y_offset); + GeglBuffer *mask_buffer; + gint offset_x; + gint offset_y; + + mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); + gimp_item_get_offset (iter->data, &offset_x, &offset_y); + + core->mask_buffer = g_object_ref (mask_buffer); + core->mask_x_offset = -offset_x; + core->mask_y_offset = -offset_y; + } + else + { + core->mask_buffer = NULL; } - gimp_applicator_set_affect (core->applicator, - gimp_drawable_get_active_mask (drawable)); - gimp_applicator_set_dest_buffer (core->applicator, - gimp_drawable_get_buffer (drawable)); - } + if (paint_options->use_applicator) + { + core->applicator = gimp_applicator_new (NULL); - /* Freeze the drawable preview so that it isn't constantly updated. */ - gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable)); + if (core->mask_buffer) + { + gimp_applicator_set_mask_buffer (core->applicator, + core->mask_buffer); + gimp_applicator_set_mask_offset (core->applicator, + core->mask_x_offset, + core->mask_y_offset); + } + + gimp_applicator_set_affect (core->applicator, + gimp_drawable_get_active_mask (iter->data)); + gimp_applicator_set_dest_buffer (core->applicator, + gimp_drawable_get_buffer (iter->data)); + } + + /* Freeze the drawable preview so that it isn't constantly updated. */ + gimp_viewable_preview_freeze (GIMP_VIEWABLE (iter->data)); + } return TRUE; } void gimp_paint_core_finish (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, gboolean push_undo) { GimpImage *image; + gboolean undo_group_started = FALSE; g_return_if_fail (GIMP_IS_PAINT_CORE (core)); - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_clear_object (&core->applicator); @@ -495,72 +493,87 @@ gimp_paint_core_finish (GimpPaintCore *core, g_clear_object (&core->mask_buffer); - image = gimp_item_get_image (GIMP_ITEM (drawable)); + image = gimp_item_get_image (GIMP_ITEM (drawables->data)); - /* Determine if any part of the image has been altered-- - * if nothing has, then just return... - */ - if ((core->x2 == core->x1) || (core->y2 == core->y1)) + for (GList *iter = drawables; iter; iter = iter->next) { - gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable)); - return; - } + /* Determine if any part of the image has been altered-- + * if nothing has, then just go to the next drawable... + */ + if ((core->x2 == core->x1) || (core->y2 == core->y1)) + { + gimp_viewable_preview_thaw (GIMP_VIEWABLE (iter->data)); + continue; + } - if (push_undo) - { - GeglBuffer *buffer; - GeglRectangle rect; + if (push_undo) + { + GeglBuffer *undo_buffer; + GeglBuffer *buffer; + GeglRectangle rect; - gimp_rectangle_intersect (core->x1, core->y1, - core->x2 - core->x1, core->y2 - core->y1, - 0, 0, - gimp_item_get_width (GIMP_ITEM (drawable)), - gimp_item_get_height (GIMP_ITEM (drawable)), - &rect.x, &rect.y, &rect.width, &rect.height); + if (! g_hash_table_steal_extended (core->undo_buffers, iter->data, + NULL, (gpointer*) &undo_buffer)) + { + g_critical ("%s: missing undo buffer for '%s'.", + G_STRFUNC, gimp_object_get_name (iter->data)); + continue; + } - gegl_rectangle_align_to_buffer (&rect, &rect, core->undo_buffer, - GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + gimp_rectangle_intersect (core->x1, core->y1, + core->x2 - core->x1, core->y2 - core->y1, + 0, 0, + gimp_item_get_width (GIMP_ITEM (iter->data)), + gimp_item_get_height (GIMP_ITEM (iter->data)), + &rect.x, &rect.y, &rect.width, &rect.height); - gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT, - core->undo_desc); + gegl_rectangle_align_to_buffer (&rect, &rect, undo_buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); - GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL); + if (! undo_group_started) + { + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT, + core->undo_desc); + undo_group_started = TRUE; + } - buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height), - gimp_drawable_get_format (drawable)); + GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL); - gimp_gegl_buffer_copy (core->undo_buffer, - &rect, - GEGL_ABYSS_NONE, - buffer, - GEGL_RECTANGLE (0, 0, 0, 0)); + buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height), + gimp_drawable_get_format (iter->data)); - gimp_drawable_push_undo (drawable, NULL, - buffer, rect.x, rect.y, rect.width, rect.height); + gimp_gegl_buffer_copy (undo_buffer, + &rect, + GEGL_ABYSS_NONE, + buffer, + GEGL_RECTANGLE (0, 0, 0, 0)); - g_object_unref (buffer); + gimp_drawable_push_undo (iter->data, NULL, + buffer, rect.x, rect.y, rect.width, rect.height); - gimp_image_undo_group_end (image); + g_object_unref (buffer); + g_object_unref (undo_buffer); + } + + gimp_viewable_preview_thaw (GIMP_VIEWABLE (iter->data)); } core->image_pickable = NULL; - g_clear_object (&core->undo_buffer); g_clear_object (&core->saved_proj_buffer); - gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable)); + if (undo_group_started) + gimp_image_undo_group_end (image); } void gimp_paint_core_cancel (GimpPaintCore *core, - GimpDrawable *drawable) + GList *drawables) { gint x, y; gint width, height; g_return_if_fail (GIMP_IS_PAINT_CORE (core)); - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); /* Determine if any part of the image has been altered-- * if nothing has, then just return... @@ -568,34 +581,46 @@ gimp_paint_core_cancel (GimpPaintCore *core, if ((core->x2 == core->x1) || (core->y2 == core->y1)) return; - if (gimp_rectangle_intersect (core->x1, core->y1, - core->x2 - core->x1, - core->y2 - core->y1, - 0, 0, - gimp_item_get_width (GIMP_ITEM (drawable)), - gimp_item_get_height (GIMP_ITEM (drawable)), - &x, &y, &width, &height)) + for (GList *iter = drawables; iter; iter = iter->next) { - GeglRectangle rect; + if (gimp_rectangle_intersect (core->x1, core->y1, + core->x2 - core->x1, + core->y2 - core->y1, + 0, 0, + gimp_item_get_width (GIMP_ITEM (iter->data)), + gimp_item_get_height (GIMP_ITEM (iter->data)), + &x, &y, &width, &height)) + { + GeglBuffer *undo_buffer; + GeglRectangle rect; - gegl_rectangle_align_to_buffer (&rect, - GEGL_RECTANGLE (x, y, width, height), - gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + if (! g_hash_table_steal_extended (core->undo_buffers, iter->data, + NULL, (gpointer*) &undo_buffer)) + { + g_critical ("%s: missing undo buffer for '%s'.", + G_STRFUNC, gimp_object_get_name (iter->data)); + continue; + } - gimp_gegl_buffer_copy (core->undo_buffer, - &rect, - GEGL_ABYSS_NONE, - gimp_drawable_get_buffer (drawable), - &rect); + gegl_rectangle_align_to_buffer (&rect, + GEGL_RECTANGLE (x, y, width, height), + gimp_drawable_get_buffer (iter->data), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + gimp_gegl_buffer_copy (undo_buffer, + &rect, + GEGL_ABYSS_NONE, + gimp_drawable_get_buffer (iter->data), + &rect); + g_object_unref (undo_buffer); + } + + gimp_drawable_update (iter->data, x, y, width, height); + + gimp_viewable_preview_thaw (GIMP_VIEWABLE (iter->data)); } - g_clear_object (&core->undo_buffer); g_clear_object (&core->saved_proj_buffer); - - gimp_drawable_update (drawable, x, y, width, height); - - gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable)); } void @@ -603,7 +628,8 @@ gimp_paint_core_cleanup (GimpPaintCore *core) { g_return_if_fail (GIMP_IS_PAINT_CORE (core)); - g_clear_object (&core->undo_buffer); + g_hash_table_remove_all (core->undo_buffers); + g_clear_object (&core->saved_proj_buffer); g_clear_object (&core->canvas_buffer); g_clear_object (&core->paint_buffer); @@ -611,20 +637,19 @@ gimp_paint_core_cleanup (GimpPaintCore *core) void gimp_paint_core_interpolate (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, guint32 time) { g_return_if_fail (GIMP_IS_PAINT_CORE (core)); - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); + g_return_if_fail (drawables != NULL); g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options)); g_return_if_fail (coords != NULL); core->cur_coords = *coords; - GIMP_PAINT_CORE_GET_CLASS (core)->interpolate (core, drawable, + GIMP_PAINT_CORE_GET_CLASS (core)->interpolate (core, drawables, paint_options, time); } @@ -779,12 +804,17 @@ gimp_paint_core_get_image_pickable (GimpPaintCore *core) } GeglBuffer * -gimp_paint_core_get_orig_image (GimpPaintCore *core) +gimp_paint_core_get_orig_image (GimpPaintCore *core, + GimpDrawable *drawable) { - g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL); - g_return_val_if_fail (core->undo_buffer != NULL, NULL); + GeglBuffer *undo_buffer; - return core->undo_buffer; + g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL); + + undo_buffer = g_hash_table_lookup (core->undo_buffers, drawable); + g_return_val_if_fail (undo_buffer != NULL, NULL); + + return undo_buffer; } GeglBuffer * @@ -807,9 +837,12 @@ gimp_paint_core_paste (GimpPaintCore *core, GimpLayerMode paint_mode, GimpPaintApplicationMode mode) { - gint width = gegl_buffer_get_width (core->paint_buffer); - gint height = gegl_buffer_get_height (core->paint_buffer); - GimpComponentMask affect = gimp_drawable_get_active_mask (drawable); + gint width = gegl_buffer_get_width (core->paint_buffer); + gint height = gegl_buffer_get_height (core->paint_buffer); + GimpComponentMask affect = gimp_drawable_get_active_mask (drawable); + GeglBuffer *undo_buffer; + + undo_buffer = g_hash_table_lookup (core->undo_buffers, drawable); if (! affect) return; @@ -851,8 +884,7 @@ gimp_paint_core_paste (GimpPaintCore *core, GEGL_RECTANGLE (0, 0, width, height), 1.0); - gimp_applicator_set_src_buffer (core->applicator, - core->undo_buffer); + gimp_applicator_set_src_buffer (core->applicator, undo_buffer); } /* Otherwise: * combine the paint mask to the paint buffer directly @@ -931,7 +963,7 @@ gimp_paint_core_paste (GimpPaintCore *core, algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_CANVAS_BUFFER_TO_COMP_MASK; /* undo buf -> paint_buf -> dest_buffer */ - params.src_buffer = core->undo_buffer; + params.src_buffer = undo_buffer; } else { @@ -998,8 +1030,9 @@ gimp_paint_core_replace (GimpPaintCore *core, gdouble image_opacity, GimpPaintApplicationMode mode) { - gint width, height; - GimpComponentMask affect; + GeglBuffer *undo_buffer; + gint width, height; + GimpComponentMask affect; if (! gimp_drawable_has_alpha (drawable)) { @@ -1022,6 +1055,8 @@ gimp_paint_core_replace (GimpPaintCore *core, if (! affect) return; + undo_buffer = g_hash_table_lookup (core->undo_buffers, drawable); + if (core->applicator) { GeglRectangle mask_rect; @@ -1060,8 +1095,7 @@ gimp_paint_core_replace (GimpPaintCore *core, core->paint_buffer_y, width, height); - gimp_applicator_set_src_buffer (core->applicator, - core->undo_buffer); + gimp_applicator_set_src_buffer (core->applicator, undo_buffer); } /* Otherwise: * use the paint mask as the mask buffer directly diff --git a/app/paint/gimppaintcore.h b/app/paint/gimppaintcore.h index 6e7f4d4c4b..189fec8f6e 100644 --- a/app/paint/gimppaintcore.h +++ b/app/paint/gimppaintcore.h @@ -59,7 +59,7 @@ struct _GimpPaintCore GimpPickable *image_pickable; /* the image pickable */ - GeglBuffer *undo_buffer; /* pixels which have been modified */ + GHashTable *undo_buffers; /* pixels which have been modified */ GeglBuffer *saved_proj_buffer; /* proj tiles which have been modified */ GeglBuffer *canvas_buffer; /* the buffer to paint the mask to */ GeglBuffer *paint_buffer; /* the buffer to paint pixels to */ @@ -81,30 +81,30 @@ struct _GimpPaintCoreClass /* virtual functions */ gboolean (* start) (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); gboolean (* pre_paint) (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time); void (* paint) (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, guint32 time); void (* post_paint) (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState paint_state, guint32 time); void (* interpolate) (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, guint32 time); @@ -127,25 +127,25 @@ struct _GimpPaintCoreClass GType gimp_paint_core_get_type (void) G_GNUC_CONST; void gimp_paint_core_paint (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpPaintState state, guint32 time); gboolean gimp_paint_core_start (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); void gimp_paint_core_finish (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, gboolean push_undo); void gimp_paint_core_cancel (GimpPaintCore *core, - GimpDrawable *drawable); + GList *drawables); void gimp_paint_core_cleanup (GimpPaintCore *core); void gimp_paint_core_interpolate (GimpPaintCore *core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, guint32 time); @@ -186,7 +186,8 @@ GeglBuffer * gimp_paint_core_get_paint_buffer (GimpPaintCore *core, GimpPickable * gimp_paint_core_get_image_pickable (GimpPaintCore *core); -GeglBuffer * gimp_paint_core_get_orig_image (GimpPaintCore *core); +GeglBuffer * gimp_paint_core_get_orig_image (GimpPaintCore *core, + GimpDrawable *drawable); GeglBuffer * gimp_paint_core_get_orig_proj (GimpPaintCore *core); void gimp_paint_core_paste (GimpPaintCore *core, diff --git a/app/paint/gimpperspectiveclone.c b/app/paint/gimpperspectiveclone.c index abb9fabb5a..17fb600d88 100644 --- a/app/paint/gimpperspectiveclone.c +++ b/app/paint/gimpperspectiveclone.c @@ -47,7 +47,7 @@ static void gimp_perspective_clone_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -119,7 +119,7 @@ gimp_perspective_clone_init (GimpPerspectiveClone *clone) static void gimp_perspective_clone_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -140,7 +140,7 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core, case GIMP_PAINT_STATE_INIT: if (source_core->set_source) { - g_object_set (source_core, "src-drawable", drawable, NULL); + g_object_set (source_core, "src-drawable", drawables->data, NULL); source_core->src_x = floor (coords->x); source_core->src_y = floor (coords->y); @@ -194,12 +194,12 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core, if (options->sample_merged) src_pickable = GIMP_PICKABLE (src_image); - dest_image = gimp_item_get_image (GIMP_ITEM (drawable)); + dest_image = gimp_item_get_image (GIMP_ITEM (drawables->data)); if ((options->sample_merged && (src_image != dest_image)) || (! options->sample_merged && - (source_core->src_drawable != drawable))) + (source_core->src_drawable != drawables->data))) { orig_buffer = gimp_pickable_get_buffer (src_pickable); } @@ -208,7 +208,7 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core, if (options->sample_merged) orig_buffer = gimp_paint_core_get_orig_proj (paint_core); else - orig_buffer = gimp_paint_core_get_orig_image (paint_core); + orig_buffer = gimp_paint_core_get_orig_image (paint_core, drawables->data); } } break; @@ -326,7 +326,8 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core, } } - gimp_source_core_motion (source_core, drawable, paint_options, sym); + for (GList *iter = drawables; iter; iter = iter->next) + gimp_source_core_motion (source_core, iter->data, paint_options, sym); } break; diff --git a/app/paint/gimpsmudge.c b/app/paint/gimpsmudge.c index e285f4d874..a0ba1f2f4a 100644 --- a/app/paint/gimpsmudge.c +++ b/app/paint/gimpsmudge.c @@ -46,7 +46,7 @@ static void gimp_smudge_finalize (GObject *object); static void gimp_smudge_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -133,7 +133,7 @@ gimp_smudge_finalize (GObject *object) static void gimp_smudge_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -141,6 +141,8 @@ gimp_smudge_paint (GimpPaintCore *paint_core, { GimpSmudge *smudge = GIMP_SMUDGE (paint_core); + g_return_if_fail (g_list_length (drawables) == 1); + switch (paint_state) { case GIMP_PAINT_STATE_INIT: @@ -169,11 +171,11 @@ gimp_smudge_paint (GimpPaintCore *paint_core, case GIMP_PAINT_STATE_MOTION: /* initialization fails if the user starts outside the drawable */ if (! smudge->initialized) - smudge->initialized = gimp_smudge_start (paint_core, drawable, + smudge->initialized = gimp_smudge_start (paint_core, drawables->data, paint_options, sym); if (smudge->initialized) - gimp_smudge_motion (paint_core, drawable, paint_options, sym); + gimp_smudge_motion (paint_core, drawables->data, paint_options, sym); break; case GIMP_PAINT_STATE_FINISH: @@ -223,7 +225,7 @@ gimp_smudge_start (GimpPaintCore *paint_core, coords = gimp_symmetry_get_origin (sym); gimp_brush_core_eval_transform_dynamics (brush_core, - drawable, + gimp_item_get_image (GIMP_ITEM (drawable)), paint_options, coords); @@ -395,7 +397,7 @@ gimp_smudge_motion (GimpPaintCore *paint_core, return; gimp_brush_core_eval_transform_dynamics (brush_core, - drawable, + image, paint_options, coords); diff --git a/app/paint/gimpsourcecore.c b/app/paint/gimpsourcecore.c index 94238ad32f..1f891a55be 100644 --- a/app/paint/gimpsourcecore.c +++ b/app/paint/gimpsourcecore.c @@ -60,12 +60,12 @@ static void gimp_source_core_get_property (GObject *object, GParamSpec *pspec); static gboolean gimp_source_core_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error); static void gimp_source_core_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -213,7 +213,7 @@ gimp_source_core_get_property (GObject *object, static gboolean gimp_source_core_start (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, const GimpCoords *coords, GError **error) @@ -221,7 +221,7 @@ gimp_source_core_start (GimpPaintCore *paint_core, GimpSourceCore *source_core = GIMP_SOURCE_CORE (paint_core); GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (paint_options); - if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawable, + if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawables, paint_options, coords, error)) { @@ -242,7 +242,7 @@ gimp_source_core_start (GimpPaintCore *paint_core, if (options->sample_merged && gimp_item_get_image (GIMP_ITEM (source_core->src_drawable)) == - gimp_item_get_image (GIMP_ITEM (drawable))) + gimp_item_get_image (GIMP_ITEM (drawables->data))) { paint_core->use_saved_proj = TRUE; } @@ -253,7 +253,7 @@ gimp_source_core_start (GimpPaintCore *paint_core, static void gimp_source_core_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, + GList *drawables, GimpPaintOptions *paint_options, GimpSymmetry *sym, GimpPaintState paint_state, @@ -271,7 +271,7 @@ gimp_source_core_paint (GimpPaintCore *paint_core, case GIMP_PAINT_STATE_INIT: if (source_core->set_source) { - gimp_source_core_set_src_drawable (source_core, drawable); + gimp_source_core_set_src_drawable (source_core, drawables->data); /* FIXME(?): subpixel source sampling */ source_core->src_x = floor (coords->x); @@ -329,8 +329,9 @@ gimp_source_core_paint (GimpPaintCore *paint_core, source_core->src_x = dest_x + source_core->offset_x; source_core->src_y = dest_y + source_core->offset_y; - gimp_source_core_motion (source_core, drawable, paint_options, - sym); + for (GList *iter = drawables; iter; iter = iter->next) + gimp_source_core_motion (source_core, iter->data, + paint_options, sym); } break; @@ -430,7 +431,7 @@ gimp_source_core_motion (GimpSourceCore *source_core, } gimp_brush_core_eval_transform_dynamics (brush_core, - drawable, + image, paint_options, origin); @@ -629,7 +630,8 @@ gimp_source_core_real_get_source (GimpSourceCore *source_core, if (options->sample_merged) dest_buffer = gimp_paint_core_get_orig_proj (GIMP_PAINT_CORE (source_core)); else - dest_buffer = gimp_paint_core_get_orig_image (GIMP_PAINT_CORE (source_core)); + dest_buffer = gimp_paint_core_get_orig_image (GIMP_PAINT_CORE (source_core), + drawable); } *paint_area_offset_x = x - (paint_buffer_x + src_offset_x); diff --git a/app/tools/gimpbrushtool.c b/app/tools/gimpbrushtool.c index 8fb3e49b07..f2a14fd0d0 100644 --- a/app/tools/gimpbrushtool.c +++ b/app/tools/gimpbrushtool.c @@ -156,23 +156,15 @@ gimp_brush_tool_oper_update (GimpTool *tool, GimpDisplay *display) { GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool); - GimpDrawable *drawable = NULL; - GList *drawables; + GimpImage *image = gimp_display_get_image (display); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); - drawables = gimp_image_get_selected_drawables (gimp_display_get_image (display)); - - if (drawables) - drawable = drawables->data; - - g_list_free (drawables); - if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)) && - drawable && proximity) + image && proximity) { GimpContext *context = GIMP_CONTEXT (paint_options); GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); @@ -187,7 +179,7 @@ gimp_brush_tool_oper_update (GimpTool *tool, if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush) { gimp_brush_core_eval_transform_dynamics (brush_core, - drawable, + image, paint_options, coords); } diff --git a/app/tools/gimppainttool-paint.c b/app/tools/gimppainttool-paint.c index 7c0baebe1d..ca47ac134d 100644 --- a/app/tools/gimppainttool-paint.c +++ b/app/tools/gimppainttool-paint.c @@ -58,8 +58,9 @@ typedef struct typedef struct { - GimpCoords coords; - guint32 time; + GList *drawables; + GimpCoords coords; + guint32 time; } InterpolateData; @@ -159,9 +160,8 @@ gimp_paint_tool_paint_thread (gpointer data) static gboolean gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool) { - GimpPaintCore *core = paint_tool->core; - GimpDrawable *drawable = paint_tool->drawable; - gboolean update; + GimpPaintCore *core = paint_tool->core; + gboolean update = FALSE; paint_timeout_pending = TRUE; @@ -170,7 +170,12 @@ gimp_paint_tool_paint_timeout (GimpPaintTool *paint_tool) paint_tool->paint_x = core->last_paint.x; paint_tool->paint_y = core->last_paint.y; - update = gimp_drawable_flush_paint (drawable); + for (GList *iter = paint_tool->drawables; iter; iter = iter->next) + { + update |= gimp_drawable_flush_paint (iter->data); + if (update) + break; + } if (update && GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_flush) GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_flush (paint_tool); @@ -205,11 +210,11 @@ gimp_paint_tool_paint_interpolate (GimpPaintTool *paint_tool, { 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, + gimp_paint_core_interpolate (core, data->drawables, paint_options, &data->coords, data->time); + g_list_free (data->drawables); g_slice_free (InterpolateData, data); } @@ -230,10 +235,9 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool, GimpPaintCore *core; GimpDisplayShell *shell; GimpImage *image; - GimpDrawable *drawable; GList *drawables; + GList *iter; GimpCoords curr_coords; - gint off_x, off_y; g_return_val_if_fail (GIMP_IS_PAINT_TOOL (paint_tool), FALSE); g_return_val_if_fail (GIMP_IS_DISPLAY (display), FALSE); @@ -249,17 +253,12 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool, image = gimp_display_get_image (display); drawables = gimp_image_get_selected_drawables (image); - g_return_val_if_fail (g_list_length (drawables) == 1, FALSE); + g_return_val_if_fail (g_list_length (drawables) == 1 || + (g_list_length (drawables) > 1 && paint_tool->can_multi_paint), + FALSE); curr_coords = *coords; - drawable = drawables->data; - g_list_free (drawables); - gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); - - curr_coords.x -= off_x; - curr_coords.y -= off_y; - paint_tool->paint_x = curr_coords.x; paint_tool->paint_y = curr_coords.y; @@ -267,7 +266,8 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool, * paint core */ if (gimp_paint_tool_paint_use_thread (paint_tool)) - gimp_drawable_start_paint (drawable); + for (iter = drawables; iter; iter = iter->next) + gimp_drawable_start_paint (iter->data); /* Prepare to start the paint core */ if (GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint_prepare) @@ -275,16 +275,19 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool, /* Start the paint core */ if (! gimp_paint_core_start (core, - drawable, paint_options, &curr_coords, + drawables, paint_options, &curr_coords, error)) { - gimp_drawable_end_paint (drawable); + for (iter = drawables; iter; iter = iter->next) + gimp_drawable_end_paint (iter->data); + g_list_free (drawables); return FALSE; } paint_tool->display = display; - paint_tool->drawable = drawable; + g_list_free (paint_tool->drawables); + paint_tool->drawables = drawables; if ((display != tool->display) || ! paint_tool->draw_line) { @@ -323,18 +326,18 @@ gimp_paint_tool_paint_start (GimpPaintTool *paint_tool, } /* Let the specific painting function initialize itself */ - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_INIT, time); /* Paint to the image */ if (paint_tool->draw_line) { - gimp_paint_core_interpolate (core, drawable, paint_options, + gimp_paint_core_interpolate (core, drawables, paint_options, &core->cur_coords, time); } else { - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_MOTION, time); } @@ -361,14 +364,14 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool, { GimpPaintOptions *paint_options; GimpPaintCore *core; - GimpDrawable *drawable; + GList *drawables; g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool)); g_return_if_fail (paint_tool->display != NULL); paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool); core = paint_tool->core; - drawable = paint_tool->drawable; + drawables = paint_tool->drawables; /* Process remaining paint items */ if (gimp_paint_tool_paint_use_thread (paint_tool)) @@ -414,13 +417,13 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool, } /* Let the specific painting function finish up */ - gimp_paint_core_paint (core, drawable, paint_options, + gimp_paint_core_paint (core, drawables, paint_options, GIMP_PAINT_STATE_FINISH, time); if (cancel) - gimp_paint_core_cancel (core, drawable); + gimp_paint_core_cancel (core, drawables); else - gimp_paint_core_finish (core, drawable, TRUE); + gimp_paint_core_finish (core, drawables, TRUE); /* Notify subclasses */ if (gimp_paint_tool_paint_use_thread (paint_tool) && @@ -431,10 +434,11 @@ gimp_paint_tool_paint_end (GimpPaintTool *paint_tool, /* Exit paint mode */ if (gimp_paint_tool_paint_use_thread (paint_tool)) - gimp_drawable_end_paint (drawable); + for (GList *iter = drawables; iter; iter = iter->next) + gimp_drawable_end_paint (iter->data); - paint_tool->display = NULL; - paint_tool->drawable = NULL; + paint_tool->display = NULL; + g_clear_pointer (&paint_tool->drawables, g_list_free); } gboolean @@ -442,8 +446,13 @@ 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); + for (GList *iter = paint_tool->drawables; iter; iter = iter->next) + { + if (gimp_drawable_is_painting (iter->data)) + return TRUE; + } + + return FALSE; } void @@ -501,9 +510,8 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool, { GimpPaintOptions *paint_options; GimpPaintCore *core; - GimpDrawable *drawable; + GList *drawables; InterpolateData *data; - gint off_x, off_y; g_return_if_fail (GIMP_IS_PAINT_TOOL (paint_tool)); g_return_if_fail (coords != NULL); @@ -511,17 +519,13 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool, paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (paint_tool); core = paint_tool->core; - drawable = paint_tool->drawable; + drawables = paint_tool->drawables; data = g_slice_new (InterpolateData); - data->coords = *coords; - data->time = time; - - gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); - - data->coords.x -= off_x; - data->coords.y -= off_y; + data->drawables = g_list_copy (drawables); + data->coords = *coords; + data->time = time; paint_tool->cursor_x = data->coords.x; paint_tool->cursor_y = data->coords.y; @@ -532,14 +536,14 @@ gimp_paint_tool_paint_motion (GimpPaintTool *paint_tool, if (paint_tool->draw_line) { gimp_paint_core_set_current_coords (core, &data->coords); + g_list_free (data->drawables); g_slice_free (InterpolateData, data); return; } - gimp_paint_tool_paint_push ( - paint_tool, - (GimpPaintToolPaintFunc) gimp_paint_tool_paint_interpolate, - data); + gimp_paint_tool_paint_push (paint_tool, + (GimpPaintToolPaintFunc) gimp_paint_tool_paint_interpolate, + data); } diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c index 0aa2edc968..cfa01541f3 100644 --- a/app/tools/gimppainttool.c +++ b/app/tools/gimppainttool.c @@ -160,9 +160,10 @@ gimp_paint_tool_init (GimpPaintTool *paint_tool) gimp_tool_control_set_action_opacity (tool->control, "context/context-opacity-set"); - paint_tool->active = TRUE; - paint_tool->pick_colors = FALSE; - paint_tool->draw_line = FALSE; + paint_tool->active = TRUE; + paint_tool->pick_colors = FALSE; + paint_tool->can_multi_paint = FALSE; + paint_tool->draw_line = FALSE; paint_tool->show_cursor = TRUE; paint_tool->draw_brush = TRUE; @@ -277,7 +278,7 @@ gimp_paint_tool_button_press (GimpTool *tool, GimpDisplayShell *shell = gimp_display_get_shell (display); GimpImage *image = gimp_display_get_image (display); GList *drawables; - GimpDrawable *drawable; + GList *iter; gboolean constrain; GError *error = NULL; @@ -289,68 +290,76 @@ gimp_paint_tool_button_press (GimpTool *tool, } drawables = gimp_image_get_selected_drawables (image); - if (g_list_length (drawables) != 1) - { - if (g_list_length (drawables) > 1) - gimp_tool_message_literal (tool, display, - _("Cannot paint on multiple layers. Select only one layer.")); - else - gimp_tool_message_literal (tool, display, - _("No selected drawables.")); - - g_list_free (drawables); - return; - } - - drawable = drawables->data; - - if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))) + if (drawables == NULL) { gimp_tool_message_literal (tool, display, - _("Cannot paint on layer groups.")); - g_list_free (drawables); + _("No selected drawables.")); return; } - - if (gimp_item_is_content_locked (GIMP_ITEM (drawable))) + else if (! paint_tool->can_multi_paint) { - gimp_tool_message_literal (tool, display, - _("The active layer's pixels are locked.")); - gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable)); - g_list_free (drawables); + if (g_list_length (drawables) != 1) + { + gimp_tool_message_literal (tool, display, + _("Cannot paint on multiple layers. Select only one layer.")); - return; + g_list_free (drawables); + return; + } } - if (! gimp_paint_tool_check_alpha (paint_tool, drawable, display, &error)) + for (iter = drawables; iter; iter = iter->next) { - GtkWidget *options_gui; - GtkWidget *mode_box; + GimpDrawable *drawable = iter->data; - gimp_tool_message_literal (tool, display, error->message); + if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))) + { + gimp_tool_message_literal (tool, display, + _("Cannot paint on layer groups.")); + g_list_free (drawables); - options_gui = gimp_tools_get_tool_options_gui ( - GIMP_TOOL_OPTIONS (options)); - mode_box = gimp_paint_options_gui_get_paint_mode_box (options_gui); + return; + } - if (gtk_widget_is_sensitive (mode_box)) - gimp_widget_blink (mode_box); + if (gimp_item_is_content_locked (GIMP_ITEM (drawable))) + { + gimp_tool_message_literal (tool, display, + _("A selected layer's pixels are locked.")); + gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable)); + g_list_free (drawables); - g_clear_error (&error); - g_list_free (drawables); + return; + } - return; - } + if (! gimp_paint_tool_check_alpha (paint_tool, drawable, display, &error)) + { + GtkWidget *options_gui; + GtkWidget *mode_box; - if (! gimp_item_is_visible (GIMP_ITEM (drawable)) && - ! config->edit_non_visible) - { - gimp_tool_message_literal (tool, display, - _("The active layer is not visible.")); - g_list_free (drawables); + gimp_tool_message_literal (tool, display, error->message); - return; + options_gui = gimp_tools_get_tool_options_gui (GIMP_TOOL_OPTIONS (options)); + mode_box = gimp_paint_options_gui_get_paint_mode_box (options_gui); + + if (gtk_widget_is_sensitive (mode_box)) + gimp_widget_blink (mode_box); + + g_clear_error (&error); + g_list_free (drawables); + + return; + } + + if (! gimp_item_is_visible (GIMP_ITEM (drawable)) && + ! config->edit_non_visible) + { + gimp_tool_message_literal (tool, display, + _("A selected layer is not visible.")); + g_list_free (drawables); + + return; + } } if (gimp_draw_tool_is_active (draw_tool)) @@ -533,27 +542,29 @@ gimp_paint_tool_cursor_update (GimpTool *tool, { GimpImage *image = gimp_display_get_image (display); GList *drawables = gimp_image_get_selected_drawables (image); - GimpDrawable *drawable = NULL; + GList *iter; if (! drawables) return; - if (g_list_length (drawables) == 1) - drawable = drawables->data; + for (iter = drawables; iter; iter = iter->next) + { + GimpDrawable *drawable = iter->data; + + if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) || + gimp_item_is_content_locked (GIMP_ITEM (drawable)) || + ! gimp_paint_tool_check_alpha (paint_tool, drawable, display, NULL) || + ! (gimp_item_is_visible (GIMP_ITEM (drawable)) || + config->edit_non_visible)) + { + modifier = GIMP_CURSOR_MODIFIER_BAD; + toggle_modifier = GIMP_CURSOR_MODIFIER_BAD; + break; + } + } g_list_free (drawables); - if (! drawable || - gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) || - gimp_item_is_content_locked (GIMP_ITEM (drawable)) || - ! gimp_paint_tool_check_alpha (paint_tool, drawable, display, NULL) || - ! (gimp_item_is_visible (GIMP_ITEM (drawable)) || - config->edit_non_visible)) - { - modifier = GIMP_CURSOR_MODIFIER_BAD; - toggle_modifier = GIMP_CURSOR_MODIFIER_BAD; - } - if (! paint_tool->show_cursor && modifier != GIMP_CURSOR_MODIFIER_BAD) { @@ -626,19 +637,16 @@ gimp_paint_tool_oper_update (GimpTool *tool, } drawables = gimp_image_get_selected_drawables (image); - if (g_list_length (drawables) == 1 && proximity) + + if ((g_list_length (drawables) == 1 || + (g_list_length (drawables) > 1 && paint_tool->can_multi_paint)) && + proximity) { gchar *status; gboolean constrain_mask = gimp_get_constrain_behavior_mask (); - gint off_x, off_y; core->cur_coords = *coords; - gimp_item_get_offset (GIMP_ITEM (drawables->data), &off_x, &off_y); - - core->cur_coords.x -= off_x; - core->cur_coords.y -= off_y; - if (display == tool->display && (state & GIMP_PAINT_TOOL_LINE_MASK)) { /* If shift is down and this is not the first paint stroke, @@ -725,31 +733,20 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool) ! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (draw_tool))) { GimpPaintCore *core = paint_tool->core; - GimpImage *image = gimp_display_get_image (draw_tool->display); GimpCanvasItem *outline = NULL; gboolean line_drawn = FALSE; gdouble cur_x, cur_y; - gint off_x, off_y; - GList *drawables = gimp_image_get_selected_drawables (image); - GimpDrawable *drawable; - - g_return_if_fail (g_list_length (drawables) == 1); - - drawable = drawables->data; - g_list_free (drawables); - - gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); if (gimp_paint_tool_paint_is_active (paint_tool) && paint_tool->snap_brush) { - cur_x = paint_tool->paint_x + off_x; - cur_y = paint_tool->paint_y + off_y; + cur_x = paint_tool->paint_x; + cur_y = paint_tool->paint_y; } else { - cur_x = paint_tool->cursor_x + off_x; - cur_y = paint_tool->cursor_y + off_y; + cur_x = paint_tool->cursor_x; + cur_y = paint_tool->cursor_y; if (paint_tool->draw_line && ! gimp_tool_control_is_active (GIMP_TOOL (draw_tool)->control)) @@ -757,8 +754,8 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool) GimpCanvasGroup *group; gdouble last_x, last_y; - last_x = core->last_coords.x + off_x; - last_y = core->last_coords.y + off_y; + last_x = core->last_coords.x; + last_y = core->last_coords.y; group = gimp_draw_tool_add_stroke_group (draw_tool); gimp_draw_tool_push_group (draw_tool, group); @@ -1009,6 +1006,21 @@ gimp_paint_tool_enable_color_picker (GimpPaintTool *tool, GIMP_COLOR_TOOL (tool)->pick_target = target; } +/** + * gimp_paint_tool_enable_multi_paint: + * @tool: a #GimpPaintTool + * + * This is a convenience function used from the init method of paint + * tools that want to allow painting with several drawables. + **/ +void +gimp_paint_tool_enable_multi_paint (GimpPaintTool *tool) +{ + g_return_if_fail (GIMP_IS_PAINT_TOOL (tool)); + + tool->can_multi_paint = TRUE; +} + void gimp_paint_tool_set_draw_fallback (GimpPaintTool *tool, gboolean draw_fallback, diff --git a/app/tools/gimppainttool.h b/app/tools/gimppainttool.h index faaf9c738a..4f1375221e 100644 --- a/app/tools/gimppainttool.h +++ b/app/tools/gimppainttool.h @@ -42,7 +42,8 @@ struct _GimpPaintTool GimpColorTool parent_instance; gboolean active; - gboolean pick_colors; /* pick color if ctrl is pressed */ + gboolean pick_colors; /* pick color if ctrl is pressed */ + gboolean can_multi_paint; /* if paint works with multiple drawables */ gboolean draw_line; gboolean show_cursor; @@ -60,7 +61,7 @@ struct _GimpPaintTool GimpPaintCore *core; GimpDisplay *display; - GimpDrawable *drawable; + GList *drawables; gdouble cursor_x; gdouble cursor_y; @@ -97,6 +98,8 @@ void gimp_paint_tool_set_active (GimpPaintTool *tool, void gimp_paint_tool_enable_color_picker (GimpPaintTool *tool, GimpColorPickTarget target); +void gimp_paint_tool_enable_multi_paint (GimpPaintTool *tool); + void gimp_paint_tool_set_draw_fallback (GimpPaintTool *tool, gboolean draw_fallback, gint fallback_size); diff --git a/app/tools/gimpsourcetool.c b/app/tools/gimpsourcetool.c index 9d9f725182..b2c5f6d44d 100644 --- a/app/tools/gimpsourcetool.c +++ b/app/tools/gimpsourcetool.c @@ -116,6 +116,8 @@ static void gimp_source_tool_init (GimpSourceTool *source) { source->show_source_outline = TRUE; + + gimp_paint_tool_enable_multi_paint (GIMP_PAINT_TOOL (source)); } static gboolean