[gimp/goat-invasion: 164/418] app: port GimpBoundary to GEGL, including its API
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/goat-invasion: 164/418] app: port GimpBoundary to GEGL, including its API
- Date: Wed, 4 Apr 2012 10:39:33 +0000 (UTC)
commit e3eccba1ceecb749e681219faa84928dbbd432de
Author: Michael Natterer <mitch gimp org>
Date: Tue Mar 20 19:55:23 2012 +0100
app: port GimpBoundary to GEGL, including its API
app/core/gimpboundary.c | 279 +++++++++++++++++++------------------
app/core/gimpboundary.h | 37 +++---
app/core/gimpbrush-boundary.c | 24 ++--
app/core/gimpchannel.c | 24 ++--
app/core/gimplayer-floating-sel.c | 14 +-
app/tools/gimpregionselecttool.c | 16 +--
6 files changed, 201 insertions(+), 193 deletions(-)
---
diff --git a/app/core/gimpboundary.c b/app/core/gimpboundary.c
index d6d04b5..154a748 100644
--- a/app/core/gimpboundary.c
+++ b/app/core/gimpboundary.c
@@ -20,16 +20,12 @@
#include <stdlib.h>
#include <string.h>
-#include <glib-object.h>
+#include <gegl.h>
#include "libgimpmath/gimpmath.h"
#include "core-types.h"
-#include "base/pixel-region.h"
-#include "base/tile.h"
-#include "base/tile-manager.h"
-
#include "gimpboundary.h"
@@ -59,48 +55,51 @@ struct _GimpBoundary
/* local function prototypes */
-static GimpBoundary * gimp_boundary_new (PixelRegion *PR);
+static GimpBoundary * gimp_boundary_new (const GeglRectangle *region);
static GimpBoundSeg * gimp_boundary_free (GimpBoundary *boundary,
gboolean free_segs);
-static void gimp_boundary_add_seg (GimpBoundary *bounrady,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- gboolean open);
-
-static void find_empty_segs (PixelRegion *maskPR,
- gint scanline,
- gint empty_segs[],
- gint max_empty,
- gint *num_empty,
- GimpBoundaryType type,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- guchar threshold);
-static void process_horiz_seg (GimpBoundary *boundary,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- gboolean open);
-static void make_horiz_segs (GimpBoundary *boundary,
- gint start,
- gint end,
- gint scanline,
- gint empty[],
- gint num_empty,
- gint top);
-static GimpBoundary * generate_boundary (PixelRegion *PR,
+static void gimp_boundary_add_seg (GimpBoundary *bounrady,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gboolean open);
+
+static void find_empty_segs (const GeglRectangle *region,
+ const guchar *line_data,
+ gint bpp,
+ gint scanline,
+ gint empty_segs[],
+ gint max_empty,
+ gint *num_empty,
+ GimpBoundaryType type,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ guchar threshold);
+static void process_horiz_seg (GimpBoundary *boundary,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gboolean open);
+static void make_horiz_segs (GimpBoundary *boundary,
+ gint start,
+ gint end,
+ gint scanline,
+ gint empty[],
+ gint num_empty,
+ gint top);
+static GimpBoundary * generate_boundary (GeglBuffer *buffer,
+ const GeglRectangle *region,
GimpBoundaryType type,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- guchar threshold);
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ guchar threshold);
static gint cmp_segptr_xy1_addr (const GimpBoundSeg **seg_ptr_a,
const GimpBoundSeg **seg_ptr_b);
@@ -153,21 +152,33 @@ static void simplify_subdivide (const GimpBoundSeg *segs,
* Return value: the boundary array.
**/
GimpBoundSeg *
-gimp_boundary_find (PixelRegion *maskPR,
- GimpBoundaryType type,
- int x1,
- int y1,
- int x2,
- int y2,
- guchar threshold,
- int *num_segs)
+gimp_boundary_find (GeglBuffer *buffer,
+ const GeglRectangle *region,
+ GimpBoundaryType type,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ guchar threshold,
+ int *num_segs)
{
- GimpBoundary *boundary;
+ GimpBoundary *boundary;
+ GeglRectangle rect = { 0, };
- g_return_val_if_fail (maskPR != NULL, NULL);
+ g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
g_return_val_if_fail (num_segs != NULL, NULL);
- boundary = generate_boundary (maskPR, type, x1, y1, x2, y2, threshold);
+ if (region)
+ {
+ rect = *region;
+ }
+ else
+ {
+ rect.width = gegl_buffer_get_width (buffer);
+ rect.height = gegl_buffer_get_height (buffer);
+ }
+
+ boundary = generate_boundary (buffer, &rect, type, x1, y1, x2, y2, threshold);
*num_segs = boundary->num_segs;
@@ -390,26 +401,26 @@ gimp_boundary_offset (GimpBoundSeg *segs,
/* private functions */
static GimpBoundary *
-gimp_boundary_new (PixelRegion *PR)
+gimp_boundary_new (const GeglRectangle *region)
{
GimpBoundary *boundary = g_slice_new0 (GimpBoundary);
- if (PR)
+ if (region)
{
gint i;
/* array for determining the vertical line segments
* which must be drawn
*/
- boundary->vert_segs = g_new (gint, PR->w + PR->x + 1);
+ boundary->vert_segs = g_new (gint, region->width + region->x + 1);
- for (i = 0; i <= (PR->w + PR->x); i++)
+ for (i = 0; i <= (region->width + region->x); i++)
boundary->vert_segs[i] = -1;
/* find the maximum possible number of empty segments
* given the current mask
*/
- boundary->max_empty_segs = PR->w + 3;
+ boundary->max_empty_segs = region->width + 3;
boundary->empty_segs_n = g_new (gint, boundary->max_empty_segs);
boundary->empty_segs_c = g_new (gint, boundary->max_empty_segs);
@@ -465,32 +476,30 @@ gimp_boundary_add_seg (GimpBoundary *boundary,
}
static void
-find_empty_segs (PixelRegion *maskPR,
- gint scanline,
- gint empty_segs[],
- gint max_empty,
- gint *num_empty,
- GimpBoundaryType type,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- guchar threshold)
+find_empty_segs (const GeglRectangle *region,
+ const guchar *line_data,
+ gint bpp,
+ gint scanline,
+ gint empty_segs[],
+ gint max_empty,
+ gint *num_empty,
+ GimpBoundaryType type,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ guchar threshold)
{
- const guchar *data = NULL;
- Tile *tile = NULL;
- gint start = 0;
- gint end = 0;
- gint endx = 0;
- gint bpp = 0;
- gint tilex = -1;
- gint last = -1;
- gint l_num_empty;
- gint x;
+ gint start = 0;
+ gint end = 0;
+ gint endx = 0;
+ gint last = -1;
+ gint l_num_empty;
+ gint x;
*num_empty = 0;
- if (scanline < maskPR->y || scanline >= (maskPR->y + maskPR->h))
+ if (scanline < region->y || scanline >= (region->y + region->height))
{
empty_segs[(*num_empty)++] = 0;
empty_segs[(*num_empty)++] = G_MAXINT;
@@ -511,8 +520,8 @@ find_empty_segs (PixelRegion *maskPR,
}
else if (type == GIMP_BOUNDARY_IGNORE_BOUNDS)
{
- start = maskPR->x;
- end = maskPR->x + maskPR->w;
+ start = region->x;
+ end = region->x + region->width;
if (scanline < y1 || scanline >= y2)
x2 = -1;
}
@@ -521,43 +530,20 @@ find_empty_segs (PixelRegion *maskPR,
l_num_empty = *num_empty;
- bpp = maskPR->bytes;
+ endx = end;
- if (! maskPR->tiles)
- {
- data = maskPR->data + scanline * maskPR->rowstride;
- endx = end;
- }
+ line_data += bpp * start;
+ line_data += bpp - 1;
for (x = start; x < end;)
{
- /* Check to see if we must advance to next tile */
- if (maskPR->tiles)
- {
- if ((x / TILE_WIDTH) != tilex)
- {
- if (tile)
- tile_release (tile, FALSE);
-
- tile = tile_manager_get_tile (maskPR->tiles,
- x, scanline, TRUE, FALSE);
- data = ((const guchar *) tile_data_pointer (tile, x, scanline) +
- bpp - 1);
-
- tilex = x / TILE_WIDTH;
- }
-
- endx = x + (TILE_WIDTH - (x % TILE_WIDTH));
- endx = MIN (end, endx);
- }
-
if (type == GIMP_BOUNDARY_IGNORE_BOUNDS && (endx > x1 || x < x2))
{
for (; x < endx; x++)
{
gint val;
- if (*data > threshold)
+ if (*line_data > threshold)
{
if (x >= x1 && x < x2)
val = -1;
@@ -569,7 +555,7 @@ find_empty_segs (PixelRegion *maskPR,
val = -1;
}
- data += bpp;
+ line_data += bpp;
if (last != val)
empty_segs[l_num_empty++] = x;
@@ -583,12 +569,12 @@ find_empty_segs (PixelRegion *maskPR,
{
gint val;
- if (*data > threshold)
+ if (*line_data > threshold)
val = 1;
else
val = -1;
- data += bpp;
+ line_data += bpp;
if (last != val)
empty_segs[l_num_empty++] = x;
@@ -604,9 +590,6 @@ find_empty_segs (PixelRegion *maskPR,
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
-
- if (tile)
- tile_release (tile, FALSE);
}
static void
@@ -672,25 +655,38 @@ make_horiz_segs (GimpBoundary *boundary,
}
static GimpBoundary *
-generate_boundary (PixelRegion *PR,
- GimpBoundaryType type,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- guchar threshold)
+generate_boundary (GeglBuffer *buffer,
+ const GeglRectangle *region,
+ GimpBoundaryType type,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ guchar threshold)
{
- GimpBoundary *boundary;
- gint scanline;
- gint i;
- gint start, end;
- gint *tmp_segs;
+ GimpBoundary *boundary;
+ const Babl *format;
+ GeglRectangle line_rect = { 0, };
+ guchar *line_data;
+ gint bpp;
+ gint scanline;
+ gint i;
+ gint start, end;
+ gint *tmp_segs;
gint num_empty_n = 0;
gint num_empty_c = 0;
gint num_empty_l = 0;
- boundary = gimp_boundary_new (PR);
+ boundary = gimp_boundary_new (region);
+
+ format = gegl_buffer_get_format (buffer);
+ bpp = babl_format_get_bytes_per_pixel (format);
+
+ line_rect.width = gegl_buffer_get_width (buffer);
+ line_rect.height = 1;
+
+ line_data = g_alloca (bpp * line_rect.width);
start = 0;
end = 0;
@@ -702,16 +698,23 @@ generate_boundary (PixelRegion *PR,
}
else if (type == GIMP_BOUNDARY_IGNORE_BOUNDS)
{
- start = PR->y;
- end = PR->y + PR->h;
+ start = region->y;
+ end = region->y + region->height;
}
/* Find the empty segments for the previous and current scanlines */
- find_empty_segs (PR, start - 1, boundary->empty_segs_l,
+ find_empty_segs (region, NULL, bpp,
+ start - 1, boundary->empty_segs_l,
boundary->max_empty_segs, &num_empty_l,
type, x1, y1, x2, y2,
threshold);
- find_empty_segs (PR, start, boundary->empty_segs_c,
+
+ line_rect.y = start;
+ gegl_buffer_get (buffer, 1.0, &line_rect, format,
+ line_data, GEGL_AUTO_ROWSTRIDE);
+
+ find_empty_segs (region, line_data, bpp,
+ start, boundary->empty_segs_c,
boundary->max_empty_segs, &num_empty_c,
type, x1, y1, x2, y2,
threshold);
@@ -719,7 +722,15 @@ generate_boundary (PixelRegion *PR,
for (scanline = start; scanline < end; scanline++)
{
/* find the empty segment list for the next scanline */
- find_empty_segs (PR, scanline + 1, boundary->empty_segs_n,
+ line_rect.y = scanline + 1;
+ if (scanline + 1 == end)
+ line_data = NULL;
+ else
+ gegl_buffer_get (buffer, 1.0, &line_rect, format,
+ line_data, GEGL_AUTO_ROWSTRIDE);
+
+ find_empty_segs (region, line_data, bpp,
+ scanline + 1, boundary->empty_segs_n,
boundary->max_empty_segs, &num_empty_n,
type, x1, y1, x2, y2,
threshold);
diff --git a/app/core/gimpboundary.h b/app/core/gimpboundary.h
index 64d423a..fabda66 100644
--- a/app/core/gimpboundary.h
+++ b/app/core/gimpboundary.h
@@ -41,26 +41,27 @@ struct _GimpBoundSeg
};
-GimpBoundSeg * gimp_boundary_find (PixelRegion *maskPR,
- GimpBoundaryType type,
- gint x1,
- gint y1,
- gint x2,
- gint y2,
- guchar threshold,
- gint *num_segs);
-GimpBoundSeg * gimp_boundary_sort (const GimpBoundSeg *segs,
- gint num_segs,
- gint *num_groups);
-GimpBoundSeg * gimp_boundary_simplify (GimpBoundSeg *sorted_segs,
- gint num_groups,
- gint *num_segs);
+GimpBoundSeg * gimp_boundary_find (GeglBuffer *buffer,
+ const GeglRectangle *region,
+ GimpBoundaryType type,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ guchar threshold,
+ gint *num_segs);
+GimpBoundSeg * gimp_boundary_sort (const GimpBoundSeg *segs,
+ gint num_segs,
+ gint *num_groups);
+GimpBoundSeg * gimp_boundary_simplify (GimpBoundSeg *sorted_segs,
+ gint num_groups,
+ gint *num_segs);
/* offsets in-place */
-void gimp_boundary_offset (GimpBoundSeg *segs,
- gint num_segs,
- gint off_x,
- gint off_y);
+void gimp_boundary_offset (GimpBoundSeg *segs,
+ gint num_segs,
+ gint off_x,
+ gint off_y);
#endif /* __GIMP_BOUNDARY_H__ */
diff --git a/app/core/gimpbrush-boundary.c b/app/core/gimpbrush-boundary.c
index cc12225..4906950 100644
--- a/app/core/gimpbrush-boundary.c
+++ b/app/core/gimpbrush-boundary.c
@@ -17,12 +17,11 @@
#include "config.h"
-#include <glib-object.h>
#include <cairo.h>
+#include <gegl.h>
#include "core-types.h"
-#include "base/pixel-region.h"
#include "base/temp-buf.h"
#include "gimpbezierdesc.h"
@@ -45,18 +44,25 @@ gimp_brush_transform_boundary_exact (GimpBrush *brush,
if (mask)
{
- PixelRegion maskPR;
- GimpBoundSeg *bound_segs;
- gint n_bound_segs;
-
- pixel_region_init_temp_buf (&maskPR, (TempBuf *) mask,
- 0, 0, mask->width, mask->height);
-
- bound_segs = gimp_boundary_find (&maskPR, GIMP_BOUNDARY_WITHIN_BOUNDS,
- 0, 0, maskPR.w, maskPR.h,
+ GeglBuffer *buffer;
+ GeglRectangle rect = { 0, 0, mask->width, mask->height };
+ GimpBoundSeg *bound_segs;
+ gint n_bound_segs;
+
+ buffer = gegl_buffer_linear_new_from_data (mask->data,
+ babl_format ("Y u8"),
+ &rect,
+ GEGL_AUTO_ROWSTRIDE,
+ NULL, NULL);
+
+ bound_segs = gimp_boundary_find (buffer, NULL,
+ GIMP_BOUNDARY_WITHIN_BOUNDS,
+ 0, 0, mask->width, mask->height,
0,
&n_bound_segs);
+ g_object_unref (buffer);
+
if (bound_segs)
{
GimpBoundSeg *stroke_segs;
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index 4dafa63..0aca136 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -1010,22 +1010,23 @@ gimp_channel_real_boundary (GimpChannel *channel,
gint x2,
gint y2)
{
- gint x3, y3, x4, y4;
- PixelRegion bPR;
-
if (! channel->boundary_known)
{
+ gint x3, y3, x4, y4;
+
/* free the out of date boundary segments */
g_free (channel->segs_in);
g_free (channel->segs_out);
if (gimp_channel_bounds (channel, &x3, &y3, &x4, &y4))
{
- pixel_region_init (&bPR,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (channel)),
- x3, y3, x4 - x3, y4 - y3, FALSE);
+ GeglBuffer *buffer;
+ GeglRectangle rect = { x3, y3, x4 - x3, y4 - y3 };
- channel->segs_out = gimp_boundary_find (&bPR, GIMP_BOUNDARY_IGNORE_BOUNDS,
+ buffer = gimp_drawable_get_read_buffer (GIMP_DRAWABLE (channel));
+
+ channel->segs_out = gimp_boundary_find (buffer, &rect,
+ GIMP_BOUNDARY_IGNORE_BOUNDS,
x1, y1, x2, y2,
GIMP_BOUNDARY_HALF_WAY,
&channel->num_segs_out);
@@ -1036,13 +1037,8 @@ gimp_channel_real_boundary (GimpChannel *channel,
if (x2 > x1 && y2 > y1)
{
- pixel_region_init (&bPR,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (channel)),
- 0, 0,
- gimp_item_get_width (GIMP_ITEM (channel)),
- gimp_item_get_height (GIMP_ITEM (channel)), FALSE);
-
- channel->segs_in = gimp_boundary_find (&bPR, GIMP_BOUNDARY_WITHIN_BOUNDS,
+ channel->segs_in = gimp_boundary_find (buffer, NULL,
+ GIMP_BOUNDARY_WITHIN_BOUNDS,
x1, y1, x2, y2,
GIMP_BOUNDARY_HALF_WAY,
&channel->num_segs_in);
diff --git a/app/core/gimplayer-floating-sel.c b/app/core/gimplayer-floating-sel.c
index 2f7c795..f6865d9 100644
--- a/app/core/gimplayer-floating-sel.c
+++ b/app/core/gimplayer-floating-sel.c
@@ -190,9 +190,6 @@ const GimpBoundSeg *
floating_sel_boundary (GimpLayer *layer,
gint *n_segs)
{
- PixelRegion bPR;
- gint i;
-
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
g_return_val_if_fail (gimp_layer_is_floating_sel (layer), NULL);
g_return_val_if_fail (n_segs != NULL, NULL);
@@ -211,11 +208,14 @@ floating_sel_boundary (GimpLayer *layer,
if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
{
+ GeglBuffer *buffer;
+ gint i;
+
/* find the segments */
- pixel_region_init (&bPR,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
- 0, 0, width, height, FALSE);
- layer->fs.segs = gimp_boundary_find (&bPR, GIMP_BOUNDARY_WITHIN_BOUNDS,
+ buffer = gimp_drawable_get_read_buffer (GIMP_DRAWABLE (layer));
+
+ layer->fs.segs = gimp_boundary_find (buffer, NULL,
+ GIMP_BOUNDARY_WITHIN_BOUNDS,
0, 0, width, height,
GIMP_BOUNDARY_HALF_WAY,
&layer->fs.num_segs);
diff --git a/app/tools/gimpregionselecttool.c b/app/tools/gimpregionselecttool.c
index 495f18a..f6f58d1 100644
--- a/app/tools/gimpregionselecttool.c
+++ b/app/tools/gimpregionselecttool.c
@@ -26,8 +26,6 @@
#include "tools-types.h"
-#include "base/pixel-region.h"
-
#include "core/gimpboundary.h"
#include "core/gimpchannel.h"
#include "core/gimpchannel-select.h"
@@ -345,8 +343,8 @@ gimp_region_select_tool_calculate (GimpRegionSelectTool *region_sel,
gint *n_segs)
{
GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GeglBuffer *buffer;
GimpBoundSeg *segs;
- PixelRegion maskPR;
gimp_display_shell_set_override_cursor (shell, GDK_WATCH);
@@ -368,14 +366,10 @@ gimp_region_select_tool_calculate (GimpRegionSelectTool *region_sel,
/* calculate and allocate a new segment array which represents the
* boundary of the contiguous region
*/
- pixel_region_init (&maskPR,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (region_sel->region_mask)),
- 0, 0,
- gimp_item_get_width (GIMP_ITEM (region_sel->region_mask)),
- gimp_item_get_height (GIMP_ITEM (region_sel->region_mask)),
- FALSE);
-
- segs = gimp_boundary_find (&maskPR, GIMP_BOUNDARY_WITHIN_BOUNDS,
+ buffer = gimp_drawable_get_read_buffer (GIMP_DRAWABLE (region_sel->region_mask));
+
+ segs = gimp_boundary_find (buffer, NULL,
+ GIMP_BOUNDARY_WITHIN_BOUNDS,
0, 0,
gimp_item_get_width (GIMP_ITEM (region_sel->region_mask)),
gimp_item_get_height (GIMP_ITEM (region_sel->region_mask)),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]