Commit 5bdb20c8 authored by Ell's avatar Ell

app: make rulers rotation aware

Place the rulers' origin at the top-left corner of the canvas
(screen space) bounding box, and set their scale to the image-
space scale along the screen-space horizontal/vertical directions
(in other words, measuring a distance using the rulers should
give the same results as the measure tool; note that rotation
comes into play here only when the horizontal and vertical
image or screen resolutions are different, since otherwise the
scale is direction invariant.)

Make scrollbar step match ruler step under the new behavior.
parent 720b73ca
......@@ -17,10 +17,13 @@
#include "config.h"
#include <math.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "display-types.h"
......@@ -30,6 +33,7 @@
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-rulers.h"
#include "gimpdisplayshell-scale.h"
/**
......@@ -43,6 +47,10 @@ gimp_display_shell_rulers_update (GimpDisplayShell *shell)
GimpImage *image;
gint image_width;
gint image_height;
gdouble offset_x = 0.0;
gdouble offset_y = 0.0;
gdouble scale_x = 1.0;
gdouble scale_y = 1.0;
gdouble resolution_x = 1.0;
gdouble resolution_y = 1.0;
gdouble horizontal_lower;
......@@ -59,10 +67,37 @@ gimp_display_shell_rulers_update (GimpDisplayShell *shell)
if (image)
{
image_width = gimp_image_get_width (image);
image_height = gimp_image_get_height (image);
gint image_x, image_y;
gdouble res_x, res_y;
gdouble cos_a, sin_a;
gimp_display_shell_scale_get_image_bounds (shell,
&image_x, &image_y,
&image_width, &image_height);
gimp_display_shell_get_rotated_scale (shell, &scale_x, &scale_y);
image_width /= scale_x;
image_height /= scale_y;
gimp_image_get_resolution (image, &resolution_x, &resolution_y);
offset_x = shell->offset_x - image_x;
offset_y = shell->offset_y - image_y;
gimp_image_get_resolution (image, &res_x, &res_y);
cos_a = cos (G_PI * shell->rotate_angle / 180.0);
sin_a = sin (G_PI * shell->rotate_angle / 180.0);
if (shell->dot_for_dot)
{
resolution_x = 1.0 / sqrt (SQR (cos_a / res_x) + SQR (sin_a / res_y));
resolution_y = 1.0 / sqrt (SQR (cos_a / res_y) + SQR (sin_a / res_x));
}
else
{
resolution_x = sqrt (SQR (res_x * cos_a) + SQR (res_y * sin_a));
resolution_y = sqrt (SQR (res_y * cos_a) + SQR (res_x * sin_a));
}
}
else
{
......@@ -70,7 +105,6 @@ gimp_display_shell_rulers_update (GimpDisplayShell *shell)
image_height = shell->disp_height;
}
/* Initialize values */
horizontal_lower = 0;
......@@ -78,8 +112,7 @@ gimp_display_shell_rulers_update (GimpDisplayShell *shell)
if (image)
{
horizontal_upper = gimp_pixels_to_units (FUNSCALEX (shell,
shell->disp_width),
horizontal_upper = gimp_pixels_to_units (shell->disp_width / scale_x,
shell->unit,
resolution_x);
horizontal_max_size = gimp_pixels_to_units (MAX (image_width,
......@@ -87,8 +120,7 @@ gimp_display_shell_rulers_update (GimpDisplayShell *shell)
shell->unit,
resolution_x);
vertical_upper = gimp_pixels_to_units (FUNSCALEY (shell,
shell->disp_height),
vertical_upper = gimp_pixels_to_units (shell->disp_height / scale_y,
shell->unit,
resolution_y);
vertical_max_size = gimp_pixels_to_units (MAX (image_width,
......@@ -110,18 +142,8 @@ gimp_display_shell_rulers_update (GimpDisplayShell *shell)
if (image)
{
gdouble offset_x;
gdouble offset_y;
offset_x = gimp_pixels_to_units (FUNSCALEX (shell,
(gdouble) shell->offset_x),
shell->unit,
resolution_x);
offset_y = gimp_pixels_to_units (FUNSCALEX (shell,
(gdouble) shell->offset_y),
shell->unit,
resolution_y);
offset_x *= horizontal_upper / shell->disp_width;
offset_y *= vertical_upper / shell->disp_height;
horizontal_lower += offset_x;
horizontal_upper += offset_x;
......
......@@ -764,6 +764,41 @@ gimp_display_shell_set_initial_scale (GimpDisplayShell *shell,
*display_height = shell_height;
}
/**
* gimp_display_shell_get_rotated_scale:
* @shell: the #GimpDisplayShell
* @scale_x: horizontal scale output
* @scale_y: vertical scale output
*
* Returns the screen space horizontal and vertical scaling
* factors, taking rotation into account.
**/
void
gimp_display_shell_get_rotated_scale (GimpDisplayShell *shell,
gdouble *scale_x,
gdouble *scale_y)
{
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
if (shell->rotate_angle == 0.0)
{
if (scale_x) *scale_x = shell->scale_x;
if (scale_y) *scale_y = shell->scale_y;
}
else
{
gdouble a = G_PI * shell->rotate_angle / 180.0;
gdouble cos_a = cos (a);
gdouble sin_a = sin (a);
if (scale_x) *scale_x = 1.0 / sqrt (SQR (cos_a / shell->scale_x) +
SQR (sin_a / shell->scale_y));
if (scale_y) *scale_y = 1.0 / sqrt (SQR (cos_a / shell->scale_y) +
SQR (sin_a / shell->scale_x));
}
}
/**
* gimp_display_shell_push_zoom_focus_pointer_pos:
* @shell:
......
......@@ -70,6 +70,9 @@ void gimp_display_shell_set_initial_scale (GimpDisplayShell *shell,
gint *display_width,
gint *display_height);
void gimp_display_shell_get_rotated_scale (GimpDisplayShell *shell,
gdouble *scale_x,
gdouble *scale_y);
/* debug API for testing */
......
......@@ -95,6 +95,7 @@ gimp_display_shell_scrollbars_setup_horizontal (GimpDisplayShell *shell,
gint bounds_width;
gdouble lower;
gdouble upper;
gdouble scale_x;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
......@@ -114,11 +115,12 @@ gimp_display_shell_scrollbars_setup_horizontal (GimpDisplayShell *shell,
lower = MIN (value, bounds_x);
upper = MAX (value + shell->disp_width, bounds_x + bounds_width);
gimp_display_shell_get_rotated_scale (shell, &scale_x, NULL);
g_object_set (shell->hsbdata,
"lower", lower,
"upper", upper,
"step-increment", (gdouble) MAX (shell->scale_x,
MINIMUM_STEP_AMOUNT),
"step-increment", (gdouble) MAX (scale_x, MINIMUM_STEP_AMOUNT),
NULL);
}
......@@ -137,6 +139,7 @@ gimp_display_shell_scrollbars_setup_vertical (GimpDisplayShell *shell,
gint bounds_height;
gdouble lower;
gdouble upper;
gdouble scale_y;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
......@@ -156,11 +159,12 @@ gimp_display_shell_scrollbars_setup_vertical (GimpDisplayShell *shell,
lower = MIN (value, bounds_y);
upper = MAX (value + shell->disp_height, bounds_y + bounds_height);
gimp_display_shell_get_rotated_scale (shell, NULL, &scale_y);
g_object_set (shell->vsbdata,
"lower", lower,
"upper", upper,
"step-increment", (gdouble) MAX (shell->scale_y,
MINIMUM_STEP_AMOUNT),
"step-increment", (gdouble) MAX (scale_y, MINIMUM_STEP_AMOUNT),
NULL);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment