[gimp] app: add ability to clone/heal from/on multiple layers.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add ability to clone/heal from/on multiple layers.
- Date: Tue, 14 Sep 2021 16:11:59 +0000 (UTC)
commit b4d189f8efadb58aa12ddd0f698f429869acc6be
Author: Jehan <jehan girinstud io>
Date: Wed Aug 18 14:23:30 2021 +0200
app: add ability to clone/heal from/on multiple layers.
When multiple layers are selected, the "sample merged" button won't
work. In such a context, each selected layer will pick from itself into
itself.
app/paint/gimpperspectiveclone.c | 18 +++++++++-----
app/paint/gimpsourcecore.c | 30 ++++++++++++++++++-----
app/paint/gimpsourcecore.h | 2 ++
app/tools/gimpcloneoptions-gui.c | 52 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 90 insertions(+), 12 deletions(-)
---
diff --git a/app/paint/gimpperspectiveclone.c b/app/paint/gimpperspectiveclone.c
index 17fb600d88..1759e87240 100644
--- a/app/paint/gimpperspectiveclone.c
+++ b/app/paint/gimpperspectiveclone.c
@@ -58,6 +58,7 @@ static gboolean gimp_perspective_clone_use_source (GimpSourceCore *source
static GeglBuffer * gimp_perspective_clone_get_source (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpPickable *src_pickable,
gint src_offset_x,
gint src_offset_y,
@@ -131,9 +132,12 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core,
GimpCloneOptions *clone_options = GIMP_CLONE_OPTIONS (paint_options);
GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (paint_options);
const GimpCoords *coords;
+ gboolean sample_merged;
/* The source is based on the original stroke */
- coords = gimp_symmetry_get_origin (sym);
+ coords = gimp_symmetry_get_origin (sym);
+
+ sample_merged = options->sample_merged && (g_list_length (drawables) > 1);
switch (paint_state)
{
@@ -191,21 +195,21 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core,
src_pickable = GIMP_PICKABLE (source_core->src_drawable);
src_image = gimp_pickable_get_image (src_pickable);
- if (options->sample_merged)
+ if (sample_merged)
src_pickable = GIMP_PICKABLE (src_image);
dest_image = gimp_item_get_image (GIMP_ITEM (drawables->data));
- if ((options->sample_merged &&
+ if ((sample_merged &&
(src_image != dest_image)) ||
- (! options->sample_merged &&
+ (! sample_merged &&
(source_core->src_drawable != drawables->data)))
{
orig_buffer = gimp_pickable_get_buffer (src_pickable);
}
else
{
- if (options->sample_merged)
+ if (sample_merged)
orig_buffer = gimp_paint_core_get_orig_proj (paint_core);
else
orig_buffer = gimp_paint_core_get_orig_image (paint_core, drawables->data);
@@ -327,7 +331,8 @@ gimp_perspective_clone_paint (GimpPaintCore *paint_core,
}
for (GList *iter = drawables; iter; iter = iter->next)
- gimp_source_core_motion (source_core, iter->data, paint_options, sym);
+ gimp_source_core_motion (source_core, iter->data, paint_options,
+ (g_list_length (drawables) > 1), sym);
}
break;
@@ -357,6 +362,7 @@ static GeglBuffer *
gimp_perspective_clone_get_source (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpPickable *src_pickable,
gint src_offset_x,
gint src_offset_y,
diff --git a/app/paint/gimpsourcecore.c b/app/paint/gimpsourcecore.c
index 1f891a55be..9a6e705599 100644
--- a/app/paint/gimpsourcecore.c
+++ b/app/paint/gimpsourcecore.c
@@ -75,6 +75,7 @@ static void gimp_source_core_paint (GimpPaintCore *paint_core,
static void gimp_source_core_motion (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpSymmetry *sym);
#endif
@@ -84,6 +85,7 @@ static GeglBuffer *
gimp_source_core_real_get_source (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpPickable *src_pickable,
gint src_offset_x,
gint src_offset_y,
@@ -240,7 +242,8 @@ gimp_source_core_start (GimpPaintCore *paint_core,
return FALSE;
}
- if (options->sample_merged &&
+ 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 (drawables->data)))
{
@@ -331,7 +334,9 @@ gimp_source_core_paint (GimpPaintCore *paint_core,
for (GList *iter = drawables; iter; iter = iter->next)
gimp_source_core_motion (source_core, iter->data,
- paint_options, sym);
+ paint_options,
+ (g_list_length (drawables) > 1),
+ sym);
}
break;
@@ -356,6 +361,7 @@ void
gimp_source_core_motion (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpSymmetry *sym)
{
@@ -407,7 +413,11 @@ gimp_source_core_motion (GimpSourceCore *source_core,
{
src_pickable = GIMP_PICKABLE (source_core->src_drawable);
- if (options->sample_merged)
+ 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;
@@ -470,6 +480,7 @@ gimp_source_core_motion (GimpSourceCore *source_core,
GIMP_SOURCE_CORE_GET_CLASS (source_core)->get_source (source_core,
drawable,
paint_options,
+ self_drawable,
src_pickable,
src_offset_x,
src_offset_y,
@@ -579,6 +590,7 @@ static GeglBuffer *
gimp_source_core_real_get_source (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpPickable *src_pickable,
gint src_offset_x,
gint src_offset_y,
@@ -596,9 +608,15 @@ gimp_source_core_real_get_source (GimpSourceCore *source_core,
GimpImage *src_image = gimp_pickable_get_image (src_pickable);
GeglBuffer *src_buffer = gimp_pickable_get_buffer (src_pickable);
GeglBuffer *dest_buffer;
+ gboolean sample_merged;
gint x, y;
gint width, height;
+ /* As a special case, we bypass sample merged value when we request
+ * each drawable to be its own source.
+ */
+ sample_merged = options->sample_merged && (! self_drawable);
+
if (! gimp_rectangle_intersect (paint_buffer_x + src_offset_x,
paint_buffer_y + src_offset_y,
gegl_buffer_get_width (paint_buffer),
@@ -619,15 +637,15 @@ gimp_source_core_real_get_source (GimpSourceCore *source_core,
* Otherwise, we need a call to get_orig_image to make sure
* we get a copy of the unblemished (offset) image
*/
- if (( options->sample_merged && (src_image != image)) ||
- (! options->sample_merged && (source_core->src_drawable != drawable)))
+ if (( sample_merged && (src_image != image)) ||
+ (! sample_merged && (source_core->src_drawable != drawable)))
{
dest_buffer = src_buffer;
}
else
{
/* get the original image */
- if (options->sample_merged)
+ if (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),
diff --git a/app/paint/gimpsourcecore.h b/app/paint/gimpsourcecore.h
index 158920b61d..6954e44a86 100644
--- a/app/paint/gimpsourcecore.h
+++ b/app/paint/gimpsourcecore.h
@@ -60,6 +60,7 @@ struct _GimpSourceCoreClass
GeglBuffer * (* get_source) (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpPickable *src_pickable,
gint src_offset_x,
gint src_offset_y,
@@ -104,6 +105,7 @@ gboolean gimp_source_core_use_source (GimpSourceCore *source_core,
void gimp_source_core_motion (GimpSourceCore *source_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
+ gboolean self_drawable,
GimpSymmetry *sym);
diff --git a/app/tools/gimpcloneoptions-gui.c b/app/tools/gimpcloneoptions-gui.c
index 4299aeea5b..fa4fa095ea 100644
--- a/app/tools/gimpcloneoptions-gui.c
+++ b/app/tools/gimpcloneoptions-gui.c
@@ -24,6 +24,9 @@
#include "tools-types.h"
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+
#include "paint/gimpcloneoptions.h"
#include "widgets/gimpviewablebox.h"
@@ -49,6 +52,50 @@ gimp_clone_options_sync_source (GBinding *binding,
return TRUE;
}
+static void
+gimp_clone_options_gui_drawables_changed (GimpImage *image,
+ GtkWidget *button)
+{
+ GList *drawables;
+
+ drawables = gimp_image_get_selected_drawables (image);
+ gtk_widget_set_sensitive (button, (g_list_length (drawables) < 2));
+ g_list_free (drawables);
+}
+
+static void
+gimp_clone_options_gui_context_image_changed (GimpContext *context,
+ GimpImage *image,
+ GtkWidget *button)
+{
+ GimpImage *prev_image;
+
+ prev_image = g_object_get_data (G_OBJECT (button), "gimp-clone-options-gui-image");
+ if (image != prev_image)
+ {
+ if (prev_image)
+ g_signal_handlers_disconnect_by_func (prev_image,
+ G_CALLBACK (gimp_clone_options_gui_drawables_changed),
+ button);
+ if (image)
+ {
+ g_signal_connect_object (image, "selected-channels-changed",
+ G_CALLBACK (gimp_clone_options_gui_drawables_changed),
+ button, 0);
+ g_signal_connect_object (image, "selected-layers-changed",
+ G_CALLBACK (gimp_clone_options_gui_drawables_changed),
+ button, 0);
+ gimp_clone_options_gui_drawables_changed (image, button);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (button, TRUE);
+ }
+
+ g_object_set_data (G_OBJECT (button), "gimp-clone-options-gui-image", image);
+ }
+}
+
GtkWidget *
gimp_clone_options_gui (GimpToolOptions *tool_options)
{
@@ -85,6 +132,11 @@ gimp_clone_options_gui (GimpToolOptions *tool_options)
NULL,
GINT_TO_POINTER (GIMP_CLONE_IMAGE), NULL);
+ g_signal_connect (gimp_get_user_context (GIMP_CONTEXT (tool_options)->gimp),
+ "image-changed",
+ G_CALLBACK (gimp_clone_options_gui_context_image_changed),
+ button);
+
hbox = gimp_prop_pattern_box_new (NULL, GIMP_CONTEXT (tool_options),
NULL, 2,
"pattern-view-type", "pattern-view-size");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]