[gimp] app: GimpToolRectangle multi-layer aware.



commit 281f17e53c3b3dc16247f99d3e9b425af2880c2b
Author: Jehan <jehan girinstud io>
Date:   Wed Jul 29 19:01:11 2020 +0200

    app: GimpToolRectangle multi-layer aware.
    
    This fixes default constraint values when multiple layers are selected.
    In particular fixed aspect ratio defaults in Crop or Rectangle Select
    tools, in layer mode, when several layers are selected, the default
    aspect ratio is the layer's ratio if all layers have the same
    dimensions, otherwise it's the image dimension ratio.
    
    Also fixes a bug when trying to create the tool rectangle while multiple
    layers are selected (the rectangle was always of size 0 at point 0).
    
    Finally fixes the auto-shrink feature with multiple layers selected. The
    rectangle will now auto-shrink to the smallest rectangle which
    encompasses the contents of all selected drawables inside the existing
    rectangle.

 app/display/gimptoolrectangle.c | 171 ++++++++++++++++++++++++++--------------
 1 file changed, 111 insertions(+), 60 deletions(-)
---
diff --git a/app/display/gimptoolrectangle.c b/app/display/gimptoolrectangle.c
index 21f5149176..e55f6d6c76 100644
--- a/app/display/gimptoolrectangle.c
+++ b/app/display/gimptoolrectangle.c
@@ -3737,14 +3737,26 @@ gimp_tool_rectangle_get_constraints (GimpToolRectangle       *rectangle,
     case GIMP_RECTANGLE_CONSTRAIN_DRAWABLE:
       if (image)
         {
-          GimpItem *item = GIMP_ITEM (gimp_image_get_active_drawable (image));
+          GList *items = gimp_image_get_selected_drawables (image);
+          GList *iter;
 
-          if (item)
+          /* Min and max constraints are respectively the smallest and
+           * highest drawable coordinates.
+           */
+          for (iter = items; iter; iter = iter->next)
             {
-              gimp_item_get_offset (item, min_x, min_y);
-              *max_x = *min_x + gimp_item_get_width  (item);
-              *max_y = *min_y + gimp_item_get_height (item);
+              gint item_min_x;
+              gint item_min_y;
+
+              gimp_item_get_offset (iter->data, &item_min_x, &item_min_y);
+
+              *min_x = MIN (*min_x, item_min_x);
+              *min_y = MIN (*min_y, item_min_y);
+              *max_x = MAX (*max_x, item_min_x + gimp_item_get_width  (iter->data));
+              *max_y = MAX (*max_y, item_min_y + gimp_item_get_height (iter->data));
             }
+
+          g_list_free (items);
         }
       break;
 
@@ -4035,17 +4047,35 @@ gimp_tool_rectangle_constraint_size_set (GimpToolRectangle *rectangle,
         {
         case GIMP_RECTANGLE_CONSTRAIN_DRAWABLE:
           {
-            GimpItem *item = GIMP_ITEM (gimp_image_get_active_layer (image));
+            GList *items = gimp_image_get_selected_layers (image);
+            GList *iter;
 
-            if (! item)
+            width  = 0.0;
+            height = 0.0;
+            for (iter = items; iter; iter = iter->next)
               {
-                width  = 1.0;
-                height = 1.0;
+                if (width == 0.0 || height == 0.0)
+                  {
+                    width  = gimp_item_get_width  (iter->data);
+                    height = gimp_item_get_height (iter->data);
+                  }
+                else if (width  != gimp_item_get_width  (iter->data) ||
+                         height != gimp_item_get_height (iter->data))
+                  {
+                    width  = 0.0;
+                    height = 0.0;
+                    break;
+                  }
               }
-            else
+
+            /* Set constraint to the selected layers' dimensions if all
+             * selected layers have the same dimension. Otherwise set to
+             * image dimensions.
+             */
+            if (width == 0.0 || height == 0.0)
               {
-                width  = gimp_item_get_width  (item);
-                height = gimp_item_get_height (item);
+                width  = gimp_image_get_width  (image);
+                height = gimp_image_get_height (image);
               }
           }
           break;
@@ -4180,15 +4210,10 @@ gimp_tool_rectangle_auto_shrink (GimpToolRectangle *rectangle,
   GimpToolRectanglePrivate *private;
   GimpDisplayShell         *shell;
   GimpImage                *image;
-  GimpPickable             *pickable;
-  gint                      offset_x = 0;
-  gint                      offset_y = 0;
-  gint                      x1, y1;
-  gint                      x2, y2;
-  gint                      shrunk_x;
-  gint                      shrunk_y;
-  gint                      shrunk_width;
-  gint                      shrunk_height;
+  GList                    *pickables = NULL;
+  GList                    *iter;
+  gdouble                   new_x1, new_y1;
+  gdouble                   new_x2, new_y2;
 
   g_return_if_fail (GIMP_IS_TOOL_RECTANGLE (rectangle));
 
@@ -4198,58 +4223,84 @@ gimp_tool_rectangle_auto_shrink (GimpToolRectangle *rectangle,
   image = gimp_display_get_image (shell->display);
 
   if (shrink_merged)
-    {
-      pickable = GIMP_PICKABLE (image);
-
-      x1 = private->x1;
-      y1 = private->y1;
-      x2 = private->x2;
-      y2 = private->y2;
-    }
+    pickables = g_list_prepend (NULL, image);
   else
+    pickables = gimp_image_get_selected_drawables (image);
+
+  if (! pickables)
+    return;
+
+  new_x1 = new_y1 = G_MAXINT;
+  new_x2 = new_y2 = G_MININT;
+  for (iter = pickables; iter; iter = iter->next)
     {
-      pickable = GIMP_PICKABLE (gimp_image_get_active_drawable (image));
+      gint x1, y1;
+      gint x2, y2;
+      gint offset_x = 0;
+      gint offset_y = 0;
+      gint shrunk_x;
+      gint shrunk_y;
+      gint shrunk_width;
+      gint shrunk_height;
+
+      if (GIMP_IS_IMAGE (iter->data))
+        {
+          x1 = private->x1;
+          y1 = private->y1;
+          x2 = private->x2;
+          y2 = private->y2;
+        }
+      else
+        {
+          gimp_item_get_offset (GIMP_ITEM (iter->data), &offset_x, &offset_y);
 
-      if (! pickable)
-        return;
+          x1 = private->x1 - offset_x;
+          y1 = private->y1 - offset_y;
+          x2 = private->x2 - offset_x;
+          y2 = private->y2 - offset_y;
+        }
 
-      gimp_item_get_offset (GIMP_ITEM (pickable), &offset_x, &offset_y);
+      switch (gimp_pickable_auto_shrink (iter->data,
+                                         x1, y1, x2 - x1, y2 - y1,
+                                         &shrunk_x,
+                                         &shrunk_y,
+                                         &shrunk_width,
+                                         &shrunk_height))
+        {
+        case GIMP_AUTO_SHRINK_SHRINK:
+            {
+              new_x1 = MIN (new_x1, offset_x + shrunk_x);
+              new_y1 = MIN (new_y1, offset_y + shrunk_y);
+              new_x2 = MAX (new_x2, offset_x + shrunk_x + shrunk_width);
+              new_y2 = MAX (new_y2, offset_y + shrunk_y + shrunk_height);
+            }
+          break;
 
-      x1 = private->x1 - offset_x;
-      y1 = private->y1 - offset_y;
-      x2 = private->x2 - offset_x;
-      y2 = private->y2 - offset_y;
+        default:
+          break;
+        }
     }
 
-  switch (gimp_pickable_auto_shrink (pickable,
-                                     x1, y1, x2 - x1, y2 - y1,
-                                     &shrunk_x,
-                                     &shrunk_y,
-                                     &shrunk_width,
-                                     &shrunk_height))
+  if (new_x1 != G_MAXINT && new_y1 != G_MAXINT &&
+      new_x2 != G_MININT && new_y2 != G_MININT)
     {
-    case GIMP_AUTO_SHRINK_SHRINK:
-      {
-        GimpRectangleFunction original_function = private->function;
-
-        private->function = GIMP_TOOL_RECTANGLE_AUTO_SHRINK;
+      GimpRectangleFunction original_function = private->function;
 
-        private->x1 = offset_x + shrunk_x;
-        private->y1 = offset_y + shrunk_y;
-        private->x2 = offset_x + shrunk_x + shrunk_width;
-        private->y2 = offset_y + shrunk_y + shrunk_height;
+      private->function = GIMP_TOOL_RECTANGLE_AUTO_SHRINK;
 
-        gimp_tool_rectangle_update_int_rect (rectangle);
+      private->x1 = new_x1;
+      private->y1 = new_y1;
+      private->x2 = new_x2;
+      private->y2 = new_y2;
 
-        gimp_tool_rectangle_change_complete (rectangle);
+      gimp_tool_rectangle_update_int_rect (rectangle);
 
-        private->function = original_function;
+      gimp_tool_rectangle_change_complete (rectangle);
 
-        gimp_tool_rectangle_update_options (rectangle);
-      }
-      break;
+      private->function = original_function;
 
-    default:
-      break;
+      gimp_tool_rectangle_update_options (rectangle);
     }
+
+  g_list_free (pickables);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]