[gimp] app: add "Preview linked items" option to transform tools



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]