[gimp] app, pdb: properly save the list of source drawables.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app, pdb: properly save the list of source drawables.
- Date: Tue, 14 Sep 2021 16:11:59 +0000 (UTC)
commit 3a9462b219420c4fcb4d91e40ca4baf29289c3ad
Author: Jehan <jehan girinstud io>
Date: Wed Aug 18 23:04:11 2021 +0200
app, pdb: properly save the list of source drawables.
By doing this, I also add the ability to use a composited projection of
the selected drawables as source. This is similar to "Sample merged"
except that instead of using the whole visible image, we use what would
have been visible if only the selected layers existed.
Note that this doesn't work together with the previously added ability
of multi-cloning from each layer to itself. This ability works for
cloning from multiple layers to one.
app/paint/gimpperspectiveclone.c | 4 +-
app/paint/gimpsourcecore.c | 179 ++++++++++++++++++++++++-----------
app/paint/gimpsourcecore.h | 6 +-
app/pdb/paint-tools-cmds.c | 24 +++--
app/tools/gimpperspectiveclonetool.c | 8 +-
app/tools/gimpsourcetool.c | 16 ++--
pdb/groups/paint_tools.pdb | 24 +++--
7 files changed, 175 insertions(+), 86 deletions(-)
---
diff --git a/app/paint/gimpperspectiveclone.c b/app/paint/gimpperspectiveclone.c
index 1759e87240..29bf79d91a 100644
--- a/app/paint/gimpperspectiveclone.c
+++ b/app/paint/gimpperspectiveclone.c
@@ -144,7 +144,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", drawables->data, NULL);
+ g_object_set (source_core, "src-drawables", drawables, NULL);
source_core->src_x = floor (coords->x);
source_core->src_y = floor (coords->y);
@@ -192,7 +192,7 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core,
* Otherwise, we need a call to get_orig_image to make sure
* we get a copy of the unblemished (offset) image
*/
- src_pickable = GIMP_PICKABLE (source_core->src_drawable);
+ src_pickable = GIMP_PICKABLE (source_core->src_drawables->data);
src_image = gimp_pickable_get_image (src_pickable);
if (sample_merged)
diff --git a/app/paint/gimpsourcecore.c b/app/paint/gimpsourcecore.c
index 9a6e705599..151a3beb31 100644
--- a/app/paint/gimpsourcecore.c
+++ b/app/paint/gimpsourcecore.c
@@ -28,10 +28,12 @@
#include "gegl/gimp-gegl-utils.h"
#include "core/gimp.h"
+#include "core/gimpcontainer.h"
#include "core/gimpdrawable.h"
#include "core/gimpdynamics.h"
#include "core/gimperror.h"
#include "core/gimpimage.h"
+#include "core/gimpimage-new.h"
#include "core/gimppickable.h"
#include "core/gimpsymmetry.h"
@@ -44,12 +46,13 @@
enum
{
PROP_0,
- PROP_SRC_DRAWABLE,
+ PROP_SRC_DRAWABLES,
PROP_SRC_X,
PROP_SRC_Y
};
+static void gimp_source_core_finalize (GObject *object);
static void gimp_source_core_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -99,7 +102,8 @@ static GeglBuffer *
GeglRectangle *src_rect);
static void gimp_source_core_set_src_drawable (GimpSourceCore *source_core,
- GimpDrawable *drawable);
+ GList *drawables);
+static void gimp_source_core_make_pickable (GimpSourceCore *source_core);
G_DEFINE_TYPE (GimpSourceCore, gimp_source_core, GIMP_TYPE_BRUSH_CORE)
@@ -114,6 +118,7 @@ gimp_source_core_class_init (GimpSourceCoreClass *klass)
GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass);
+ object_class->finalize = gimp_source_core_finalize;
object_class->set_property = gimp_source_core_set_property;
object_class->get_property = gimp_source_core_get_property;
@@ -126,11 +131,10 @@ gimp_source_core_class_init (GimpSourceCoreClass *klass)
klass->get_source = gimp_source_core_real_get_source;
klass->motion = NULL;
- g_object_class_install_property (object_class, PROP_SRC_DRAWABLE,
- g_param_spec_object ("src-drawable",
- NULL, NULL,
- GIMP_TYPE_DRAWABLE,
- GIMP_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_SRC_DRAWABLES,
+ g_param_spec_pointer ("src-drawables",
+ NULL, NULL,
+ GIMP_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_SRC_X,
g_param_spec_int ("src-x", NULL, NULL,
@@ -148,18 +152,29 @@ gimp_source_core_class_init (GimpSourceCoreClass *klass)
static void
gimp_source_core_init (GimpSourceCore *source_core)
{
- source_core->set_source = FALSE;
+ source_core->set_source = FALSE;
- source_core->src_drawable = NULL;
- source_core->src_x = 0;
- source_core->src_y = 0;
+ source_core->src_drawables = NULL;
+ source_core->src_x = 0;
+ source_core->src_y = 0;
- source_core->orig_src_x = 0;
- source_core->orig_src_y = 0;
+ source_core->orig_src_x = 0;
+ source_core->orig_src_y = 0;
- source_core->offset_x = 0;
- source_core->offset_y = 0;
- source_core->first_stroke = TRUE;
+ source_core->offset_x = 0;
+ source_core->offset_y = 0;
+ source_core->first_stroke = TRUE;
+}
+
+static void
+gimp_source_core_finalize (GObject *object)
+{
+ GimpSourceCore *source_core = GIMP_SOURCE_CORE (object);
+
+ g_clear_object (&source_core->src_image);
+ g_clear_pointer (&source_core->src_drawables, g_list_free);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
@@ -172,9 +187,9 @@ gimp_source_core_set_property (GObject *object,
switch (property_id)
{
- case PROP_SRC_DRAWABLE:
+ case PROP_SRC_DRAWABLES:
gimp_source_core_set_src_drawable (source_core,
- g_value_get_object (value));
+ g_value_get_pointer (value));
break;
case PROP_SRC_X:
source_core->src_x = g_value_get_int (value);
@@ -198,8 +213,8 @@ gimp_source_core_get_property (GObject *object,
switch (property_id)
{
- case PROP_SRC_DRAWABLE:
- g_value_set_object (value, source_core->src_drawable);
+ case PROP_SRC_DRAWABLES:
+ g_value_set_pointer (value, source_core->src_drawables);
break;
case PROP_SRC_X:
g_value_set_int (value, source_core->src_x);
@@ -235,7 +250,7 @@ gimp_source_core_start (GimpPaintCore *paint_core,
if (! source_core->set_source &&
gimp_source_core_use_source (source_core, options))
{
- if (! source_core->src_drawable)
+ if (! source_core->src_drawables)
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
_("Set a source image first."));
@@ -244,7 +259,7 @@ gimp_source_core_start (GimpPaintCore *paint_core,
if (options->sample_merged &&
g_list_length (drawables) == 1 &&
- gimp_item_get_image (GIMP_ITEM (source_core->src_drawable)) ==
+ gimp_item_get_image (GIMP_ITEM (source_core->src_drawables->data)) ==
gimp_item_get_image (GIMP_ITEM (drawables->data)))
{
paint_core->use_saved_proj = TRUE;
@@ -274,7 +289,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, drawables->data);
+ gimp_source_core_set_src_drawable (source_core, drawables);
/* FIXME(?): subpixel source sampling */
source_core->src_x = floor (coords->x);
@@ -289,6 +304,8 @@ gimp_source_core_paint (GimpPaintCore *paint_core,
source_core->first_stroke = TRUE;
}
+
+ gimp_source_core_make_pickable (source_core);
break;
case GIMP_PAINT_STATE_MOTION:
@@ -411,16 +428,15 @@ gimp_source_core_motion (GimpSourceCore *source_core,
if (gimp_source_core_use_source (source_core, options))
{
- src_pickable = GIMP_PICKABLE (source_core->src_drawable);
-
if (self_drawable)
{
src_pickable = GIMP_PICKABLE (drawable);
}
else if (options->sample_merged)
{
- GimpImage *src_image = gimp_pickable_get_image (src_pickable);
- gint off_x, off_y;
+ GimpImage *src_image;
+
+ src_image = gimp_pickable_get_image (source_core->src_drawables->data);
if (! gimp_paint_core_get_show_all (paint_core))
{
@@ -428,15 +444,12 @@ gimp_source_core_motion (GimpSourceCore *source_core,
}
else
{
- src_pickable = GIMP_PICKABLE (
- gimp_image_get_projection (src_image));
+ src_pickable = GIMP_PICKABLE (gimp_image_get_projection (src_image));
}
-
- gimp_item_get_offset (GIMP_ITEM (source_core->src_drawable),
- &off_x, &off_y);
-
- base_src_offset_x += off_x;
- base_src_offset_y += off_y;
+ }
+ else
+ {
+ src_pickable = source_core->src_pickable;
}
}
@@ -638,7 +651,8 @@ gimp_source_core_real_get_source (GimpSourceCore *source_core,
* we get a copy of the unblemished (offset) image
*/
if (( sample_merged && (src_image != image)) ||
- (! sample_merged && (source_core->src_drawable != drawable)))
+ (! sample_merged && (g_list_length (source_core->src_drawables) != 1 ||
+ source_core->src_drawables->data != drawable)))
{
dest_buffer = src_buffer;
}
@@ -666,10 +680,7 @@ static void
gimp_source_core_src_drawable_removed (GimpDrawable *drawable,
GimpSourceCore *source_core)
{
- if (drawable == source_core->src_drawable)
- {
- source_core->src_drawable = NULL;
- }
+ source_core->src_drawables = g_list_remove (source_core->src_drawables, drawable);
g_signal_handlers_disconnect_by_func (drawable,
gimp_source_core_src_drawable_removed,
@@ -678,22 +689,84 @@ gimp_source_core_src_drawable_removed (GimpDrawable *drawable,
static void
gimp_source_core_set_src_drawable (GimpSourceCore *source_core,
- GimpDrawable *drawable)
+ GList *drawables)
{
- if (source_core->src_drawable == drawable)
- return;
+ GimpImage *image = NULL;
+ GList *iter;
+
+ if (g_list_length (source_core->src_drawables) == g_list_length (drawables))
+ {
+ GList *iter2;
+
+ for (iter = source_core->src_drawables, iter2 = drawables;
+ iter; iter = iter->next, iter2 = iter2->next)
+ {
+ if (iter->data != iter2->data)
+ break;
+ }
+ if (iter == NULL)
+ return;
+ }
+ for (GList *iter = drawables; iter; iter = iter->next)
+ {
+ /* Make sure all drawables are from the same image. */
+ if (image == NULL)
+ image = gimp_item_get_image (GIMP_ITEM (iter->data));
+ else
+ g_return_if_fail (image == gimp_item_get_image (GIMP_ITEM (iter->data)));
+ }
+
+ if (source_core->src_drawables)
+ {
+ for (GList *iter = source_core->src_drawables; iter; iter = iter->next)
+ g_signal_handlers_disconnect_by_func (iter->data,
+ gimp_source_core_src_drawable_removed,
+ source_core);
- if (source_core->src_drawable)
- g_signal_handlers_disconnect_by_func (source_core->src_drawable,
- gimp_source_core_src_drawable_removed,
- source_core);
+ g_list_free (source_core->src_drawables);
+ }
+
+ source_core->src_drawables = g_list_copy (drawables);
- source_core->src_drawable = drawable;
+ if (source_core->src_drawables)
+ {
+ for (GList *iter = source_core->src_drawables; iter; iter = iter->next)
+ g_signal_connect (iter->data, "removed",
+ G_CALLBACK (gimp_source_core_src_drawable_removed),
+ source_core);
+ }
- if (source_core->src_drawable)
- g_signal_connect (source_core->src_drawable, "removed",
- G_CALLBACK (gimp_source_core_src_drawable_removed),
- source_core);
+ g_object_notify (G_OBJECT (source_core), "src-drawables");
+}
- g_object_notify (G_OBJECT (source_core), "src-drawable");
+static void
+gimp_source_core_make_pickable (GimpSourceCore *source_core)
+{
+ g_clear_object (&source_core->src_image);
+ source_core->src_pickable = NULL;
+
+ if (source_core->src_drawables)
+ {
+ GimpImage *image;
+
+ image = gimp_item_get_image (GIMP_ITEM (source_core->src_drawables->data));
+
+ if (g_list_length (source_core->src_drawables) > 1)
+ {
+ /* A composited projection of src_drawables as if they were on
+ * their own in the image. Some kind of sample_merged limited
+ * to these drawables.
+ */
+ source_core->src_image = gimp_image_new_from_drawables (image->gimp, source_core->src_drawables,
+ FALSE);
+ gimp_container_remove (image->gimp->images, GIMP_OBJECT (source_core->src_image));
+
+ source_core->src_pickable = GIMP_PICKABLE (source_core->src_image);
+ gimp_pickable_flush (source_core->src_pickable);
+ }
+ else
+ {
+ source_core->src_pickable = GIMP_PICKABLE (source_core->src_drawables->data);
+ }
+ }
}
diff --git a/app/paint/gimpsourcecore.h b/app/paint/gimpsourcecore.h
index 6954e44a86..f662216ada 100644
--- a/app/paint/gimpsourcecore.h
+++ b/app/paint/gimpsourcecore.h
@@ -38,10 +38,14 @@ struct _GimpSourceCore
gboolean set_source;
- GimpDrawable *src_drawable;
+ GList *src_drawables;
gint src_x;
gint src_y;
+ /* The pickable to use when not in sample merged mode. */
+ GimpPickable *src_pickable;
+ GimpImage *src_image;
+
gint orig_src_x;
gint orig_src_y;
diff --git a/app/pdb/paint-tools-cmds.c b/app/pdb/paint-tools-cmds.c
index f37a72e737..c8a1ae7ba2 100644
--- a/app/pdb/paint-tools-cmds.c
+++ b/app/pdb/paint-tools-cmds.c
@@ -228,7 +228,10 @@ clone_invoker (GimpProcedure *procedure,
GIMP_PDB_ITEM_CONTENT, error) &&
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
+ GList *src_drawables;
+
options = gimp_config_duplicate (GIMP_CONFIG (options));
+ src_drawables = g_list_prepend (NULL, src_drawable);
g_object_set (options,
"clone-type", clone_type,
@@ -236,11 +239,12 @@ clone_invoker (GimpProcedure *procedure,
success = paint_tools_stroke (gimp, context, options, drawable,
num_strokes, strokes, error,
- "undo-desc", options->paint_info->blurb,
- "src-drawable", src_drawable,
- "src-x", (gint) floor (src_x),
- "src-y", (gint) floor (src_y),
+ "undo-desc", options->paint_info->blurb,
+ "src-drawables", src_drawables,
+ "src-x", (gint) floor (src_x),
+ "src-y", (gint) floor (src_y),
NULL);
+ g_list_free (src_drawables);
}
else
success = FALSE;
@@ -615,15 +619,19 @@ heal_invoker (GimpProcedure *procedure,
GIMP_PDB_ITEM_CONTENT, error) &&
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
+ GList *src_drawables;
+
options = gimp_config_duplicate (GIMP_CONFIG (options));
+ src_drawables = g_list_prepend (NULL, src_drawable);
success = paint_tools_stroke (gimp, context, options, drawable,
num_strokes, strokes, error,
- "undo-desc", options->paint_info->blurb,
- "src-drawable", src_drawable,
- "src-x", (gint) floor (src_x),
- "src-y", (gint) floor (src_y),
+ "undo-desc", options->paint_info->blurb,
+ "src-drawables", src_drawables,
+ "src-x", (gint) floor (src_x),
+ "src-y", (gint) floor (src_y),
NULL);
+ g_list_free (src_drawables);
}
else
success = FALSE;
diff --git a/app/tools/gimpperspectiveclonetool.c b/app/tools/gimpperspectiveclonetool.c
index b59d3a9869..f1567eadaa 100644
--- a/app/tools/gimpperspectiveclonetool.c
+++ b/app/tools/gimpperspectiveclonetool.c
@@ -566,7 +566,7 @@ gimp_perspective_clone_tool_cursor_update (GimpTool *tool,
{
cursor = GIMP_CURSOR_CROSSHAIR_SMALL;
}
- else if (! GIMP_SOURCE_CORE (GIMP_PAINT_TOOL (tool)->core)->src_drawable)
+ else if (! GIMP_SOURCE_CORE (GIMP_PAINT_TOOL (tool)->core)->src_drawables)
{
modifier = GIMP_CURSOR_MODIFIER_BAD;
}
@@ -624,7 +624,7 @@ gimp_perspective_clone_tool_oper_update (GimpTool *tool,
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (core);
GimpSourceCore *source_core = GIMP_SOURCE_CORE (core);
- if (source_core->src_drawable == NULL)
+ if (source_core->src_drawables == NULL)
{
gimp_tool_replace_status (tool, display,
_("Ctrl-Click to set a clone source"));
@@ -759,7 +759,7 @@ gimp_perspective_clone_tool_draw (GimpDrawTool *draw_tool)
gimp_draw_tool_pop_group (draw_tool);
}
- if (source_core->src_drawable && clone_tool->src_display)
+ if (source_core->src_drawables && clone_tool->src_display)
{
GimpDisplay *tmp_display;
@@ -788,7 +788,7 @@ gimp_perspective_clone_tool_halt (GimpPerspectiveCloneTool *clone_tool)
clone_tool->src_display = NULL;
g_object_set (GIMP_PAINT_TOOL (tool)->core,
- "src-drawable", NULL,
+ "src-drawables", NULL,
NULL);
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool)))
diff --git a/app/tools/gimpsourcetool.c b/app/tools/gimpsourcetool.c
index b2c5f6d44d..34f505e627 100644
--- a/app/tools/gimpsourcetool.c
+++ b/app/tools/gimpsourcetool.c
@@ -168,7 +168,7 @@ gimp_source_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
gimp_source_tool_set_src_display (source_tool, NULL);
g_object_set (GIMP_PAINT_TOOL (tool)->core,
- "src-drawable", NULL,
+ "src-drawables", NULL,
NULL);
break;
@@ -302,7 +302,7 @@ gimp_source_tool_cursor_update (GimpTool *tool,
{
cursor = GIMP_CURSOR_CROSSHAIR_SMALL;
}
- else if (! GIMP_SOURCE_CORE (GIMP_PAINT_TOOL (tool)->core)->src_drawable)
+ else if (! GIMP_SOURCE_CORE (GIMP_PAINT_TOOL (tool)->core)->src_drawables)
{
modifier = GIMP_CURSOR_MODIFIER_BAD;
}
@@ -341,7 +341,7 @@ gimp_source_tool_oper_update (GimpTool *tool,
if (gimp_source_core_use_source (source, options))
{
- if (source->src_drawable == NULL)
+ if (source->src_drawables == NULL)
{
GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask ();
@@ -400,20 +400,16 @@ gimp_source_tool_draw (GimpDrawTool *draw_tool)
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
if (gimp_source_core_use_source (source, options) &&
- source->src_drawable && source_tool->src_display)
+ source->src_drawables && source_tool->src_display)
{
GimpDisplayShell *src_shell;
- gint off_x;
- gint off_y;
gdouble src_x;
gdouble src_y;
src_shell = gimp_display_get_shell (source_tool->src_display);
- gimp_item_get_offset (GIMP_ITEM (source->src_drawable), &off_x, &off_y);
-
- src_x = source_tool->src_x + off_x + 0.5;
- src_y = source_tool->src_y + off_y + 0.5;
+ src_x = source_tool->src_x + 0.5;
+ src_y = source_tool->src_y + 0.5;
if (source_tool->src_outline)
{
diff --git a/pdb/groups/paint_tools.pdb b/pdb/groups/paint_tools.pdb
index 227ea80c4e..52ad2d5b27 100644
--- a/pdb/groups/paint_tools.pdb
+++ b/pdb/groups/paint_tools.pdb
@@ -172,7 +172,10 @@ HELP
GIMP_PDB_ITEM_CONTENT, error) &&
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
+ GList *src_drawables;
+
options = gimp_config_duplicate (GIMP_CONFIG (options));
+ src_drawables = g_list_prepend (NULL, src_drawable);
g_object_set (options,
"clone-type", clone_type,
@@ -180,11 +183,12 @@ HELP
success = paint_tools_stroke (gimp, context, options, drawable,
num_strokes, strokes, error,
- "undo-desc", options->paint_info->blurb,
- "src-drawable", src_drawable,
- "src-x", (gint) floor (src_x),
- "src-y", (gint) floor (src_y),
+ "undo-desc", options->paint_info->blurb,
+ "src-drawables", src_drawables,
+ "src-x", (gint) floor (src_x),
+ "src-y", (gint) floor (src_y),
NULL);
+ g_list_free (src_drawables);
}
else
success = FALSE;
@@ -531,15 +535,19 @@ HELP
GIMP_PDB_ITEM_CONTENT, error) &&
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
+ GList *src_drawables;
+
options = gimp_config_duplicate (GIMP_CONFIG (options));
+ src_drawables = g_list_prepend (NULL, src_drawable);
success = paint_tools_stroke (gimp, context, options, drawable,
num_strokes, strokes, error,
- "undo-desc", options->paint_info->blurb,
- "src-drawable", src_drawable,
- "src-x", (gint) floor (src_x),
- "src-y", (gint) floor (src_y),
+ "undo-desc", options->paint_info->blurb,
+ "src-drawables", src_drawables,
+ "src-x", (gint) floor (src_x),
+ "src-y", (gint) floor (src_y),
NULL);
+ g_list_free (src_drawables);
}
else
success = FALSE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]