[gimp/goat-invasion: 142/526] app: port bucket fill to GEGL
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/goat-invasion: 142/526] app: port bucket fill to GEGL
- Date: Sun, 22 Apr 2012 13:11:12 +0000 (UTC)
commit 3e42c14ea69d87174269889390c7ef622fbc12d2
Author: Michael Natterer <mitch gimp org>
Date: Mon Mar 19 02:30:18 2012 +0100
app: port bucket fill to GEGL
Add mask offset parameters to gimp_gegl_create_apply_opacity_node()
so it's possible to use a part of the mask only, bucket fill
uses that to avoid uneccessary work where the mask is empty.
Should use the same in gimp_drawable_stroke_scan_convert().
app/core/gimpdrawable-bucket-fill.c | 112 +++++++++++++++++------------------
app/core/gimpdrawable-stroke.c | 5 +-
app/core/gimplayer.c | 3 +-
app/gegl/gimp-gegl-nodes.c | 27 ++++++++-
app/gegl/gimp-gegl-nodes.h | 5 +-
5 files changed, 88 insertions(+), 64 deletions(-)
---
diff --git a/app/core/gimpdrawable-bucket-fill.c b/app/core/gimpdrawable-bucket-fill.c
index c8c05d6..42a7e5a 100644
--- a/app/core/gimpdrawable-bucket-fill.c
+++ b/app/core/gimpdrawable-bucket-fill.c
@@ -27,12 +27,13 @@
#include "core-types.h"
#include "base/pixel-region.h"
-#include "base/temp-buf.h"
#include "base/tile-manager.h"
-#include "paint-funcs/paint-funcs.h"
+#include "gegl/gimp-gegl-nodes.h"
+#include "gegl/gimp-gegl-utils.h"
#include "gimp.h"
+#include "gimp-apply-operation.h"
#include "gimpchannel.h"
#include "gimpchannel-combine.h"
#include "gimpcontext.h"
@@ -138,14 +139,15 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
GimpPattern *pattern)
{
GimpImage *image;
- TileManager *buf_tiles;
- PixelRegion bufPR, maskPR;
- GimpChannel *mask = NULL;
- gint bytes;
+ GimpChannel *mask;
+ TileManager *tiles;
+ GeglBuffer *buffer;
+ GeglBuffer *mask_buffer;
+ GeglNode *apply_opacity;
+ PixelRegion bufPR;
gint x1, y1, x2, y2;
- guchar col[MAX_CHANNELS];
- TempBuf *pat_buf = NULL;
- gboolean new_buf = FALSE;
+ gint mask_offset_x = 0;
+ gint mask_offset_y = 0;
gboolean selection;
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
@@ -157,30 +159,11 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
image = gimp_item_get_image (GIMP_ITEM (drawable));
- bytes = gimp_drawable_bytes (drawable);
selection = gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2);
if ((x1 == x2) || (y1 == y2))
return;
- if (fill_mode == GIMP_FG_BUCKET_FILL ||
- fill_mode == GIMP_BG_BUCKET_FILL)
- {
- gimp_image_transform_rgb (image, gimp_drawable_type (drawable),
- color, col);
- }
- else if (fill_mode == GIMP_PATTERN_BUCKET_FILL)
- {
- pat_buf = gimp_image_transform_temp_buf (image,
- gimp_drawable_type (drawable),
- pattern->mask, &new_buf);
- }
- else
- {
- g_warning ("%s: invalid fill_mode passed", G_STRFUNC);
- return;
- }
-
gimp_set_busy (image->gimp);
/* Do a seed bucket fill...To do this, calculate a new
@@ -209,16 +192,16 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
-off_x, -off_y);
}
+ mask_buffer = gimp_drawable_get_read_buffer (GIMP_DRAWABLE (mask));
+
gimp_channel_bounds (mask, &x1, &y1, &x2, &y2);
/* make sure we handle the mask correctly if it was sample-merged */
if (sample_merged)
{
- GimpItem *item;
+ GimpItem *item = GIMP_ITEM (drawable);
gint off_x, off_y;
- item = GIMP_ITEM (drawable);
-
/* Limit the channel bounds to the drawable's extents */
gimp_item_get_offset (item, &off_x, &off_y);
@@ -227,11 +210,10 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
x2 = CLAMP (x2, off_x, (off_x + gimp_item_get_width (item)));
y2 = CLAMP (y2, off_y, (off_y + gimp_item_get_height (item)));
- pixel_region_init (&maskPR,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
- x1, y1, (x2 - x1), (y2 - y1), TRUE);
+ mask_offset_x = x1;
+ mask_offset_y = y1;
- /* translate mask bounds to drawable coords */
+ /* translate mask bounds to drawable coords */
x1 -= off_x;
y1 -= off_y;
x2 -= off_x;
@@ -239,48 +221,64 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
}
else
{
- pixel_region_init (&maskPR,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
- x1, y1, (x2 - x1), (y2 - y1), TRUE);
+ mask_offset_x = x1;
+ mask_offset_y = y1;
}
- /* if the image doesn't have an alpha channel, make sure that
- * the buf_tiles have. We need the alpha channel to fill with
- * the region calculated above
- */
- if (! gimp_drawable_has_alpha (drawable))
- bytes++;
-
- buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
- pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
+ tiles = tile_manager_new ((x2 - x1), (y2 - y1),
+ gimp_drawable_bytes_with_alpha (drawable));
+ buffer = gimp_tile_manager_create_buffer (tiles,
+ gimp_drawable_get_format_with_alpha (drawable),
+ TRUE);
switch (fill_mode)
{
case GIMP_FG_BUCKET_FILL:
case GIMP_BG_BUCKET_FILL:
- color_region_mask (&bufPR, &maskPR, col);
+ {
+ GeglColor *gegl_color = gegl_color_new (NULL);
+
+ gimp_gegl_color_set_rgba (gegl_color, color);
+ gegl_buffer_set_color (buffer, NULL, gegl_color);
+
+ g_object_unref (gegl_color);
+ }
break;
case GIMP_PATTERN_BUCKET_FILL:
- pattern_region (&bufPR, &maskPR, pat_buf, x1, y1);
+ {
+ GeglBuffer *pattern_buffer = gimp_pattern_create_buffer (pattern);
+
+ gegl_buffer_set_pattern (buffer, NULL, pattern_buffer, -x1, -y1);
+
+ g_object_unref (pattern_buffer);
+ }
break;
}
+ apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 1.0,
+ mask_offset_x,
+ mask_offset_y);
+
+ gimp_apply_operation (buffer, NULL, NULL,
+ apply_opacity, 1.0,
+ buffer, NULL);
+
+ g_object_unref (apply_opacity);
+
+ g_object_unref (buffer);
+ g_object_unref (mask);
+
/* Apply it to the image */
- pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
+ pixel_region_init (&bufPR, tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimp_drawable_apply_region (drawable, &bufPR,
TRUE, C_("undo-type", "Bucket Fill"),
opacity, paint_mode,
NULL, NULL, x1, y1);
- tile_manager_unref (buf_tiles);
-
- gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1);
- /* free the mask */
- g_object_unref (mask);
+ tile_manager_unref (tiles);
- if (new_buf)
- temp_buf_free (pat_buf);
+ gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1);
gimp_unset_busy (image->gimp);
}
diff --git a/app/core/gimpdrawable-stroke.c b/app/core/gimpdrawable-stroke.c
index ac2b3f7..80b21fc 100644
--- a/app/core/gimpdrawable-stroke.c
+++ b/app/core/gimpdrawable-stroke.c
@@ -390,10 +390,11 @@ gimp_drawable_stroke_scan_convert (GimpDrawable *drawable,
break;
}
- apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 1.0);
+ apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 1.0,
+ 0, 0);
gimp_apply_operation (base_buffer, NULL, NULL,
- apply_opacity, TRUE,
+ apply_opacity, 1.0,
base_buffer, NULL);
g_object_unref (apply_opacity);
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index c8402e1..319d7705 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -1601,7 +1601,8 @@ gimp_layer_apply_mask (GimpLayer *layer,
mask_buffer = gimp_drawable_get_read_buffer (GIMP_DRAWABLE (mask));
dest_buffer = gimp_drawable_get_write_buffer (GIMP_DRAWABLE (layer));
- apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 1.0);
+ apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 1.0,
+ 0, 0);
gimp_drawable_apply_operation_to_buffer (GIMP_DRAWABLE (layer), NULL, NULL,
apply_opacity, TRUE, dest_buffer);
diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c
index 739a7ca..c99986a 100644
--- a/app/gegl/gimp-gegl-nodes.c
+++ b/app/gegl/gimp-gegl-nodes.c
@@ -70,7 +70,10 @@ gimp_gegl_create_flatten_node (const GimpRGB *background)
GeglNode *
gimp_gegl_create_apply_opacity_node (GeglBuffer *mask,
- gdouble opacity)
+ gdouble opacity,
+ /* offsets *into* the mask */
+ gint mask_offset_x,
+ gint mask_offset_y)
{
GeglNode *node;
GeglNode *input;
@@ -96,8 +99,26 @@ gimp_gegl_create_apply_opacity_node (GeglBuffer *mask,
gegl_node_connect_to (input, "output",
opacity_node, "input");
- gegl_node_connect_to (mask_source, "output",
- opacity_node, "aux");
+
+ if (mask_offset_x != 0 || mask_offset_y != 0)
+ {
+ GeglNode *translate = gegl_node_new_child (node,
+ "operation", "gegl:translate",
+ "x", (gdouble) -mask_offset_x,
+ "y", (gdouble) -mask_offset_y,
+ NULL);
+
+ gegl_node_connect_to (mask_source, "output",
+ translate, "input");
+ gegl_node_connect_to (translate, "output",
+ opacity_node, "aux");
+ }
+ else
+ {
+ gegl_node_connect_to (mask_source, "output",
+ opacity_node, "aux");
+ }
+
gegl_node_connect_to (opacity_node, "output",
output, "input");
diff --git a/app/gegl/gimp-gegl-nodes.h b/app/gegl/gimp-gegl-nodes.h
index 8e341db..01cce1c 100644
--- a/app/gegl/gimp-gegl-nodes.h
+++ b/app/gegl/gimp-gegl-nodes.h
@@ -24,7 +24,10 @@
GeglNode * gimp_gegl_create_flatten_node (const GimpRGB *background);
GeglNode * gimp_gegl_create_apply_opacity_node (GeglBuffer *mask,
- gdouble opacity);
+ gdouble opacity,
+ /* offsets *into* the mask */
+ gint mask_offset_x,
+ gint mask_offset_y);
#endif /* __GIMP_GEGL_NODES_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]