[gimp] app: consolidate all transform API in gimpdisplayshell-transform.[ch]



commit 37d589335faa178b6027f5bbf53b773d2aaa00d8
Author: Michael Natterer <mitch gimp org>
Date:   Thu Apr 25 00:29:58 2013 +0200

    app: consolidate all transform API in gimpdisplayshell-transform.[ch]
    
    Added complete API for zoom/unzoom (scale and scroll) and
    rotate/unrotate, with the same set of functions as the existing
    transform/untransform. Moved some special case functions to the
    namespaces they belong.

 app/display/gimpcanvasitem.c             |   11 +-
 app/display/gimpdisplayshell-draw.c      |    8 +-
 app/display/gimpdisplayshell-items.c     |   12 +-
 app/display/gimpdisplayshell-rotate.c    |   78 -----
 app/display/gimpdisplayshell-rotate.h    |   41 +--
 app/display/gimpdisplayshell-selection.c |   24 +-
 app/display/gimpdisplayshell-transform.c |  557 +++++++++++++++++++++++++++---
 app/display/gimpdisplayshell-transform.h |  106 ++++++-
 app/tools/gimpdrawtool.c                 |   20 +-
 9 files changed, 653 insertions(+), 204 deletions(-)
---
diff --git a/app/display/gimpcanvasitem.c b/app/display/gimpcanvasitem.c
index 9e1a260..e31644b 100644
--- a/app/display/gimpcanvasitem.c
+++ b/app/display/gimpcanvasitem.c
@@ -629,18 +629,12 @@ gimp_canvas_item_transform_xy (GimpCanvasItem *item,
                                gint           *ty)
 {
   GimpCanvasItemPrivate *private;
-  gint64                 nx;
-  gint64                 ny;
 
   g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
 
   private = GET_PRIVATE (item);
 
-  nx = x * private->shell->scale_x - private->shell->offset_x;
-  ny = y * private->shell->scale_y - private->shell->offset_y;
-
-  *tx = CLAMP (nx, G_MININT, G_MAXINT);
-  *ty = CLAMP (ny, G_MININT, G_MAXINT);
+  gimp_display_shell_zoom_xy (private->shell, x, y, tx, ty);
 }
 
 void
@@ -656,8 +650,7 @@ gimp_canvas_item_transform_xy_f (GimpCanvasItem *item,
 
   private = GET_PRIVATE (item);
 
-  *tx = SCALEX (private->shell, x) - private->shell->offset_x;
-  *ty = SCALEY (private->shell, y) - private->shell->offset_y;
+  gimp_display_shell_zoom_xy_f (private->shell, x, y, tx, ty);
 }
 
 
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 0e0e032..408f2ab 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -37,8 +37,8 @@
 #include "gimpdisplayshell.h"
 #include "gimpdisplayshell-draw.h"
 #include "gimpdisplayshell-render.h"
-#include "gimpdisplayshell-rotate.h"
 #include "gimpdisplayshell-scale.h"
+#include "gimpdisplayshell-transform.h"
 #include "gimpdisplayxfer.h"
 
 
@@ -149,9 +149,9 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
       gint    image_width;
       gint    image_height;
 
-      gimp_display_shell_rotate_untransform_bounds (shell,
-                                                    x, y, x + w, y + h,
-                                                    &tx1, &ty1, &tx2, &ty2);
+      gimp_display_shell_unrotate_bounds (shell,
+                                          x, y, x + w, y + h,
+                                          &tx1, &ty1, &tx2, &ty2);
 
       x1 = floor (tx1 - 0.5);
       y1 = floor (ty1 - 0.5);
diff --git a/app/display/gimpdisplayshell-items.c b/app/display/gimpdisplayshell-items.c
index e8fe8dd..17d63c4 100644
--- a/app/display/gimpdisplayshell-items.c
+++ b/app/display/gimpdisplayshell-items.c
@@ -34,7 +34,7 @@
 #include "gimpdisplayshell.h"
 #include "gimpdisplayshell-expose.h"
 #include "gimpdisplayshell-items.h"
-#include "gimpdisplayshell-rotate.h"
+#include "gimpdisplayshell-transform.h"
 
 
 /*  local function prototypes  */
@@ -249,11 +249,11 @@ gimp_display_shell_item_update (GimpCanvasItem   *item,
 
           cairo_region_get_rectangle (region, i, &rect);
 
-          gimp_display_shell_rotate_transform_bounds (shell,
-                                                      rect.x, rect.y,
-                                                      rect.x + rect.width,
-                                                      rect.y + rect.height,
-                                                      &tx1, &ty1, &tx2, &ty2);
+          gimp_display_shell_rotate_bounds (shell,
+                                            rect.x, rect.y,
+                                            rect.x + rect.width,
+                                            rect.y + rect.height,
+                                            &tx1, &ty1, &tx2, &ty2);
 
           x1 = floor (tx1 - 0.5);
           y1 = floor (ty1 - 0.5);
diff --git a/app/display/gimpdisplayshell-rotate.c b/app/display/gimpdisplayshell-rotate.c
index 6150069..676c5bd 100644
--- a/app/display/gimpdisplayshell-rotate.c
+++ b/app/display/gimpdisplayshell-rotate.c
@@ -24,8 +24,6 @@
 
 #include "display-types.h"
 
-#include "core/gimp-utils.h"
-
 #include "gimpdisplay.h"
 #include "gimpdisplayshell.h"
 #include "gimpdisplayshell-expose.h"
@@ -149,79 +147,3 @@ gimp_display_shell_rotate_update_transform (GimpDisplayShell *shell)
       shell->rotate_untransform = NULL;
     }
 }
-
-void
-gimp_display_shell_rotate_transform_bounds (GimpDisplayShell *shell,
-                                            gdouble           x1,
-                                            gdouble           y1,
-                                            gdouble           x2,
-                                            gdouble           y2,
-                                            gdouble          *nx1,
-                                            gdouble          *ny1,
-                                            gdouble          *nx2,
-                                            gdouble          *ny2)
-{
-  gdouble tx1, ty1;
-  gdouble tx2, ty2;
-  gdouble tx3, ty3;
-  gdouble tx4, ty4;
-
-  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-
-  tx1 = x1;
-  ty1 = y1;
-  tx2 = x1;
-  ty2 = y2;
-  tx3 = x2;
-  ty3 = y1;
-  tx4 = x2;
-  ty4 = y2;
-
-  cairo_matrix_transform_point (shell->rotate_transform, &tx1, &ty1);
-  cairo_matrix_transform_point (shell->rotate_transform, &tx2, &ty2);
-  cairo_matrix_transform_point (shell->rotate_transform, &tx3, &ty3);
-  cairo_matrix_transform_point (shell->rotate_transform, &tx4, &ty4);
-
-  *nx1 = MIN4 (tx1, tx2, tx3, tx4);
-  *ny1 = MIN4 (ty1, ty2, ty3, ty4);
-  *nx2 = MAX4 (tx1, tx2, tx3, tx4);
-  *ny2 = MAX4 (ty1, ty2, ty3, ty4);
-}
-
-void
-gimp_display_shell_rotate_untransform_bounds (GimpDisplayShell *shell,
-                                              gdouble           x1,
-                                              gdouble           y1,
-                                              gdouble           x2,
-                                              gdouble           y2,
-                                              gdouble          *nx1,
-                                              gdouble          *ny1,
-                                              gdouble          *nx2,
-                                              gdouble          *ny2)
-{
-  gdouble tx1, ty1;
-  gdouble tx2, ty2;
-  gdouble tx3, ty3;
-  gdouble tx4, ty4;
-
-  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-
-  tx1 = x1;
-  ty1 = y1;
-  tx2 = x1;
-  ty2 = y2;
-  tx3 = x2;
-  ty3 = y1;
-  tx4 = x2;
-  ty4 = y2;
-
-  cairo_matrix_transform_point (shell->rotate_untransform, &tx1, &ty1);
-  cairo_matrix_transform_point (shell->rotate_untransform, &tx2, &ty2);
-  cairo_matrix_transform_point (shell->rotate_untransform, &tx3, &ty3);
-  cairo_matrix_transform_point (shell->rotate_untransform, &tx4, &ty4);
-
-  *nx1 = MIN4 (tx1, tx2, tx3, tx4);
-  *ny1 = MIN4 (ty1, ty2, ty3, ty4);
-  *nx2 = MAX4 (tx1, tx2, tx3, tx4);
-  *ny2 = MAX4 (ty1, ty2, ty3, ty4);
-}
diff --git a/app/display/gimpdisplayshell-rotate.h b/app/display/gimpdisplayshell-rotate.h
index 99fb0ca..82d3cb1 100644
--- a/app/display/gimpdisplayshell-rotate.h
+++ b/app/display/gimpdisplayshell-rotate.h
@@ -19,37 +19,18 @@
 #define __GIMP_DISPLAY_SHELL_ROTATE_H__
 
 
-void    gimp_display_shell_rotate                     (GimpDisplayShell *shell,
-                                                       gdouble           delta);
-void    gimp_display_shell_rotate_to                  (GimpDisplayShell *shell,
-                                                       gdouble           value);
-void    gimp_display_shell_rotate_drag                (GimpDisplayShell *shell,
-                                                       gdouble           last_x,
-                                                       gdouble           last_y,
-                                                       gdouble           cur_x,
-                                                       gdouble           cur_y,
-                                                       gboolean          constrain);
+void   gimp_display_shell_rotate                  (GimpDisplayShell *shell,
+                                                   gdouble           delta);
+void   gimp_display_shell_rotate_to               (GimpDisplayShell *shell,
+                                                   gdouble           value);
+void   gimp_display_shell_rotate_drag             (GimpDisplayShell *shell,
+                                                   gdouble           last_x,
+                                                   gdouble           last_y,
+                                                   gdouble           cur_x,
+                                                   gdouble           cur_y,
+                                                   gboolean          constrain);
 
-void     gimp_display_shell_rotate_update_transform   (GimpDisplayShell *shell);
-
-void     gimp_display_shell_rotate_transform_bounds   (GimpDisplayShell *shell,
-                                                       gdouble           x1,
-                                                       gdouble           y1,
-                                                       gdouble           x2,
-                                                       gdouble           y2,
-                                                       gdouble          *nx1,
-                                                       gdouble          *ny1,
-                                                       gdouble          *nx2,
-                                                       gdouble          *ny2);
-void     gimp_display_shell_rotate_untransform_bounds (GimpDisplayShell *shell,
-                                                       gdouble           x1,
-                                                       gdouble           y1,
-                                                       gdouble           x2,
-                                                       gdouble           y2,
-                                                       gdouble          *nx1,
-                                                       gdouble          *ny1,
-                                                       gdouble          *nx2,
-                                                       gdouble          *ny2);
+void   gimp_display_shell_rotate_update_transform (GimpDisplayShell *shell);
 
 
 #endif  /*  __GIMP_DISPLAY_SHELL_ROTATE_H__  */
diff --git a/app/display/gimpdisplayshell-selection.c b/app/display/gimpdisplayshell-selection.c
index cc48fe8..0181efd 100644
--- a/app/display/gimpdisplayshell-selection.c
+++ b/app/display/gimpdisplayshell-selection.c
@@ -68,7 +68,7 @@ static void      selection_undraw         (Selection          *selection);
 
 static void      selection_render_mask    (Selection          *selection);
 
-static void      selection_transform_segs (Selection          *selection,
+static void      selection_zoom_segs      (Selection          *selection,
                                            const GimpBoundSeg *src_segs,
                                            GimpSegment        *dest_segs,
                                            gint                n_segs);
@@ -307,18 +307,18 @@ selection_render_mask (Selection *selection)
 }
 
 static void
-selection_transform_segs (Selection          *selection,
-                          const GimpBoundSeg *src_segs,
-                          GimpSegment        *dest_segs,
-                          gint                n_segs)
+selection_zoom_segs (Selection          *selection,
+                     const GimpBoundSeg *src_segs,
+                     GimpSegment        *dest_segs,
+                     gint                n_segs)
 {
   const gint xclamp = selection->shell->disp_width + 1;
   const gint yclamp = selection->shell->disp_height + 1;
   gint       i;
 
-  gimp_display_shell_transform_segments (selection->shell,
-                                         src_segs, dest_segs, n_segs,
-                                         0.0, 0.0);
+  gimp_display_shell_zoom_segments (selection->shell,
+                                    src_segs, dest_segs, n_segs,
+                                    0.0, 0.0);
 
   for (i = 0; i < n_segs; i++)
     {
@@ -368,8 +368,8 @@ selection_generate_segs (Selection *selection)
   if (selection->n_segs_in)
     {
       selection->segs_in = g_new (GimpSegment, selection->n_segs_in);
-      selection_transform_segs (selection, segs_in,
-                                selection->segs_in, selection->n_segs_in);
+      selection_zoom_segs (selection, segs_in,
+                           selection->segs_in, selection->n_segs_in);
 
       selection_render_mask (selection);
     }
@@ -382,8 +382,8 @@ selection_generate_segs (Selection *selection)
   if (selection->n_segs_out)
     {
       selection->segs_out = g_new (GimpSegment, selection->n_segs_out);
-      selection_transform_segs (selection, segs_out,
-                                selection->segs_out, selection->n_segs_out);
+      selection_zoom_segs (selection, segs_out,
+                           selection->segs_out, selection->n_segs_out);
     }
   else
     {
diff --git a/app/display/gimpdisplayshell-transform.c b/app/display/gimpdisplayshell-transform.c
index 11aafdf..f5364fc 100644
--- a/app/display/gimpdisplayshell-transform.c
+++ b/app/display/gimpdisplayshell-transform.c
@@ -36,6 +36,509 @@
 
 
 /**
+ * gimp_display_shell_zoom_coords:
+ * @shell:          a #GimpDisplayShell
+ * @image_coords:   image coordinates
+ * @display_coords: returns the corresponding display coordinates
+ *
+ * Zooms from image coordinates to display coordinates, so that
+ * objects can be rendered at the correct points on the display.
+ **/
+void
+gimp_display_shell_zoom_coords (const GimpDisplayShell *shell,
+                                const GimpCoords       *image_coords,
+                                GimpCoords             *display_coords)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (image_coords != NULL);
+  g_return_if_fail (display_coords != NULL);
+
+  *display_coords = *image_coords;
+
+  display_coords->x = SCALEX (shell, image_coords->x);
+  display_coords->y = SCALEY (shell, image_coords->y);
+
+  display_coords->x -= shell->offset_x;
+  display_coords->y -= shell->offset_y;
+}
+
+/**
+ * gimp_display_shell_unzoom_coords:
+ * @shell:          a #GimpDisplayShell
+ * @display_coords: display coordinates
+ * @image_coords:   returns the corresponding image coordinates
+ *
+ * Zooms from display coordinates to image coordinates, so that
+ * points on the display can be mapped to points in the image.
+ **/
+void
+gimp_display_shell_unzoom_coords (const GimpDisplayShell *shell,
+                                  const GimpCoords       *display_coords,
+                                  GimpCoords             *image_coords)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (display_coords != NULL);
+  g_return_if_fail (image_coords != NULL);
+
+  *image_coords = *display_coords;
+
+  image_coords->x += shell->offset_x;
+  image_coords->y += shell->offset_y;
+
+  image_coords->x /= shell->scale_x;
+  image_coords->y /= shell->scale_y;
+}
+
+/**
+ * gimp_display_shell_zoom_xy:
+ * @shell:
+ * @x:
+ * @y:
+ * @nx:
+ * @ny:
+ *
+ * Zooms an image coordinate to a shell coordinate.
+ **/
+void
+gimp_display_shell_zoom_xy (const GimpDisplayShell *shell,
+                            gdouble                 x,
+                            gdouble                 y,
+                            gint                   *nx,
+                            gint                   *ny)
+{
+  gint64 tx;
+  gint64 ty;
+
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  tx = x * shell->scale_x - shell->offset_x;
+  ty = y * shell->scale_y - shell->offset_y;
+
+  tx -= shell->offset_x;
+  ty -= shell->offset_y;
+
+  /*  The projected coordinates might overflow a gint in the case of
+   *  big images at high zoom levels, so we clamp them here to avoid
+   *  problems.
+   */
+  *nx = CLAMP (tx, G_MININT, G_MAXINT);
+  *ny = CLAMP (ty, G_MININT, G_MAXINT);
+}
+
+/**
+ * gimp_display_shell_unzoom_xy:
+ * @shell:       a #GimpDisplayShell
+ * @x:           x coordinate in display coordinates
+ * @y:           y coordinate in display coordinates
+ * @nx:          returns x oordinate in image coordinates
+ * @ny:          returns y coordinate in image coordinates
+ * @round:       if %TRUE, round the results to the nearest integer;
+ *               if %FALSE, simply cast them to @gint.
+ *
+ * Zoom from display coordinates to image coordinates, so that
+ * points on the display can be mapped to the corresponding points
+ * in the image.
+ **/
+void
+gimp_display_shell_unzoom_xy (const GimpDisplayShell *shell,
+                              gint                    x,
+                              gint                    y,
+                              gint                   *nx,
+                              gint                   *ny,
+                              gboolean                round)
+{
+  gint64 tx;
+  gint64 ty;
+
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  if (round)
+    {
+      tx = SIGNED_ROUND (((gdouble) x + shell->offset_x) / shell->scale_x);
+      ty = SIGNED_ROUND (((gdouble) y + shell->offset_y) / shell->scale_y);
+    }
+  else
+    {
+      tx = ((gint64) x + shell->offset_x) / shell->scale_x;
+      ty = ((gint64) y + shell->offset_y) / shell->scale_y;
+    }
+
+  *nx = CLAMP (tx, G_MININT, G_MAXINT);
+  *ny = CLAMP (ty, G_MININT, G_MAXINT);
+}
+
+/**
+ * gimp_display_shell_zoom_xy_f:
+ * @shell: a #GimpDisplayShell
+ * @x:     image x coordinate of point
+ * @y:     image y coordinate of point
+ * @nx:    returned shell canvas x coordinate
+ * @ny:    returned shell canvas y coordinate
+ *
+ * Zooms from image coordinates to display shell canvas
+ * coordinates.
+ **/
+void
+gimp_display_shell_zoom_xy_f (const GimpDisplayShell *shell,
+                              gdouble                 x,
+                              gdouble                 y,
+                              gdouble                *nx,
+                              gdouble                *ny)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  *nx = SCALEX (shell, x) - shell->offset_x;
+  *ny = SCALEY (shell, y) - shell->offset_y;
+}
+
+/**
+ * gimp_display_shell_unzoom_xy_f:
+ * @shell:       a #GimpDisplayShell
+ * @x:           x coordinate in display coordinates
+ * @y:           y coordinate in display coordinates
+ * @nx:          place to return x coordinate in image coordinates
+ * @ny:          place to return y coordinate in image coordinates
+ *
+ * This function is identical to gimp_display_shell_unzoom_xy(),
+ * except that the input and output coordinates are doubles rather than
+ * ints, and consequently there is no option related to rounding.
+ **/
+void
+gimp_display_shell_unzoom_xy_f (const GimpDisplayShell *shell,
+                                gdouble                 x,
+                                gdouble                 y,
+                                gdouble                *nx,
+                                gdouble                *ny)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  *nx = (x + shell->offset_x) / shell->scale_x;
+  *ny = (y + shell->offset_y) / shell->scale_y;
+}
+
+/**
+ * gimp_display_shell_zoom_segments:
+ * @shell:       a #GimpDisplayShell
+ * @src_segs:    array of segments in image coordinates
+ * @dest_segs:   returns the corresponding segments in display coordinates
+ * @n_segs:      number of segments
+ *
+ * Zooms from image coordinates to display coordinates, so that
+ * objects can be rendered at the correct points on the display.
+ **/
+void
+gimp_display_shell_zoom_segments (const GimpDisplayShell *shell,
+                                  const GimpBoundSeg     *src_segs,
+                                  GimpSegment            *dest_segs,
+                                  gint                    n_segs,
+                                  gdouble                 offset_x,
+                                  gdouble                 offset_y)
+{
+  gint i;
+
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+  for (i = 0; i < n_segs ; i++)
+    {
+      gdouble x1, x2;
+      gdouble y1, y2;
+
+      x1 = src_segs[i].x1 + offset_x;
+      x2 = src_segs[i].x2 + offset_x;
+      y1 = src_segs[i].y1 + offset_y;
+      y2 = src_segs[i].y2 + offset_y;
+
+      dest_segs[i].x1 = SCALEX (shell, x1) - shell->offset_x;
+      dest_segs[i].x2 = SCALEX (shell, x2) - shell->offset_x;
+      dest_segs[i].y1 = SCALEY (shell, y1) - shell->offset_y;
+      dest_segs[i].y2 = SCALEY (shell, y2) - shell->offset_y;
+    }
+}
+
+/**
+ * gimp_display_shell_rotate_coords:
+ * @shell:          a #GimpDisplayShell
+ * @image_coords:   unrotated display coordinates
+ * @display_coords: returns the corresponding rotated display coordinates
+ *
+ * Rotates from unrotated display coordinates to rotated display
+ * coordinates, so that objects can be rendered at the correct points
+ * on the display.
+ **/
+void
+gimp_display_shell_rotate_coords (const GimpDisplayShell *shell,
+                                  const GimpCoords       *unrotated_coords,
+                                  GimpCoords             *rotated_coords)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (unrotated_coords != NULL);
+  g_return_if_fail (rotated_coords != NULL);
+
+  *rotated_coords = *rotated_coords;
+
+  if (shell->rotate_transform)
+    cairo_matrix_transform_point (shell->rotate_transform,
+                                  &rotated_coords->x,
+                                  &rotated_coords->y);
+}
+
+/**
+ * gimp_display_shell_unrotate_coords:
+ * @shell:          a #GimpDisplayShell
+ * @display_coords: rotated display coordinates
+ * @image_coords:   returns the corresponding unrotated display coordinates
+ *
+ * Rotates from rotated display coordinates to unrotated display coordinates.
+ **/
+void
+gimp_display_shell_unrotate_coords (const GimpDisplayShell *shell,
+                                    const GimpCoords       *rotated_coords,
+                                    GimpCoords             *unrotated_coords)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (rotated_coords != NULL);
+  g_return_if_fail (unrotated_coords != NULL);
+
+  *unrotated_coords = *rotated_coords;
+
+  if (shell->rotate_untransform)
+    cairo_matrix_transform_point (shell->rotate_untransform,
+                                  &unrotated_coords->x,
+                                  &unrotated_coords->y);
+}
+
+/**
+ * gimp_display_shell_rotate_xy:
+ * @shell:
+ * @x:
+ * @y:
+ * @nx:
+ * @ny:
+ *
+ * Rotates an unrotated display coordinate to a rotated shell coordinate.
+ **/
+void
+gimp_display_shell_rotate_xy (const GimpDisplayShell *shell,
+                              gdouble                 x,
+                              gdouble                 y,
+                              gint                   *nx,
+                              gint                   *ny)
+{
+  gint64 tx;
+  gint64 ty;
+
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  if (shell->rotate_transform)
+    cairo_matrix_transform_point (shell->rotate_transform, &x, &y);
+
+  tx = x;
+  ty = y;
+
+  /*  The projected coordinates might overflow a gint in the case of
+   *  big images at high zoom levels, so we clamp them here to avoid
+   *  problems.
+   */
+  *nx = CLAMP (tx, G_MININT, G_MAXINT);
+  *ny = CLAMP (ty, G_MININT, G_MAXINT);
+}
+
+/**
+ * gimp_display_shell_unrotate_xy:
+ * @shell:       a #GimpDisplayShell
+ * @x:           x coordinate in rotated display coordinates
+ * @y:           y coordinate in rotated display coordinates
+ * @nx:          returns x oordinate in unrotated display coordinates
+ * @ny:          returns y coordinate in unrotated display coordinates
+ *
+ * Rotate from rotated display coordinates to unrotated display
+ * coordinates.
+ **/
+void
+gimp_display_shell_unrotate_xy (const GimpDisplayShell *shell,
+                                gint                    x,
+                                gint                    y,
+                                gint                   *nx,
+                                gint                   *ny)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  if (shell->rotate_untransform)
+    {
+      gdouble fx = x;
+      gdouble fy = y;
+
+      cairo_matrix_transform_point (shell->rotate_untransform, &fy, &fy);
+
+      *nx = CLAMP (fx, G_MININT, G_MAXINT);
+      *ny = CLAMP (fy, G_MININT, G_MAXINT);
+    }
+  else
+    {
+      *nx = x;
+      *ny = y;
+    }
+}
+
+/**
+ * gimp_display_shell_rotate_xy_f:
+ * @shell: a #GimpDisplayShell
+ * @x:     image x coordinate of point
+ * @y:     image y coordinate of point
+ * @nx:    returned shell canvas x coordinate
+ * @ny:    returned shell canvas y coordinate
+ *
+ * Rotates from untransformed display coordinates to rotated display
+ * coordinates.
+ **/
+void
+gimp_display_shell_rotate_xy_f (const GimpDisplayShell *shell,
+                                gdouble                 x,
+                                gdouble                 y,
+                                gdouble                *nx,
+                                gdouble                *ny)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  *nx = x;
+  *ny = y;
+
+  if (shell->rotate_transform)
+    cairo_matrix_transform_point (shell->rotate_transform, nx, ny);
+}
+
+/**
+ * gimp_display_shell_unrotate_xy_f:
+ * @shell:       a #GimpDisplayShell
+ * @x:           x coordinate in rotated display coordinates
+ * @y:           y coordinate in rotated display coordinates
+ * @nx:          place to return x coordinate in unrotated display coordinates
+ * @ny:          place to return y coordinate in unrotated display  coordinates
+ *
+ * This function is identical to gimp_display_shell_unrotate_xy(),
+ * except that the input and output coordinates are doubles rather
+ * than ints.
+ **/
+void
+gimp_display_shell_unrotate_xy_f (const GimpDisplayShell *shell,
+                                  gdouble                 x,
+                                  gdouble                 y,
+                                  gdouble                *nx,
+                                  gdouble                *ny)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (nx != NULL);
+  g_return_if_fail (ny != NULL);
+
+  *nx = x;
+  *ny = y;
+
+  if (shell->rotate_untransform)
+    cairo_matrix_transform_point (shell->rotate_untransform, nx, ny);
+}
+
+void
+gimp_display_shell_rotate_bounds (GimpDisplayShell *shell,
+                                  gdouble           x1,
+                                  gdouble           y1,
+                                  gdouble           x2,
+                                  gdouble           y2,
+                                  gdouble          *nx1,
+                                  gdouble          *ny1,
+                                  gdouble          *nx2,
+                                  gdouble          *ny2)
+{
+
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+  if (shell->rotate_transform)
+    {
+      gdouble tx1 = x1;
+      gdouble ty1 = y1;
+      gdouble tx2 = x1;
+      gdouble ty2 = y2;
+      gdouble tx3 = x2;
+      gdouble ty3 = y1;
+      gdouble tx4 = x2;
+      gdouble ty4 = y2;
+
+      cairo_matrix_transform_point (shell->rotate_transform, &tx1, &ty1);
+      cairo_matrix_transform_point (shell->rotate_transform, &tx2, &ty2);
+      cairo_matrix_transform_point (shell->rotate_transform, &tx3, &ty3);
+      cairo_matrix_transform_point (shell->rotate_transform, &tx4, &ty4);
+
+      *nx1 = MIN4 (tx1, tx2, tx3, tx4);
+      *ny1 = MIN4 (ty1, ty2, ty3, ty4);
+      *nx2 = MAX4 (tx1, tx2, tx3, tx4);
+      *ny2 = MAX4 (ty1, ty2, ty3, ty4);
+    }
+  else
+    {
+      *nx1 = x1;
+      *ny1 = y1;
+      *nx2 = x2;
+      *ny2 = y2;
+    }
+}
+
+void
+gimp_display_shell_unrotate_bounds (GimpDisplayShell *shell,
+                                    gdouble           x1,
+                                    gdouble           y1,
+                                    gdouble           x2,
+                                    gdouble           y2,
+                                    gdouble          *nx1,
+                                    gdouble          *ny1,
+                                    gdouble          *nx2,
+                                    gdouble          *ny2)
+{
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+  if (shell->rotate_untransform)
+    {
+      gdouble tx1 = x1;
+      gdouble ty1 = y1;
+      gdouble tx2 = x1;
+      gdouble ty2 = y2;
+      gdouble tx3 = x2;
+      gdouble ty3 = y1;
+      gdouble tx4 = x2;
+      gdouble ty4 = y2;
+
+      cairo_matrix_transform_point (shell->rotate_untransform, &tx1, &ty1);
+      cairo_matrix_transform_point (shell->rotate_untransform, &tx2, &ty2);
+      cairo_matrix_transform_point (shell->rotate_untransform, &tx3, &ty3);
+      cairo_matrix_transform_point (shell->rotate_untransform, &tx4, &ty4);
+
+      *nx1 = MIN4 (tx1, tx2, tx3, tx4);
+      *ny1 = MIN4 (ty1, ty2, ty3, ty4);
+      *nx2 = MAX4 (tx1, tx2, tx3, tx4);
+      *ny2 = MAX4 (ty1, ty2, ty3, ty4);
+    }
+  else
+    {
+      *nx1 = x1;
+      *ny1 = y1;
+      *nx2 = x2;
+      *ny2 = y2;
+    }
+}
+
+/**
  * gimp_display_shell_transform_coords:
  * @shell:          a #GimpDisplayShell
  * @image_coords:   image coordinates
@@ -126,19 +629,24 @@ gimp_display_shell_transform_xy (const GimpDisplayShell *shell,
   tx = x * shell->scale_x - shell->offset_x;
   ty = y * shell->scale_y - shell->offset_y;
 
+  tx -= shell->offset_x;
+  ty -= shell->offset_y;
+
   if (shell->rotate_transform)
     {
       gdouble fx = tx;
       gdouble fy = ty;
 
-      cairo_matrix_transform_point (shell->rotate_transform, &fy, &fy);
+      cairo_matrix_transform_point (shell->rotate_transform, &fx, &fy);
 
       tx = fx;
       ty = fy;
     }
 
-  /* The projected coordinates might overflow a gint in the case of big
-     images at high zoom levels, so we clamp them here to avoid problems.  */
+  /*  The projected coordinates might overflow a gint in the case of
+   *  big images at high zoom levels, so we clamp them here to avoid
+   *  problems.
+   */
   *nx = CLAMP (tx, G_MININT, G_MAXINT);
   *ny = CLAMP (ty, G_MININT, G_MAXINT);
 }
@@ -185,8 +693,8 @@ gimp_display_shell_untransform_xy (const GimpDisplayShell *shell,
 
   if (round)
     {
-      tx = SIGNED_ROUND (((gint64) x + shell->offset_x) / shell->scale_x);
-      ty = SIGNED_ROUND (((gint64) y + shell->offset_y) / shell->scale_y);
+      tx = SIGNED_ROUND (((gdouble) x + shell->offset_x) / shell->scale_x);
+      ty = SIGNED_ROUND (((gdouble) y + shell->offset_y) / shell->scale_y);
     }
   else
     {
@@ -340,45 +848,6 @@ gimp_display_shell_untransform_bounds (const GimpDisplayShell *shell,
 }
 
 /**
- * gimp_display_shell_transform_segments:
- * @shell:       a #GimpDisplayShell
- * @src_segs:    array of segments in image coordinates
- * @dest_segs:   returns the corresponding segments in display coordinates
- * @n_segs:      number of segments
- *
- * Transforms from image coordinates to display coordinates, so that
- * objects can be rendered at the correct points on the display.
- **/
-void
-gimp_display_shell_transform_segments (const GimpDisplayShell *shell,
-                                       const GimpBoundSeg     *src_segs,
-                                       GimpSegment            *dest_segs,
-                                       gint                    n_segs,
-                                       gdouble                 offset_x,
-                                       gdouble                 offset_y)
-{
-  gint i;
-
-  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-
-  for (i = 0; i < n_segs ; i++)
-    {
-      gdouble x1, x2;
-      gdouble y1, y2;
-
-      x1 = src_segs[i].x1 + offset_x;
-      x2 = src_segs[i].x2 + offset_x;
-      y1 = src_segs[i].y1 + offset_y;
-      y2 = src_segs[i].y2 + offset_y;
-
-      dest_segs[i].x1 = SCALEX (shell, x1) - shell->offset_x;
-      dest_segs[i].x2 = SCALEX (shell, x2) - shell->offset_x;
-      dest_segs[i].y1 = SCALEY (shell, y1) - shell->offset_y;
-      dest_segs[i].y2 = SCALEY (shell, y2) - shell->offset_y;
-    }
-}
-
-/**
  * gimp_display_shell_untransform_viewport:
  * @shell:  a #GimpDisplayShell
  * @x:      returns image x coordinate of display upper left corner
diff --git a/app/display/gimpdisplayshell-transform.h b/app/display/gimpdisplayshell-transform.h
index ead1cdb..f365236 100644
--- a/app/display/gimpdisplayshell-transform.h
+++ b/app/display/gimpdisplayshell-transform.h
@@ -19,6 +19,105 @@
 #define __GIMP_DISPLAY_SHELL_TRANSFORM_H__
 
 
+/*  zoom: functions to transform from image space to unrotated display
+ *  space and back, taking into account scroll offset and scale
+ */
+
+void  gimp_display_shell_zoom_coords          (const GimpDisplayShell *shell,
+                                               const GimpCoords       *image_coords,
+                                               GimpCoords             *display_coords);
+void  gimp_display_shell_unzoom_coords        (const GimpDisplayShell *shell,
+                                               const GimpCoords       *display_coords,
+                                               GimpCoords             *image_coords);
+
+void  gimp_display_shell_zoom_xy              (const GimpDisplayShell *shell,
+                                               gdouble                 x,
+                                               gdouble                 y,
+                                               gint                   *nx,
+                                               gint                   *ny);
+void  gimp_display_shell_unzoom_xy            (const GimpDisplayShell *shell,
+                                               gint                    x,
+                                               gint                    y,
+                                               gint                   *nx,
+                                               gint                   *ny,
+                                               gboolean                round);
+
+void  gimp_display_shell_zoom_xy_f            (const GimpDisplayShell *shell,
+                                               gdouble                 x,
+                                               gdouble                 y,
+                                               gdouble                *nx,
+                                               gdouble                *ny);
+void  gimp_display_shell_unzoom_xy_f          (const GimpDisplayShell *shell,
+                                               gdouble                 x,
+                                               gdouble                 y,
+                                               gdouble                *nx,
+                                               gdouble                *ny);
+
+void  gimp_display_shell_zoom_segments        (const GimpDisplayShell *shell,
+                                               const GimpBoundSeg     *src_segs,
+                                               GimpSegment            *dest_segs,
+                                               gint                    n_segs,
+                                               gdouble                 offset_x,
+                                               gdouble                 offset_y);
+
+
+/*  rotate: functions to transform from unrotated but zoomed display
+ *  space to rotated display space and back
+ */
+
+void  gimp_display_shell_rotate_coords        (const GimpDisplayShell *shell,
+                                               const GimpCoords       *image_coords,
+                                               GimpCoords             *display_coords);
+void  gimp_display_shell_unrotate_coords      (const GimpDisplayShell *shell,
+                                               const GimpCoords       *display_coords,
+                                               GimpCoords             *image_coords);
+
+void  gimp_display_shell_rotate_xy            (const GimpDisplayShell *shell,
+                                               gdouble                 x,
+                                               gdouble                 y,
+                                               gint                   *nx,
+                                               gint                   *ny);
+void  gimp_display_shell_unrotate_xy          (const GimpDisplayShell *shell,
+                                               gint                    x,
+                                               gint                    y,
+                                               gint                   *nx,
+                                               gint                   *ny);
+
+void  gimp_display_shell_rotate_xy_f          (const GimpDisplayShell *shell,
+                                               gdouble                 x,
+                                               gdouble                 y,
+                                               gdouble                *nx,
+                                               gdouble                *ny);
+void  gimp_display_shell_unrotate_xy_f        (const GimpDisplayShell *shell,
+                                               gdouble                 x,
+                                               gdouble                 y,
+                                               gdouble                *nx,
+                                               gdouble                *ny);
+
+void  gimp_display_shell_rotate_bounds        (GimpDisplayShell       *shell,
+                                               gdouble                 x1,
+                                               gdouble                 y1,
+                                               gdouble                 x2,
+                                               gdouble                 y2,
+                                               gdouble                *nx1,
+                                               gdouble                *ny1,
+                                               gdouble                *nx2,
+                                               gdouble                *ny2);
+void  gimp_display_shell_unrotate_bounds      (GimpDisplayShell       *shell,
+                                               gdouble                 x1,
+                                               gdouble                 y1,
+                                               gdouble                 x2,
+                                               gdouble                 y2,
+                                               gdouble                *nx1,
+                                               gdouble                *ny1,
+                                               gdouble                *nx2,
+                                               gdouble                *ny2);
+
+
+/*  transform: functions to transform from image space to rotated display
+ *  space and back, taking into account scroll offset, scale, and rotation
+ */
+
 void  gimp_display_shell_transform_coords     (const GimpDisplayShell *shell,
                                                const GimpCoords       *image_coords,
                                                GimpCoords             *display_coords);
@@ -68,13 +167,6 @@ void  gimp_display_shell_untransform_bounds   (const GimpDisplayShell *shell,
                                                gdouble                *nx2,
                                                gdouble                *ny2);
 
-void  gimp_display_shell_transform_segments   (const GimpDisplayShell *shell,
-                                               const GimpBoundSeg     *src_segs,
-                                               GimpSegment            *dest_segs,
-                                               gint                    n_segs,
-                                               gdouble                 offset_x,
-                                               gdouble                 offset_y);
-
 void  gimp_display_shell_untransform_viewport (const GimpDisplayShell *shell,
                                                gint                   *x,
                                                gint                   *y,
diff --git a/app/tools/gimpdrawtool.c b/app/tools/gimpdrawtool.c
index 6182812..48b6614 100644
--- a/app/tools/gimpdrawtool.c
+++ b/app/tools/gimpdrawtool.c
@@ -1009,20 +1009,12 @@ gimp_draw_tool_on_handle (GimpDrawTool     *draw_tool,
 
   shell = gimp_display_get_shell (display);
 
-  gimp_display_shell_transform_xy_f (shell,
-                                     x, y,
-                                     &tx, &ty);
-  gimp_display_shell_transform_xy_f (shell,
-                                     handle_x, handle_y,
-                                     &handle_tx, &handle_ty);
-
-  if (shell->rotate_untransform)
-    {
-      cairo_matrix_transform_point (shell->rotate_untransform,
-                                    &tx, &ty);
-      cairo_matrix_transform_point (shell->rotate_untransform,
-                                    &handle_tx, &handle_ty);
-    }
+  gimp_display_shell_zoom_xy_f (shell,
+                                x, y,
+                                &tx, &ty);
+  gimp_display_shell_zoom_xy_f (shell,
+                                handle_x, handle_y,
+                                &handle_tx, &handle_ty);
 
   switch (type)
     {



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