From 1c2fe3b51c782b08b20559fa9c5573281ec58223 Mon Sep 17 00:00:00 2001 From: Ell Date: Tue, 12 Feb 2019 06:25:28 -0500 Subject: [PATCH] app: implement gimp_paint_core_replace() using gimp_paint_core_loops_process() Implement the no-applicator path of gimp_paint_core_replace() in terms of gimp_paint_core_loops_process(), using the algorithms added in the previous commit, instead of using gimp_drawable_replace_buffer(). This improves speed, consolidates code, and fixes some cases in which the latter is broken. Furthermore, when using CONSTANT paint application-mode, use the paint-core's undo_buffer as the compositing source, rather than the drawable buffer, which is the correct behavior. (cherry picked from commit ddb69b77a7610f578f5143af1cdeed2c27d4f3e4) --- app/paint/gimppaintcore.c | 155 ++++++++++++++++++++++++++++---------- 1 file changed, 115 insertions(+), 40 deletions(-) diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c index e9b4b6c342..9905a2ea7c 100644 --- a/app/paint/gimppaintcore.c +++ b/app/paint/gimppaintcore.c @@ -987,9 +987,7 @@ gimp_paint_core_replace (GimpPaintCore *core, gdouble image_opacity, GimpPaintApplicationMode mode) { - GeglRectangle mask_rect; - GeglBuffer *paint_mask_buffer; - gint width, height; + gint width, height; if (! gimp_drawable_has_alpha (drawable)) { @@ -1007,14 +1005,17 @@ gimp_paint_core_replace (GimpPaintCore *core, width = gegl_buffer_get_width (core->paint_buffer); height = gegl_buffer_get_height (core->paint_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. - */ - paint_mask != NULL) + if (core->applicator) { - if (core->applicator) + GeglRectangle mask_rect; + GeglBuffer *paint_mask_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. + */ + paint_mask != NULL) { paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); @@ -1032,48 +1033,122 @@ gimp_paint_core_replace (GimpPaintCore *core, GIMP_IS_AIRBRUSH (core)); g_object_unref (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, + width, height); } else { - /* Mix paint mask and canvas_buffer */ - combine_paint_mask_to_canvas_buffer (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)); + paint_mask_buffer = + gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); + + mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x, + paint_mask_offset_y, + width, height); } - /* initialize the maskPR from the canvas buffer */ - paint_mask_buffer = g_object_ref (core->canvas_buffer); + /* apply the paint area to the image */ + gimp_drawable_replace_buffer (drawable, core->paint_buffer, + GEGL_RECTANGLE (0, 0, width, height), + FALSE, NULL, + image_opacity, + paint_mask_buffer, &mask_rect, + core->paint_buffer_x, + core->paint_buffer_y); - mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, - core->paint_buffer_y, - width, height); + g_object_unref (paint_mask_buffer); } else { - paint_mask_buffer = - gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); + GimpPaintCoreLoopsParams params = {}; + GimpPaintCoreLoopsAlgorithm algorithms = GIMP_PAINT_CORE_LOOPS_ALGORITHM_NONE; - mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x, - paint_mask_offset_y, - width, height); + params.paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer); + params.paint_buf_offset_x = core->paint_buffer_x; + params.paint_buf_offset_y = core->paint_buffer_y; + + if (! params.paint_buf) + return; + + if (core->comp_buffer) + params.dest_buffer = core->comp_buffer; + else + params.dest_buffer = gimp_drawable_get_buffer (drawable); + + if (mode == GIMP_PAINT_CONSTANT) + { + params.canvas_buffer = core->canvas_buffer; + + /* This step is skipped by the ink tool, which writes + * directly to canvas_buffer + */ + if (paint_mask != NULL) + { + /* Mix paint mask and canvas_buffer */ + params.paint_mask = paint_mask; + params.paint_mask_offset_x = paint_mask_offset_x; + params.paint_mask_offset_y = paint_mask_offset_y; + params.stipple = GIMP_IS_AIRBRUSH (core); + params.paint_opacity = paint_opacity; + + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_COMBINE_PAINT_MASK_TO_CANVAS_BUFFER; + } + + /* Write canvas_buffer to the compositing mask */ + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_CANVAS_BUFFER_TO_COMP_MASK; + + /* undo buf -> paint_buf -> dest_buffer */ + params.src_buffer = core->undo_buffer; + } + else + { + g_return_if_fail (paint_mask); + + /* Write paint_mask to the compositing mask, does not modify + * canvas_buffer + */ + params.paint_mask = paint_mask; + params.paint_mask_offset_x = paint_mask_offset_x; + params.paint_mask_offset_y = paint_mask_offset_y; + params.paint_opacity = paint_opacity; + + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_PAINT_MASK_TO_COMP_MASK; + + /* dest_buffer -> paint_buf -> dest_buffer */ + if (core->comp_buffer) + params.src_buffer = gimp_drawable_get_buffer (drawable); + else + params.src_buffer = params.dest_buffer; + } + + params.mask_buffer = core->mask_buffer; + params.mask_offset_x = core->mask_x_offset; + params.mask_offset_y = core->mask_y_offset; + params.image_opacity = image_opacity; + params.paint_mode = GIMP_LAYER_MODE_REPLACE; + + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_DO_LAYER_BLEND; + + gimp_paint_core_loops_process (¶ms, algorithms); + + if (core->comp_buffer) + { + mask_components_onto (params.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), + gimp_drawable_get_linear (drawable)); + } } - /* apply the paint area to the image */ - gimp_drawable_replace_buffer (drawable, core->paint_buffer, - GEGL_RECTANGLE (0, 0, width, height), - FALSE, NULL, - image_opacity, - paint_mask_buffer, &mask_rect, - core->paint_buffer_x, - core->paint_buffer_y); - - g_object_unref (paint_mask_buffer); - /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y);