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.
This commit is contained in:
Ell 2018-07-15 17:58:55 -04:00
parent a0129504c8
commit 4fefab1798
9 changed files with 103 additions and 98 deletions

View File

@ -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;
offset_angle *= G_PI / 180.0;
gimp_vector2_set (&line_dir,
cos (angle),
sin (angle));
diff.x = (*end_x - start_x) / xres;
diff.y = (*end_y - start_y) / yres;
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;
angle = (atan2 (diff.y, diff.x) - offset_angle) * n_snap_lines / G_PI;
angle = RINT (angle) * G_PI / n_snap_lines + offset_angle;
*end_x = constrained_point.x;
*end_y = constrained_point.y;
}
}
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

View File

@ -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);

View File

@ -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);
}
/**

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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 */

View File

@ -531,7 +531,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,

View File

@ -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 */

View File

@ -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,