[gimp] app: add gimp_drawable_filter_set_clip()
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add gimp_drawable_filter_set_clip()
- Date: Thu, 1 Aug 2019 21:42:46 +0000 (UTC)
commit b7f53262fc3df9b5cd0c460afc029a9075e822f0
Author: Ell <ell_se yahoo com>
Date: Thu Aug 1 23:33:03 2019 +0300
app: add gimp_drawable_filter_set_clip()
In GimpDrawableFilter, add a new gimp_drawable_filter_set_clip()
function, which controls whether the filter clips the result to the
drawable's boundary, or extends it past it. The latter is only
possible for layers, when the selection mask is empty.
app/core/gimpdrawablefilter.c | 191 ++++++++++++++++++++++++++++++++----------
app/core/gimpdrawablefilter.h | 2 +
2 files changed, 147 insertions(+), 46 deletions(-)
---
diff --git a/app/core/gimpdrawablefilter.c b/app/core/gimpdrawablefilter.c
index 5c4c1c8527..276f04877f 100644
--- a/app/core/gimpdrawablefilter.c
+++ b/app/core/gimpdrawablefilter.c
@@ -65,6 +65,7 @@ struct _GimpDrawableFilter
gboolean has_input;
+ gboolean clip;
GimpFilterRegion region;
gboolean crop_enabled;
GeglRectangle crop_rect;
@@ -80,6 +81,7 @@ struct _GimpDrawableFilter
gboolean gamma_hack;
GeglRectangle filter_area;
+ gboolean filter_clip;
GeglNode *translate;
GeglNode *crop_before;
@@ -93,6 +95,8 @@ struct _GimpDrawableFilter
static void gimp_drawable_filter_dispose (GObject *object);
static void gimp_drawable_filter_finalize (GObject *object);
+static void gimp_drawable_filter_sync_clip (GimpDrawableFilter *filter,
+ gboolean sync_region);
static void gimp_drawable_filter_sync_region (GimpDrawableFilter *filter);
static void gimp_drawable_filter_sync_crop (GimpDrawableFilter *filter,
gboolean old_crop_enabled,
@@ -156,6 +160,7 @@ gimp_drawable_filter_class_init (GimpDrawableFilterClass *klass)
static void
gimp_drawable_filter_init (GimpDrawableFilter *drawable_filter)
{
+ drawable_filter->clip = TRUE;
drawable_filter->region = GIMP_FILTER_REGION_SELECTION;
drawable_filter->preview_alignment = GIMP_ALIGN_LEFT;
drawable_filter->preview_position = 1.0;
@@ -269,6 +274,20 @@ gimp_drawable_filter_new (GimpDrawable *drawable,
return filter;
}
+void
+gimp_drawable_filter_set_clip (GimpDrawableFilter *filter,
+ gboolean clip)
+{
+ g_return_if_fail (GIMP_IS_DRAWABLE_FILTER (filter));
+
+ if (clip != filter->clip)
+ {
+ filter->clip = clip;
+
+ gimp_drawable_filter_sync_clip (filter, TRUE);
+ }
+}
+
void
gimp_drawable_filter_set_region (GimpDrawableFilter *filter,
GimpFilterRegion region)
@@ -423,6 +442,11 @@ gimp_drawable_filter_apply (GimpDrawableFilter *filter,
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (filter->drawable)));
gimp_drawable_filter_add_filter (filter);
+
+ gimp_drawable_filter_sync_clip (filter, TRUE);
+
+ gimp_drawable_update_bounding_box (filter->drawable);
+
gimp_drawable_filter_update_drawable (filter, area);
}
@@ -448,7 +472,7 @@ gimp_drawable_filter_commit (GimpDrawableFilter *filter,
GIMP_FILTER (filter),
progress,
gimp_object_get_name (filter),
- TRUE,
+ filter->filter_clip,
cancellable,
FALSE);
@@ -477,6 +501,46 @@ gimp_drawable_filter_abort (GimpDrawableFilter *filter)
/* private functions */
+static void
+gimp_drawable_filter_sync_clip (GimpDrawableFilter *filter,
+ gboolean sync_region)
+{
+ gboolean clip = filter->clip;
+
+ if (! clip)
+ {
+ if (! GIMP_IS_LAYER (filter->drawable))
+ clip = TRUE;
+ }
+
+ if (! clip)
+ {
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (filter->drawable));
+ GimpChannel *mask = gimp_image_get_mask (image);
+
+ if (! gimp_channel_is_empty (mask))
+ clip = TRUE;
+ }
+
+ if (! clip)
+ {
+ GeglRectangle bounding_box;
+
+ bounding_box = gegl_node_get_bounding_box (filter->operation);
+
+ if (gegl_rectangle_is_infinite_plane (&bounding_box))
+ clip = TRUE;
+ }
+
+ if (clip != filter->filter_clip)
+ {
+ filter->filter_clip = clip;
+
+ if (sync_region)
+ gimp_drawable_filter_sync_region (filter);
+ }
+}
+
static void
gimp_drawable_filter_sync_region (GimpDrawableFilter *filter)
{
@@ -495,10 +559,22 @@ gimp_drawable_filter_sync_region (GimpDrawableFilter *filter)
NULL);
}
- gegl_node_set (filter->crop_after,
- "width", (gdouble) filter->filter_area.width,
- "height", (gdouble) filter->filter_area.height,
- NULL);
+ if (filter->filter_clip)
+ {
+ gegl_node_set (filter->crop_after,
+ "operation", "gegl:crop",
+ "x", 0.0,
+ "y", 0.0,
+ "width", (gdouble) filter->filter_area.width,
+ "height", (gdouble) filter->filter_area.height,
+ NULL);
+ }
+ else
+ {
+ gegl_node_set (filter->crop_after,
+ "operation", "gegl:nop",
+ NULL);
+ }
gimp_applicator_set_apply_offset (filter->applicator,
filter->filter_area.x,
@@ -523,13 +599,31 @@ gimp_drawable_filter_sync_region (GimpDrawableFilter *filter)
NULL);
}
- gegl_node_set (filter->crop_after,
- "width", width,
- "height", height,
- NULL);
+ if (filter->filter_clip)
+ {
+ gegl_node_set (filter->crop_after,
+ "operation", "gegl:crop",
+ "x", (gdouble) filter->filter_area.x,
+ "y", (gdouble) filter->filter_area.y,
+ "width", (gdouble) filter->filter_area.width,
+ "height", (gdouble) filter->filter_area.height,
+ NULL);
+ }
+ else
+ {
+ gegl_node_set (filter->crop_after,
+ "operation", "gegl:nop",
+ NULL);
+ }
gimp_applicator_set_apply_offset (filter->applicator, 0, 0);
}
+
+ if (gimp_drawable_filter_is_filtering (filter))
+ {
+ if (gimp_drawable_update_bounding_box (filter->drawable))
+ g_signal_emit (filter, drawable_filter_signals[FLUSH], 0);
+ }
}
static gboolean
@@ -541,37 +635,41 @@ gimp_drawable_filter_get_crop_rect (GimpDrawableFilter *filter,
gdouble preview_position,
GeglRectangle *rect)
{
- gint width;
- gint height;
+ GeglRectangle bounds;
+ gint width;
+ gint height;
+ gint x1, x2;
+ gint y1, y2;
+
+ bounds = gegl_rectangle_infinite_plane ();
- rect->x = 0;
- rect->y = 0;
- rect->width = gimp_item_get_width (GIMP_ITEM (filter->drawable));
- rect->height = gimp_item_get_height (GIMP_ITEM (filter->drawable));
+ width = gimp_item_get_width (GIMP_ITEM (filter->drawable));
+ height = gimp_item_get_height (GIMP_ITEM (filter->drawable));
- width = rect->width;
- height = rect->height;
+ x1 = bounds.x;
+ x2 = bounds.x + bounds.width;
+
+ y1 = bounds.y;
+ y2 = bounds.y + bounds.height;
if (preview_enabled)
{
switch (preview_alignment)
{
case GIMP_ALIGN_LEFT:
- rect->width *= preview_position;
+ x2 = width * preview_position;
break;
case GIMP_ALIGN_RIGHT:
- rect->width *= (1.0 - preview_position);
- rect->x = width - rect->width;
+ x1 = width * preview_position;
break;
case GIMP_ALIGN_TOP:
- rect->height *= preview_position;
+ y2 = height * preview_position;
break;
case GIMP_ALIGN_BOTTOM:
- rect->height *= (1.0 - preview_position);
- rect->y = height - rect->height;
+ y1 = height * preview_position;
break;
default:
@@ -579,10 +677,12 @@ gimp_drawable_filter_get_crop_rect (GimpDrawableFilter *filter,
}
}
+ gegl_rectangle_set (rect, x1, y1, x2 - x1, y2 - y1);
+
if (crop_enabled)
gegl_rectangle_intersect (rect, rect, crop_rect);
- return ! gegl_rectangle_equal_coords (rect, 0, 0, width, height);
+ return ! gegl_rectangle_equal (rect, &bounds);
}
static void
@@ -616,30 +716,20 @@ gimp_drawable_filter_sync_crop (GimpDrawableFilter *filter,
gimp_applicator_set_crop (filter->applicator, enabled ? &new_rect : NULL);
- if (update && ! gegl_rectangle_equal (&old_rect, &new_rect))
+ if (update &&
+ gimp_drawable_filter_is_filtering (filter) &&
+ ! gegl_rectangle_equal (&old_rect, &new_rect))
{
- cairo_region_t *region;
- gint n_rects;
- gint i;
+ GeglRectangle diff_rects[4];
+ gint n_diff_rects;
+ gint i;
- region = cairo_region_create_rectangle ((cairo_rectangle_int_t *)
- &old_rect);
- cairo_region_xor_rectangle (region,
- (cairo_rectangle_int_t *) &new_rect);
+ gimp_drawable_update_bounding_box (filter->drawable);
- n_rects = cairo_region_num_rectangles (region);
+ n_diff_rects = gegl_rectangle_xor (diff_rects, &old_rect, &new_rect);
- for (i = 0; i < n_rects; i++)
- {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (region, i, &rect);
-
- gimp_drawable_filter_update_drawable (filter,
- (const GeglRectangle *) &rect);
- }
-
- cairo_region_destroy (region);
+ for (i = 0; i < n_diff_rects; i++)
+ gimp_drawable_filter_update_drawable (filter, &diff_rects[i]);
}
}
@@ -791,6 +881,7 @@ gimp_drawable_filter_add_filter (GimpDrawableFilter *filter)
gimp_viewable_preview_freeze (GIMP_VIEWABLE (filter->drawable));
gimp_drawable_filter_sync_mask (filter);
+ gimp_drawable_filter_sync_clip (filter, FALSE);
gimp_drawable_filter_sync_region (filter);
gimp_drawable_filter_sync_crop (filter,
filter->crop_enabled,
@@ -808,6 +899,8 @@ gimp_drawable_filter_add_filter (GimpDrawableFilter *filter)
gimp_drawable_add_filter (filter->drawable,
GIMP_FILTER (filter));
+ gimp_drawable_update_bounding_box (filter->drawable);
+
g_signal_connect (image, "component-active-changed",
G_CALLBACK (gimp_drawable_filter_affect_changed),
filter);
@@ -864,6 +957,8 @@ gimp_drawable_filter_remove_filter (GimpDrawableFilter *filter)
gimp_drawable_remove_filter (filter->drawable,
GIMP_FILTER (filter));
+ gimp_drawable_update_bounding_box (filter->drawable);
+
gimp_viewable_preview_thaw (GIMP_VIEWABLE (filter->drawable));
return TRUE;
@@ -876,12 +971,15 @@ static void
gimp_drawable_filter_update_drawable (GimpDrawableFilter *filter,
const GeglRectangle *area)
{
+ GeglRectangle bounding_box;
GeglRectangle update_area;
+ bounding_box = gimp_drawable_get_bounding_box (filter->drawable);
+
if (area)
{
if (! gegl_rectangle_intersect (&update_area,
- area, &filter->filter_area))
+ area, &bounding_box))
{
return;
}
@@ -897,7 +995,7 @@ gimp_drawable_filter_update_drawable (GimpDrawableFilter *filter,
&update_area);
if (! gegl_rectangle_intersect (&update_area,
- &update_area, &filter->filter_area))
+ &update_area, &bounding_box))
{
return;
}
@@ -932,6 +1030,7 @@ gimp_drawable_filter_mask_changed (GimpImage *image,
gimp_drawable_filter_update_drawable (filter, NULL);
gimp_drawable_filter_sync_mask (filter);
+ gimp_drawable_filter_sync_clip (filter, FALSE);
gimp_drawable_filter_sync_region (filter);
gimp_drawable_filter_update_drawable (filter, NULL);
diff --git a/app/core/gimpdrawablefilter.h b/app/core/gimpdrawablefilter.h
index 8800190475..53dd214955 100644
--- a/app/core/gimpdrawablefilter.h
+++ b/app/core/gimpdrawablefilter.h
@@ -55,6 +55,8 @@ GimpDrawableFilter *
GeglNode *operation,
const gchar *icon_name);
+void gimp_drawable_filter_set_clip (GimpDrawableFilter *filter,
+ gboolean clip);
void gimp_drawable_filter_set_region (GimpDrawableFilter *filter,
GimpFilterRegion region);
void gimp_drawable_filter_set_crop (GimpDrawableFilter *filter,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]