app: Layer expansion while painting now works with layers with mask

When painting the layers with a layer mask, if the layer need to be
expanded, the layer mask is also expanded with it. The same is done even
if layer mask is being painted upon.

Undo works with these layers by adding resizing of both the layer and
mask to the undo group if the layer is resized during painting.
This commit is contained in:
Shubham 2023-07-07 23:15:13 +05:30 committed by Jehan
parent 5191c17fb7
commit 3ccec0b128
1 changed files with 86 additions and 15 deletions

View File

@ -43,11 +43,13 @@
#include "core/gimpimage-guides.h"
#include "core/gimpimage-symmetry.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimplayer.h"
#include "core/gimplayermask.h"
#include "core/gimppickable.h"
#include "core/gimpprojection.h"
#include "core/gimpsymmetry.h"
#include "core/gimptempbuf.h"
#include "core/gimpimage-undo-push.h"
#include "gimppaintcore.h"
#include "gimppaintcoreundo.h"
@ -599,6 +601,9 @@ gimp_paint_core_finish (GimpPaintCore *core,
}
else
{
/* drawable is expanded only if drawable is layer or layer mask*/
g_return_if_fail (GIMP_IS_LAYER (iter->data) || GIMP_IS_LAYER_MASK (iter->data));
/* create a copy of original buffer from undo data */
buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
old_rect.width,
@ -615,17 +620,47 @@ gimp_paint_core_finish (GimpPaintCore *core,
GEGL_RECTANGLE (0, 0, 0, 0));
/* make a backup copy of drawable to restore */
drawable_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
rect.width,
rect.height),
gimp_drawable_get_format (iter->data));
drawable_buffer = g_object_ref (gimp_drawable_get_buffer (GIMP_DRAWABLE (iter->data)));
gimp_gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (iter->data)),
GEGL_RECTANGLE (0, 0, rect.width, rect.height),
GEGL_ABYSS_NONE,
drawable_buffer,
GEGL_RECTANGLE (0, 0, 0, 0));
if (GIMP_IS_LAYER_MASK (drawables->data) || GIMP_LAYER (drawables->data)->mask)
{
GeglBuffer *other_new;
GeglBuffer *other_old;
GimpDrawable *other_drawable;
if (GIMP_IS_LAYER_MASK (drawables->data))
other_drawable = GIMP_DRAWABLE ((GIMP_LAYER_MASK (drawables->data))->layer);
else
other_drawable = GIMP_DRAWABLE (GIMP_LAYER (drawables->data)->mask);
/* create a copy of original buffer by taking the required area */
other_old = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
old_rect.width,
old_rect.height),
gimp_drawable_get_format (other_drawable));
gimp_gegl_buffer_copy (gimp_drawable_get_buffer (other_drawable),
GEGL_RECTANGLE (old_rect.x - rect.x,
old_rect.y - rect.y,
old_rect.width,
old_rect.height),
GEGL_ABYSS_NONE,
other_old,
GEGL_RECTANGLE (0, 0, 0, 0));
/* make a backup copy of drawable to restore */
other_new = g_object_ref (gimp_drawable_get_buffer (other_drawable));
gimp_drawable_set_buffer_full (other_drawable, FALSE, NULL,
other_old, &old_rect,
FALSE);
gimp_drawable_set_buffer_full (other_drawable, TRUE, NULL,
other_new, &rect,
FALSE);
g_object_unref (other_new);
g_object_unref (other_old);
}
/* Restore drawable to state before painting started */
gimp_drawable_set_buffer_full (iter->data, FALSE, NULL,
buffer, &old_rect,
@ -779,6 +814,7 @@ gimp_paint_core_expand_drawable (GimpPaintCore *core,
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
GimpContext *context = GIMP_CONTEXT (options);
GimpFillType fill_type = GIMP_FILL_TRANSPARENT;
GimpLayer *layer;
GeglBuffer *undo_buffer;
GeglBuffer *new_buffer;
const Babl *format;
@ -875,11 +911,46 @@ gimp_paint_core_expand_drawable (GimpPaintCore *core,
if (new_width != drawable_width || *new_off_x ||
new_height != drawable_height || *new_off_y)
{
GIMP_ITEM_GET_CLASS (GIMP_ITEM (drawable))->resize (GIMP_ITEM (drawable),
context, fill_type,
new_width, new_height,
*new_off_x, *new_off_y);
gimp_image_flush (gimp_item_get_image (GIMP_ITEM (drawable)));
/* resize the layer even if editing the layer mask */
if (GIMP_IS_LAYER_MASK (drawable))
layer = (GIMP_LAYER_MASK (drawable))->layer;
else
layer = GIMP_LAYER (drawable);
g_object_freeze_notify (G_OBJECT (layer));
if (GIMP_IS_LAYER_MASK (drawable))
gimp_drawable_start_paint (GIMP_DRAWABLE (layer));
GIMP_LAYER_GET_CLASS (layer)->resize (layer, context, fill_type,
new_width, new_height,
*new_off_x, *new_off_y);
if (GIMP_IS_LAYER_MASK (drawable))
gimp_drawable_end_paint (GIMP_DRAWABLE (layer));
if (layer->mask)
{
g_object_freeze_notify (G_OBJECT (layer->mask));
/* Fixme: using paint start and paint end to prevent pushing undo is inefficient */
/* Resize channel will not be pushed to stack if the drawable is being drawn upon */
if (!GIMP_IS_LAYER_MASK (drawable))
gimp_drawable_start_paint (GIMP_DRAWABLE (layer->mask));
GIMP_ITEM_GET_CLASS (layer->mask)->resize (GIMP_ITEM (layer->mask), context, fill_type,
new_width, new_height,
*new_off_x, *new_off_y);
if (!GIMP_IS_LAYER_MASK (drawable))
gimp_drawable_end_paint (GIMP_DRAWABLE (layer->mask));
g_object_thaw_notify (G_OBJECT (layer->mask));
}
g_object_thaw_notify (G_OBJECT (layer));
gimp_image_flush (image);
format = gegl_buffer_get_format (core->canvas_buffer);
new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, new_width, new_height),