[gimp] app: make painting possibly multi-drawable aware.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: make painting possibly multi-drawable aware.
- Date: Tue, 14 Sep 2021 16:11:59 +0000 (UTC)
commit 8934d439759c49a472a42de9b4b23acb63f0c509
Author: Jehan <jehan girinstud io>
Date: Mon Aug 16 23:46:32 2021 +0200
app: make painting possibly multi-drawable aware.
- Make the various virtual methods of GimpPaintCore use a list of
drawables as argument instead of a single drawable.
- gimp_brush_core_eval_transform_dynamics() can work with an image as
argument rather than a drawable as it doesn't actually depends on
specific drawable data.
- New function gimp_paint_tool_enable_multi_paint() to be used in init()
method of paint tools to announce that this tool can work with
multiple layers selected.
- Use gimp_paint_tool_enable_multi_paint() in the GimpSourceTool base
class only for now.
This is a first step for multi-layer drawing, but we don't want it to be
possible in just any random cases, which is why I add a special function
to advertize this capability. We will use it for special-casing the
clone (as well as heal and perspective tools most likely) tool to work
on several layers at once. At this step, it is still very bugged and not
really working properly. In particular, since we don't process the
drawable offset early anymore (because it makes no sense when we pass a
list of drawables with different offsets), I suspect that all the
offset-related code will be very broken.
app/paint/gimpairbrush.c | 22 ++-
app/paint/gimpbrushcore.c | 44 +++--
app/paint/gimpbrushcore.h | 2 +-
app/paint/gimpclone.c | 6 +-
app/paint/gimpconvolve.c | 11 +-
app/paint/gimpdodgeburn.c | 13 +-
app/paint/gimpheal.c | 8 +-
app/paint/gimpink.c | 9 +-
app/paint/gimpmybrushcore.c | 26 +--
app/paint/gimppaintbrush.c | 30 ++--
app/paint/gimppaintcore-stroke.c | 56 +++---
app/paint/gimppaintcore.c | 366 +++++++++++++++++++++------------------
app/paint/gimppaintcore.h | 25 +--
app/paint/gimpperspectiveclone.c | 15 +-
app/paint/gimpsmudge.c | 14 +-
app/paint/gimpsourcecore.c | 24 +--
app/tools/gimpbrushtool.c | 14 +-
app/tools/gimppainttool-paint.c | 102 +++++------
app/tools/gimppainttool.c | 184 +++++++++++---------
app/tools/gimppainttool.h | 7 +-
app/tools/gimpsourcetool.c | 2 +
21 files changed, 540 insertions(+), 440 deletions(-)
---
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);
+ for (GList *iter = drawables; iter; iter = iter->next)
+ {
+ /* Allocate the undo structures */
+ g_hash_table_insert (core->undo_buffers, iter->data,
+ gimp_gegl_buffer_dup (gimp_drawable_get_buffer (iter->data)));
- core->canvas_buffer =
- gegl_buffer_new (GEGL_RECTANGLE (0, 0,
- gimp_item_get_width (item),
- gimp_item_get_height (item)),
- babl_format ("Y float"));
+ /* Allocate the canvas blocks structure */
+ if (core->canvas_buffer)
+ g_object_unref (core->canvas_buffer);
- /* Get the initial undo extents */
+ 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"));
- core->x1 = core->x2 = core->cur_coords.x;
- core->y1 = core->y2 = core->cur_coords.y;
+ /* Get the initial undo extents */
- core->last_paint.x = -1e6;
- core->last_paint.y = -1e6;
+ core->x1 = core->x2 = core->cur_coords.x;
+ core->y1 = core->y2 = core->cur_coords.y;
- mask = gimp_image_get_mask (image);
+ core->last_paint.x = -1e6;
+ core->last_paint.y = -1e6;
- /* don't apply the mask to itself and don't apply an empty mask */
- if (GIMP_DRAWABLE (mask) != drawable && ! gimp_channel_is_empty (mask))
- {
- GeglBuffer *mask_buffer;
- gint offset_x;
- gint offset_y;
+ mask = gimp_image_get_mask (image);
- mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
- gimp_item_get_offset (item, &offset_x, &offset_y);
+ /* 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))
+ {
+ GeglBuffer *mask_buffer;
+ gint offset_x;
+ gint 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;
- }
+ mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
+ gimp_item_get_offset (iter->data, &offset_x, &offset_y);
- if (paint_options->use_applicator)
- {
- core->applicator = gimp_applicator_new (NULL);
+ 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;
+ }
- if (core->mask_buffer)
+ if (paint_options->use_applicator)
{
- 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);
+ core->applicator = gimp_applicator_new (NULL);
+
+ 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));
}
- gimp_applicator_set_affect (core->applicator,
- gimp_drawable_get_active_mask (drawable));
- gimp_applicator_set_dest_buffer (core->applicator,
- gimp_drawable_get_buffer (drawable));
+ /* Freeze the drawable preview so that it isn't constantly updated. */
+ gimp_viewable_preview_freeze (GIMP_VIEWABLE (iter->data));
}
- /* Freeze the drawable preview so that it isn't constantly updated. */
- gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable));
-
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);
+
+ if (! undo_group_started)
+ {
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT,
+ core->undo_desc);
+ undo_group_started = TRUE;
+ }
- GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL);
+ GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL);
- buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height),
- gimp_drawable_get_format (drawable));
+ buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height),
+ gimp_drawable_get_format (iter->data));
- gimp_gegl_buffer_copy (core->undo_buffer,
- &rect,
- GEGL_ABYSS_NONE,
- buffer,
- GEGL_RECTANGLE (0, 0, 0, 0));
+ gimp_gegl_buffer_copy (undo_buffer,
+ &rect,
+ GEGL_ABYSS_NONE,
+ buffer,
+ GEGL_RECTANGLE (0, 0, 0, 0));
- gimp_drawable_push_undo (drawable, NULL,
- buffer, rect.x, rect.y, rect.width, rect.height);
+ gimp_drawable_push_undo (iter->data, NULL,
+ buffer, rect.x, rect.y, rect.width, rect.height);
- g_object_unref (buffer);
+ g_object_unref (buffer);
+ g_object_unref (undo_buffer);
+ }
- gimp_image_undo_group_end (image);
+ 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;
-
- gegl_rectangle_align_to_buffer (&rect,
- GEGL_RECTANGLE (x, y, width, height),
- gimp_drawable_get_buffer (drawable),
- GEGL_RECTANGLE_ALIGNMENT_SUPERSET);
-
- gimp_gegl_buffer_copy (core->undo_buffer,
- &rect,
- GEGL_ABYSS_NONE,
- gimp_drawable_get_buffer (drawable),
- &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;
- g_clear_object (&core->undo_buffer);
- g_clear_object (&core->saved_proj_buffer);
+ 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,
+ 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_drawable_update (drawable, x, y, width, height);
+ gimp_viewable_preview_thaw (GIMP_VIEWABLE (iter->data));
+ }
- gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable));
+ g_clear_object (&core->saved_proj_buffer);
}
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)
{
+ GeglBuffer *undo_buffer;
+
g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL);
- g_return_val_if_fail (core->undo_buffer != NULL, NULL);
- return core->undo_buffer;
+ 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 (drawables == NULL)
{
- 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."));
+ 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)))
+ else if (! paint_tool->can_multi_paint)
{
- gimp_tool_message_literal (tool, display,
- _("Cannot paint on layer groups."));
- 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_item_is_content_locked (GIMP_ITEM (drawable)))
+ for (iter = drawables; iter; iter = iter->next)
{
- 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);
+ GimpDrawable *drawable = iter->data;
- return;
- }
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ {
+ gimp_tool_message_literal (tool, display,
+ _("Cannot paint on layer groups."));
+ g_list_free (drawables);
- if (! gimp_paint_tool_check_alpha (paint_tool, drawable, display, &error))
- {
- GtkWidget *options_gui;
- GtkWidget *mode_box;
+ return;
+ }
- gimp_tool_message_literal (tool, display, error->message);
+ 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);
- 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_paint_tool_check_alpha (paint_tool, drawable, display, &error))
+ {
+ GtkWidget *options_gui;
+ GtkWidget *mode_box;
- g_clear_error (&error);
- 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 (! 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);
+ if (gtk_widget_is_sensitive (mode_box))
+ gimp_widget_blink (mode_box);
- return;
+ 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;
-
- 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))
+ for (iter = drawables; iter; iter = iter->next)
{
- modifier = GIMP_CURSOR_MODIFIER_BAD;
- toggle_modifier = GIMP_CURSOR_MODIFIER_BAD;
+ 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 (! 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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]