[gimp] Bug 791741 - Transparent rectangles when image is drawn
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 791741 - Transparent rectangles when image is drawn
- Date: Tue, 19 Dec 2017 20:05:10 +0000 (UTC)
commit 231578411013e3009d6793d95ae2d742c8166cea
Author: Ell <ell_se yahoo com>
Date: Tue Dec 19 14:42:28 2017 -0500
Bug 791741 - Transparent rectangles when image is drawn
Add gimp_display_shell_[un]transform_with_scale(), which are
similar to gimp_display_shell_[un]transform(), however, they
transform the bounding box to/from uniformly-scaled image space,
given the scale factor as a parameter. These functions are more
accurate than using gimp_display_shell_[un]transform() and applying
the scaling separately, in particular, when the scale matches the
(horizontal or vertical) display scale.
Use these functions in gimp_display_shell_draw_image(), to avoid an
off-by-one error when transforming screen-space chunks to image-
space chunks, which leads to the symptoms described in the bug.
Fix another potential off-by-one error affecting non-uniformly
scaled images, and window scale factors other than 1.
app/display/gimpdisplayshell-draw.c | 29 ++--
app/display/gimpdisplayshell-transform.c | 86 +++++++++
app/display/gimpdisplayshell-transform.h | 295 ++++++++++++++++--------------
3 files changed, 260 insertions(+), 150 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index c696775..372f275 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -166,11 +166,13 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
#endif
- scale = MIN (scale, GIMP_DISPLAY_RENDER_MAX_SCALE);
+ scale = MIN (scale, GIMP_DISPLAY_RENDER_MAX_SCALE);
+ scale *= MAX (shell->scale_x, shell->scale_y);
- scale *= MAX (shell->scale_x, shell->scale_y);
- chunk_width *= shell->scale_x / scale;
- chunk_height *= shell->scale_y / scale;
+ if (scale != shell->scale_x)
+ chunk_width = (chunk_width - 1.0) * (shell->scale_x / scale);
+ if (scale != shell->scale_y)
+ chunk_height = (chunk_height - 1.0) * (shell->scale_y / scale);
if (shell->rotate_untransform)
{
@@ -198,15 +200,16 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
gint ix, iy;
gint iw, ih;
- /* map chunk from screen space to image space */
- gimp_display_shell_untransform_bounds (shell,
- x1, y1, x2, y2,
- &ix1, &iy1, &ix2, &iy2);
+ /* map chunk from screen space to scaled image space */
+ gimp_display_shell_untransform_bounds_with_scale (
+ shell, scale,
+ x1, y1, x2, y2,
+ &ix1, &iy1, &ix2, &iy2);
- ix = floor (ix1 * scale);
- iy = floor (iy1 * scale);
- iw = ceil (ix2 * scale) - ix;
- ih = ceil (iy2 * scale) - iy;
+ ix = floor (ix1);
+ iy = floor (iy1);
+ iw = ceil (ix2) - ix;
+ ih = ceil (iy2) - iy;
cairo_save (cr);
@@ -214,7 +217,7 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
cairo_rectangle (cr, x1, y1, x2 - x1, y2 - y1);
cairo_clip (cr);
- /* transform to image space, and apply uneven scaling */
+ /* transform to scaled image space, and apply uneven scaling */
if (shell->rotate_transform)
cairo_transform (cr, shell->rotate_transform);
cairo_translate (cr, -shell->offset_x, -shell->offset_y);
diff --git a/app/display/gimpdisplayshell-transform.c b/app/display/gimpdisplayshell-transform.c
index a247a94..84918ab 100644
--- a/app/display/gimpdisplayshell-transform.c
+++ b/app/display/gimpdisplayshell-transform.c
@@ -863,6 +863,92 @@ gimp_display_shell_untransform_bounds (GimpDisplayShell *shell,
}
}
+/* transforms a bounding box from image-space, uniformly scaled by a factor of
+ * 'scale', to display-space. this is equivalent to, but more accurate than,
+ * dividing the input by 'scale', and using
+ * gimp_display_shell_transform_bounds(), in particular, in that if 'scale'
+ * equals 'shell->scale_x' or 'shell->scale_y', there is no loss in accuracy
+ * in the corresponding dimension due to scaling (although there might be loss
+ * of accuracy due to rotation or translation.)
+ */
+void
+gimp_display_shell_transform_bounds_with_scale (GimpDisplayShell *shell,
+ gdouble scale,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2)
+{
+ gdouble factor_x;
+ gdouble factor_y;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+ g_return_if_fail (scale > 0.0);
+ g_return_if_fail (nx1 != NULL);
+ g_return_if_fail (ny1 != NULL);
+ g_return_if_fail (nx2 != NULL);
+ g_return_if_fail (ny2 != NULL);
+
+ factor_x = shell->scale_x / scale;
+ factor_y = shell->scale_y / scale;
+
+ x1 = x1 * factor_x - shell->offset_x;
+ y1 = y1 * factor_y - shell->offset_y;
+ x2 = x2 * factor_x - shell->offset_x;
+ y2 = y2 * factor_y - shell->offset_y;
+
+ gimp_display_shell_rotate_bounds (shell,
+ x1, y1, x2, y2,
+ nx1, ny1, nx2, ny2);
+}
+
+/* transforms a bounding box from display-space to image-space, uniformly
+ * scaled by a factor of 'scale'. this is equivalent to, but more accurate
+ * than, using gimp_display_shell_untransform_bounds(), and multiplying the
+ * output by 'scale', in particular, in that if 'scale' equals 'shell->scale_x'
+ * or 'shell->scale_y', there is no loss in accuracy in the corresponding
+ * dimension due to scaling (although there might be loss of accuracy due to
+ * rotation or translation.)
+ */
+void
+gimp_display_shell_untransform_bounds_with_scale (GimpDisplayShell *shell,
+ gdouble scale,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2)
+{
+ gdouble factor_x;
+ gdouble factor_y;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+ g_return_if_fail (scale > 0.0);
+ g_return_if_fail (nx1 != NULL);
+ g_return_if_fail (ny1 != NULL);
+ g_return_if_fail (nx2 != NULL);
+ g_return_if_fail (ny2 != NULL);
+
+ factor_x = scale / shell->scale_x;
+ factor_y = scale / shell->scale_y;
+
+ gimp_display_shell_unrotate_bounds (shell,
+ x1, y1, x2, y2,
+ nx1, ny1, nx2, ny2);
+
+ *nx1 = (*nx1 + shell->offset_x) * factor_x;
+ *ny1 = (*ny1 + shell->offset_y) * factor_y;
+ *nx2 = (*nx2 + shell->offset_x) * factor_x;
+ *ny2 = (*ny2 + shell->offset_y) * factor_y;
+}
+
/**
* gimp_display_shell_untransform_viewport:
* @shell: a #GimpDisplayShell
diff --git a/app/display/gimpdisplayshell-transform.h b/app/display/gimpdisplayshell-transform.h
index 8d5bd6b..9b6a1a0 100644
--- a/app/display/gimpdisplayshell-transform.h
+++ b/app/display/gimpdisplayshell-transform.h
@@ -23,95 +23,95 @@
* space and back, taking into account scroll offset and scale
*/
-void gimp_display_shell_zoom_coords (GimpDisplayShell *shell,
- const GimpCoords *image_coords,
- GimpCoords *display_coords);
-void gimp_display_shell_unzoom_coords (GimpDisplayShell *shell,
- const GimpCoords *display_coords,
- GimpCoords *image_coords);
-
-void gimp_display_shell_zoom_xy (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gint *nx,
- gint *ny);
-void gimp_display_shell_unzoom_xy (GimpDisplayShell *shell,
- gint x,
- gint y,
- gint *nx,
- gint *ny,
- gboolean round);
-
-void gimp_display_shell_zoom_xy_f (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gdouble *nx,
- gdouble *ny);
-void gimp_display_shell_unzoom_xy_f (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gdouble *nx,
- gdouble *ny);
-
-void gimp_display_shell_zoom_segments (GimpDisplayShell *shell,
- const GimpBoundSeg *src_segs,
- GimpSegment *dest_segs,
- gint n_segs,
- gdouble offset_x,
- gdouble offset_y);
+void gimp_display_shell_zoom_coords (GimpDisplayShell *shell,
+ const GimpCoords *image_coords,
+ GimpCoords *display_coords);
+void gimp_display_shell_unzoom_coords (GimpDisplayShell *shell,
+ const GimpCoords *display_coords,
+ GimpCoords *image_coords);
+
+void gimp_display_shell_zoom_xy (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gint *nx,
+ gint *ny);
+void gimp_display_shell_unzoom_xy (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint *nx,
+ gint *ny,
+ gboolean round);
+
+void gimp_display_shell_zoom_xy_f (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gdouble *nx,
+ gdouble *ny);
+void gimp_display_shell_unzoom_xy_f (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gdouble *nx,
+ gdouble *ny);
+
+void gimp_display_shell_zoom_segments (GimpDisplayShell *shell,
+ const GimpBoundSeg *src_segs,
+ GimpSegment *dest_segs,
+ gint n_segs,
+ gdouble offset_x,
+ gdouble offset_y);
/* rotate: functions to transform from unrotated and unflipped but
* zoomed display space to rotated and filpped display space and back
*/
-void gimp_display_shell_rotate_coords (GimpDisplayShell *shell,
- const GimpCoords *image_coords,
- GimpCoords *display_coords);
-void gimp_display_shell_unrotate_coords (GimpDisplayShell *shell,
- const GimpCoords *display_coords,
- GimpCoords *image_coords);
-
-void gimp_display_shell_rotate_xy (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gint *nx,
- gint *ny);
-void gimp_display_shell_unrotate_xy (GimpDisplayShell *shell,
- gint x,
- gint y,
- gint *nx,
- gint *ny);
-
-void gimp_display_shell_rotate_xy_f (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gdouble *nx,
- gdouble *ny);
-void gimp_display_shell_unrotate_xy_f (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gdouble *nx,
- gdouble *ny);
-
-void gimp_display_shell_rotate_bounds (GimpDisplayShell *shell,
- gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2,
- gdouble *nx1,
- gdouble *ny1,
- gdouble *nx2,
- gdouble *ny2);
-void gimp_display_shell_unrotate_bounds (GimpDisplayShell *shell,
- gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2,
- gdouble *nx1,
- gdouble *ny1,
- gdouble *nx2,
- gdouble *ny2);
+void gimp_display_shell_rotate_coords (GimpDisplayShell *shell,
+ const GimpCoords *image_coords,
+ GimpCoords *display_coords);
+void gimp_display_shell_unrotate_coords (GimpDisplayShell *shell,
+ const GimpCoords *display_coords,
+ GimpCoords *image_coords);
+
+void gimp_display_shell_rotate_xy (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gint *nx,
+ gint *ny);
+void gimp_display_shell_unrotate_xy (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint *nx,
+ gint *ny);
+
+void gimp_display_shell_rotate_xy_f (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gdouble *nx,
+ gdouble *ny);
+void gimp_display_shell_unrotate_xy_f (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gdouble *nx,
+ gdouble *ny);
+
+void gimp_display_shell_rotate_bounds (GimpDisplayShell *shell,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2);
+void gimp_display_shell_unrotate_bounds (GimpDisplayShell *shell,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2);
/* transform: functions to transform from image space to rotated
@@ -119,60 +119,81 @@ void gimp_display_shell_unrotate_bounds (GimpDisplayShell *shell,
* rotation and flipping
*/
-void gimp_display_shell_transform_coords (GimpDisplayShell *shell,
- const GimpCoords *image_coords,
- GimpCoords *display_coords);
-void gimp_display_shell_untransform_coords (GimpDisplayShell *shell,
- const GimpCoords *display_coords,
- GimpCoords *image_coords);
-
-void gimp_display_shell_transform_xy (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gint *nx,
- gint *ny);
-void gimp_display_shell_untransform_xy (GimpDisplayShell *shell,
- gint x,
- gint y,
- gint *nx,
- gint *ny,
- gboolean round);
-
-void gimp_display_shell_transform_xy_f (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gdouble *nx,
- gdouble *ny);
-void gimp_display_shell_untransform_xy_f (GimpDisplayShell *shell,
- gdouble x,
- gdouble y,
- gdouble *nx,
- gdouble *ny);
-
-void gimp_display_shell_transform_bounds (GimpDisplayShell *shell,
- gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2,
- gdouble *nx1,
- gdouble *ny1,
- gdouble *nx2,
- gdouble *ny2);
-void gimp_display_shell_untransform_bounds (GimpDisplayShell *shell,
- gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2,
- gdouble *nx1,
- gdouble *ny1,
- gdouble *nx2,
- gdouble *ny2);
-
-void gimp_display_shell_untransform_viewport (GimpDisplayShell *shell,
- gint *x,
- gint *y,
- gint *width,
- gint *height);
+void gimp_display_shell_transform_coords (GimpDisplayShell *shell,
+ const GimpCoords *image_coords,
+ GimpCoords *display_coords);
+void gimp_display_shell_untransform_coords (GimpDisplayShell *shell,
+ const GimpCoords *display_coords,
+ GimpCoords *image_coords);
+
+void gimp_display_shell_transform_xy (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gint *nx,
+ gint *ny);
+void gimp_display_shell_untransform_xy (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint *nx,
+ gint *ny,
+ gboolean round);
+
+void gimp_display_shell_transform_xy_f (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gdouble *nx,
+ gdouble *ny);
+void gimp_display_shell_untransform_xy_f (GimpDisplayShell *shell,
+ gdouble x,
+ gdouble y,
+ gdouble *nx,
+ gdouble *ny);
+
+void gimp_display_shell_transform_bounds (GimpDisplayShell *shell,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2);
+void gimp_display_shell_untransform_bounds (GimpDisplayShell *shell,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2);
+
+void gimp_display_shell_transform_bounds_with_scale (GimpDisplayShell *shell,
+ gdouble scale,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2);
+void gimp_display_shell_untransform_bounds_with_scale (GimpDisplayShell *shell,
+ gdouble scale,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2,
+ gdouble *nx1,
+ gdouble *ny1,
+ gdouble *nx2,
+ gdouble *ny2);
+
+void gimp_display_shell_untransform_viewport (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height);
#endif /* __GIMP_DISPLAY_SHELL_TRANSFORM_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]