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) if (core->applicator)
{ {
GeglRectangle mask_rect; GeglRectangle mask_rect;
GeglBuffer *paint_mask_buffer; GeglBuffer *mask_buffer;
if (mode == GIMP_PAINT_CONSTANT &&
/* 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 /* Some tools (ink) paint the mask to paint_core->canvas_buffer
* directly. Don't need to copy it in this case. * directly. Don't need to copy it in this case.
*/ */
paint_mask != NULL) if (paint_mask != NULL)
{ {
paint_mask_buffer = GeglBuffer *paint_mask_buffer =
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
/* combine the paint mask and the canvas buffer */ gimp_gegl_combine_mask_weird (paint_mask_buffer,
gimp_gegl_combine_mask_weird (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x,
GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y,
paint_mask_offset_y, width, height),
width, height), core->canvas_buffer,
core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x,
GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y,
core->paint_buffer_y, width, height),
width, height), paint_opacity,
paint_opacity, GIMP_IS_AIRBRUSH (core));
GIMP_IS_AIRBRUSH (core));
g_object_unref (paint_mask_buffer); g_object_unref (paint_mask_buffer);
}
/* initialize the maskPR from the canvas buffer */ mask_buffer = g_object_ref (core->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);
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, gimp_applicator_set_src_buffer (core->applicator,
core->paint_buffer_y, core->undo_buffer);
width, height);
} }
/* Otherwise:
* use the paint mask as the mask buffer directly
*/
else else
{ {
paint_mask_buffer = mask_buffer =
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); 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, gimp_applicator_set_src_buffer (core->applicator,
paint_mask_offset_y, gimp_drawable_get_buffer (drawable));
width, height);
} }
/* apply the paint area to the image */ if (core->mask_buffer)
gimp_drawable_replace_buffer (drawable, core->paint_buffer, {
GEGL_RECTANGLE (0, 0, width, height), GeglBuffer *combined_mask_buffer;
FALSE, NULL, GeglRectangle combined_mask_rect;
image_opacity, GeglRectangle aligned_combined_mask_rect;
paint_mask_buffer, &mask_rect,
core->paint_buffer_x,
core->paint_buffer_y);
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 else
{ {