[gimp] app: fix a few canvas scroll/scale rounding inconsistencies
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: fix a few canvas scroll/scale rounding inconsistencies
- Date: Tue, 9 Aug 2016 21:34:37 +0000 (UTC)
commit 720b73ca868c380c35c81e6d63b93bbaad18d308
Author: Ell <ell_se yahoo com>
Date: Sun Jul 24 13:01:12 2016 +0000
app: fix a few canvas scroll/scale rounding inconsistencies
Apply rounding more consistently across some of the scroll/scale
functions, to avoid annoying one-pixel-off scrollbar size/position
issues.
app/display/gimpdisplayshell-scale.c | 214 +++++++++++++++--------------
app/display/gimpdisplayshell-scale.h | 5 +
app/display/gimpdisplayshell-scroll.c | 108 +++++++++------
app/display/gimpdisplayshell-scrollbars.c | 89 ++++--------
4 files changed, 210 insertions(+), 206 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-scale.c b/app/display/gimpdisplayshell-scale.c
index 42c1ccb..3ca4ce1 100644
--- a/app/display/gimpdisplayshell-scale.c
+++ b/app/display/gimpdisplayshell-scale.c
@@ -17,6 +17,8 @@
#include "config.h"
+#include <math.h>
+
#include <gegl.h>
#include <gtk/gtk.h>
@@ -65,10 +67,12 @@ static void gimp_display_shell_calculate_scale_x_and_y
gdouble *scale_x,
gdouble *scale_y);
- static void gimp_display_shell_scale_to (GimpDisplayShell *shell,
+static void gimp_display_shell_scale_to (GimpDisplayShell *shell,
gdouble scale,
gdouble viewport_x,
gdouble viewport_y);
+static void gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell,
+ gboolean fill);
static gboolean gimp_display_shell_scale_image_starts_to_fit
(GimpDisplayShell *shell,
@@ -227,6 +231,50 @@ gimp_display_shell_scale_get_image_size (GimpDisplayShell *shell,
}
/**
+ * gimp_display_shell_scale_get_image_bounds:
+ * @shell:
+ * @x:
+ * @y:
+ * @w:
+ * @h:
+ *
+ * Gets the screen-space boudning box of the image, after it has
+ * been transformed (i.e., scaled, rotated, and scrolled).
+ **/
+void
+gimp_display_shell_scale_get_image_bounds (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ GimpImage *image;
+ gdouble x1, y1;
+ gdouble x2, y2;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ image = gimp_display_get_image (shell->display);
+
+ gimp_display_shell_transform_bounds (shell,
+ 0, 0,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ &x1, &y1,
+ &x2, &y2);
+
+ x1 = ceil (x1);
+ y1 = ceil (y1);
+ x2 = floor (x2);
+ y2 = floor (y2);
+
+ if (x) *x = x1 + shell->offset_x;
+ if (y) *y = y1 + shell->offset_y;
+ if (w) *w = x2 - x1;
+ if (h) *h = y2 - y1;
+}
+
+/**
* gimp_display_shell_scale_image_is_within_viewport:
* @shell:
*
@@ -465,11 +513,8 @@ gimp_display_shell_scale_to_rectangle (GimpDisplayShell *shell,
* center of viewport in screen coords without
* offset
*/
- offset_x = RINT (factor * (x + width / 2.0) -
- (shell->disp_width / 2.0));
-
- offset_y = RINT (factor * (y + height / 2.0) -
- (shell->disp_height / 2.0));
+ offset_x = RINT (factor * (x + width / 2.0) - (shell->disp_width / 2));
+ offset_y = RINT (factor * (y + height / 2.0) - (shell->disp_height / 2));
break;
case GIMP_ZOOM_OUT:
@@ -482,10 +527,10 @@ gimp_display_shell_scale_to_rectangle (GimpDisplayShell *shell,
* center of rectangle in screen coords without
* offset
*/
- offset_x = RINT (factor * (shell->offset_x + shell->disp_width / 2.0) -
- ((x + width / 2.0) - shell->offset_x));
+ offset_x = RINT (factor * (shell->offset_x + shell->disp_width / 2) -
+ ((x + width / 2.0) - shell->offset_x));
- offset_y = RINT (factor * (shell->offset_y + shell->disp_height / 2.0) -
+ offset_y = RINT (factor * (shell->offset_y + shell->disp_height / 2) -
((y + height / 2.0) - shell->offset_y));
break;
@@ -514,55 +559,11 @@ gimp_display_shell_scale_to_rectangle (GimpDisplayShell *shell,
void
gimp_display_shell_scale_fit_in (GimpDisplayShell *shell)
{
- GimpImage *image;
- gdouble image_x;
- gdouble image_y;
- gdouble image_width;
- gdouble image_height;
- gdouble zoom_factor;
-
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
- image = gimp_display_get_image (shell->display);
-
- gimp_display_shell_transform_bounds (shell,
- 0, 0,
- gimp_image_get_width (image),
- gimp_image_get_height (image),
- &image_x, &image_y,
- &image_width, &image_height);
-
- gimp_display_shell_unzoom_xy_f (shell,
- image_x, image_y,
- &image_x, &image_y);
- gimp_display_shell_unzoom_xy_f (shell,
- image_width, image_height,
- &image_width, &image_height);
-
- image_width -= image_x;
- image_height -= image_y;
-
- if (! shell->dot_for_dot)
- {
- gdouble xres;
- gdouble yres;
-
- gimp_image_get_resolution (image, &xres, &yres);
-
- image_width = RINT (image_width * shell->monitor_xres / xres);
- image_height = RINT (image_height * shell->monitor_yres / yres);
- }
-
- zoom_factor = MIN (shell->disp_width / image_width,
- shell->disp_height / image_height);
-
- gimp_display_shell_scale (shell,
- GIMP_ZOOM_TO,
- zoom_factor,
- GIMP_ZOOM_FOCUS_BEST_GUESS);
-
- gimp_display_shell_scroll_center_image (shell, TRUE, TRUE);
-}
+ gimp_display_shell_scale_fit_or_fill (shell,
+ /* fill = */ FALSE);
+ }
/**
* gimp_display_shell_scale_fill:
@@ -574,54 +575,10 @@ gimp_display_shell_scale_fit_in (GimpDisplayShell *shell)
void
gimp_display_shell_scale_fill (GimpDisplayShell *shell)
{
- GimpImage *image;
- gdouble image_x;
- gdouble image_y;
- gdouble image_width;
- gdouble image_height;
- gdouble zoom_factor;
-
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
- image = gimp_display_get_image (shell->display);
-
- gimp_display_shell_transform_bounds (shell,
- 0, 0,
- gimp_image_get_width (image),
- gimp_image_get_height (image),
- &image_x, &image_y,
- &image_width, &image_height);
-
- gimp_display_shell_unzoom_xy_f (shell,
- image_x, image_y,
- &image_x, &image_y);
- gimp_display_shell_unzoom_xy_f (shell,
- image_width, image_height,
- &image_width, &image_height);
-
- image_width -= image_x;
- image_height -= image_y;
-
- if (! shell->dot_for_dot)
- {
- gdouble xres;
- gdouble yres;
-
- gimp_image_get_resolution (image, &xres, &yres);
-
- image_width = RINT (image_width * shell->monitor_xres / xres);
- image_height = RINT (image_height * shell->monitor_yres / yres);
- }
-
- zoom_factor = MAX (shell->disp_width / image_width,
- shell->disp_height / image_height);
-
- gimp_display_shell_scale (shell,
- GIMP_ZOOM_TO,
- zoom_factor,
- GIMP_ZOOM_FOCUS_BEST_GUESS);
-
- gimp_display_shell_scroll_center_image (shell, TRUE, TRUE);
+ gimp_display_shell_scale_fit_or_fill (shell,
+ /* fill = */ TRUE);
}
/**
@@ -961,6 +918,59 @@ gimp_display_shell_scale_to (GimpDisplayShell *shell,
gimp_display_shell_resume (shell);
}
+/**
+ * gimp_display_shell_scale_fit_or_fill:
+ * @shell: the #GimpDisplayShell
+ * @fill: whether to scale the image to fill the viewport,
+ * or fit inside the viewport
+ *
+ * A common implementation for gimp_display_shell_scale_{fit_in,fill}().
+ **/
+static void
+gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell,
+ gboolean fill)
+{
+ GimpImage *image;
+ gdouble image_x;
+ gdouble image_y;
+ gdouble image_width;
+ gdouble image_height;
+ gdouble current_scale;
+ gdouble zoom_factor;
+
+ image = gimp_display_get_image (shell->display);
+
+ gimp_display_shell_transform_bounds (shell,
+ 0, 0,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ &image_x, &image_y,
+ &image_width, &image_height);
+
+ image_width -= image_x;
+ image_height -= image_y;
+
+ current_scale = gimp_zoom_model_get_factor (shell->zoom);
+
+ if (fill)
+ {
+ zoom_factor = MAX (shell->disp_width / image_width,
+ shell->disp_height / image_height);
+ }
+ else
+ {
+ zoom_factor = MIN (shell->disp_width / image_width,
+ shell->disp_height / image_height);
+ }
+
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_TO,
+ zoom_factor * current_scale,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+
+ gimp_display_shell_scroll_center_image (shell, TRUE, TRUE);
+}
+
static gboolean
gimp_display_shell_scale_image_starts_to_fit (GimpDisplayShell *shell,
gdouble new_scale,
diff --git a/app/display/gimpdisplayshell-scale.h b/app/display/gimpdisplayshell-scale.h
index 033a78d..4e55f26 100644
--- a/app/display/gimpdisplayshell-scale.h
+++ b/app/display/gimpdisplayshell-scale.h
@@ -29,6 +29,11 @@ void gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *shell,
void gimp_display_shell_scale_get_image_size (GimpDisplayShell *shell,
gint *w,
gint *h);
+void gimp_display_shell_scale_get_image_bounds (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
gboolean gimp_display_shell_scale_image_is_within_viewport
(GimpDisplayShell *shell,
gboolean *horizontally,
diff --git a/app/display/gimpdisplayshell-scroll.c b/app/display/gimpdisplayshell-scroll.c
index 089d738..75c81fb 100644
--- a/app/display/gimpdisplayshell-scroll.c
+++ b/app/display/gimpdisplayshell-scroll.c
@@ -18,6 +18,7 @@
#include "config.h"
#include <stdlib.h>
+#include <math.h>
#include <gegl.h>
#include <gtk/gtk.h>
@@ -159,58 +160,61 @@ gimp_display_shell_scroll_clamp_and_update (GimpDisplayShell *shell)
if (image)
{
- gdouble dx, dy;
- gdouble dw, dh;
- gint min_offset_x;
- gint max_offset_x;
- gint min_offset_y;
- gint max_offset_y;
- gint offset_x;
- gint offset_y;
+ gint bounds_x;
+ gint bounds_y;
+ gint bounds_width;
+ gint bounds_height;
+ gint min_offset_x;
+ gint max_offset_x;
+ gint min_offset_y;
+ gint max_offset_y;
+ gint offset_x;
+ gint offset_y;
gimp_display_shell_rotate_update_transform (shell);
- gimp_display_shell_transform_bounds (shell,
- 0, 0,
- gimp_image_get_width (image),
- gimp_image_get_height (image),
- &dx, &dy,
- &dw, &dh);
+ gimp_display_shell_scale_get_image_bounds (shell,
+ &bounds_x, &bounds_y,
+ &bounds_width, &bounds_height);
- /* Convert scrolled (x1, y1, x2, y2) to unscrolled (x, y, width, height). */
- dw -= dx;
- dh -= dy;
- dx += shell->offset_x;
- dy += shell->offset_y;
-
- if (shell->disp_width < dw)
+ if (shell->disp_width < bounds_width)
{
- min_offset_x = dx - shell->disp_width * OVERPAN_FACTOR;
- max_offset_x = dx + dw - shell->disp_width * (1.0 - OVERPAN_FACTOR);
+ min_offset_x = bounds_x -
+ shell->disp_width * OVERPAN_FACTOR;
+ max_offset_x = bounds_x + bounds_width -
+ shell->disp_width * (1.0 - OVERPAN_FACTOR);
}
else
{
gint overpan_amount;
- overpan_amount = shell->disp_width - dw * (1.0 - OVERPAN_FACTOR);
+ overpan_amount = shell->disp_width -
+ bounds_width * (1.0 - OVERPAN_FACTOR);
- min_offset_x = dx - overpan_amount;
- max_offset_x = dx + dw + overpan_amount - shell->disp_width;
+ min_offset_x = bounds_x -
+ overpan_amount;
+ max_offset_x = bounds_x + bounds_width - shell->disp_width +
+ overpan_amount;
}
- if (shell->disp_height < dh)
+ if (shell->disp_height < bounds_height)
{
- min_offset_y = dy - shell->disp_height * OVERPAN_FACTOR;
- max_offset_y = dy + dh - shell->disp_height * (1.0 - OVERPAN_FACTOR);
+ min_offset_y = bounds_y
+ - shell->disp_height * OVERPAN_FACTOR;
+ max_offset_y = bounds_y + bounds_height -
+ shell->disp_height * (1.0 - OVERPAN_FACTOR);
}
else
{
gint overpan_amount;
- overpan_amount = shell->disp_height - dh * (1.0 - OVERPAN_FACTOR);
+ overpan_amount = shell->disp_height -
+ bounds_height * (1.0 - OVERPAN_FACTOR);
- min_offset_y = dy - overpan_amount;
- max_offset_y = dy + dh + overpan_amount - shell->disp_height;
+ min_offset_y = bounds_y -
+ overpan_amount;
+ max_offset_y = bounds_y + bounds_height +
+ overpan_amount - shell->disp_height;
}
/* Clamp */
@@ -341,11 +345,14 @@ gimp_display_shell_scroll_center_image (GimpDisplayShell *shell,
gboolean horizontally,
gboolean vertically)
{
- GimpImage *image;
- gint center_x;
- gint center_y;
- gint offset_x = 0;
- gint offset_y = 0;
+ gint image_x;
+ gint image_y;
+ gint image_width;
+ gint image_height;
+ gint center_x;
+ gint center_y;
+ gint offset_x = 0;
+ gint offset_y = 0;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
@@ -354,19 +361,30 @@ gimp_display_shell_scroll_center_image (GimpDisplayShell *shell,
(! vertically && ! horizontally))
return;
- image = gimp_display_get_image (shell->display);
+ gimp_display_shell_scale_get_image_bounds (shell,
+ &image_x, &image_y,
+ &image_width, &image_height);
- gimp_display_shell_transform_xy (shell,
- gimp_image_get_width (image) / 2,
- gimp_image_get_height (image) / 2,
- ¢er_x,
- ¢er_y);
+ if (shell->disp_width > image_width)
+ {
+ image_x -= (shell->disp_width - image_width) / 2;
+ image_width = shell->disp_width;
+ }
+
+ if (shell->disp_height > image_height)
+ {
+ image_y -= (shell->disp_height - image_height) / 2;
+ image_height = shell->disp_height;
+ }
+
+ center_x = image_x + image_width / 2;
+ center_y = image_y + image_height / 2;
if (horizontally)
- offset_x = center_x - shell->disp_width / 2;
+ offset_x = center_x - shell->disp_width / 2 - shell->offset_x;
if (vertically)
- offset_y = center_y - shell->disp_height / 2;
+ offset_y = center_y - shell->disp_height / 2 - shell->offset_y;
gimp_display_shell_scroll (shell, offset_x, offset_y);
}
diff --git a/app/display/gimpdisplayshell-scrollbars.c b/app/display/gimpdisplayshell-scrollbars.c
index fd61d81..34c461b 100644
--- a/app/display/gimpdisplayshell-scrollbars.c
+++ b/app/display/gimpdisplayshell-scrollbars.c
@@ -17,6 +17,8 @@
#include "config.h"
+#include <math.h>
+
#include <gegl.h>
#include <gtk/gtk.h>
@@ -27,7 +29,6 @@
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-scale.h"
-#include "gimpdisplayshell-transform.h"
#include "gimpdisplayshell-scrollbars.h"
@@ -90,44 +91,29 @@ void
gimp_display_shell_scrollbars_setup_horizontal (GimpDisplayShell *shell,
gdouble value)
{
- GimpImage *image;
- gdouble dx, dy;
- gdouble dw, dh;
- gdouble lower;
- gdouble upper;
+ gint bounds_x;
+ gint bounds_width;
+ gdouble lower;
+ gdouble upper;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
- if (! shell->display)
- return;
-
- image = gimp_display_get_image (shell->display);
- if (! image)
+ if (! shell->display || ! gimp_display_get_image (shell->display))
return;
- gimp_display_shell_transform_bounds (shell,
- 0, 0,
- gimp_image_get_width (image),
- gimp_image_get_height (image),
- &dx, &dy,
- &dw, &dh);
+ gimp_display_shell_scale_get_image_bounds (shell,
+ &bounds_x, NULL,
+ &bounds_width, NULL);
- /* Convert scrolled (x1, x2) to unscrolled (x, width). */
- dw -= dx;
- dx += shell->offset_x;
-
- if (shell->disp_width < dw)
- {
- lower = MIN (value, dx);
- upper = MAX (value + shell->disp_width, dx + dw);
- }
- else
+ if (shell->disp_width > bounds_width)
{
- lower = MIN (value, dx - (shell->disp_width - dw) / 2);
- upper = MAX (value + shell->disp_width,
- dx + dw + (shell->disp_width - dw) / 2);
+ bounds_x -= (shell->disp_width - bounds_width) / 2;
+ bounds_width = shell->disp_width;
}
+ lower = MIN (value, bounds_x);
+ upper = MAX (value + shell->disp_width, bounds_x + bounds_width);
+
g_object_set (shell->hsbdata,
"lower", lower,
"upper", upper,
@@ -147,44 +133,29 @@ void
gimp_display_shell_scrollbars_setup_vertical (GimpDisplayShell *shell,
gdouble value)
{
- GimpImage *image;
- gdouble dx, dy;
- gdouble dw, dh;
- gdouble lower;
- gdouble upper;
+ gint bounds_y;
+ gint bounds_height;
+ gdouble lower;
+ gdouble upper;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
- if (! shell->display)
- return;
-
- image = gimp_display_get_image (shell->display);
- if (! image)
+ if (! shell->display || ! gimp_display_get_image (shell->display))
return;
- gimp_display_shell_transform_bounds (shell,
- 0, 0,
- gimp_image_get_width (image),
- gimp_image_get_height (image),
- &dx, &dy,
- &dw, &dh);
-
- /* Convert scrolled (y1, y2) to unscrolled (y, height). */
- dh -= dy;
- dy += shell->offset_y;
+ gimp_display_shell_scale_get_image_bounds (shell,
+ NULL, &bounds_y,
+ NULL, &bounds_height);
- if (shell->disp_height < dh)
+ if (shell->disp_height > bounds_height)
{
- lower = MIN (value, dy);
- upper = MAX (value + shell->disp_height, dy + dh);
- }
- else
- {
- lower = MIN (value, dy - (shell->disp_height - dh) / 2);
- upper = MAX (value + shell->disp_height,
- dy + dh + (shell->disp_height - dh) / 2);
+ bounds_y -= (shell->disp_height - bounds_height) / 2;
+ bounds_height = shell->disp_height;
}
+ lower = MIN (value, bounds_y);
+ upper = MAX (value + shell->disp_height, bounds_y + bounds_height);
+
g_object_set (shell->vsbdata,
"lower", lower,
"upper", upper,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]