app: in gimp_paint_core_replace(), improve applicator path

In the applicator path of gimp_paint_core_replace(), actually use
the paint-core's applicator, 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 3451ffb62c)
This commit is contained in:
Ell
2019-02-12 07:58:08 -05:00
parent 940197e2d7
commit 0066a47013

View File

@ -1006,59 +1006,126 @@ gimp_paint_core_replace (GimpPaintCore *core,
if (core->applicator)
{
GeglRectangle mask_rect;
GeglBuffer *paint_mask_buffer;
if (mode == GIMP_PAINT_CONSTANT &&
GeglBuffer *mask_buffer;
/* If the mode is CONSTANT:
* combine the paint mask to the canvas buffer, and use it as the 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);
if (paint_mask != NULL)
{
GeglBuffer *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));
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);
g_object_unref (paint_mask_buffer);
}
/* initialize the maskPR from the canvas buffer */
paint_mask_buffer = g_object_ref (core->canvas_buffer);
mask_buffer = g_object_ref (core->canvas_buffer);
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
core->paint_buffer_y,
width, height);
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
core->paint_buffer_y,
width, height);
gimp_applicator_set_src_buffer (core->applicator,
core->undo_buffer);
}
/* Otherwise:
* use the paint mask as the mask buffer directly
*/
else
{
paint_mask_buffer =
mask_buffer =
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x,
paint_mask_offset_y,
width, height);
mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x,
paint_mask_offset_y,
width, height);
gimp_applicator_set_src_buffer (core->applicator,
gimp_drawable_get_buffer (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);
if (core->mask_buffer)
{
GeglBuffer *combined_mask_buffer;
GeglRectangle combined_mask_rect;
GeglRectangle aligned_combined_mask_rect;
g_object_unref (paint_mask_buffer);
combined_mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
core->paint_buffer_y,
width, height);
gimp_gegl_rectangle_align_to_tile_grid (
&aligned_combined_mask_rect, &combined_mask_rect,
gimp_drawable_get_buffer (drawable));
combined_mask_buffer = gegl_buffer_new (&aligned_combined_mask_rect,
babl_format ("Y float"));
gegl_buffer_copy (core->mask_buffer,
GEGL_RECTANGLE (aligned_combined_mask_rect.x -
core->mask_x_offset,
aligned_combined_mask_rect.y -
core->mask_y_offset,
aligned_combined_mask_rect.width,
aligned_combined_mask_rect.height),
GEGL_ABYSS_NONE,
combined_mask_buffer, &aligned_combined_mask_rect);
gimp_gegl_combine_mask (mask_buffer, &mask_rect,
combined_mask_buffer, &combined_mask_rect,
1.0);
g_object_unref (mask_buffer);
mask_buffer = combined_mask_buffer;
mask_rect = combined_mask_rect;
}
gimp_applicator_set_mask_buffer (core->applicator, mask_buffer);
gimp_applicator_set_mask_offset (core->applicator,
core->paint_buffer_x - mask_rect.x,
core->paint_buffer_y - mask_rect.y);
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);
gimp_applicator_set_opacity (core->applicator, image_opacity);
gimp_applicator_set_mode (core->applicator, GIMP_LAYER_MODE_REPLACE,
GIMP_LAYER_COLOR_SPACE_AUTO,
GIMP_LAYER_COLOR_SPACE_AUTO,
gimp_layer_mode_get_paint_composite_mode (
GIMP_LAYER_MODE_REPLACE));
/* apply the paint area to the image */
gimp_applicator_blit (core->applicator,
GEGL_RECTANGLE (core->paint_buffer_x,
core->paint_buffer_y,
width, height));
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);
g_object_unref (mask_buffer);
}
else
{