app: derive GimpEraser from GimpPaintbrush

In GimpPaintbrush, factor out the code responsible for determining
the current dab's paint parameters and content to a new
GimpPaintbrush::get_paint_params() virtual function.

Derive GimpEraser from GimpPaintbrush, instead of directly from
GimpBrushCore, implementing get_paint_params() appropriately.
This allows GimpEraser to reuse the paint-buffer content across
dabs, improving performance.
This commit is contained in:
Ell 2019-05-26 14:38:24 -04:00
parent 3b56bd7a9a
commit aba4eef916
4 changed files with 163 additions and 175 deletions

View File

@ -38,19 +38,26 @@
#include "gimp-intl.h"
static void gimp_eraser_paint (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpPaintState paint_state,
guint32 time);
static void gimp_eraser_motion (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym);
static void gimp_eraser_paint (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpPaintState paint_state,
guint32 time);
static void gimp_eraser_get_paint_params (GimpPaintbrush *paintbrush,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpLayerMode *paint_mode,
GimpPaintApplicationMode *paint_appl_mode,
const GimpTempBuf **paint_pixmap,
GimpRGB *paint_color);
G_DEFINE_TYPE (GimpEraser, gimp_eraser, GIMP_TYPE_BRUSH_CORE)
G_DEFINE_TYPE (GimpEraser, gimp_eraser, GIMP_TYPE_PAINTBRUSH)
#define parent_class gimp_eraser_parent_class
void
@ -68,12 +75,12 @@ gimp_eraser_register (Gimp *gimp,
static void
gimp_eraser_class_init (GimpEraserClass *klass)
{
GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass);
GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
GimpPaintbrushClass *paintbrush_class = GIMP_PAINTBRUSH_CLASS (klass);
paint_core_class->paint = gimp_eraser_paint;
paint_core_class->paint = gimp_eraser_paint;
brush_core_class->handles_changing_brush = TRUE;
paintbrush_class->get_paint_params = gimp_eraser_get_paint_params;
}
static void
@ -108,108 +115,37 @@ gimp_eraser_paint (GimpPaintCore *paint_core,
}
}
break;
case GIMP_PAINT_STATE_MOTION:
gimp_eraser_motion (paint_core, drawable, paint_options, sym);
break;
default:
break;
}
GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable,
paint_options, sym,
paint_state, time);
}
static void
gimp_eraser_motion (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym)
gimp_eraser_get_paint_params (GimpPaintbrush *paintbrush,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpLayerMode *paint_mode,
GimpPaintApplicationMode *paint_appl_mode,
const GimpTempBuf **paint_pixmap,
GimpRGB *paint_color)
{
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core);
GimpEraserOptions *options = GIMP_ERASER_OPTIONS (paint_options);
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics;
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
gdouble fade_point;
gdouble opacity;
GimpLayerMode paint_mode;
GeglBuffer *paint_buffer;
gint paint_buffer_x;
gint paint_buffer_y;
GimpRGB background;
GeglColor *color;
gdouble force;
const GimpCoords *coords;
gint n_strokes;
gint paint_width, paint_height;
gint i;
GimpEraserOptions *options = GIMP_ERASER_OPTIONS (paint_options);
GimpContext *context = GIMP_CONTEXT (paint_options);
fade_point = gimp_paint_options_get_fade (paint_options, image,
paint_core->pixel_dist);
coords = gimp_symmetry_get_origin (sym);
opacity = gimp_dynamics_get_linear_value (dynamics,
GIMP_DYNAMICS_OUTPUT_OPACITY,
coords,
paint_options,
fade_point);
if (opacity == 0.0)
return;
gimp_context_get_background (context, &background);
gimp_context_get_background (context, paint_color);
gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable),
&background, &background);
color = gimp_gegl_color_new (&background, gimp_drawable_get_space (drawable));
paint_color, paint_color);
if (options->anti_erase)
paint_mode = GIMP_LAYER_MODE_ANTI_ERASE;
*paint_mode = GIMP_LAYER_MODE_ANTI_ERASE;
else if (gimp_drawable_has_alpha (drawable))
paint_mode = GIMP_LAYER_MODE_ERASE;
*paint_mode = GIMP_LAYER_MODE_ERASE;
else
paint_mode = GIMP_LAYER_MODE_NORMAL_LEGACY;
gimp_brush_core_eval_transform_dynamics (brush_core,
drawable,
paint_options,
coords);
n_strokes = gimp_symmetry_get_size (sym);
for (i = 0; i < n_strokes; i++)
{
coords = gimp_symmetry_get_coords (sym, i);
gimp_brush_core_eval_transform_symmetry (brush_core, sym, i);
if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE))
force = gimp_dynamics_get_linear_value (dynamics,
GIMP_DYNAMICS_OUTPUT_FORCE,
coords,
paint_options,
fade_point);
else
force = paint_options->brush_force;
paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
paint_options,
paint_mode,
coords,
&paint_buffer_x,
&paint_buffer_y,
&paint_width,
&paint_height);
if (! paint_buffer)
continue;
gegl_buffer_set_color (paint_buffer, NULL, color);
gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
coords,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
paint_mode,
gimp_paint_options_get_brush_mode (paint_options),
force,
paint_options->application_mode);
}
g_object_unref (color);
*paint_mode = GIMP_LAYER_MODE_NORMAL_LEGACY;
}

View File

@ -19,7 +19,7 @@
#define __GIMP_ERASER_H__
#include "gimpbrushcore.h"
#include "gimppaintbrush.h"
#define GIMP_TYPE_ERASER (gimp_eraser_get_type ())
@ -34,12 +34,12 @@ typedef struct _GimpEraserClass GimpEraserClass;
struct _GimpEraser
{
GimpBrushCore parent_instance;
GimpPaintbrush parent_instance;
};
struct _GimpEraserClass
{
GimpBrushCoreClass parent_class;
GimpPaintbrushClass parent_class;
};

View File

@ -46,12 +46,21 @@
#include "gimp-intl.h"
static void gimp_paintbrush_paint (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpPaintState paint_state,
guint32 time);
static void gimp_paintbrush_paint (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpPaintState paint_state,
guint32 time);
static void gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpLayerMode *paint_mode,
GimpPaintApplicationMode *paint_appl_mode,
const GimpTempBuf **paint_pixmap,
GimpRGB *paint_color);
G_DEFINE_TYPE (GimpPaintbrush, gimp_paintbrush, GIMP_TYPE_BRUSH_CORE)
@ -78,6 +87,8 @@ gimp_paintbrush_class_init (GimpPaintbrushClass *klass)
paint_core_class->paint = gimp_paintbrush_paint;
brush_core_class->handles_changing_brush = TRUE;
klass->get_paint_params = gimp_paintbrush_real_get_paint_params;
}
static void
@ -139,6 +150,66 @@ gimp_paintbrush_paint (GimpPaintCore *paint_core,
}
}
static void
gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpLayerMode *paint_mode,
GimpPaintApplicationMode *paint_appl_mode,
const GimpTempBuf **paint_pixmap,
GimpRGB *paint_color)
{
GimpPaintCore *paint_core = GIMP_PAINT_CORE (paintbrush);
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paintbrush);
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpDynamics *dynamics = brush_core->dynamics;
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
const GimpCoords *coords = gimp_symmetry_get_origin (sym);
gdouble fade_point;
gdouble grad_point;
fade_point = gimp_paint_options_get_fade (paint_options, image,
paint_core->pixel_dist);
grad_point = gimp_dynamics_get_linear_value (dynamics,
GIMP_DYNAMICS_OUTPUT_COLOR,
coords,
paint_options,
fade_point);
*paint_mode = gimp_context_get_paint_mode (context);
if (gimp_paint_options_get_gradient_color (paint_options, image,
grad_point,
paint_core->pixel_dist,
paint_color))
{
/* optionally take the color from the current gradient */
gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable),
paint_color, paint_color);
*paint_appl_mode = GIMP_PAINT_INCREMENTAL;
}
else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))
{
/* otherwise check if the brush has a pixmap and use that to
* color the area
*/
*paint_pixmap = gimp_brush_core_get_brush_pixmap (brush_core);
*paint_appl_mode = GIMP_PAINT_INCREMENTAL;
}
else
{
/* otherwise fill the area with the foreground color */
gimp_context_get_foreground (context, paint_color);
gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable),
paint_color, paint_color);
}
}
void
_gimp_paintbrush_motion (GimpPaintCore *paint_core,
GimpDrawable *drawable,
@ -146,24 +217,16 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
GimpSymmetry *sym,
gdouble opacity)
{
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core);
GimpPaintbrush *paintbrush = GIMP_PAINTBRUSH (paint_core);
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpDynamics *dynamics = brush_core->dynamics;
GimpImage *image;
GimpLayerMode paint_mode;
GeglBuffer *paint_buffer;
gint paint_buffer_x;
gint paint_buffer_y;
GimpPaintApplicationMode paint_appl_mode;
gdouble fade_point;
gdouble grad_point;
gdouble force;
const GimpCoords *coords;
gint n_strokes;
gint i;
image = gimp_item_get_image (GIMP_ITEM (drawable));
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core);
GimpPaintbrush *paintbrush = GIMP_PAINTBRUSH (paint_core);
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpDynamics *dynamics = brush_core->dynamics;
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
gdouble fade_point;
gdouble force;
const GimpCoords *coords;
gint n_strokes;
gint i;
fade_point = gimp_paint_options_get_fade (paint_options, image,
paint_core->pixel_dist);
@ -178,15 +241,6 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
if (opacity == 0.0)
return;
paint_appl_mode = paint_options->application_mode;
grad_point = gimp_dynamics_get_linear_value (dynamics,
GIMP_DYNAMICS_OUTPUT_COLOR,
coords,
paint_options,
fade_point);
if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush)
{
gimp_brush_core_eval_transform_dynamics (brush_core,
@ -195,14 +249,28 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
coords);
}
paint_mode = gimp_context_get_paint_mode (context);
n_strokes = gimp_symmetry_get_size (sym);
for (i = 0; i < n_strokes; i++)
{
const GimpTempBuf *paint_pixmap = NULL;
GimpRGB paint_color;
gint paint_width, paint_height;
GimpLayerMode paint_mode;
GimpPaintApplicationMode paint_appl_mode;
GeglBuffer *paint_buffer;
gint paint_buffer_x;
gint paint_buffer_y;
const GimpTempBuf *paint_pixmap = NULL;
GimpRGB paint_color;
gint paint_width, paint_height;
paint_appl_mode = paint_options->application_mode;
GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_paint_params (paintbrush,
drawable,
paint_options,
sym,
&paint_mode,
&paint_appl_mode,
&paint_pixmap,
&paint_color);
coords = gimp_symmetry_get_coords (sym, i);
@ -220,33 +288,10 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
if (! paint_buffer)
continue;
if (gimp_paint_options_get_gradient_color (paint_options, image,
grad_point,
paint_core->pixel_dist,
&paint_color))
if (! paint_pixmap)
{
/* optionally take the color from the current gradient */
gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable),
&paint_color, &paint_color);
paint_appl_mode = GIMP_PAINT_INCREMENTAL;
}
else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))
{
/* otherwise check if the brush has a pixmap and use that to
* color the area
*/
paint_pixmap = gimp_brush_core_get_brush_pixmap (brush_core);
paint_appl_mode = GIMP_PAINT_INCREMENTAL;
}
else
{
/* otherwise fill the area with the foreground color */
gimp_context_get_foreground (context, &paint_color);
gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable),
&paint_color, &paint_color);
opacity *= paint_color.a;
gimp_rgb_set_alpha (&paint_color, GIMP_OPACITY_OPAQUE);
}
/* fill the paint buffer. we can skip this step when reusing the
@ -299,9 +344,6 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core,
{
GeglColor *color;
opacity *= paint_color.a;
gimp_rgb_set_alpha (&paint_color, GIMP_OPACITY_OPAQUE);
color = gimp_gegl_color_new (&paint_color,
gimp_drawable_get_space (drawable));

View File

@ -44,6 +44,16 @@ struct _GimpPaintbrush
struct _GimpPaintbrushClass
{
GimpBrushCoreClass parent_class;
/* virtual functions */
void (* get_paint_params) (GimpPaintbrush *paintbrush,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpSymmetry *sym,
GimpLayerMode *paint_mode,
GimpPaintApplicationMode *paint_appl_mode,
const GimpTempBuf **paint_pixmap,
GimpRGB *paint_color);
};