[gimp/gimp-2-10] app: fix line-angle constraint when xres != yres



commit 4cb91320a4ba162c72bdc5866963cbafe9529a9a
Author: Ell <ell_se yahoo com>
Date:   Sun Jul 15 17:58:55 2018 -0400

    app: fix line-angle constraint when xres != yres
    
    Fix gimp_constrain_line() and friends to properly constrain line
    angles when the image's horizontal and vertical resolutions are
    different, and dot-for-dot is disabled.
    
    (cherry picked from commit 4fefab1798a1f1b29d9b94b1fa95fb249d233284)

 app/core/gimp-utils.c                | 85 +++++++++---------------------------
 app/core/gimp-utils.h                |  4 +-
 app/display/gimpdisplayshell-utils.c | 37 +++++++++++++---
 app/display/gimpdisplayshell-utils.h | 31 +++++++------
 app/paint/gimppaintcore.c            | 16 ++++---
 app/paint/gimppaintcore.h            |  4 +-
 app/tools/gimpeditselectiontool.c    |  2 +-
 app/tools/gimppainttool-paint.c      | 13 ++++--
 app/tools/gimppainttool.c            | 13 ++++--
 9 files changed, 105 insertions(+), 100 deletions(-)
---
diff --git a/app/core/gimp-utils.c b/app/core/gimp-utils.c
index 625fce6ede..8be6c3c5d8 100644
--- a/app/core/gimp-utils.c
+++ b/app/core/gimp-utils.c
@@ -546,42 +546,6 @@ gimp_get_fill_params (GimpContext   *context,
   return TRUE;
 }
 
-/**
- * gimp_utils_point_to_line_distance:
- * @point:              The point to calculate the distance for.
- * @point_on_line:      A point on the line.
- * @line_direction:     Normalized line direction vector.
- * @closest_line_point: Gets set to the point on the line that is
- *                      closest to @point.
- *
- * Returns: The shortest distance from @point to the line defined by
- *          @point_on_line and @normalized_line_direction.
- **/
-static gdouble
-gimp_utils_point_to_line_distance (const GimpVector2 *point,
-                                   const GimpVector2 *point_on_line,
-                                   const GimpVector2 *line_direction,
-                                   GimpVector2       *closest_line_point)
-{
-  GimpVector2 distance_vector;
-  GimpVector2 tmp_a;
-  GimpVector2 tmp_b;
-  gdouble     d;
-
-  gimp_vector2_sub (&tmp_a, point, point_on_line);
-
-  d = gimp_vector2_inner_product (&tmp_a, line_direction);
-
-  tmp_b = gimp_vector2_mul_val (*line_direction, d);
-
-  *closest_line_point = gimp_vector2_add_val (*point_on_line,
-                                              tmp_b);
-
-  gimp_vector2_sub (&distance_vector, closest_line_point, point);
-
-  return gimp_vector2_length (&distance_vector);
-}
-
 /**
  * gimp_constrain_line:
  * @start_x:
@@ -590,6 +554,8 @@ gimp_utils_point_to_line_distance (const GimpVector2 *point,
  * @end_y:
  * @n_snap_lines: Number evenly disributed lines to snap to.
  * @offset_angle: The angle by which to offset the lines, in degrees.
+ * @xres:         The horizontal resolution.
+ * @yres:         The vertical resolution.
  *
  * Projects a line onto the specified subset of evenly radially
  * distributed lines. @n_lines of 2 makes the line snap horizontally
@@ -602,38 +568,29 @@ gimp_constrain_line (gdouble  start_x,
                      gdouble *end_x,
                      gdouble *end_y,
                      gint     n_snap_lines,
-                     gdouble  offset_angle)
+                     gdouble  offset_angle,
+                     gdouble  xres,
+                     gdouble  yres)
 {
-  GimpVector2 line_point          = {  start_x,  start_y };
-  GimpVector2 point               = { *end_x,   *end_y   };
-  GimpVector2 constrained_point;
-  GimpVector2 line_dir;
-  gdouble     shortest_dist_moved = G_MAXDOUBLE;
-  gdouble     dist_moved;
+  GimpVector2 diff;
+  GimpVector2 dir;
   gdouble     angle;
-  gint        i;
 
-  for (i = 0; i < n_snap_lines; i++)
-    {
-      angle  = i * G_PI / n_snap_lines;
-      angle += offset_angle * G_PI / 180.0;
-
-      gimp_vector2_set (&line_dir,
-                        cos (angle),
-                        sin (angle));
-
-      dist_moved = gimp_utils_point_to_line_distance (&point,
-                                                      &line_point,
-                                                      &line_dir,
-                                                      &constrained_point);
-      if (dist_moved < shortest_dist_moved)
-        {
-          shortest_dist_moved = dist_moved;
+  offset_angle *= G_PI / 180.0;
 
-          *end_x = constrained_point.x;
-          *end_y = constrained_point.y;
-        }
-    }
+  diff.x = (*end_x - start_x) / xres;
+  diff.y = (*end_y - start_y) / yres;
+
+  angle = (atan2 (diff.y, diff.x) - offset_angle) * n_snap_lines / G_PI;
+  angle = RINT (angle) * G_PI / n_snap_lines + offset_angle;
+
+  dir.x = cos (angle);
+  dir.y = sin (angle);
+
+  gimp_vector2_mul (&dir, gimp_vector2_inner_product (&dir, &diff));
+
+  *end_x = start_x + dir.x * xres;
+  *end_y = start_y + dir.y * yres;
 }
 
 gint
diff --git a/app/core/gimp-utils.h b/app/core/gimp-utils.h
index 50868c898c..956216e82b 100644
--- a/app/core/gimp-utils.h
+++ b/app/core/gimp-utils.h
@@ -74,7 +74,9 @@ void         gimp_constrain_line                   (gdouble          start_x,
                                                     gdouble         *end_x,
                                                     gdouble         *end_y,
                                                     gint             n_snap_lines,
-                                                    gdouble          offset_angle);
+                                                    gdouble          offset_angle,
+                                                    gdouble          xres,
+                                                    gdouble          yres);
 
 gint         gimp_file_compare                     (GFile           *file1,
                                                     GFile           *file2);
diff --git a/app/display/gimpdisplayshell-utils.c b/app/display/gimpdisplayshell-utils.c
index 88719a6616..1d4854f93f 100644
--- a/app/display/gimpdisplayshell-utils.c
+++ b/app/display/gimpdisplayshell-utils.c
@@ -35,15 +35,32 @@
 
 #include "gimp-intl.h"
 
-gdouble
-gimp_display_shell_get_constrained_line_offset_angle (GimpDisplayShell *shell)
+void
+gimp_display_shell_get_constrained_line_params (GimpDisplayShell *shell,
+                                                gdouble          *offset_angle,
+                                                gdouble          *xres,
+                                                gdouble          *yres)
 {
-  g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), 0.0);
+  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (offset_angle != NULL);
+  g_return_if_fail (xres != NULL);
+  g_return_if_fail (yres != NULL);
 
   if (shell->flip_horizontally ^ shell->flip_vertically)
-    return +shell->rotate_angle;
+    *offset_angle = +shell->rotate_angle;
   else
-    return -shell->rotate_angle;
+    *offset_angle = -shell->rotate_angle;
+
+  *xres = 1.0;
+  *yres = 1.0;
+
+  if (! shell->dot_for_dot)
+    {
+      GimpImage *image = gimp_display_get_image (shell->display);
+
+      if (image)
+        gimp_image_get_resolution (image, xres, yres);
+    }
 }
 
 void
@@ -54,14 +71,22 @@ gimp_display_shell_constrain_line (GimpDisplayShell *shell,
                                    gdouble          *end_y,
                                    gint              n_snap_lines)
 {
+  gdouble offset_angle;
+  gdouble xres, yres;
+
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (end_x != NULL);
   g_return_if_fail (end_y != NULL);
 
+  gimp_display_shell_get_constrained_line_params (shell,
+                                                  &offset_angle,
+                                                  &xres, &yres);
+
   gimp_constrain_line (start_x, start_y,
                        end_x,   end_y,
                        n_snap_lines,
-                       gimp_display_shell_get_constrained_line_offset_angle (shell));
+                       offset_angle,
+                       xres, yres);
 }
 
 /**
diff --git a/app/display/gimpdisplayshell-utils.h b/app/display/gimpdisplayshell-utils.h
index 254815fd0a..d397ed6a18 100644
--- a/app/display/gimpdisplayshell-utils.h
+++ b/app/display/gimpdisplayshell-utils.h
@@ -19,20 +19,23 @@
 #define __GIMP_DISPLAY_SHELL_UTILS_H__
 
 
-gdouble   gimp_display_shell_get_constrained_line_offset_angle (GimpDisplayShell *shell);
-void      gimp_display_shell_constrain_line                    (GimpDisplayShell *shell,
-                                                                gdouble           start_x,
-                                                                gdouble           start_y,
-                                                                gdouble          *end_x,
-                                                                gdouble          *end_y,
-                                                                gint              n_snap_lines);
-gchar   * gimp_display_shell_get_line_status                   (GimpDisplayShell *shell,
-                                                                const gchar      *status,
-                                                                const gchar      *separator,
-                                                                gdouble           x1,
-                                                                gdouble           y1,
-                                                                gdouble           x2,
-                                                                gdouble           y2);
+void    gimp_display_shell_get_constrained_line_params (GimpDisplayShell *shell,
+                                                        gdouble          *offset_angle,
+                                                        gdouble          *xres,
+                                                        gdouble          *yres);
+void    gimp_display_shell_constrain_line              (GimpDisplayShell *shell,
+                                                        gdouble           start_x,
+                                                        gdouble           start_y,
+                                                        gdouble          *end_x,
+                                                        gdouble          *end_y,
+                                                        gint              n_snap_lines);
+gchar * gimp_display_shell_get_line_status             (GimpDisplayShell *shell,
+                                                        const gchar      *status,
+                                                        const gchar      *separator,
+                                                        gdouble           x1,
+                                                        gdouble           y1,
+                                                        gdouble           x2,
+                                                        gdouble           y2);
 
 
 #endif  /*  __GIMP_DISPLAY_SHELL_UTILS_H__  */
diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c
index 2ff8fd0fb6..ceedd16844 100644
--- a/app/paint/gimppaintcore.c
+++ b/app/paint/gimppaintcore.c
@@ -673,9 +673,12 @@ gimp_paint_core_get_last_coords (GimpPaintCore *core,
 
 /**
  * gimp_paint_core_round_line:
- * @core:                 the #GimpPaintCore
- * @options:              the #GimpPaintOptions to use
- * @constrain_15_degrees: the modifier state
+ * @core:                   the #GimpPaintCore
+ * @options:                the #GimpPaintOptions to use
+ * @constrain_15_degrees:   the modifier state
+ * @constrain_offset_angle: the angle by which to offset the lines, in degrees
+ * @constrain_xres:         the horizontal resolution
+ * @constrain_yres:         the vertical resolution
  *
  * Adjusts core->last_coords and core_cur_coords in preparation to
  * drawing a straight line. If @center_pixels is TRUE the endpoints
@@ -689,7 +692,9 @@ void
 gimp_paint_core_round_line (GimpPaintCore    *core,
                             GimpPaintOptions *paint_options,
                             gboolean          constrain_15_degrees,
-                            gdouble           constrain_offset_angle)
+                            gdouble           constrain_offset_angle,
+                            gdouble           constrain_xres,
+                            gdouble           constrain_yres)
 {
   g_return_if_fail (GIMP_IS_PAINT_CORE (core));
   g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options));
@@ -706,7 +711,8 @@ gimp_paint_core_round_line (GimpPaintCore    *core,
     gimp_constrain_line (core->last_coords.x, core->last_coords.y,
                          &core->cur_coords.x, &core->cur_coords.y,
                          GIMP_CONSTRAIN_LINE_15_DEGREES,
-                         constrain_offset_angle);
+                         constrain_offset_angle,
+                         constrain_xres, constrain_yres);
 }
 
 
diff --git a/app/paint/gimppaintcore.h b/app/paint/gimppaintcore.h
index ba788982fa..350c7b0d8b 100644
--- a/app/paint/gimppaintcore.h
+++ b/app/paint/gimppaintcore.h
@@ -160,7 +160,9 @@ void      gimp_paint_core_get_last_coords           (GimpPaintCore    *core,
 void      gimp_paint_core_round_line                (GimpPaintCore    *core,
                                                      GimpPaintOptions *options,
                                                      gboolean          constrain_15_degrees,
-                                                     gdouble           constrain_offset_angle);
+                                                     gdouble           constrain_offset_angle,
+                                                     gdouble           constrain_xres,
+                                                     gdouble           constrain_yres);
 
 
 /*  protected functions  */
diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c
index 8320f5492a..9c37a40e3e 100644
--- a/app/tools/gimpeditselectiontool.c
+++ b/app/tools/gimpeditselectiontool.c
@@ -530,7 +530,7 @@ gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
     {
       gimp_constrain_line (edit_select->start_x, edit_select->start_y,
                            &new_x, &new_y,
-                           GIMP_CONSTRAIN_LINE_45_DEGREES, 0.0);
+                           GIMP_CONSTRAIN_LINE_45_DEGREES, 0.0, 1.0, 1.0);
     }
 
   gimp_edit_selection_tool_calc_coords (edit_select, image,
diff --git a/app/tools/gimppainttool-paint.c b/app/tools/gimppainttool-paint.c
index 39ce1ec1be..51fb4bce2e 100644
--- a/app/tools/gimppainttool-paint.c
+++ b/app/tools/gimppainttool-paint.c
@@ -289,13 +289,18 @@ gimp_paint_tool_paint_start (GimpPaintTool     *paint_tool,
     }
   else if (paint_tool->draw_line)
     {
+      gdouble offset_angle;
+      gdouble xres, yres;
+
+      gimp_display_shell_get_constrained_line_params (shell,
+                                                      &offset_angle,
+                                                      &xres, &yres);
+
       /*  If shift is down and this is not the first paint
        *  stroke, then draw a line from the last coords to the pointer
        */
-      gimp_paint_core_round_line (
-        core, paint_options,
-        constrain,
-        gimp_display_shell_get_constrained_line_offset_angle (shell));
+      gimp_paint_core_round_line (core, paint_options,
+                                  constrain, offset_angle, xres, yres);
     }
 
   /*  Notify subclasses  */
diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c
index ce85abef39..335904dfaa 100644
--- a/app/tools/gimppainttool.c
+++ b/app/tools/gimppainttool.c
@@ -570,11 +570,16 @@ gimp_paint_tool_oper_update (GimpTool         *tool,
            *  draw a line.
            */
           gchar   *status_help;
+          gdouble  offset_angle;
+          gdouble  xres, yres;
 
-          gimp_paint_core_round_line (
-            core, paint_options,
-            (state & constrain_mask) != 0,
-            gimp_display_shell_get_constrained_line_offset_angle (shell));
+          gimp_display_shell_get_constrained_line_params (shell,
+                                                          &offset_angle,
+                                                          &xres, &yres);
+
+          gimp_paint_core_round_line (core, paint_options,
+                                      (state & constrain_mask) != 0,
+                                      offset_angle, xres, yres);
 
           status_help = gimp_suggest_modifiers (paint_tool->status_line,
                                                 constrain_mask & ~state,


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