[gimp] app: add the GimpApplicator back for painting, but make its use optional
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add the GimpApplicator back for painting, but make its use optional
- Date: Tue, 21 May 2013 16:56:04 +0000 (UTC)
commit 741792875e2e20216bd87ddca4b5b7ad2e1ee033
Author: Michael Natterer <mitch gimp org>
Date: Tue May 21 18:52:40 2013 +0200
app: add the GimpApplicator back for painting, but make its use optional
Default to using the new code. This is out of pure curiosity how
GEGL changes affect painting with a purely graph-based method.
app/paint/gimppaintcore.c | 320 ++++++++++++++++++++++++++------------
app/paint/gimppaintcore.h | 3 +-
app/paint/gimppaintoptions.c | 17 ++
app/paint/gimppaintoptions.h | 2 +
app/tools/gimppaintoptions-gui.c | 11 ++
5 files changed, 255 insertions(+), 98 deletions(-)
---
diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c
index 1f99847..c6adeb7 100644
--- a/app/paint/gimppaintcore.c
+++ b/app/paint/gimppaintcore.c
@@ -27,8 +27,10 @@
#include "paint-types.h"
+#include "gegl/gimp-gegl-loops.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
+#include "gegl/gimpapplicator.h"
#include "core/gimp.h"
#include "core/gimp-utils.h"
@@ -402,10 +404,7 @@ gimp_paint_core_start (GimpPaintCore *core,
mask = gimp_image_get_mask (image);
/* don't apply the mask to itself and don't apply an empty mask */
- if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask))
- mask = NULL;
-
- if (mask)
+ if (GIMP_DRAWABLE (mask) != drawable && ! gimp_channel_is_empty (mask))
{
GeglBuffer *mask_buffer;
gint offset_x;
@@ -414,8 +413,7 @@ gimp_paint_core_start (GimpPaintCore *core,
mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
gimp_item_get_offset (item, &offset_x, &offset_y);
- g_object_ref (mask_buffer);
- core->mask_buffer = mask_buffer;
+ core->mask_buffer = g_object_ref (mask_buffer);
core->mask_x_offset = -offset_x;
core->mask_y_offset = -offset_y;
}
@@ -426,30 +424,49 @@ gimp_paint_core_start (GimpPaintCore *core,
core->linear_mode = gimp_drawable_get_linear (drawable);
- /* Allocate the scratch buffer if there's a component mask */
- if (gimp_drawable_get_active_mask (drawable) != GIMP_COMPONENT_ALL)
+ if (paint_options->use_applicator)
{
- if (core->linear_mode)
+ core->applicator = gimp_applicator_new (NULL, core->linear_mode);
+
+ if (core->mask_buffer)
{
- core->comp_buffer =
- gegl_buffer_new (GEGL_RECTANGLE (0, 0,
- gimp_item_get_width (item),
- gimp_item_get_height (item)),
- babl_format ("RGBA float"));
+ gimp_applicator_set_mask_buffer (core->applicator,
+ core->mask_buffer);
+ gimp_applicator_set_mask_offset (core->applicator,
+ core->mask_x_offset,
+ core->mask_y_offset);
}
- else
+
+ gimp_applicator_set_affect (core->applicator,
+ gimp_drawable_get_active_mask (drawable));
+ gimp_applicator_set_dest_buffer (core->applicator,
+ gimp_drawable_get_buffer (drawable));
+ }
+ else
+ {
+ if (core->comp_buffer)
{
+ g_object_unref (core->comp_buffer);
+ core->comp_buffer = NULL;
+ }
+
+ /* Allocate the scratch buffer if there's a component mask */
+ if (gimp_drawable_get_active_mask (drawable) != GIMP_COMPONENT_ALL)
+ {
+ const Babl *format;
+
+ if (core->linear_mode)
+ format = babl_format ("RGBA float");
+ else
+ format = babl_format ("R'G'B'A float");
+
core->comp_buffer =
gegl_buffer_new (GEGL_RECTANGLE (0, 0,
gimp_item_get_width (item),
gimp_item_get_height (item)),
- babl_format ("R'G'B'A float"));
+ format);
}
}
- else
- {
- core->comp_buffer = NULL;
- }
/* Freeze the drawable preview so that it isn't constantly updated. */
gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable));
@@ -468,6 +485,12 @@ gimp_paint_core_finish (GimpPaintCore *core,
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
+ if (core->applicator)
+ {
+ g_object_unref (core->applicator);
+ core->applicator = NULL;
+ }
+
if (core->stroke_buffer)
{
g_array_free (core->stroke_buffer, TRUE);
@@ -776,84 +799,166 @@ gimp_paint_core_paste (GimpPaintCore *core,
GimpLayerModeEffects paint_mode,
GimpPaintApplicationMode mode)
{
- GimpTempBuf *paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer);
- GeglBuffer *dest_buffer;
- GeglBuffer *src_buffer;
-
- gint width = gimp_temp_buf_get_width (paint_buf);
- gint height = gimp_temp_buf_get_height (paint_buf);
+ gint width = gegl_buffer_get_width (core->paint_buffer);
+ gint height = gegl_buffer_get_height (core->paint_buffer);
- if (!paint_buf)
- return;
+ if (core->applicator)
+ {
+ /* If the mode is CONSTANT:
+ * combine the canvas buf, the paint mask to the canvas buffer
+ */
+ if (mode == GIMP_PAINT_CONSTANT)
+ {
+ /* Some tools (ink) paint the mask to paint_core->canvas_buffer
+ * directly. Don't need to copy it in this case.
+ */
+ if (paint_mask != NULL)
+ {
+ GeglBuffer *paint_mask_buffer =
+ gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
+
+ gimp_gegl_combine_mask_weird (paint_mask_buffer,
+ GEGL_RECTANGLE (paint_mask_offset_x,
+ paint_mask_offset_y,
+ width, height),
+ core->canvas_buffer,
+ GEGL_RECTANGLE (core->paint_buffer_x,
+ core->paint_buffer_y,
+ width, height),
+ paint_opacity,
+ GIMP_IS_AIRBRUSH (core));
+
+ g_object_unref (paint_mask_buffer);
+ }
- if (core->comp_buffer)
- dest_buffer = core->comp_buffer;
- else
- dest_buffer = gimp_drawable_get_buffer (drawable);
+ gimp_gegl_apply_mask (core->canvas_buffer,
+ GEGL_RECTANGLE (core->paint_buffer_x,
+ core->paint_buffer_y,
+ width, height),
+ core->paint_buffer,
+ GEGL_RECTANGLE (0, 0, width, height),
+ 1.0);
- if (mode == GIMP_PAINT_CONSTANT)
- {
- /* This step is skipped by the ink tool, which writes directly to canvas_buffer */
- if (paint_mask != NULL)
+ gimp_applicator_set_src_buffer (core->applicator,
+ core->undo_buffer);
+ }
+ /* Otherwise:
+ * combine the canvas buf and the paint mask to the canvas buf
+ */
+ else
{
- /* Mix paint mask and canvas_buffer */
- combine_paint_mask_to_canvas_mask (paint_mask,
- paint_mask_offset_x,
- paint_mask_offset_y,
- core->canvas_buffer,
- core->paint_buffer_x,
- core->paint_buffer_y,
- paint_opacity,
- GIMP_IS_AIRBRUSH (core));
+ GeglBuffer *paint_mask_buffer =
+ gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
+
+ gimp_gegl_apply_mask (paint_mask_buffer,
+ GEGL_RECTANGLE (paint_mask_offset_x,
+ paint_mask_offset_y,
+ width, height),
+ core->paint_buffer,
+ GEGL_RECTANGLE (0, 0, width, height),
+ paint_opacity);
+
+ g_object_unref (paint_mask_buffer);
+
+ gimp_applicator_set_src_buffer (core->applicator,
+ gimp_drawable_get_buffer (drawable));
}
- /* Write canvas_buffer to paint_buf */
- canvas_buffer_to_paint_buf_alpha (paint_buf,
- core->canvas_buffer,
+ gimp_applicator_set_apply_buffer (core->applicator,
+ core->paint_buffer);
+ gimp_applicator_set_apply_offset (core->applicator,
core->paint_buffer_x,
core->paint_buffer_y);
- /* undo buf -> paint_buf -> dest_buffer */
- src_buffer = core->undo_buffer;
+ gimp_applicator_set_mode (core->applicator,
+ image_opacity, paint_mode);
+
+ /* apply the paint area to the image */
+ gimp_applicator_blit (core->applicator,
+ GEGL_RECTANGLE (core->paint_buffer_x,
+ core->paint_buffer_y,
+ width, height));
}
else
{
- g_return_if_fail (paint_mask);
+ GimpTempBuf *paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer);
+ GeglBuffer *dest_buffer;
+ GeglBuffer *src_buffer;
- /* Write paint_mask to paint_buf, does not modify canvas_buffer */
- paint_mask_to_paint_buffer (paint_mask,
- paint_mask_offset_x,
- paint_mask_offset_y,
- paint_buf,
- paint_opacity);
+ if (! paint_buf)
+ return;
- /* dest_buffer -> paint_buf -> dest_buffer */
- src_buffer = dest_buffer;
- }
+ if (core->comp_buffer)
+ dest_buffer = core->comp_buffer;
+ else
+ dest_buffer = gimp_drawable_get_buffer (drawable);
+
+ if (mode == GIMP_PAINT_CONSTANT)
+ {
+ /* This step is skipped by the ink tool, which writes
+ * directly to canvas_buffer
+ */
+ if (paint_mask != NULL)
+ {
+ /* Mix paint mask and canvas_buffer */
+ combine_paint_mask_to_canvas_mask (paint_mask,
+ paint_mask_offset_x,
+ paint_mask_offset_y,
+ core->canvas_buffer,
+ core->paint_buffer_x,
+ core->paint_buffer_y,
+ paint_opacity,
+ GIMP_IS_AIRBRUSH (core));
+ }
- do_layer_blend (src_buffer,
- dest_buffer,
- paint_buf,
- core->mask_buffer,
- image_opacity,
- core->paint_buffer_x,
- core->paint_buffer_y,
- core->mask_x_offset,
- core->mask_y_offset,
- core->linear_mode,
- paint_mode);
+ /* Write canvas_buffer to paint_buf */
+ canvas_buffer_to_paint_buf_alpha (paint_buf,
+ core->canvas_buffer,
+ core->paint_buffer_x,
+ core->paint_buffer_y);
- if (core->comp_buffer)
- {
- mask_components_onto (src_buffer,
- core->comp_buffer,
- gimp_drawable_get_buffer (drawable),
- GEGL_RECTANGLE(core->paint_buffer_x,
- core->paint_buffer_y,
- width,
- height),
- gimp_drawable_get_active_mask (drawable),
- core->linear_mode);
+ /* undo buf -> paint_buf -> dest_buffer */
+ src_buffer = core->undo_buffer;
+ }
+ else
+ {
+ g_return_if_fail (paint_mask);
+
+ /* Write paint_mask to paint_buf, does not modify canvas_buffer */
+ paint_mask_to_paint_buffer (paint_mask,
+ paint_mask_offset_x,
+ paint_mask_offset_y,
+ paint_buf,
+ paint_opacity);
+
+ /* dest_buffer -> paint_buf -> dest_buffer */
+ src_buffer = dest_buffer;
+ }
+
+ do_layer_blend (src_buffer,
+ dest_buffer,
+ paint_buf,
+ core->mask_buffer,
+ image_opacity,
+ core->paint_buffer_x,
+ core->paint_buffer_y,
+ core->mask_x_offset,
+ core->mask_y_offset,
+ core->linear_mode,
+ paint_mode);
+
+ if (core->comp_buffer)
+ {
+ mask_components_onto (src_buffer,
+ core->comp_buffer,
+ gimp_drawable_get_buffer (drawable),
+ GEGL_RECTANGLE(core->paint_buffer_x,
+ core->paint_buffer_y,
+ width,
+ height),
+ gimp_drawable_get_active_mask (drawable),
+ core->linear_mode);
+ }
}
/* Update the undo extents */
@@ -888,8 +993,8 @@ gimp_paint_core_replace (GimpPaintCore *core,
GimpPaintApplicationMode mode)
{
GeglRectangle mask_rect;
- gint width, height;
GeglBuffer *paint_mask_buffer;
+ gint width, height;
if (! gimp_drawable_has_alpha (drawable))
{
@@ -911,22 +1016,42 @@ gimp_paint_core_replace (GimpPaintCore *core,
/* Some tools (ink) paint the mask to paint_core->canvas_buffer
* directly. Don't need to copy it in this case.
*/
- (paint_mask != NULL))
+ paint_mask != NULL)
{
- /* Mix paint mask and canvas_buffer */
- combine_paint_mask_to_canvas_mask (paint_mask,
- paint_mask_offset_x,
- paint_mask_offset_y,
- core->canvas_buffer,
- core->paint_buffer_x,
- core->paint_buffer_y,
- paint_opacity,
- GIMP_IS_AIRBRUSH (core));
+ if (core->applicator)
+ {
+ paint_mask_buffer =
+ gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
+
+ /* combine the paint mask and the canvas buffer */
+ gimp_gegl_combine_mask_weird (paint_mask_buffer,
+ GEGL_RECTANGLE (paint_mask_offset_x,
+ paint_mask_offset_y,
+ width, height),
+ core->canvas_buffer,
+ GEGL_RECTANGLE (core->paint_buffer_x,
+ core->paint_buffer_y,
+ width, height),
+ paint_opacity,
+ GIMP_IS_AIRBRUSH (core));
- /* initialize the maskPR from the canvas buffer */
- paint_mask_buffer = core->canvas_buffer;
+ g_object_unref (paint_mask_buffer);
+ }
+ else
+ {
+ /* Mix paint mask and canvas_buffer */
+ combine_paint_mask_to_canvas_mask (paint_mask,
+ paint_mask_offset_x,
+ paint_mask_offset_y,
+ core->canvas_buffer,
+ core->paint_buffer_x,
+ core->paint_buffer_y,
+ paint_opacity,
+ GIMP_IS_AIRBRUSH (core));
+ }
- g_object_ref (paint_mask_buffer);
+ /* initialize the maskPR from the canvas buffer */
+ paint_mask_buffer = g_object_ref (core->canvas_buffer);
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
core->paint_buffer_y,
@@ -934,7 +1059,8 @@ gimp_paint_core_replace (GimpPaintCore *core,
}
else
{
- paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
+ paint_mask_buffer =
+ gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x,
paint_mask_offset_y,
diff --git a/app/paint/gimppaintcore.h b/app/paint/gimppaintcore.h
index 0ea1b91..c935b5c 100644
--- a/app/paint/gimppaintcore.h
+++ b/app/paint/gimppaintcore.h
@@ -69,6 +69,8 @@ struct _GimpPaintCore
gint mask_x_offset;
gint mask_y_offset;
+ GimpApplicator *applicator;
+
GArray *stroke_buffer;
};
@@ -181,7 +183,6 @@ void gimp_paint_core_paste (GimpPaintCore *core,
GimpLayerModeEffects paint_mode,
GimpPaintApplicationMode mode);
-
void gimp_paint_core_replace (GimpPaintCore *core,
const GimpTempBuf *paint_mask,
gint paint_mask_offset_x,
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index 10430a2..a7c069f 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -72,6 +72,8 @@ enum
PROP_PAINT_INFO,
+ PROP_USE_APPLICATOR, /* temp debug */
+
PROP_BRUSH_SIZE,
PROP_BRUSH_ASPECT_RATIO,
PROP_BRUSH_ANGLE,
@@ -141,6 +143,13 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_USE_APPLICATOR,
+ g_param_spec_boolean ("use-applicator",
+ NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BRUSH_SIZE,
"brush-size", _("Brush Size"),
1.0, 10000.0, DEFAULT_BRUSH_SIZE,
@@ -325,6 +334,10 @@ gimp_paint_options_set_property (GObject *object,
options->paint_info = g_value_dup_object (value);
break;
+ case PROP_USE_APPLICATOR:
+ options->use_applicator = g_value_get_boolean (value);
+ break;
+
case PROP_BRUSH_SIZE:
options->brush_size = g_value_get_double (value);
break;
@@ -445,6 +458,10 @@ gimp_paint_options_get_property (GObject *object,
g_value_set_object (value, options->paint_info);
break;
+ case PROP_USE_APPLICATOR:
+ g_value_set_boolean (value, options->use_applicator);
+ break;
+
case PROP_BRUSH_SIZE:
g_value_set_double (value, options->brush_size);
break;
diff --git a/app/paint/gimppaintoptions.h b/app/paint/gimppaintoptions.h
index 70c4e40..ab17463 100644
--- a/app/paint/gimppaintoptions.h
+++ b/app/paint/gimppaintoptions.h
@@ -80,6 +80,8 @@ struct _GimpPaintOptions
GimpPaintInfo *paint_info;
+ gboolean use_applicator;
+
gdouble brush_size;
gdouble brush_angle;
gdouble brush_aspect_ratio;
diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c
index 2113d46..458ca47 100644
--- a/app/tools/gimppaintoptions-gui.c
+++ b/app/tools/gimppaintoptions-gui.c
@@ -112,6 +112,17 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
gtk_widget_show (scale);
+ /* temp debug foo */
+ if (g_type_is_a (tool_type, GIMP_TYPE_PAINT_TOOL))
+ {
+ GtkWidget *button;
+
+ button = gimp_prop_check_button_new (config, "use-applicator",
+ "Use GimpApplicator");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+ }
+
/* the brush */
if (g_type_is_a (tool_type, GIMP_TYPE_BRUSH_TOOL))
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]