[gimp] app: add "Preview linked items" option to transform tools
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add "Preview linked items" option to transform tools
- Date: Sat, 18 Jan 2020 13:19:12 +0000 (UTC)
commit d24713349d0456f5f29b317d2d3b47eb278f2f5b
Author: Ell <ell_se yahoo com>
Date: Sat Jan 18 15:11:51 2020 +0200
app: add "Preview linked items" option to transform tools
Add a new "Preview linked items" option to the transform-grid
tools. When this option is enabled, together with composited
previews, the transform preview includes all linked layers/channels
when transforming a layer/channel. Note that paths aren't included
for now.
Ultimately, we'd probably want to cut down on the various preview
options and enable this by default, but let's make this optional
for now.
This commit also improves composited-preview clipping in some
cases.
app/tools/gimptransformgridoptions.c | 25 +++++-
app/tools/gimptransformgridoptions.h | 1 +
app/tools/gimptransformgridtool.c | 170 +++++++++++++++++++++++++++++------
app/tools/gimptransformgridtool.h | 4 +-
4 files changed, 170 insertions(+), 30 deletions(-)
---
diff --git a/app/tools/gimptransformgridoptions.c b/app/tools/gimptransformgridoptions.c
index f1c0bedbd5..f91376904d 100644
--- a/app/tools/gimptransformgridoptions.c
+++ b/app/tools/gimptransformgridoptions.c
@@ -51,6 +51,7 @@ enum
PROP_DIRECTION_LINKED,
PROP_SHOW_PREVIEW,
PROP_COMPOSITED_PREVIEW,
+ PROP_PREVIEW_LINKED,
PROP_SYNCHRONOUS_PREVIEW,
PROP_PREVIEW_OPACITY,
PROP_GRID_TYPE,
@@ -120,6 +121,13 @@ gimp_transform_grid_options_class_init (GimpTransformGridOptionsClass *klass)
FALSE,
GIMP_PARAM_STATIC_STRINGS);
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_PREVIEW_LINKED,
+ "preview-linked",
+ _("Preview linked items"),
+ _("Include linked items in the preview"),
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
+
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SYNCHRONOUS_PREVIEW,
"synchronous-preview",
_("Synchronous preview"),
@@ -247,6 +255,9 @@ gimp_transform_grid_options_set_property (GObject *object,
case PROP_COMPOSITED_PREVIEW:
options->composited_preview = g_value_get_boolean (value);
break;
+ case PROP_PREVIEW_LINKED:
+ options->preview_linked = g_value_get_boolean (value);
+ break;
case PROP_SYNCHRONOUS_PREVIEW:
options->synchronous_preview = g_value_get_boolean (value);
break;
@@ -318,6 +329,9 @@ gimp_transform_grid_options_get_property (GObject *object,
case PROP_COMPOSITED_PREVIEW:
g_value_set_boolean (value, options->composited_preview);
break;
+ case PROP_PREVIEW_LINKED:
+ g_value_set_boolean (value, options->preview_linked);
+ break;
case PROP_SYNCHRONOUS_PREVIEW:
g_value_set_boolean (value, options->synchronous_preview);
break;
@@ -381,6 +395,7 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
GimpTransformGridToolClass *tg_class;
GtkWidget *vbox;
GtkWidget *vbox2;
+ GtkWidget *vbox3;
GtkWidget *button;
GtkWidget *frame;
GtkWidget *combo;
@@ -427,10 +442,18 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
/* the preview frame */
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+ vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+
+ button = gimp_prop_check_button_new (config, "preview-linked", NULL);
+ gtk_box_pack_start (GTK_BOX (vbox3), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
button = gimp_prop_check_button_new (config, "synchronous-preview", NULL);
+ gtk_box_pack_start (GTK_BOX (vbox3), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
frame = gimp_prop_expanding_frame_new (config, "composited-preview", NULL,
- button, NULL);
+ vbox3, NULL);
gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
diff --git a/app/tools/gimptransformgridoptions.h b/app/tools/gimptransformgridoptions.h
index 5f493e4777..48d2edc0d2 100644
--- a/app/tools/gimptransformgridoptions.h
+++ b/app/tools/gimptransformgridoptions.h
@@ -40,6 +40,7 @@ struct _GimpTransformGridOptions
gboolean direction_linked;
gboolean show_preview;
gboolean composited_preview;
+ gboolean preview_linked;
gboolean synchronous_preview;
gdouble preview_opacity;
GimpGuidesType grid_type;
diff --git a/app/tools/gimptransformgridtool.c b/app/tools/gimptransformgridtool.c
index d0dd3313f3..da3d669bcb 100644
--- a/app/tools/gimptransformgridtool.c
+++ b/app/tools/gimptransformgridtool.c
@@ -40,6 +40,7 @@
#include "core/gimpfilter.h"
#include "core/gimpgrouplayer.h"
#include "core/gimpimage.h"
+#include "core/gimpimage-item-list.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimplayer.h"
@@ -85,7 +86,7 @@ typedef struct
GimpDrawable *drawable;
GimpDrawableFilter *filter;
- GimpDrawable *clip_drawable;
+ GimpDrawable *root_drawable;
GeglNode *transform_node;
GeglNode *crop_node;
@@ -94,6 +95,12 @@ typedef struct
GeglRectangle bounds;
} Filter;
+typedef struct
+{
+ GimpTransformGridTool *tg_tool;
+ GimpDrawable *root_drawable;
+} AddFilterData;
+
typedef struct
{
gint64 time;
@@ -184,6 +191,10 @@ static void gimp_transform_grid_tool_widget_response (GimpToolWidget
static void gimp_transform_grid_tool_filter_flush (GimpDrawableFilter *filter,
GimpTransformGridTool *tg_tool);
+static void gimp_transform_grid_tool_image_linked_items_changed
+ (GimpImage *image,
+ GimpTransformGridTool *tg_tool);
+
static void gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_commit (GimpTransformGridTool *tg_tool);
@@ -201,12 +212,13 @@ static void gimp_transform_grid_tool_response (GimpToolGui
static gboolean gimp_transform_grid_tool_composited_preview (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool);
+static void gimp_transform_grid_tool_update_filters (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_hide_active_object (GimpTransformGridTool *tg_tool,
GimpObject *object);
static void gimp_transform_grid_tool_show_active_object (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
- GimpTransformGridTool *tg_tool);
+ AddFilterData *data);
static void gimp_transform_grid_tool_remove_filter (GimpDrawable *drawable,
GimpTransformGridTool *tg_tool);
@@ -216,6 +228,7 @@ static void gimp_transform_grid_tool_effective_mode_changed
static Filter * filter_new (GimpTransformGridTool *tg_tool,
GimpDrawable *drawable,
+ GimpDrawable *root_drawable,
gboolean add_filter);
static void filter_free (Filter *filter);
@@ -371,6 +384,11 @@ gimp_transform_grid_tool_initialize (GimpTool *tool,
memcpy (undo_info->trans_infos, tg_tool->trans_infos,
sizeof (tg_tool->trans_infos));
+ g_signal_connect (
+ image, "linked-items-changed",
+ G_CALLBACK (gimp_transform_grid_tool_image_linked_items_changed),
+ tg_tool);
+
return TRUE;
}
@@ -690,6 +708,12 @@ gimp_transform_grid_tool_options_notify (GimpTool *tool,
gimp_transform_grid_tool_update_preview (tg_tool);
}
}
+ else if (! strcmp (pspec->name, "preview-linked") &&
+ tg_tool->filters)
+ {
+ gimp_transform_grid_tool_update_filters (tg_tool);
+ gimp_transform_grid_tool_update_preview (tg_tool);
+ }
else if (! strcmp (pspec->name, "interpolation") ||
! strcmp (pspec->name, "clip") ||
! strcmp (pspec->name, "preview-opacity"))
@@ -1111,12 +1135,33 @@ gimp_transform_grid_tool_filter_flush (GimpDrawableFilter *filter,
gimp_projection_flush (gimp_image_get_projection (image));
}
+static void
+gimp_transform_grid_tool_image_linked_items_changed (GimpImage *image,
+ GimpTransformGridTool *tg_tool)
+{
+ if (tg_tool->filters)
+ {
+ gimp_transform_grid_tool_update_filters (tg_tool);
+ gimp_transform_grid_tool_update_preview (tg_tool);
+ }
+}
+
static void
gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
{
GimpTool *tool = GIMP_TOOL (tg_tool);
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
+ if (tool->display)
+ {
+ GimpImage *image = gimp_display_get_image (tool->display);
+
+ g_signal_handlers_disconnect_by_func (
+ image,
+ gimp_transform_grid_tool_image_linked_items_changed,
+ tg_tool);
+ }
+
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tg_tool)))
gimp_draw_tool_stop (GIMP_DRAW_TOOL (tg_tool));
@@ -1124,6 +1169,7 @@ gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
g_clear_object (&tg_tool->widget);
g_clear_pointer (&tg_tool->filters, g_hash_table_unref);
+ g_clear_pointer (&tg_tool->preview_drawables, g_list_free);
if (tg_tool->gui)
gimp_tool_gui_hide (tg_tool->gui);
@@ -1506,6 +1552,9 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
gint i;
+ if (! tool->display)
+ return;
+
if (tg_options->show_preview &&
gimp_transform_grid_tool_composited_preview (tg_tool) &&
tr_tool->transform_valid)
@@ -1521,7 +1570,7 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) filter_free);
- gimp_transform_grid_tool_add_filter (tool->drawable, tg_tool);
+ gimp_transform_grid_tool_update_filters (tg_tool);
}
g_hash_table_iter_init (&iter, tg_tool->filters);
@@ -1534,6 +1583,8 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
GeglRectangle bounds;
gint offset_x;
gint offset_y;
+ gint width;
+ gint height;
gint x1, y1;
gint x2, y2;
gboolean update = FALSE;
@@ -1543,6 +1594,9 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y);
+ width = gimp_item_get_width (GIMP_ITEM (drawable));
+ height = gimp_item_get_height (GIMP_ITEM (drawable));
+
gimp_matrix3_identity (&transform);
gimp_matrix3_translate (&transform, +offset_x, +offset_y);
gimp_matrix3_mult (&tr_tool->transform, &transform);
@@ -1550,12 +1604,12 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
gimp_transform_resize_boundary (&tr_tool->transform,
gimp_item_get_clip (
- GIMP_ITEM (filter->clip_drawable),
+ GIMP_ITEM (filter->root_drawable),
tr_options->clip),
- tr_tool->x1, tr_tool->y1,
- tr_tool->x2, tr_tool->y2,
- &x1, &y1,
- &x2, &y2);
+ offset_x, offset_y,
+ offset_x + width, offset_y + height,
+ &x1, &y1,
+ &x2, &y2);
bounds.x = x1 - offset_x;
bounds.y = y1 - offset_y;
@@ -1627,6 +1681,7 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
else
{
g_clear_pointer (&tg_tool->filters, g_hash_table_unref);
+ g_clear_pointer (&tg_tool->preview_drawables, g_list_free);
}
if (tg_tool->preview)
@@ -1687,6 +1742,68 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
}
}
+static void
+gimp_transform_grid_tool_update_filters (GimpTransformGridTool *tg_tool)
+{
+ GimpTool *tool = GIMP_TOOL (tg_tool);
+ GimpTransformGridOptions *options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
+ GHashTable *new_drawables;
+ GList *drawables;
+ GList *iter;
+ GimpDrawable *drawable;
+ GHashTableIter hash_iter;
+
+ if (! tg_tool->filters)
+ return;
+
+ if (options->preview_linked &&
+ gimp_item_get_linked (GIMP_ITEM (tool->drawable)))
+ {
+ GimpImage *image = gimp_display_get_image (tool->display);
+
+ drawables = gimp_image_item_list_get_list (image,
+ GIMP_ITEM_TYPE_LAYERS |
+ GIMP_ITEM_TYPE_CHANNELS,
+ GIMP_ITEM_SET_LINKED);
+
+ drawables = gimp_image_item_list_filter (drawables);
+ }
+ else
+ {
+ drawables = g_list_prepend (NULL, tool->drawable);
+ }
+
+ new_drawables = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ for (iter = drawables; iter; iter = g_list_next (iter))
+ g_hash_table_add (new_drawables, iter->data);
+
+ for (iter = tg_tool->preview_drawables; iter; iter = g_list_next (iter))
+ {
+ drawable = iter->data;
+
+ if (! g_hash_table_remove (new_drawables, drawable))
+ gimp_transform_grid_tool_remove_filter (drawable, tg_tool);
+ }
+
+ g_hash_table_iter_init (&hash_iter, new_drawables);
+
+ while (g_hash_table_iter_next (&hash_iter, (gpointer *) &drawable, NULL))
+ {
+ AddFilterData data;
+
+ data.tg_tool = tg_tool;
+ data.root_drawable = drawable;
+
+ gimp_transform_grid_tool_add_filter (drawable, &data);
+ }
+
+ g_hash_table_unref (new_drawables);
+
+ g_list_free (tg_tool->preview_drawables);
+ tg_tool->preview_drawables = drawables;
+}
+
static void
gimp_transform_grid_tool_hide_active_object (GimpTransformGridTool *tg_tool,
GimpObject *object)
@@ -1750,8 +1867,8 @@ gimp_transform_grid_tool_show_active_object (GimpTransformGridTool *tg_tool)
}
static void
-gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
- GimpTransformGridTool *tg_tool)
+gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
+ AddFilterData *data)
{
Filter *filter;
GimpLayerMode mode = GIMP_LAYER_MODE_NORMAL;
@@ -1764,39 +1881,29 @@ gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
if (mode != GIMP_LAYER_MODE_PASS_THROUGH)
{
- filter = filter_new (tg_tool, drawable, TRUE);
+ filter = filter_new (data->tg_tool, drawable, data->root_drawable, TRUE);
}
else
{
GimpContainer *container;
- filter = filter_new (tg_tool, drawable, FALSE);
+ filter = filter_new (data->tg_tool, drawable, data->root_drawable, FALSE);
container = gimp_viewable_get_children (GIMP_VIEWABLE (drawable));
gimp_container_foreach (container,
(GFunc) gimp_transform_grid_tool_add_filter,
- tg_tool);
+ data);
}
- filter->clip_drawable = drawable;
-
- g_hash_table_insert (tg_tool->filters, drawable, filter);
+ g_hash_table_insert (data->tg_tool->filters, drawable, filter);
if (GIMP_IS_LAYER (drawable))
{
GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));
if (mask)
- {
- Filter *mask_filter;
-
- gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (mask), tg_tool);
-
- mask_filter = g_hash_table_lookup (tg_tool->filters, mask);
-
- mask_filter->clip_drawable = drawable;
- }
+ gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (mask), data);
}
}
@@ -1844,8 +1951,13 @@ gimp_transform_grid_tool_effective_mode_changed (GimpLayer *layer,
if (old_pass_through != new_pass_through)
{
+ AddFilterData data;
+
+ data.tg_tool = tg_tool;
+ data.root_drawable = filter->root_drawable;
+
gimp_transform_grid_tool_remove_filter (GIMP_DRAWABLE (layer), tg_tool);
- gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (layer), tg_tool);
+ gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (layer), &data);
gimp_transform_grid_tool_update_preview (tg_tool);
}
@@ -1854,6 +1966,7 @@ gimp_transform_grid_tool_effective_mode_changed (GimpLayer *layer,
static Filter *
filter_new (GimpTransformGridTool *tg_tool,
GimpDrawable *drawable,
+ GimpDrawable *root_drawable,
gboolean add_filter)
{
Filter *filter = g_slice_new0 (Filter);
@@ -1861,8 +1974,9 @@ filter_new (GimpTransformGridTool *tg_tool,
GeglNode *input_node;
GeglNode *output_node;
- filter->tg_tool = tg_tool;
- filter->drawable = drawable;
+ filter->tg_tool = tg_tool;
+ filter->drawable = drawable;
+ filter->root_drawable = root_drawable;
if (add_filter)
{
diff --git a/app/tools/gimptransformgridtool.h b/app/tools/gimptransformgridtool.h
index bc3ad1e69a..cb90671db5 100644
--- a/app/tools/gimptransformgridtool.h
+++ b/app/tools/gimptransformgridtool.h
@@ -61,12 +61,14 @@ struct _GimpTransformGridTool
GimpToolWidget *widget;
GimpToolWidget *grab_widget;
- GHashTable *filters;
GimpCanvasItem *preview;
GimpCanvasItem *boundary_in;
GimpCanvasItem *boundary_out;
GPtrArray *strokes;
+ GHashTable *filters;
+ GList *preview_drawables;
+
GimpToolGui *gui;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]