[gimp] app: exclude invisible filters from filter-stack graph
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: exclude invisible filters from filter-stack graph
- Date: Tue, 5 Dec 2017 21:18:25 +0000 (UTC)
commit e02cb6adfeb9e9ceabb209c72148e8728b4845ee
Author: Ell <ell_se yahoo com>
Date: Tue Dec 5 14:30:01 2017 -0500
app: exclude invisible filters from filter-stack graph
Currently, when a GimpFilter's visibility changes, we rely on its
various visibility-changed signal handlers to rewire the filter
node's graph to reflect the change. This has two main
disadvantages:
- There's no easy, generic way to toggle a filter's effect,
especially one that is not subclassed, since GimpFilter only
takes care of the case where visibility becomes FALSE, and does
nothing by itself when it becomes TRUE again.
- While GimpDrawable does handle the visibility => TRUE case, it
doesn't disconnect the filter's input from its mode and
(potentially) source nodes when it becomes invisible. As a
result, while none of the drawable's graph is processed as part
of the composition when not visible, the mode and source nodes
do get invalidated when the filter's input is invalidated, such
as while painting on a layer below the drawable. This is
particularly bad for pass-through groups, since their source
node can be an arbitrarily complex graph, whose invlidation
incurs a nontrivial overhead.
Instead, don't touch the filter's node at all when visibility
changes, and rather have GimpFilterStack remove it from the graph
entirely when the filter becomes invisible, and re-add it once it
becomes visible again. This solves both of the above problems, as
well as simplifies the code.
app/core/gimpdrawable.c | 113 +++++++++-------------------
app/core/gimpfilter.c | 62 +++------------
app/core/gimpfilterstack.c | 176 ++++++++++++++++++++++----------------------
3 files changed, 137 insertions(+), 214 deletions(-)
---
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 7643362..95c44d7 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -91,7 +91,6 @@ static gboolean gimp_drawable_get_size (GimpViewable *viewable,
gint *width,
gint *height);
-static void gimp_drawable_visibility_changed (GimpFilter *filter);
static GeglNode * gimp_drawable_get_node (GimpFilter *filter);
static void gimp_drawable_removed (GimpItem *item);
@@ -226,42 +225,41 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
- object_class->dispose = gimp_drawable_dispose;
- object_class->finalize = gimp_drawable_finalize;
- object_class->set_property = gimp_drawable_set_property;
- object_class->get_property = gimp_drawable_get_property;
-
- gimp_object_class->get_memsize = gimp_drawable_get_memsize;
-
- viewable_class->get_size = gimp_drawable_get_size;
- viewable_class->get_new_preview = gimp_drawable_get_new_preview;
- viewable_class->get_new_pixbuf = gimp_drawable_get_new_pixbuf;
-
- filter_class->visibility_changed = gimp_drawable_visibility_changed;
- filter_class->get_node = gimp_drawable_get_node;
-
- item_class->removed = gimp_drawable_removed;
- item_class->duplicate = gimp_drawable_duplicate;
- item_class->scale = gimp_drawable_scale;
- item_class->resize = gimp_drawable_resize;
- item_class->flip = gimp_drawable_flip;
- item_class->rotate = gimp_drawable_rotate;
- item_class->transform = gimp_drawable_transform;
-
- klass->update = gimp_drawable_real_update;
- klass->alpha_changed = NULL;
- klass->estimate_memsize = gimp_drawable_real_estimate_memsize;
- klass->invalidate_boundary = NULL;
- klass->get_active_components = NULL;
- klass->get_active_mask = NULL;
- klass->convert_type = gimp_drawable_real_convert_type;
- klass->apply_buffer = gimp_drawable_real_apply_buffer;
- klass->replace_buffer = gimp_drawable_real_replace_buffer;
- klass->get_buffer = gimp_drawable_real_get_buffer;
- klass->set_buffer = gimp_drawable_real_set_buffer;
- klass->push_undo = gimp_drawable_real_push_undo;
- klass->swap_pixels = gimp_drawable_real_swap_pixels;
- klass->get_source_node = gimp_drawable_real_get_source_node;
+ object_class->dispose = gimp_drawable_dispose;
+ object_class->finalize = gimp_drawable_finalize;
+ object_class->set_property = gimp_drawable_set_property;
+ object_class->get_property = gimp_drawable_get_property;
+
+ gimp_object_class->get_memsize = gimp_drawable_get_memsize;
+
+ viewable_class->get_size = gimp_drawable_get_size;
+ viewable_class->get_new_preview = gimp_drawable_get_new_preview;
+ viewable_class->get_new_pixbuf = gimp_drawable_get_new_pixbuf;
+
+ filter_class->get_node = gimp_drawable_get_node;
+
+ item_class->removed = gimp_drawable_removed;
+ item_class->duplicate = gimp_drawable_duplicate;
+ item_class->scale = gimp_drawable_scale;
+ item_class->resize = gimp_drawable_resize;
+ item_class->flip = gimp_drawable_flip;
+ item_class->rotate = gimp_drawable_rotate;
+ item_class->transform = gimp_drawable_transform;
+
+ klass->update = gimp_drawable_real_update;
+ klass->alpha_changed = NULL;
+ klass->estimate_memsize = gimp_drawable_real_estimate_memsize;
+ klass->invalidate_boundary = NULL;
+ klass->get_active_components = NULL;
+ klass->get_active_mask = NULL;
+ klass->convert_type = gimp_drawable_real_convert_type;
+ klass->apply_buffer = gimp_drawable_real_apply_buffer;
+ klass->replace_buffer = gimp_drawable_real_replace_buffer;
+ klass->get_buffer = gimp_drawable_real_get_buffer;
+ klass->set_buffer = gimp_drawable_real_set_buffer;
+ klass->push_undo = gimp_drawable_real_push_undo;
+ klass->swap_pixels = gimp_drawable_real_swap_pixels;
+ klass->get_source_node = gimp_drawable_real_get_source_node;
g_object_class_override_property (object_class, PROP_BUFFER, "buffer");
@@ -387,35 +385,6 @@ gimp_drawable_get_size (GimpViewable *viewable,
return TRUE;
}
-static void
-gimp_drawable_visibility_changed (GimpFilter *filter)
-{
- GimpDrawable *drawable = GIMP_DRAWABLE (filter);
- GeglNode *node;
-
- /* don't use gimp_filter_get_node() because that would create
- * the node.
- */
- node = gimp_filter_peek_node (filter);
-
- if (node)
- {
- GeglNode *output = gegl_node_get_output_proxy (node, "output");
-
- if (gimp_filter_get_visible (filter))
- {
- gegl_node_connect_to (drawable->private->mode_node, "output",
- output, "input");
- }
- else
- {
- /* Handled by GimpFilter */
- }
- }
-
- GIMP_FILTER_CLASS (parent_class)->visibility_changed (filter);
-}
-
static GeglNode *
gimp_drawable_get_node (GimpFilter *filter)
{
@@ -438,16 +407,8 @@ gimp_drawable_get_node (GimpFilter *filter)
gegl_node_connect_to (input, "output",
drawable->private->mode_node, "input");
-
- if (gimp_filter_get_visible (filter))
- {
- gegl_node_connect_to (drawable->private->mode_node, "output",
- output, "input");
- }
- else
- {
- /* Handled by GimpFilter */
- }
+ gegl_node_connect_to (drawable->private->mode_node, "output",
+ output, "input");
return node;
}
diff --git a/app/core/gimpfilter.c b/app/core/gimpfilter.c
index b2ad85f..951633d 100644
--- a/app/core/gimpfilter.c
+++ b/app/core/gimpfilter.c
@@ -63,21 +63,20 @@ struct _GimpFilterPrivate
/* local function prototypes */
-static void gimp_filter_finalize (GObject *object);
-static void gimp_filter_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gimp_filter_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec);
+static void gimp_filter_finalize (GObject *object);
+static void gimp_filter_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_filter_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
-static gint64 gimp_filter_get_memsize (GimpObject *object,
- gint64 *gui_size);
+static gint64 gimp_filter_get_memsize (GimpObject *object,
+ gint64 *gui_size);
-static void gimp_filter_real_visibility_changed (GimpFilter *filter);
-static GeglNode * gimp_filter_real_get_node (GimpFilter *filter);
+static GeglNode * gimp_filter_real_get_node (GimpFilter *filter);
G_DEFINE_TYPE (GimpFilter, gimp_filter, GIMP_TYPE_VIEWABLE)
@@ -108,7 +107,7 @@ gimp_filter_class_init (GimpFilterClass *klass)
gimp_object_class->get_memsize = gimp_filter_get_memsize;
- klass->visibility_changed = gimp_filter_real_visibility_changed;
+ klass->visibility_changed = NULL;
klass->get_node = gimp_filter_real_get_node;
g_object_class_install_property (object_class, PROP_VISIBLE,
@@ -202,28 +201,6 @@ gimp_filter_get_memsize (GimpObject *object,
gui_size);
}
-static void
-gimp_filter_real_visibility_changed (GimpFilter *filter)
-{
- GeglNode *node = gimp_filter_peek_node (filter);
-
- if (node)
- {
- if (gimp_filter_get_visible (filter))
- {
- /* Leave this up to subclasses */
- }
- else
- {
- GeglNode *input = gegl_node_get_input_proxy (node, "input");
- GeglNode *output = gegl_node_get_output_proxy (node, "output");
-
- gegl_node_connect_to (input, "output",
- output, "input");
- }
- }
-}
-
static GeglNode *
gimp_filter_real_get_node (GimpFilter *filter)
{
@@ -231,19 +208,6 @@ gimp_filter_real_get_node (GimpFilter *filter)
private->node = gegl_node_new ();
- if (gimp_filter_get_visible (filter))
- {
- /* Leave this up to subclasses */
- }
- else
- {
- GeglNode *input = gegl_node_get_input_proxy (private->node, "input");
- GeglNode *output = gegl_node_get_output_proxy (private->node, "output");
-
- gegl_node_connect_to (input, "output",
- output, "input");
- }
-
return private->node;
}
diff --git a/app/core/gimpfilterstack.c b/app/core/gimpfilterstack.c
index a3cb8a1..18b1e91 100644
--- a/app/core/gimpfilterstack.c
+++ b/app/core/gimpfilterstack.c
@@ -110,13 +110,16 @@ gimp_filter_stack_add (GimpContainer *container,
GIMP_CONTAINER_CLASS (parent_class)->add (container, object);
- if (stack->graph)
+ if (gimp_filter_get_visible (filter))
{
- gegl_node_add_child (stack->graph, gimp_filter_get_node (filter));
- gimp_filter_stack_add_node (stack, filter);
- }
+ if (stack->graph)
+ {
+ gegl_node_add_child (stack->graph, gimp_filter_get_node (filter));
+ gimp_filter_stack_add_node (stack, filter);
+ }
- gimp_filter_stack_update_last_node (stack);
+ gimp_filter_stack_update_last_node (stack);
+ }
}
static void
@@ -126,7 +129,7 @@ gimp_filter_stack_remove (GimpContainer *container,
GimpFilterStack *stack = GIMP_FILTER_STACK (container);
GimpFilter *filter = GIMP_FILTER (object);
- if (stack->graph)
+ if (stack->graph && gimp_filter_get_visible (filter))
{
gimp_filter_stack_remove_node (stack, filter);
gegl_node_remove_child (stack->graph, gimp_filter_get_node (filter));
@@ -134,8 +137,11 @@ gimp_filter_stack_remove (GimpContainer *container,
GIMP_CONTAINER_CLASS (parent_class)->remove (container, object);
- gimp_filter_set_is_last_node (filter, FALSE);
- gimp_filter_stack_update_last_node (stack);
+ if (gimp_filter_get_visible (filter))
+ {
+ gimp_filter_set_is_last_node (filter, FALSE);
+ gimp_filter_stack_update_last_node (stack);
+ }
}
static void
@@ -146,15 +152,18 @@ gimp_filter_stack_reorder (GimpContainer *container,
GimpFilterStack *stack = GIMP_FILTER_STACK (container);
GimpFilter *filter = GIMP_FILTER (object);
- if (stack->graph)
+ if (stack->graph && gimp_filter_get_visible (filter))
gimp_filter_stack_remove_node (stack, filter);
GIMP_CONTAINER_CLASS (parent_class)->reorder (container, object, new_index);
- gimp_filter_stack_update_last_node (stack);
+ if (gimp_filter_get_visible (filter))
+ {
+ gimp_filter_stack_update_last_node (stack);
- if (stack->graph)
- gimp_filter_stack_add_node (stack, filter);
+ if (stack->graph)
+ gimp_filter_stack_add_node (stack, filter);
+ }
}
@@ -176,9 +185,7 @@ GeglNode *
gimp_filter_stack_get_graph (GimpFilterStack *stack)
{
GList *list;
- GeglNode *first = NULL;
- GeglNode *previous = NULL;
- GeglNode *input;
+ GeglNode *previous;
GeglNode *output;
g_return_val_if_fail (GIMP_IS_FILTER_STACK (stack), NULL);
@@ -188,40 +195,32 @@ gimp_filter_stack_get_graph (GimpFilterStack *stack)
stack->graph = gegl_node_new ();
+ previous = gegl_node_get_input_proxy (stack->graph, "input");
+
for (list = GIMP_LIST (stack)->queue->tail;
list;
list = g_list_previous (list))
{
GimpFilter *filter = list->data;
- GeglNode *node = gimp_filter_get_node (filter);
+ GeglNode *node;
- if (! first)
- first = node;
+ if (! gimp_filter_get_visible (filter))
+ continue;
+
+ node = gimp_filter_get_node (filter);
gegl_node_add_child (stack->graph, node);
- if (previous)
- gegl_node_connect_to (previous, "output",
- node, "input");
+ gegl_node_connect_to (previous, "output",
+ node, "input");
previous = node;
}
- input = gegl_node_get_input_proxy (stack->graph, "input");
output = gegl_node_get_output_proxy (stack->graph, "output");
- if (first && previous)
- {
- gegl_node_connect_to (input, "output",
- first, "input");
- gegl_node_connect_to (previous, "output",
- output, "input");
- }
- else
- {
- gegl_node_connect_to (input, "output",
- output, "input");
- }
+ gegl_node_connect_to (previous, "output",
+ output, "input");
return stack->graph;
}
@@ -233,88 +232,70 @@ static void
gimp_filter_stack_add_node (GimpFilterStack *stack,
GimpFilter *filter)
{
- GimpFilter *filter_below;
- GeglNode *node_above;
- GeglNode *node_below;
- GeglNode *node;
- gint index;
+ GeglNode *node;
+ GeglNode *node_above = NULL;
+ GeglNode *node_below = NULL;
+ GList *iter;
node = gimp_filter_get_node (filter);
- index = gimp_container_get_child_index (GIMP_CONTAINER (stack),
- GIMP_OBJECT (filter));
- if (index == 0)
- {
- node_above = gegl_node_get_output_proxy (stack->graph, "output");
- }
- else
+ iter = g_list_find (GIMP_LIST (stack)->queue->head, filter);
+
+ while ((iter = g_list_previous (iter)))
{
- GimpFilter *filter_above = (GimpFilter *)
- gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1);
+ GimpFilter *filter_above = iter->data;
- node_above = gimp_filter_get_node (filter_above);
- }
+ if (gimp_filter_get_visible (filter_above))
+ {
+ node_above = gimp_filter_get_node (filter_above);
- gegl_node_connect_to (node, "output",
- node_above, "input");
+ break;
+ }
+ }
- filter_below = (GimpFilter *)
- gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index + 1);
+ if (! node_above)
+ node_above = gegl_node_get_output_proxy (stack->graph, "output");
- if (filter_below)
- {
- node_below = gimp_filter_get_node (filter_below);
- }
- else
- {
- node_below = gegl_node_get_input_proxy (stack->graph, "input");
- }
+ node_below = gegl_node_get_producer (node_above, "input", NULL);
gegl_node_connect_to (node_below, "output",
node, "input");
+ gegl_node_connect_to (node, "output",
+ node_above, "input");
}
static void
gimp_filter_stack_remove_node (GimpFilterStack *stack,
GimpFilter *filter)
{
- GimpFilter *filter_below;
- GeglNode *node_above;
- GeglNode *node_below;
- GeglNode *node;
- gint index;
+ GeglNode *node;
+ GeglNode *node_above = NULL;
+ GeglNode *node_below = NULL;
+ GList *iter;
node = gimp_filter_get_node (filter);
- gegl_node_disconnect (node, "input");
+ iter = g_list_find (GIMP_LIST (stack)->queue->head, filter);
- index = gimp_container_get_child_index (GIMP_CONTAINER (stack),
- GIMP_OBJECT (filter));
-
- if (index == 0)
- {
- node_above = gegl_node_get_output_proxy (stack->graph, "output");
- }
- else
+ while ((iter = g_list_previous (iter)))
{
- GimpFilter *filter_above = (GimpFilter *)
- gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1);
+ GimpFilter *filter_above = iter->data;
- node_above = gimp_filter_get_node (filter_above);
+ if (gimp_filter_get_visible (filter_above))
+ {
+ node_above = gimp_filter_get_node (filter_above);
+
+ break;
+ }
}
- filter_below = (GimpFilter *)
- gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index + 1);
+ if (! node_above)
+ node_above = gegl_node_get_output_proxy (stack->graph, "output");
- if (filter_below)
- {
- node_below = gimp_filter_get_node (filter_below);
- }
- else
- {
- node_below = gegl_node_get_input_proxy (stack->graph, "input");
- }
+ node_below = gegl_node_get_producer (node, "input", NULL);
+
+ gegl_node_disconnect (node, "input");
gegl_node_connect_to (node_below, "output",
node_above, "input");
@@ -348,5 +329,22 @@ static void
gimp_filter_stack_filter_visible (GimpFilter *filter,
GimpFilterStack *stack)
{
+ if (stack->graph)
+ {
+ if (gimp_filter_get_visible (filter))
+ {
+ gegl_node_add_child (stack->graph, gimp_filter_get_node (filter));
+ gimp_filter_stack_add_node (stack, filter);
+ }
+ else
+ {
+ gimp_filter_stack_remove_node (stack, filter);
+ gegl_node_remove_child (stack->graph, gimp_filter_get_node (filter));
+ }
+ }
+
gimp_filter_stack_update_last_node (stack);
+
+ if (! gimp_filter_get_visible (filter))
+ gimp_filter_set_is_last_node (filter, FALSE);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]