app: add "clip" parameter to gimp_drawable_merge_filter()

Add a new "clip" parameter to gimp_drawable_merge_filter().  When
set to FALSE, the function resizes the drawable to the bounding box
of the filter's output, instead of clipping the output to the
drawable's boundary.
This commit is contained in:
Ell 2019-08-01 23:29:59 +03:00
parent 35729ee02a
commit 89a9cf7e49
4 changed files with 117 additions and 34 deletions

View File

@ -29,6 +29,7 @@
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-loops.h"
#include "gimp.h"
#include "gimp-utils.h"
#include "gimpdrawable.h"
#include "gimpdrawable-filters.h"
@ -36,6 +37,8 @@
#include "gimpfilter.h"
#include "gimpfilterstack.h"
#include "gimpimage.h"
#include "gimpimage-undo.h"
#include "gimplayer.h"
#include "gimpprogress.h"
#include "gimpprojection.h"
@ -108,6 +111,7 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
GimpFilter *filter,
GimpProgress *progress,
const gchar *undo_desc,
gboolean clip,
gboolean cancellable,
gboolean update)
{
@ -115,6 +119,8 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
GimpApplicator *applicator;
gboolean applicator_cache = FALSE;
const Babl *applicator_output_format = NULL;
GeglBuffer *buffer = NULL;
GeglBuffer *dest_buffer;
GeglBuffer *undo_buffer;
GeglRectangle undo_rect;
GeglBuffer *cache = NULL;
@ -129,13 +135,36 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
image = gimp_item_get_image (GIMP_ITEM (drawable));
applicator = gimp_filter_get_applicator (filter);
dest_buffer = gimp_drawable_get_buffer (drawable);
rect = gegl_node_get_bounding_box (gimp_filter_get_node (filter));
if (! clip && gegl_rectangle_equal (&rect,
gegl_buffer_get_extent (dest_buffer)))
{
clip = TRUE;
}
if (clip)
{
if (! gimp_item_mask_intersect (GIMP_ITEM (drawable),
&rect.x, &rect.y,
&rect.width, &rect.height))
{
return TRUE;
}
}
else
{
buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height),
gimp_drawable_get_format (drawable));
dest_buffer = g_object_new (GEGL_TYPE_BUFFER,
"source", buffer,
"shift-x", -rect.x,
"shift-y", -rect.y,
NULL);
}
if (applicator)
{
@ -164,6 +193,8 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
gimp_applicator_set_output_format (applicator, NULL);
}
if (clip)
{
gegl_rectangle_align_to_buffer (
&undo_rect,
&rect,
@ -180,27 +211,65 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
GEGL_ABYSS_NONE,
undo_buffer,
GEGL_RECTANGLE (0, 0, 0, 0));
}
gimp_projection_stop_rendering (gimp_image_get_projection (image));
if (gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable),
progress, undo_desc,
gimp_filter_get_node (filter),
gimp_drawable_get_buffer (drawable),
&rect, FALSE,
dest_buffer, &rect, FALSE,
cache, rects, n_rects,
cancellable))
{
/* finished successfully */
if (clip)
{
gimp_drawable_push_undo (drawable, undo_desc, undo_buffer,
undo_rect.x, undo_rect.y,
undo_rect.width, undo_rect.height);
}
else
{
GimpLayerMask *mask = NULL;
gint offset_x;
gint offset_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y);
if (GIMP_IS_LAYER (drawable))
mask = gimp_layer_get_mask (GIMP_LAYER (drawable));
if (mask)
{
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE_MOD,
undo_desc);
}
gimp_drawable_set_buffer_full (
drawable, TRUE, undo_desc, buffer,
GEGL_RECTANGLE (offset_x + rect.x, offset_y + rect.y, 0, 0),
FALSE);
if (mask)
{
gimp_item_resize (GIMP_ITEM (mask),
gimp_get_default_context (image->gimp),
GIMP_FILL_TRANSPARENT,
rect.width, rect.height,
rect.x, rect.y);
gimp_image_undo_group_end (image);
}
}
}
else
{
/* canceled by the user */
if (clip)
{
gimp_gegl_buffer_copy (undo_buffer,
GEGL_RECTANGLE (0, 0,
undo_rect.width,
@ -208,11 +277,20 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
GEGL_ABYSS_NONE,
gimp_drawable_get_buffer (drawable),
&undo_rect);
}
success = FALSE;
}
if (clip)
{
g_object_unref (undo_buffer);
}
else
{
g_object_unref (buffer);
g_object_unref (dest_buffer);
}
if (cache)
{

View File

@ -37,6 +37,7 @@ gboolean gimp_drawable_merge_filter (GimpDrawable *drawable,
GimpFilter *filter,
GimpProgress *progress,
const gchar *undo_desc,
gboolean clip,
gboolean cancellable,
gboolean update);

View File

@ -448,6 +448,7 @@ gimp_drawable_filter_commit (GimpDrawableFilter *filter,
GIMP_FILTER (filter),
progress,
gimp_object_get_name (filter),
TRUE,
cancellable,
FALSE);

View File

@ -135,7 +135,10 @@ floating_sel_anchor (GimpLayer *layer)
}
if (filter)
gimp_drawable_merge_filter (drawable, filter, NULL, NULL, FALSE, FALSE);
{
gimp_drawable_merge_filter (drawable, filter, NULL, NULL,
TRUE, FALSE, FALSE);
}
gimp_image_remove_layer (image, layer, TRUE, NULL);