From 2f31d12f869c115b60b62b1d66a29237e282b0c8 Mon Sep 17 00:00:00 2001 From: Pedro Gimeno Date: Sun, 25 May 2003 23:23:34 +0000 Subject: [PATCH] Fix off-by-one when dragging the selection. Fixes the last pending issue 2003-05-26 Pedro Gimeno * app/tools/gimpeditselectiontool.c (selection_transform_segs): Fix off-by-one when dragging the selection. Fixes the last pending issue of bug #17904. Use temporary variables for clamp values. * app/display/gimpdisplayshell-selection.c (selection_transform_segs): Perform the clamping that fixes bug #110014 here instead of in the callers. Solves a rare case that was not properly handled before. (selection_render_points, selection_generate_segs): Remove the clamping code from here. * app/tools/gimpdrawtool.c (gimp_draw_tool_draw_rectangle): More clampings to avoid overflow of 16-bit coordinates. --- ChangeLog | 16 ++++++ app/display/gimpdisplayshell-selection.c | 72 +++++++++--------------- app/tools/gimpdrawtool.c | 5 ++ app/tools/gimpeditselectiontool.c | 32 +++++++++-- 4 files changed, 76 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7514da8986..af35fc404b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2003-05-26 Pedro Gimeno + + * app/tools/gimpeditselectiontool.c (selection_transform_segs): + Fix off-by-one when dragging the selection. Fixes the last pending + issue of bug #17904. Use temporary variables for clamp values. + + * app/display/gimpdisplayshell-selection.c + (selection_transform_segs): Perform the clamping that fixes + bug #110014 here instead of in the callers. Solves a rare case + that was not properly handled before. + (selection_render_points, selection_generate_segs): Remove the + clamping code from here. + + * app/tools/gimpdrawtool.c (gimp_draw_tool_draw_rectangle): More + clampings to avoid overflow of 16-bit coordinates. + 2003-05-25 Maurits Rijk * plug-ins/imagemap/imap_csim_parse.[ch]: regenerated diff --git a/app/display/gimpdisplayshell-selection.c b/app/display/gimpdisplayshell-selection.c index 6bbeab25d5..83954f484a 100644 --- a/app/display/gimpdisplayshell-selection.c +++ b/app/display/gimpdisplayshell-selection.c @@ -486,14 +486,10 @@ selection_render_points (Selection *select) gint dx, dy; gint dxa, dya; gint r; - gint xsize, ysize; - gint x2, y2; if (select->segs_in == NULL) return; - g_return_if_fail (select->shell != NULL); - for (j = 0; j < 8; j++) { max_npoints[j] = MAX_POINTS_INC; @@ -501,9 +497,6 @@ selection_render_points (Selection *select) select->num_points_in[j] = 0; } - xsize = select->shell->disp_width; - ysize = select->shell->disp_height; - for (i = 0; i < select->num_segs_in; i++) { #ifdef VERBOSE @@ -513,9 +506,8 @@ selection_render_points (Selection *select) select->segs_in[i].x2, select->segs_in[i].y2); #endif - x = CLAMP (select->segs_in[i].x1, -1, xsize); - x2 = CLAMP (select->segs_in[i].x2, -1, xsize); - dxa = x2 - x; + x = select->segs_in[i].x1; + dxa = select->segs_in[i].x2 - x; if (dxa > 0) { dx = 1; @@ -525,9 +517,8 @@ selection_render_points (Selection *select) dxa = -dxa; dx = -1; } - y = CLAMP (select->segs_in[i].y1, -1, ysize); - y2 = CLAMP (select->segs_in[i].y2, -1, ysize); - dya = y2 - y; + y = select->segs_in[i].y1; + dya = select->segs_in[i].y2 - y; if (dya > 0) { dy = 1; @@ -551,7 +542,7 @@ selection_render_points (Selection *select) y += dy; r -= (dxa << 1); } - } while (x != x2); + } while (x != select->segs_in[i].x2); } else if (dxa < dya) { @@ -567,7 +558,7 @@ selection_render_points (Selection *select) x += dx; r -= (dya << 1); } - } while (y != y2); + } while (y != select->segs_in[i].y2); } else selection_add_point (select->points_in, @@ -645,6 +636,10 @@ selection_transform_segs (Selection *select, { gint x, y; gint i; + gint xclamp, yclamp; + + xclamp = select->shell->disp_width + 1; + yclamp = select->shell->disp_height + 1; for (i = 0; i < num_segs; i++) { @@ -653,16 +648,16 @@ selection_transform_segs (Selection *select, &x, &y, FALSE); - dest_segs[i].x1 = x; - dest_segs[i].y1 = y; + dest_segs[i].x1 = CLAMP (x, -1, xclamp); + dest_segs[i].y1 = CLAMP (y, -1, yclamp); gimp_display_shell_transform_xy (select->shell, src_segs[i].x2, src_segs[i].y2, &x, &y, FALSE); - dest_segs[i].x2 = x; - dest_segs[i].y2 = y; + dest_segs[i].x2 = CLAMP (x, -1, xclamp); + dest_segs[i].y2 = CLAMP (y, -1, yclamp); /* If this segment is a closing segment && the segments lie inside * the region, OR if this is an opening segment and the segments @@ -670,19 +665,19 @@ selection_transform_segs (Selection *select, * we need to transform it by one display pixel */ if (!src_segs[i].open) - { - /* If it is vertical */ - if (dest_segs[i].x1 == dest_segs[i].x2) - { - dest_segs[i].x1 -= 1; - dest_segs[i].x2 -= 1; - } - else - { - dest_segs[i].y1 -= 1; - dest_segs[i].y2 -= 1; - } - } + { + /* If it is vertical */ + if (dest_segs[i].x1 == dest_segs[i].x2) + { + dest_segs[i].x1 -= 1; + dest_segs[i].x2 -= 1; + } + else + { + dest_segs[i].y1 -= 1; + dest_segs[i].y2 -= 1; + } + } } } @@ -733,22 +728,9 @@ selection_generate_segs (Selection *select) if (select->num_segs_layer) { - gint i; - GdkSegment *seg; - select->segs_layer = g_new (GdkSegment, select->num_segs_layer); selection_transform_segs (select, segs_layer, select->segs_layer, select->num_segs_layer); - - seg = select->segs_layer; - for (i = 0; i < select->num_segs_layer; i++) - { - seg->x1 = CLAMP (seg->x1, -1, select->shell->disp_width); - seg->y1 = CLAMP (seg->y1, -1, select->shell->disp_height); - seg->x2 = CLAMP (seg->x2, -1, select->shell->disp_width); - seg->y2 = CLAMP (seg->y2, -1, select->shell->disp_height); - seg++; - } } else { diff --git a/app/tools/gimpdrawtool.c b/app/tools/gimpdrawtool.c index 3a3ff8d703..b92b55462d 100644 --- a/app/tools/gimpdrawtool.c +++ b/app/tools/gimpdrawtool.c @@ -385,6 +385,11 @@ gimp_draw_tool_draw_rectangle (GimpDrawTool *draw_tool, &tx2, &ty2, use_offsets); + tx1 = CLAMP (tx1, -1, shell->disp_width + 1); + ty1 = CLAMP (ty1, -1, shell->disp_height + 1); + tx2 = CLAMP (tx2, -1, shell->disp_width + 1); + ty2 = CLAMP (ty2, -1, shell->disp_height + 1); + tx2 -= tx1; ty2 -= ty1; w = (tx2 >= 0.0) ? RINT (tx2) : 0; diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c index 34e09f0c2b..ec87945485 100644 --- a/app/tools/gimpeditselectiontool.c +++ b/app/tools/gimpeditselectiontool.c @@ -666,9 +666,13 @@ selection_transform_segs (GimpEditSelectionTool *edit_select, GimpDisplayShell *shell; gint x, y; gint i; + gint xclamp, yclamp; shell = GIMP_DISPLAY_SHELL (GIMP_TOOL (edit_select)->gdisp->shell); + xclamp = shell->disp_width + 1; + yclamp = shell->disp_height + 1; + for (i = 0; i < num_segs; i++) { gimp_display_shell_transform_xy (shell, @@ -677,8 +681,8 @@ selection_transform_segs (GimpEditSelectionTool *edit_select, &x, &y, FALSE); - dest_segs[i].x1 = CLAMP (x, -1, shell->disp_width); - dest_segs[i].y1 = CLAMP (y, -1, shell->disp_height); + dest_segs[i].x1 = CLAMP (x, -1, xclamp); + dest_segs[i].y1 = CLAMP (y, -1, yclamp); gimp_display_shell_transform_xy (shell, src_segs[i].x2 + edit_select->cumlx, @@ -686,8 +690,28 @@ selection_transform_segs (GimpEditSelectionTool *edit_select, &x, &y, FALSE); - dest_segs[i].x2 = CLAMP (x, -1, shell->disp_width); - dest_segs[i].y2 = CLAMP (y, -1, shell->disp_height); + dest_segs[i].x2 = CLAMP (x, -1, xclamp); + dest_segs[i].y2 = CLAMP (y, -1, yclamp); + + /* If this segment is a closing segment && the segments lie inside + * the region, OR if this is an opening segment and the segments + * lie outside the region... + * we need to transform it by one display pixel + */ + if (!src_segs[i].open) + { + /* If it is vertical */ + if (dest_segs[i].x1 == dest_segs[i].x2) + { + dest_segs[i].x1 -= 1; + dest_segs[i].x2 -= 1; + } + else + { + dest_segs[i].y1 -= 1; + dest_segs[i].y2 -= 1; + } + } } }