mirror of https://github.com/GNOME/gimp.git
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:
parent
a0129504c8
commit
4fefab1798
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue