[gimp] app: improve gimp_brush_core_color_area_with_pixmap()
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: improve gimp_brush_core_color_area_with_pixmap()
- Date: Sun, 24 Feb 2019 18:24:49 +0000 (UTC)
commit 5b09af4390403152bde3a971ca49b8231cbf7914
Author: Ell <ell_se yahoo com>
Date: Sun Feb 24 12:54:58 2019 -0500
app: improve gimp_brush_core_color_area_with_pixmap()
Reimplement gimp_brush_core_color_area_with_pixmap(), which copies
the brush's dab to the paint buffer when using a pixmap brush, in
terms of gimp-gegl-loops. This simplifies the functions,
parallelizes processing, and transparently handles float brushes.
Replace the "mode" parameter of the function with an "apply_mask"
parameter, which specifies whether to apply the brush's mask to
the dab as part of copying. Avoid applying the mask in
GimpPaintbrush; previously, we would erroneously apply the mask
twice when using the paintbrush tool: once when copying the
dab to the paint buffer, and again when pasting the paint buffer
to the canvas.
We still apply the mask in GimpSmudge, which results in the same
double-application behavior, however, this might be less practical
to fix.
app/paint/gimpbrushcore.c | 229 +++++++++++----------------------------------
app/paint/gimpbrushcore.h | 2 +-
app/paint/gimppaintbrush.c | 2 +-
app/paint/gimpsmudge.c | 2 +-
4 files changed, 57 insertions(+), 178 deletions(-)
---
diff --git a/app/paint/gimpbrushcore.c b/app/paint/gimpbrushcore.c
index a5756f8707..d2f499fdb1 100644
--- a/app/paint/gimpbrushcore.c
+++ b/app/paint/gimpbrushcore.c
@@ -29,6 +29,7 @@
#include "operations/layer-modes/gimp-layer-modes.h"
#include "gegl/gimp-babl.h"
+#include "gegl/gimp-gegl-loops.h"
#include "core/gimpbrush-header.h"
#include "core/gimpbrushgenerated.h"
@@ -110,15 +111,6 @@ static const GimpTempBuf *
static void gimp_brush_core_invalidate_cache (GimpBrush *brush,
GimpBrushCore *core);
-/* brush pipe utility functions */
-static void gimp_brush_core_paint_line_pixmap_mask (const Babl *fish,
- const GimpTempBuf *pixmap_mask,
- const GimpTempBuf *brush_mask,
- gfloat *d,
- gint x,
- gint y,
- gint width);
-
G_DEFINE_TYPE (GimpBrushCore, gimp_brush_core, GIMP_TYPE_PAINT_CORE)
@@ -1221,198 +1213,85 @@ gimp_brush_core_eval_transform_dynamics (GimpBrushCore *core,
}
}
-
-/**************************************************/
-/* Brush pipe utility functions */
-/**************************************************/
-
void
-gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core,
- GimpDrawable *drawable,
- const GimpCoords *coords,
- GeglNode *op,
- GeglBuffer *area,
- gint area_x,
- gint area_y,
- GimpBrushApplicationMode mode)
+gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core,
+ GimpDrawable *drawable,
+ const GimpCoords *coords,
+ GeglNode *op,
+ GeglBuffer *area,
+ gint area_x,
+ gint area_y,
+ gboolean apply_mask)
{
- GeglBufferIterator *iter;
- GeglRectangle *roi;
- gint ulx;
- gint uly;
- gint offsetx;
- gint offsety;
- const GimpTempBuf *pixmap_mask;
- const GimpTempBuf *brush_mask;
- const Babl *area_format;
- const Babl *pixmap_format;
- const Babl *fish = NULL;
+ const GimpTempBuf *pixmap;
+ GeglBuffer *pixmap_buffer;
+ const GimpTempBuf *mask;
+ GeglBuffer *mask_buffer;
+ gint area_width;
+ gint area_height;
+ gint ul_x;
+ gint ul_y;
+ gint offset_x;
+ gint offset_y;
g_return_if_fail (GIMP_IS_BRUSH (core->brush));
g_return_if_fail (gimp_brush_get_pixmap (core->brush) != NULL);
- /* scale the brushes */
- pixmap_mask = gimp_brush_core_transform_pixmap (core, core->brush, op);
+ /* scale the brush */
+ pixmap = gimp_brush_core_transform_pixmap (core, core->brush, op);
- if (! pixmap_mask)
+ if (! pixmap)
return;
- if (mode != GIMP_BRUSH_HARD)
- brush_mask = gimp_brush_core_transform_mask (core, core->brush, op);
+ if (apply_mask)
+ mask = gimp_brush_core_transform_mask (core, core->brush, op);
else
- brush_mask = NULL;
+ mask = NULL;
/* Calculate upper left corner of brush as in
* gimp_paint_core_get_paint_area. Ugly to have to do this here, too.
*/
- ulx = (gint) floor (coords->x) - (gimp_temp_buf_get_width (pixmap_mask) >> 1);
- uly = (gint) floor (coords->y) - (gimp_temp_buf_get_height (pixmap_mask) >> 1);
+ ul_x = (gint) floor (coords->x) - (gimp_temp_buf_get_width (pixmap) >> 1);
+ ul_y = (gint) floor (coords->y) - (gimp_temp_buf_get_height (pixmap) >> 1);
/* Not sure why this is necessary, but empirically the code does
* not work without it for even-sided brushes. See bug #166622.
*/
- if (gimp_temp_buf_get_width (pixmap_mask) % 2 == 0)
- ulx += ROUND (coords->x) - floor (coords->x);
- if (gimp_temp_buf_get_height (pixmap_mask) % 2 == 0)
- uly += ROUND (coords->y) - floor (coords->y);
-
- offsetx = area_x - ulx;
- offsety = area_y - uly;
-
- area_format = gegl_buffer_get_format (area);
- pixmap_format = gimp_temp_buf_get_format (pixmap_mask);
-
- iter = gegl_buffer_iterator_new (area, NULL, 0, area_format,
- GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1);
-
- if (mode == GIMP_BRUSH_SOFT && brush_mask)
- {
- GimpImageBaseType pixmap_base_type;
- GimpPrecision pixmap_precision;
- const Babl *pixmap_space;
-
- pixmap_base_type = gimp_babl_format_get_base_type (pixmap_format);
- pixmap_precision = gimp_babl_format_get_precision (pixmap_format);
- pixmap_space = babl_format_get_space (pixmap_format);
-
- fish = babl_fish (gimp_babl_format (pixmap_base_type, pixmap_precision,
- TRUE, pixmap_space),
- area_format);
- }
- else
- {
- fish = babl_fish (pixmap_format, area_format);
-
- brush_mask = NULL;
- }
-
- roi = &iter->items[0].roi;
-
- while (gegl_buffer_iterator_next (iter))
- {
- gfloat *d = iter->items[0].data;
- gint y;
-
- for (y = 0; y < roi->height; y++)
- {
- gimp_brush_core_paint_line_pixmap_mask (fish,
- pixmap_mask, brush_mask,
- d, offsetx, y + offsety,
- roi->width);
- d += roi->width * 4;
- }
- }
-}
-
-static void
-gimp_brush_core_paint_line_pixmap_mask (const Babl *fish,
- const GimpTempBuf *pixmap_mask,
- const GimpTempBuf *brush_mask,
- gfloat *d,
- gint x,
- gint y,
- gint width)
-{
- const Babl *pixmap_format;
- gint pixmap_bytes;
- gint pixmap_width;
- gint pixmap_height;
- guchar *b;
+ if (gimp_temp_buf_get_width (pixmap) % 2 == 0)
+ ul_x += ROUND (coords->x) - floor (coords->x);
+ if (gimp_temp_buf_get_height (pixmap) % 2 == 0)
+ ul_y += ROUND (coords->y) - floor (coords->y);
- pixmap_width = gimp_temp_buf_get_width (pixmap_mask);
- pixmap_height = gimp_temp_buf_get_height (pixmap_mask);
+ offset_x = area_x - ul_x;
+ offset_y = area_y - ul_y;
- /* Make sure x, y are positive */
- x %= pixmap_width;
- if (x < 0)
- x += pixmap_width;
+ area_width = gegl_buffer_get_width (area);
+ area_height = gegl_buffer_get_height (area);
- y %= pixmap_height;
- if (y < 0)
- y += pixmap_height;
+ pixmap_buffer = gimp_temp_buf_create_buffer (pixmap);
- pixmap_format = gimp_temp_buf_get_format (pixmap_mask);
- pixmap_bytes = babl_format_get_bytes_per_pixel (pixmap_format);
+ gimp_gegl_buffer_copy (pixmap_buffer,
+ GEGL_RECTANGLE (offset_x, offset_y,
+ area_width, area_height),
+ GEGL_ABYSS_NONE,
+ area,
+ GEGL_RECTANGLE (0, 0,
+ area_width, area_height));
- /* Point to the appropriate scanline */
- b = (gimp_temp_buf_get_data (pixmap_mask) +
- y * pixmap_width * pixmap_bytes);
+ g_object_unref (pixmap_buffer);
- if (brush_mask)
+ if (mask)
{
- const guchar *mask = (gimp_temp_buf_get_data (brush_mask) +
- y * pixmap_width);
- guchar *line_buf = g_alloca (width * (pixmap_bytes + 1));
- guchar *l = line_buf;
- gint i;
-
- g_return_if_fail (gimp_temp_buf_get_width (brush_mask) == pixmap_width);
- g_return_if_fail (gimp_temp_buf_get_height (brush_mask) == pixmap_height);
-
- /* put the source pixmap's pixels, plus the mask's alpha, into
- * one line, so we can use one single call to babl_process() to
- * convert the entire line
- */
-
- for (i = 0; i < width; i++)
- {
- gint p_bytes = pixmap_bytes;
- guchar *p = b + x * p_bytes;
+ mask_buffer = gimp_temp_buf_create_buffer (mask);
- while (p_bytes--)
- *l++ = *p++;
-
- *l++ = mask[x++];
-
- if (x == pixmap_width)
- x = 0;
- }
-
- babl_process (fish, line_buf, d, width);
- }
- else
- {
- guchar *line_buf = g_alloca (width * (pixmap_bytes));
- guchar *l = line_buf;
- gint i;
-
- /* put the source pixmap's pixels into one line, so we can use
- * one single call to babl_process() to convert the entire line
- */
- for (i = 0; i < width; i++)
- {
- gint p_bytes = pixmap_bytes;
- guchar *p = b + x * p_bytes;
-
- while (p_bytes--)
- *l++ = *p++;
-
- x++;
-
- if (x == pixmap_width)
- x = 0;
- }
+ gimp_gegl_apply_mask (mask_buffer,
+ GEGL_RECTANGLE (offset_x, offset_y,
+ area_width, area_height),
+ area,
+ GEGL_RECTANGLE (0, 0,
+ area_width, area_height),
+ 1.0);
- babl_process (fish, line_buf, d, width);
+ g_object_unref (mask_buffer);
}
}
diff --git a/app/paint/gimpbrushcore.h b/app/paint/gimpbrushcore.h
index b733f0f50f..b46a1080ae 100644
--- a/app/paint/gimpbrushcore.h
+++ b/app/paint/gimpbrushcore.h
@@ -128,7 +128,7 @@ void gimp_brush_core_color_area_with_pixmap
GeglBuffer *area,
gint area_x,
gint area_y,
- GimpBrushApplicationMode mode);
+ gboolean apply_mask);
const GimpTempBuf * gimp_brush_core_get_brush_mask
(GimpBrushCore *core,
diff --git a/app/paint/gimppaintbrush.c b/app/paint/gimppaintbrush.c
index 367d1c0f94..944bbfe1fb 100644
--- a/app/paint/gimppaintbrush.c
+++ b/app/paint/gimppaintbrush.c
@@ -235,7 +235,7 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
paint_buffer,
paint_buffer_x,
paint_buffer_y,
- gimp_paint_options_get_brush_mode (paint_options));
+ FALSE);
paint_appl_mode = GIMP_PAINT_INCREMENTAL;
}
diff --git a/app/paint/gimpsmudge.c b/app/paint/gimpsmudge.c
index 5d11a78b6d..c991e03f24 100644
--- a/app/paint/gimpsmudge.c
+++ b/app/paint/gimpsmudge.c
@@ -501,7 +501,7 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
paint_buffer,
paint_buffer_x,
paint_buffer_y,
- gimp_paint_options_get_brush_mode (paint_options));
+ TRUE);
}
gimp_gegl_smudge_with_paint (accum_buffer,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]