[gimp] Bug 586462 - Layer inserts misplaced



commit eda6fa1c14777a534711fe05821ef308023fe4e7
Author: Michael Natterer <mitch gimp org>
Date:   Mon Jul 30 16:20:11 2012 +0200

    Bug 586462 - Layer inserts misplaced
    
    Another attempt to fix paste/drop positions for good.
    
    Paste/drop target is either the selected area of a drawable, the
    drawable itself, or the image:
    
    - if the paste is larger than the target, center on the target
    - if there is a viewport, and the viewport intersects with the
      target, center on the intersection
    - otherwise, center on the target
    
    Finally, if we did viewport-centered pasting, make sure the paste is
    as completely within image bounds as possible.

 app/core/gimp-edit.c               |   92 ++++++++++++++++++++++++------------
 app/display/gimpdisplayshell-dnd.c |   34 +++++++++-----
 2 files changed, 84 insertions(+), 42 deletions(-)
---
diff --git a/app/core/gimp-edit.c b/app/core/gimp-edit.c
index 8bca73d..86d8923 100644
--- a/app/core/gimp-edit.c
+++ b/app/core/gimp-edit.c
@@ -156,12 +156,13 @@ gimp_edit_paste (GimpImage    *image,
 {
   GimpLayer  *layer;
   const Babl *format;
-  gint        center_x;
-  gint        center_y;
-  gint        offset_x;
-  gint        offset_y;
+  gint        image_width;
+  gint        image_height;
   gint        width;
   gint        height;
+  gint        offset_x;
+  gint        offset_y;
+  gboolean    clamp_to_image = TRUE;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
   g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL);
@@ -187,6 +188,23 @@ gimp_edit_paste (GimpImage    *image,
   if (! layer)
     return NULL;
 
+  image_width  = gimp_image_get_width  (image);
+  image_height = gimp_image_get_height (image);
+
+  width  = gimp_item_get_width  (GIMP_ITEM (layer));
+  height = gimp_item_get_height (GIMP_ITEM (layer));
+
+  if (viewport_width  == image_width &&
+      viewport_height == image_height)
+    {
+      /* if the whole image is visible, act as if there was no viewport */
+
+      viewport_x      = 0;
+      viewport_y      = 0;
+      viewport_width  = 0;
+      viewport_height = 0;
+    }
+
   if (drawable)
     {
       /*  if pasting to a drawable  */
@@ -201,9 +219,13 @@ gimp_edit_paste (GimpImage    *image,
       have_mask = gimp_item_mask_bounds (GIMP_ITEM (drawable),
                                          &x1, &y1, &x2, &y2);
 
-      if (! have_mask         &&
-          viewport_width  > 0 &&
+      if (! have_mask         && /* if we have no mask */
+          viewport_width  > 0 && /* and we have a viewport */
           viewport_height > 0 &&
+          (width  < (x2 - x1) || /* and the paste is smaller than the target */
+           height < (y2 - y1)) &&
+
+          /* and the viewport intersects with the target */
           gimp_rectangle_intersect (viewport_x, viewport_y,
                                     viewport_width, viewport_height,
                                     off_x, off_y,
@@ -211,43 +233,53 @@ gimp_edit_paste (GimpImage    *image,
                                     &paste_x, &paste_y,
                                     &paste_width, &paste_height))
         {
-          center_x = paste_x + paste_width  / 2;
-          center_y = paste_y + paste_height / 2;
+          /*  center on the viewport  */
+
+          offset_x = paste_x + (paste_width - width)  / 2;
+          offset_y = paste_y + (paste_height- height) / 2;
         }
       else
         {
-          center_x = off_x + (x1 + x2) / 2;
-          center_y = off_y + (y1 + y2) / 2;
+          /*  otherwise center on the target  */
+
+          offset_x = off_x + ((x1 + x2) - width)  / 2;
+          offset_y = off_y + ((y1 + y2) - height) / 2;
+
+          /*  and keep it that way  */
+          clamp_to_image = FALSE;
         }
     }
-  else if (viewport_width > 0 && viewport_height > 0)
+  else if (viewport_width  > 0 &&  /* if we have a viewport */
+           viewport_height > 0 &&
+           (width  < image_width || /* and the paste is       */
+            height < image_height)) /* smaller than the image */
     {
-      /*  if we got a viewport set the offsets to the center of the viewport  */
+      /*  center on the viewport  */
 
-      center_x = viewport_x + viewport_width  / 2;
-      center_y = viewport_y + viewport_height / 2;
+      offset_x = viewport_x + (viewport_width  - width)  / 2;
+      offset_y = viewport_y + (viewport_height - height) / 2;
     }
   else
     {
-      /*  otherwise the offsets to the center of the image  */
-
-      center_x = gimp_image_get_width  (image) / 2;
-      center_y = gimp_image_get_height (image) / 2;
-    }
+      /*  otherwise center on the image  */
 
-  width  = gimp_item_get_width  (GIMP_ITEM (layer));
-  height = gimp_item_get_height (GIMP_ITEM (layer));
+      offset_x = (image_width  - width)  / 2;
+      offset_y = (image_height - height) / 2;
 
-  offset_x = center_x - width  / 2;
-  offset_y = center_y - height / 2;
+      /*  and keep it that way  */
+      clamp_to_image = FALSE;
+    }
 
-  /*  Ensure that the pasted layer is always within the image, if it
-   *  fits and aligned at top left if it doesn't. (See bug #142944).
-   */
-  offset_x = MIN (offset_x, gimp_image_get_width  (image) - width);
-  offset_y = MIN (offset_y, gimp_image_get_height (image) - height);
-  offset_x = MAX (offset_x, 0);
-  offset_y = MAX (offset_y, 0);
+  if (clamp_to_image)
+    {
+      /*  Ensure that the pasted layer is always within the image, if it
+       *  fits and aligned at top left if it doesn't. (See bug #142944).
+       */
+      offset_x = MIN (offset_x, image_width  - width);
+      offset_y = MIN (offset_y, image_height - height);
+      offset_x = MAX (offset_x, 0);
+      offset_y = MAX (offset_y, 0);
+    }
 
   gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y);
 
diff --git a/app/display/gimpdisplayshell-dnd.c b/app/display/gimpdisplayshell-dnd.c
index 259553e..cdb64e7 100644
--- a/app/display/gimpdisplayshell-dnd.c
+++ b/app/display/gimpdisplayshell-dnd.c
@@ -161,20 +161,30 @@ gimp_display_shell_dnd_init (GimpDisplayShell *shell)
  */
 static void
 gimp_display_shell_dnd_position_item (GimpDisplayShell *shell,
+                                      GimpImage        *image,
                                       GimpItem         *item)
 {
-  gint x, y;
-  gint width, height;
-  gint off_x, off_y;
+  gint item_width  = gimp_item_get_width  (item);
+  gint item_height = gimp_item_get_height (item);
 
-  gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);
-
-  gimp_item_get_offset (item, &off_x, &off_y);
+  if (item_width  >= gimp_image_get_width  (image) &&
+      item_height >= gimp_image_get_height (image))
+    {
+      gimp_item_set_offset (item,
+                            (gimp_image_get_width  (image) - item_width)  / 2,
+                            (gimp_image_get_height (image) - item_height) / 2);
+    }
+  else
+    {
+      gint x, y;
+      gint width, height;
 
-  off_x = x + (width  - gimp_item_get_width  (item)) / 2 - off_x;
-  off_y = y + (height - gimp_item_get_height (item)) / 2 - off_y;
+      gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);
 
-  gimp_item_translate (item, off_x, off_y, FALSE);
+      gimp_item_set_offset (item,
+                            x + (width  - item_width)  / 2,
+                            y + (height - item_height) / 2);
+    }
 }
 
 static void
@@ -230,7 +240,7 @@ gimp_display_shell_drop_drawable (GtkWidget    *widget,
       gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE,
                                    _("Drop New Layer"));
 
-      gimp_display_shell_dnd_position_item (shell, new_item);
+      gimp_display_shell_dnd_position_item (shell, image, new_item);
 
       gimp_item_set_visible (new_item, TRUE, FALSE);
       gimp_item_set_linked (new_item, FALSE, FALSE);
@@ -630,7 +640,7 @@ gimp_display_shell_drop_component (GtkWidget       *widget,
       gimp_image_undo_group_start (dest_image, GIMP_UNDO_GROUP_EDIT_PASTE,
                                    _("Drop New Layer"));
 
-      gimp_display_shell_dnd_position_item (shell, new_item);
+      gimp_display_shell_dnd_position_item (shell, image, new_item);
 
       gimp_image_add_layer (dest_image, new_layer,
                             GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
@@ -687,7 +697,7 @@ gimp_display_shell_drop_pixbuf (GtkWidget *widget,
       gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE,
                                    _("Drop New Layer"));
 
-      gimp_display_shell_dnd_position_item (shell, new_item);
+      gimp_display_shell_dnd_position_item (shell, image, new_item);
 
       gimp_image_add_layer (image, new_layer,
                             GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);



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