From 06da10bc082eb2f76bcce27a2180b66ef20c09af Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Sun, 26 Sep 2010 22:41:04 +0200 Subject: [PATCH] app: change boundary drawing by tools to work like the selection - GimpCanvasBoundary takes unsorted BoundSeg arrays now and uses gimp_display_shell_transform_boundary() and gimp_cairo_add_boundary(). - Nobody calls boundary_sort() any longer for the purpose of displaying a boundary. - gimp_display_shell_transform_boundary() got offset parameters so it can transform things that are not in the image's coordinate system. --- app/base/boundary.c | 29 ++----- app/display/gimpcanvasboundary.c | 105 +++++++++-------------- app/display/gimpdisplayshell-selection.c | 3 +- app/display/gimpdisplayshell-transform.c | 29 +++---- app/display/gimpdisplayshell-transform.h | 4 +- app/paint/gimpbrushcore.c | 21 ++--- app/tools/gimpeditselectiontool.c | 11 +-- app/tools/gimpregionselecttool.c | 10 +-- app/tools/gimptransformtool.c | 60 +++++-------- 9 files changed, 96 insertions(+), 176 deletions(-) diff --git a/app/base/boundary.c b/app/base/boundary.c index d6d7ff9d24..a89408640a 100644 --- a/app/base/boundary.c +++ b/app/base/boundary.c @@ -373,30 +373,15 @@ boundary_transform (const BoundSeg *segs, for (i = 0; i < *num_segs; i++) { - /* dont transform sorting sentinels */ - if (!(segs[i].x1 == -1 && - segs[i].y1 == -1 && - segs[i].x2 == -1 && - segs[i].y2 == -1)) - { - gdouble x1, y1, x2, y2; + gdouble x1, y1, x2, y2; - gimp_matrix3_transform_point (matrix, segs[i].x1, segs[i].y1, &x1, &y1); - gimp_matrix3_transform_point (matrix, segs[i].x2, segs[i].y2, &x2, &y2); + gimp_matrix3_transform_point (matrix, segs[i].x1, segs[i].y1, &x1, &y1); + gimp_matrix3_transform_point (matrix, segs[i].x2, segs[i].y2, &x2, &y2); - boundary_add_seg (boundary, - (gint) ceil(x1), (gint) ceil(y1), - (gint) ceil(x2), (gint) ceil(y2), - segs[i].open); - } - else - { - /* Keep the sorting sentinel */ - boundary_add_seg (boundary, - -1, -1, - -1, -1, - segs[i].open); - } + boundary_add_seg (boundary, + RINT (x1), RINT (y1), + RINT (x2), RINT (y2), + segs[i].open); } *num_segs = boundary->num_segs; diff --git a/app/display/gimpcanvasboundary.c b/app/display/gimpcanvasboundary.c index 6c9c989927..1da42193ac 100644 --- a/app/display/gimpcanvasboundary.c +++ b/app/display/gimpcanvasboundary.c @@ -32,6 +32,8 @@ #include "core/gimpparamspecs.h" +#include "widgets/gimpcairo.h" + #include "gimpcanvasboundary.h" #include "gimpdisplayshell.h" #include "gimpdisplayshell-transform.h" @@ -121,6 +123,8 @@ gimp_canvas_boundary_class_init (GimpCanvasBoundaryClass *klass) static void gimp_canvas_boundary_init (GimpCanvasBoundary *boundary) { + gimp_canvas_item_set_line_cap (GIMP_CANVAS_ITEM (boundary), + CAIRO_LINE_CAP_SQUARE); } static void @@ -191,36 +195,35 @@ gimp_canvas_boundary_get_property (GObject *object, static void gimp_canvas_boundary_transform (GimpCanvasItem *item, GimpDisplayShell *shell, - BoundSeg *segs) + GdkSegment *segs) { GimpCanvasBoundaryPrivate *private = GET_PRIVATE (item); gint i; + gimp_display_shell_transform_segments (shell, + private->segs, segs, private->n_segs, + private->offset_x, private->offset_y); + for (i = 0; i < private->n_segs; i++) { - if (private->segs[i].x1 == -1 && - private->segs[i].y1 == -1 && - private->segs[i].x2 == -1 && - private->segs[i].y2 == -1) + /* 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 (! private->segs[i].open) { - segs[i] = private->segs[i]; - } - else - { - gimp_display_shell_transform_xy (shell, - private->segs[i].x1 + - private->offset_x, - private->segs[i].y1 + - private->offset_y, - &segs[i].x1, - &segs[i].y1); - gimp_display_shell_transform_xy (shell, - private->segs[i].x2 + - private->offset_x, - private->segs[i].y2 + - private->offset_y, - &segs[i].x2, - &segs[i].y2); + /* If it is vertical */ + if (segs[i].x1 == segs[i].x2) + { + segs[i].x1 -= 1; + segs[i].x2 -= 1; + } + else + { + segs[i].y1 -= 1; + segs[i].y2 -= 1; + } } } } @@ -231,38 +234,14 @@ gimp_canvas_boundary_draw (GimpCanvasItem *item, cairo_t *cr) { GimpCanvasBoundaryPrivate *private = GET_PRIVATE (item); - BoundSeg *segs; - gint i; + GdkSegment *segs; - segs = g_new0 (BoundSeg, private->n_segs); + segs = g_new0 (GdkSegment, private->n_segs); gimp_canvas_boundary_transform (item, shell, segs); - cairo_move_to (cr, segs[0].x1 + 0.5, segs[0].y1 + 0.5); + gimp_cairo_add_segments (cr, segs, private->n_segs); - for (i = 1; i < private->n_segs; i++) - { - if (segs[i].x1 == -1 && - segs[i].y1 == -1 && - segs[i].x2 == -1 && - segs[i].y2 == -1) - { - cairo_close_path (cr); - _gimp_canvas_item_stroke (item, shell, cr); - - i++; - if (i == private->n_segs) - break; - - cairo_move_to (cr, segs[i].x1 + 0.5, segs[i].y1 + 0.5); - } - else - { - cairo_line_to (cr, segs[i].x1 + 0.5, segs[i].y1 + 0.5); - } - } - - cairo_close_path (cr); _gimp_canvas_item_stroke (item, shell, cr); g_free (segs); @@ -274,11 +253,11 @@ gimp_canvas_boundary_get_extents (GimpCanvasItem *item, { GimpCanvasBoundaryPrivate *private = GET_PRIVATE (item); GdkRectangle rectangle; - BoundSeg *segs; + GdkSegment *segs; gint x1, y1, x2, y2; gint i; - segs = g_new0 (BoundSeg, private->n_segs); + segs = g_new0 (GdkSegment, private->n_segs); gimp_canvas_boundary_transform (item, shell, segs); @@ -289,21 +268,15 @@ gimp_canvas_boundary_get_extents (GimpCanvasItem *item, for (i = 1; i < private->n_segs; i++) { - if (segs[i].x1 != -1 || - segs[i].y1 != -1 || - segs[i].x2 != -1 || - segs[i].y2 != -1) - { - gint x3 = segs[i].x1 - 1; - gint y3 = segs[i].y1 - 1; - gint x4 = x3 + 3; - gint y4 = y3 + 3; + gint x3 = segs[i].x1 - 1; + gint y3 = segs[i].y1 - 1; + gint x4 = x3 + 3; + gint y4 = y3 + 3; - x1 = MIN (x1, x3); - y1 = MIN (y1, y3); - x2 = MAX (x2, x4); - y2 = MAX (y2, y4); - } + x1 = MIN (x1, x3); + y1 = MIN (y1, y3); + x2 = MAX (x2, x4); + y2 = MAX (y2, y4); } g_free (segs); diff --git a/app/display/gimpdisplayshell-selection.c b/app/display/gimpdisplayshell-selection.c index cbbfe49808..936fbcf796 100644 --- a/app/display/gimpdisplayshell-selection.c +++ b/app/display/gimpdisplayshell-selection.c @@ -409,7 +409,8 @@ selection_transform_segs (Selection *selection, gint i; gimp_display_shell_transform_segments (selection->shell, - src_segs, dest_segs, n_segs); + src_segs, dest_segs, n_segs, + 0.0, 0.0); for (i = 0; i < n_segs; i++) { diff --git a/app/display/gimpdisplayshell-transform.c b/app/display/gimpdisplayshell-transform.c index f0e6f45fe6..3c86bf4fcd 100644 --- a/app/display/gimpdisplayshell-transform.c +++ b/app/display/gimpdisplayshell-transform.c @@ -307,7 +307,9 @@ void gimp_display_shell_transform_segments (const GimpDisplayShell *shell, const BoundSeg *src_segs, GdkSegment *dest_segs, - gint n_segs) + gint n_segs, + gdouble offset_x, + gdouble offset_y) { gint i; @@ -315,23 +317,18 @@ gimp_display_shell_transform_segments (const GimpDisplayShell *shell, for (i = 0; i < n_segs ; i++) { - gint64 x1, x2; - gint64 y1, y2; + gdouble x1, x2; + gdouble y1, y2; - x1 = src_segs[i].x1; - x2 = src_segs[i].x2; - y1 = src_segs[i].y1; - y2 = src_segs[i].y2; + x1 = src_segs[i].x1 + offset_x; + x2 = src_segs[i].x2 + offset_x; + y1 = src_segs[i].y1 + offset_y; + y2 = src_segs[i].y2 + offset_y; - x1 = (x1 * shell->x_src_dec) / shell->x_dest_inc; - x2 = (x2 * shell->x_src_dec) / shell->x_dest_inc; - y1 = (y1 * shell->y_src_dec) / shell->y_dest_inc; - y2 = (y2 * shell->y_src_dec) / shell->y_dest_inc; - - dest_segs[i].x1 = CLAMP (x1 - shell->offset_x, G_MININT, G_MAXINT); - dest_segs[i].x2 = CLAMP (x2 - shell->offset_x, G_MININT, G_MAXINT); - dest_segs[i].y1 = CLAMP (y1 - shell->offset_y, G_MININT, G_MAXINT); - dest_segs[i].y2 = CLAMP (y2 - shell->offset_y, G_MININT, G_MAXINT); + dest_segs[i].x1 = SCALEX (shell, x1) - shell->offset_x; + dest_segs[i].x2 = SCALEX (shell, x2) - shell->offset_x; + dest_segs[i].y1 = SCALEY (shell, y1) - shell->offset_y; + dest_segs[i].y2 = SCALEY (shell, y2) - shell->offset_y; } } diff --git a/app/display/gimpdisplayshell-transform.h b/app/display/gimpdisplayshell-transform.h index 296b0a22cb..9e44355d30 100644 --- a/app/display/gimpdisplayshell-transform.h +++ b/app/display/gimpdisplayshell-transform.h @@ -60,7 +60,9 @@ void gimp_display_shell_transform_coords (const GimpDisplayShell *shell, void gimp_display_shell_transform_segments (const GimpDisplayShell *shell, const BoundSeg *src_segs, GdkSegment *dest_segs, - gint n_segs); + gint n_segs, + gdouble offset_x, + gdouble offset_y); void gimp_display_shell_untransform_viewport (const GimpDisplayShell *shell, gint *x, diff --git a/app/paint/gimpbrushcore.c b/app/paint/gimpbrushcore.c index 8eabb8c6d6..fac579b091 100644 --- a/app/paint/gimpbrushcore.c +++ b/app/paint/gimpbrushcore.c @@ -997,9 +997,7 @@ gimp_brush_core_create_bound_segs (GimpBrushCore *core, if (mask) { - PixelRegion PR = { 0, }; - BoundSeg *boundary; - gint num_groups; + PixelRegion PR = { 0, }; pixel_region_init_temp_buf (&PR, mask, 0, 0, mask->width, mask->height); @@ -1010,19 +1008,10 @@ gimp_brush_core_create_bound_segs (GimpBrushCore *core, if (mask->width > 32 && mask->height > 32) smooth_region (&PR); - - boundary = boundary_find (&PR, BOUNDARY_WITHIN_BOUNDS, - 0, 0, PR.w, PR.h, - 0, - &core->n_brush_bound_segs); - - core->brush_bound_segs = boundary_sort (boundary, - core->n_brush_bound_segs, - &num_groups); - - core->n_brush_bound_segs += num_groups; - - g_free (boundary); + core->brush_bound_segs = boundary_find (&PR, BOUNDARY_WITHIN_BOUNDS, + 0, 0, PR.w, PR.h, + 0, + &core->n_brush_bound_segs); core->brush_bound_width = mask->width; core->brush_bound_height = mask->height; diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c index ba463d55a2..b1cfbfcad9 100644 --- a/app/tools/gimpeditselectiontool.c +++ b/app/tools/gimpeditselectiontool.c @@ -194,7 +194,6 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool, gint off_x, off_y; const BoundSeg *segs_in; const BoundSeg *segs_out; - gint num_groups; const gchar *undo_desc; edit_select = g_object_new (GIMP_TYPE_EDIT_SELECTION_TOOL, @@ -281,13 +280,11 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool, &edit_select->num_segs_in, &edit_select->num_segs_out, 0, 0, 0, 0); - edit_select->segs_in = boundary_sort (segs_in, edit_select->num_segs_in, - &num_groups); - edit_select->num_segs_in += num_groups; + edit_select->segs_in = g_memdup (segs_in, + edit_select->num_segs_in * sizeof (BoundSeg)); - edit_select->segs_out = boundary_sort (segs_out, edit_select->num_segs_out, - &num_groups); - edit_select->num_segs_out += num_groups; + edit_select->segs_out = g_memdup (segs_out, + edit_select->num_segs_out * sizeof (BoundSeg)); if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_VECTORS) { diff --git a/app/tools/gimpregionselecttool.c b/app/tools/gimpregionselecttool.c index 41d2a51b8d..9e28af0a99 100644 --- a/app/tools/gimpregionselecttool.c +++ b/app/tools/gimpregionselecttool.c @@ -342,9 +342,7 @@ gimp_region_select_tool_calculate (GimpRegionSelectTool *region_sel, { GimpDisplayShell *shell = gimp_display_get_shell (display); BoundSeg *segs; - BoundSeg *sorted; PixelRegion maskPR; - gint n_groups; gimp_display_shell_set_override_cursor (shell, GDK_WATCH); @@ -380,13 +378,7 @@ gimp_region_select_tool_calculate (GimpRegionSelectTool *region_sel, BOUNDARY_HALF_WAY, n_segs); - sorted = boundary_sort (segs, *n_segs, &n_groups); - - *n_segs += n_groups; - - g_free (segs); - gimp_display_shell_unset_override_cursor (shell); - return sorted; + return segs; } diff --git a/app/tools/gimptransformtool.c b/app/tools/gimptransformtool.c index b7059ba507..d72c8b8d9a 100644 --- a/app/tools/gimptransformtool.c +++ b/app/tools/gimptransformtool.c @@ -949,7 +949,6 @@ gimp_transform_tool_draw (GimpDrawTool *draw_tool) BoundSeg *segs_out; gint num_segs_in; gint num_segs_out; - gint num_groups; gint i; gimp_channel_boundary (gimp_image_get_mask (image), @@ -957,11 +956,8 @@ gimp_transform_tool_draw (GimpDrawTool *draw_tool) &num_segs_in, &num_segs_out, 0, 0, 0, 0); - segs_in = boundary_sort (orig_in, num_segs_in, &num_groups); - num_segs_in += num_groups; - - segs_out = boundary_sort (orig_out, num_segs_out, &num_groups); - num_segs_out += num_groups; + segs_in = g_memdup (orig_in, num_segs_in * sizeof (BoundSeg)); + segs_out = g_memdup (orig_out, num_segs_out * sizeof (BoundSeg)); if (segs_in) { @@ -969,23 +965,17 @@ gimp_transform_tool_draw (GimpDrawTool *draw_tool) { gdouble tx, ty; - if (segs_in[i].x1 != -1 && - segs_in[i].y1 != -1 && - segs_in[i].x2 != -1 && - segs_in[i].y2 != -1) - { - gimp_matrix3_transform_point (&matrix, - segs_in[i].x1, segs_in[i].y1, - &tx, &ty); - segs_in[i].x1 = RINT (tx); - segs_in[i].y1 = RINT (ty); + gimp_matrix3_transform_point (&matrix, + segs_in[i].x1, segs_in[i].y1, + &tx, &ty); + segs_in[i].x1 = RINT (tx); + segs_in[i].y1 = RINT (ty); - gimp_matrix3_transform_point (&matrix, - segs_in[i].x2, segs_in[i].y2, - &tx, &ty); - segs_in[i].x2 = RINT (tx); - segs_in[i].y2 = RINT (ty); - } + gimp_matrix3_transform_point (&matrix, + segs_in[i].x2, segs_in[i].y2, + &tx, &ty); + segs_in[i].x2 = RINT (tx); + segs_in[i].y2 = RINT (ty); } gimp_draw_tool_add_boundary (draw_tool, @@ -1000,23 +990,17 @@ gimp_transform_tool_draw (GimpDrawTool *draw_tool) { gdouble tx, ty; - if (segs_out[i].x1 != -1 && - segs_out[i].y1 != -1 && - segs_out[i].x2 != -1 && - segs_out[i].y2 != -1) - { - gimp_matrix3_transform_point (&matrix, - segs_out[i].x1, segs_out[i].y1, - &tx, &ty); - segs_out[i].x1 = RINT (tx); - segs_out[i].y1 = RINT (ty); + gimp_matrix3_transform_point (&matrix, + segs_out[i].x1, segs_out[i].y1, + &tx, &ty); + segs_out[i].x1 = RINT (tx); + segs_out[i].y1 = RINT (ty); - gimp_matrix3_transform_point (&matrix, - segs_out[i].x2, segs_out[i].y2, - &tx, &ty); - segs_out[i].x2 = RINT (tx); - segs_out[i].y2 = RINT (ty); - } + gimp_matrix3_transform_point (&matrix, + segs_out[i].x2, segs_out[i].y2, + &tx, &ty); + segs_out[i].x2 = RINT (tx); + segs_out[i].y2 = RINT (ty); } gimp_draw_tool_add_boundary (draw_tool,