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 ddb69b77a7
)
This commit is contained in:
@ -987,9 +987,7 @@ gimp_paint_core_replace (GimpPaintCore *core,
|
|||||||
gdouble image_opacity,
|
gdouble image_opacity,
|
||||||
GimpPaintApplicationMode mode)
|
GimpPaintApplicationMode mode)
|
||||||
{
|
{
|
||||||
GeglRectangle mask_rect;
|
gint width, height;
|
||||||
GeglBuffer *paint_mask_buffer;
|
|
||||||
gint width, height;
|
|
||||||
|
|
||||||
if (! gimp_drawable_has_alpha (drawable))
|
if (! gimp_drawable_has_alpha (drawable))
|
||||||
{
|
{
|
||||||
@ -1007,14 +1005,17 @@ gimp_paint_core_replace (GimpPaintCore *core,
|
|||||||
width = gegl_buffer_get_width (core->paint_buffer);
|
width = gegl_buffer_get_width (core->paint_buffer);
|
||||||
height = gegl_buffer_get_height (core->paint_buffer);
|
height = gegl_buffer_get_height (core->paint_buffer);
|
||||||
|
|
||||||
if (mode == GIMP_PAINT_CONSTANT &&
|
if (core->applicator)
|
||||||
|
|
||||||
/* 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)
|
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 =
|
paint_mask_buffer =
|
||||||
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
|
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
|
||||||
@ -1032,48 +1033,122 @@ gimp_paint_core_replace (GimpPaintCore *core,
|
|||||||
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 */
|
||||||
|
paint_mask_buffer = g_object_ref (core->canvas_buffer);
|
||||||
|
|
||||||
|
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
|
||||||
|
core->paint_buffer_y,
|
||||||
|
width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Mix paint mask and canvas_buffer */
|
paint_mask_buffer =
|
||||||
combine_paint_mask_to_canvas_buffer (paint_mask,
|
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
|
||||||
paint_mask_offset_x,
|
|
||||||
paint_mask_offset_y,
|
mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x,
|
||||||
core->canvas_buffer,
|
paint_mask_offset_y,
|
||||||
core->paint_buffer_x,
|
width, height);
|
||||||
core->paint_buffer_y,
|
|
||||||
paint_opacity,
|
|
||||||
GIMP_IS_AIRBRUSH (core));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the maskPR from the canvas buffer */
|
/* apply the paint area to the image */
|
||||||
paint_mask_buffer = g_object_ref (core->canvas_buffer);
|
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,
|
g_object_unref (paint_mask_buffer);
|
||||||
core->paint_buffer_y,
|
|
||||||
width, height);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paint_mask_buffer =
|
GimpPaintCoreLoopsParams params = {};
|
||||||
gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
|
GimpPaintCoreLoopsAlgorithm algorithms = GIMP_PAINT_CORE_LOOPS_ALGORITHM_NONE;
|
||||||
|
|
||||||
mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x,
|
params.paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer);
|
||||||
paint_mask_offset_y,
|
params.paint_buf_offset_x = core->paint_buffer_x;
|
||||||
width, height);
|
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 */
|
/* Update the undo extents */
|
||||||
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
||||||
core->y1 = MIN (core->y1, core->paint_buffer_y);
|
core->y1 = MIN (core->y1, core->paint_buffer_y);
|
||||||
|
Reference in New Issue
Block a user