From aba4eef916172460dde062ac76c86cf6e1f71a52 Mon Sep 17 00:00:00 2001 From: Ell Date: Sun, 26 May 2019 14:38:24 -0400 Subject: [PATCH] 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. --- app/paint/gimperaser.c | 146 +++++++++--------------------- app/paint/gimperaser.h | 6 +- app/paint/gimppaintbrush.c | 176 +++++++++++++++++++++++-------------- app/paint/gimppaintbrush.h | 10 +++ 4 files changed, 163 insertions(+), 175 deletions(-) diff --git a/app/paint/gimperaser.c b/app/paint/gimperaser.c index 37732603de..b360f18ca9 100644 --- a/app/paint/gimperaser.c +++ b/app/paint/gimperaser.c @@ -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; } diff --git a/app/paint/gimperaser.h b/app/paint/gimperaser.h index 748cf253e4..5b04a3292f 100644 --- a/app/paint/gimperaser.h +++ b/app/paint/gimperaser.h @@ -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; }; diff --git a/app/paint/gimppaintbrush.c b/app/paint/gimppaintbrush.c index 321d4933eb..b1042290cd 100644 --- a/app/paint/gimppaintbrush.c +++ b/app/paint/gimppaintbrush.c @@ -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)); diff --git a/app/paint/gimppaintbrush.h b/app/paint/gimppaintbrush.h index 1e94b8e1ab..0631439826 100644 --- a/app/paint/gimppaintbrush.h +++ b/app/paint/gimppaintbrush.h @@ -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); };