1 /* This file is part of GEGL
2  *
3  * GEGL is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * GEGL is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15  *
16  * Copyright 2003 Calvin Williamson
17  *           2006 Øyvind Kolås
18  *           2013 Daniel Sabo
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include <glib-object.h>
26 #include <gobject/gvaluecollector.h>
27 
28 #include "gegl-types-internal.h"
29 
30 #include "gegl.h"
31 #include "gegl-debug.h"
32 #include "gegl-node-private.h"
33 #include "gegl-connection.h"
34 #include "gegl-pad.h"
35 #include "gegl-visitable.h"
36 #include "gegl-config.h"
37 
38 #include "gegl-region.h"
39 
40 #include "graph/gegl-visitor.h"
41 #include "graph/gegl-callback-visitor.h"
42 #include "graph/gegl-node-output-visitable.h"
43 
44 #include "operation/gegl-operation.h"
45 #include "operation/gegl-operation-private.h"
46 #include "operation/gegl-operation-context-private.h"
47 #include "operation/gegl-operations.h"
48 #include "operation/gegl-operation-meta.h"
49 
50 #include "process/gegl-eval-manager.h"
51 
52 enum
53 {
54   PROP_0,
55   PROP_OP_CLASS,
56   PROP_OPERATION,
57   PROP_NAME,
58   PROP_DONT_CACHE,
59   PROP_CACHE_POLICY,
60   PROP_USE_OPENCL,
61   PROP_PASSTHROUGH
62 };
63 
64 enum
65 {
66   INVALIDATED,
67   COMPUTED,
68   PROGRESS,
69   LAST_SIGNAL
70 };
71 
72 
73 struct _GeglNodePrivate
74 {
75   GSList          *source_connections;
76   GSList          *sink_connections;
77   GSList          *children;  /*  used for children */
78   GeglNode        *parent;
79   gchar           *name;
80   gchar           *debug_name;
81   GeglEvalManager *eval_manager;
82 };
83 
84 
85 static guint gegl_node_signals[LAST_SIGNAL] = {0};
86 
87 
88 static void            gegl_node_class_init               (GeglNodeClass *klass);
89 static void            gegl_node_init                     (GeglNode      *self);
90 static void            gegl_node_finalize                 (GObject       *self_object);
91 static void            gegl_node_dispose                  (GObject       *self_object);
92 static void            gegl_node_local_set_property       (GObject       *gobject,
93                                                            guint          prop_id,
94                                                            const GValue  *value,
95                                                            GParamSpec    *pspec);
96 static void            gegl_node_local_get_property       (GObject       *gobject,
97                                                            guint          prop_id,
98                                                            GValue        *value,
99                                                            GParamSpec    *pspec);
100 static gboolean        gegl_node_pads_exist               (GeglNode      *sink,
101                                                            const gchar   *sink_pad_name,
102                                                            GeglNode      *source,
103                                                            const gchar   *source_pad_name);
104 static GeglConnection *gegl_node_find_connection          (GeglNode      *sink,
105                                                            GeglPad       *sink_pad);
106 static void            gegl_node_visitable_iface_init     (gpointer       ginterface,
107                                                            gpointer       interface_data);
108 static gboolean        gegl_node_visitable_accept         (GeglVisitable *visitable,
109                                                            GeglVisitor   *visitor);
110 static GSList*         gegl_node_visitable_depends_on     (GeglVisitable *visitable);
111 static void            gegl_node_set_operation_object     (GeglNode      *self,
112                                                            GeglOperation *operation);
113 static void            gegl_node_set_op_class             (GeglNode      *self,
114                                                            const gchar   *op_class,
115                                                            const gchar   *first_property,
116                                                            va_list        var_args);
117 static void            gegl_node_disconnect_sinks         (GeglNode      *self);
118 static void            gegl_node_disconnect_sources       (GeglNode      *self);
119 static void            gegl_node_property_changed         (GObject       *gobject,
120                                                            GParamSpec    *arg1,
121                                                            gpointer       user_data);
122 
123 static void            gegl_node_update_debug_name        (GeglNode *node);
124 
125 
G_DEFINE_TYPE_WITH_CODE(GeglNode,gegl_node,G_TYPE_OBJECT,G_ADD_PRIVATE (GeglNode)G_IMPLEMENT_INTERFACE (GEGL_TYPE_VISITABLE,gegl_node_visitable_iface_init))126 G_DEFINE_TYPE_WITH_CODE (GeglNode, gegl_node, G_TYPE_OBJECT,
127                          G_ADD_PRIVATE (GeglNode)
128                          G_IMPLEMENT_INTERFACE (GEGL_TYPE_VISITABLE,
129                                                 gegl_node_visitable_iface_init))
130 
131 
132 static void
133 gegl_node_class_init (GeglNodeClass *klass)
134 {
135   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
136 
137   gobject_class->finalize     = gegl_node_finalize;
138   gobject_class->dispose      = gegl_node_dispose;
139   gobject_class->set_property = gegl_node_local_set_property;
140   gobject_class->get_property = gegl_node_local_get_property;
141 
142   g_object_class_install_property (gobject_class, PROP_OPERATION,
143                                    g_param_spec_object ("gegl-operation",
144                                                         "Operation Object",
145                                                         "The associated GeglOperation instance",
146                                                         GEGL_TYPE_OPERATION,
147                                                         G_PARAM_READWRITE |
148                                                         G_PARAM_STATIC_STRINGS |
149                                                         G_PARAM_CONSTRUCT));
150 
151   g_object_class_install_property (gobject_class, PROP_OP_CLASS,
152                                    g_param_spec_string ("operation",
153                                                         "Operation Type",
154                                                         "The type of associated GeglOperation",
155                                                         "",
156                                                         G_PARAM_CONSTRUCT |
157                                                         G_PARAM_STATIC_STRINGS |
158                                                         G_PARAM_READWRITE));
159 
160   g_object_class_install_property (gobject_class, PROP_DONT_CACHE,
161                                    g_param_spec_boolean ("dont-cache",
162                                                          "Do not cache",
163                                                         "Do not cache the result of this operation, the property is inherited by children created from a node."
164                                                         " (Deprecated for \"cache-policy\".)",
165                                                         FALSE,
166                                                         G_PARAM_CONSTRUCT |
167                                                         G_PARAM_STATIC_STRINGS |
168                                                         G_PARAM_READWRITE));
169 
170   g_object_class_install_property (gobject_class, PROP_CACHE_POLICY,
171                                    g_param_spec_enum ("cache-policy",
172                                                       "Cache Policy",
173                                                       "Cache policy for this node, the property is inherited by children created from a node.",
174                                                       GEGL_TYPE_CACHE_POLICY,
175                                                       GEGL_CACHE_POLICY_AUTO,
176                                                       G_PARAM_CONSTRUCT |
177                                                       G_PARAM_STATIC_STRINGS |
178                                                       G_PARAM_READWRITE));
179 
180   g_object_class_install_property (gobject_class, PROP_USE_OPENCL,
181                                    g_param_spec_boolean ("use-opencl",
182                                                          "Use OpenCL",
183                                                          "Use the OpenCL version of this operation if available, this property is inherited by children created from a node.",
184                                                          TRUE,
185                                                          G_PARAM_CONSTRUCT |
186                                                          G_PARAM_STATIC_STRINGS |
187                                                          G_PARAM_READWRITE));
188 
189 
190   g_object_class_install_property (gobject_class, PROP_NAME,
191                                    g_param_spec_string ("name",
192                                                         "Name",
193                                                         "The name of the node",
194                                                         "",
195                                                         G_PARAM_CONSTRUCT |
196                                                         G_PARAM_STATIC_STRINGS |
197                                                         G_PARAM_READWRITE));
198 
199   g_object_class_install_property (gobject_class, PROP_PASSTHROUGH,
200                                    g_param_spec_boolean ("passthrough",
201                                                          "Passthrough",
202                                                         "Act as a nop, passing input unmodifed through to ouput.",
203                                                         FALSE,
204                                                         G_PARAM_CONSTRUCT |
205                                                         G_PARAM_STATIC_STRINGS |
206                                                         G_PARAM_READWRITE));
207 
208   gegl_node_signals[INVALIDATED] =
209     g_signal_new ("invalidated",
210                   G_TYPE_FROM_CLASS (klass),
211                   G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
212                   0, NULL, NULL, NULL,
213                   G_TYPE_NONE, 1,
214                   GEGL_TYPE_RECTANGLE);
215 
216   gegl_node_signals[COMPUTED] =
217     g_signal_new ("computed",
218                   G_TYPE_FROM_CLASS (klass),
219                   G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
220                   0, NULL, NULL, NULL,
221                   G_TYPE_NONE, 1,
222                   GEGL_TYPE_RECTANGLE);
223 
224   gegl_node_signals[PROGRESS] =
225     g_signal_new ("progress",
226                   G_TYPE_FROM_CLASS (klass),
227                   G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
228                   0, NULL, NULL, NULL,
229                   G_TYPE_NONE, 1, G_TYPE_DOUBLE);
230 }
231 
232 static void
gegl_node_init(GeglNode * self)233 gegl_node_init (GeglNode *self)
234 {
235   self->priv = gegl_node_get_instance_private (self);
236 
237   self->pads             = NULL;
238   self->input_pads       = NULL;
239   self->output_pads      = NULL;
240   self->operation        = NULL;
241   self->is_graph         = FALSE;
242   self->cache            = NULL;
243   self->output_visitable = gegl_node_output_visitable_new (self);
244   g_mutex_init (&self->mutex);
245 
246 }
247 
248 static void
gegl_node_visitable_iface_init(gpointer ginterface,gpointer interface_data)249 gegl_node_visitable_iface_init (gpointer ginterface,
250                                 gpointer interface_data)
251 {
252   GeglVisitableClass *visitable_class = ginterface;
253 
254   visitable_class->accept         = gegl_node_visitable_accept;
255   visitable_class->depends_on     = gegl_node_visitable_depends_on;
256 }
257 
258 static void
gegl_node_dispose(GObject * gobject)259 gegl_node_dispose (GObject *gobject)
260 {
261   GeglNode *self = GEGL_NODE (gobject);
262 
263   if (self->priv->parent != NULL)
264     {
265       GeglNode *parent = self->priv->parent;
266       self->priv->parent = NULL;
267       gegl_node_remove_child (parent, self);
268     }
269 
270   gegl_node_remove_children (self);
271   g_clear_object (&self->cache);
272   g_clear_object (&self->priv->eval_manager);
273 
274   G_OBJECT_CLASS (gegl_node_parent_class)->dispose (gobject);
275 }
276 
277 static void
gegl_node_finalize(GObject * gobject)278 gegl_node_finalize (GObject *gobject)
279 {
280   GeglNode *self = GEGL_NODE (gobject);
281 
282   gegl_node_disconnect_sources (self);
283   gegl_node_disconnect_sinks (self);
284 
285   g_slist_free_full (self->pads, g_object_unref);
286   g_slist_free (self->input_pads);
287   g_slist_free (self->output_pads);
288 
289   g_clear_object (&self->operation);
290   g_clear_object (&self->output_visitable);
291   g_free (self->priv->name);
292   g_free (self->priv->debug_name);
293 
294   g_mutex_clear (&self->mutex);
295 
296   G_OBJECT_CLASS (gegl_node_parent_class)->finalize (gobject);
297 }
298 
299 static void
gegl_node_local_set_property(GObject * gobject,guint property_id,const GValue * value,GParamSpec * pspec)300 gegl_node_local_set_property (GObject      *gobject,
301                               guint         property_id,
302                               const GValue *value,
303                               GParamSpec   *pspec)
304 {
305   GeglNode *node = GEGL_NODE (gobject);
306 
307   switch (property_id)
308     {
309       case PROP_NAME:
310         gegl_node_set_name (node, g_value_get_string (value));
311         break;
312 
313       case PROP_DONT_CACHE:
314         node->dont_cache = g_value_get_boolean (value);
315         break;
316 
317       case PROP_CACHE_POLICY:
318         node->cache_policy = g_value_get_enum (value);
319         break;
320 
321       case PROP_PASSTHROUGH:
322         node->passthrough = g_value_get_boolean (value);
323         break;
324 
325       case PROP_USE_OPENCL:
326         node->use_opencl = g_value_get_boolean (value);
327         break;
328 
329       case PROP_OP_CLASS:
330         {
331           va_list null; /* dummy to pass along, it's not used anyways since
332                          * the preceding argument is NULL, gcc might warn about
333                          * use of uninitialized variable.
334                          */
335 #if defined(__GNUC__)
336           memset(&null, 0, sizeof(null));
337 #endif
338           gegl_node_set_op_class (node, g_value_get_string (value), NULL, null);
339         }
340         break;
341 
342       case PROP_OPERATION:
343         gegl_node_set_operation_object (node, g_value_get_object (value));
344         break;
345 
346       default:
347         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
348         break;
349     }
350 }
351 
352 static void
gegl_node_local_get_property(GObject * gobject,guint property_id,GValue * value,GParamSpec * pspec)353 gegl_node_local_get_property (GObject    *gobject,
354                               guint       property_id,
355                               GValue     *value,
356                               GParamSpec *pspec)
357 {
358   GeglNode *node = GEGL_NODE (gobject);
359 
360   switch (property_id)
361     {
362       case PROP_OP_CLASS:
363         if (node->operation)
364           g_value_set_string (value, GEGL_OPERATION_GET_CLASS (node->operation)->name);
365         break;
366 
367       case PROP_DONT_CACHE:
368         g_value_set_boolean (value, node->dont_cache);
369         break;
370 
371       case PROP_CACHE_POLICY:
372         g_value_set_enum (value, node->cache_policy);
373         break;
374 
375       case PROP_PASSTHROUGH:
376         g_value_set_boolean (value, node->passthrough);
377         break;
378 
379       case PROP_USE_OPENCL:
380         g_value_set_boolean (value, node->use_opencl);
381         break;
382 
383       case PROP_NAME:
384         g_value_set_string (value, gegl_node_get_name (node));
385         break;
386 
387       case PROP_OPERATION:
388         g_value_set_object (value, node->operation);
389         break;
390 
391       default:
392         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
393         break;
394     }
395 }
396 
397 /**
398  * gegl_node_get_pad:
399  * @self: a #GeglNode.
400  * @name: property name.
401  *
402  * Get a property.
403  *
404  * Returns: A #GeglPad.
405  **/
406 GeglPad *
gegl_node_get_pad(GeglNode * self,const gchar * name)407 gegl_node_get_pad (GeglNode    *self,
408                    const gchar *name)
409 {
410   GSList *list;
411 
412   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
413   g_return_val_if_fail (name != NULL, NULL);
414 
415   if (!self->pads)
416     return NULL;
417 
418   for (list = self->pads; list; list = g_slist_next (list))
419     {
420       GeglPad *property = list->data;
421 
422       if (!strcmp (name, gegl_pad_get_name (property)))
423         return property;
424     }
425 
426   return NULL;
427 }
428 
429 gboolean
gegl_node_has_pad(GeglNode * self,const gchar * name)430 gegl_node_has_pad (GeglNode      *self,
431                    const gchar   *name)
432 {
433   return gegl_node_get_pad (self, name) != NULL;
434 }
435 
436 static inline gchar **
_make_pad_list(GSList * iter)437 _make_pad_list (GSList *iter)
438 {
439   gchar **list;
440   gint    i;
441 
442   if (!iter)
443     return NULL;
444 
445   list = g_new0 (gchar *, g_slist_length (iter) + 1);
446 
447   for (i = 0; iter; iter = iter->next, i++)
448     {
449       GeglPad *pad = iter->data;
450       list[i] = g_strdup (pad->name);
451     }
452 
453   return list;
454 }
455 
456 gchar **
gegl_node_list_input_pads(GeglNode * self)457 gegl_node_list_input_pads (GeglNode *self)
458 {
459   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
460 
461   return _make_pad_list (self->input_pads);
462 }
463 
464 gchar **
gegl_node_list_output_pads(GeglNode * self)465 gegl_node_list_output_pads (GeglNode *self)
466 {
467   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
468 
469   return _make_pad_list (self->output_pads);
470 }
471 
472 /**
473  * gegl_node_get_pads:
474  * @self: a #GeglNode.
475  *
476  * Returns: A list of #GeglPad.
477  **/
478 GSList *
gegl_node_get_pads(GeglNode * self)479 gegl_node_get_pads (GeglNode *self)
480 {
481   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
482 
483   return self->pads;
484 }
485 
486 /**
487  * gegl_node_get_input_pads:
488  * @self: a #GeglNode.
489  *
490  * Returns: A list of #GeglPad.
491  **/
492 GSList *
gegl_node_get_input_pads(GeglNode * self)493 gegl_node_get_input_pads (GeglNode *self)
494 {
495   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
496 
497   return self->input_pads;
498 }
499 
500 void
gegl_node_add_pad(GeglNode * self,GeglPad * pad)501 gegl_node_add_pad (GeglNode *self,
502                    GeglPad  *pad)
503 {
504   g_return_if_fail (GEGL_IS_NODE (self));
505   g_return_if_fail (GEGL_IS_PAD (pad));
506 
507   if (gegl_node_get_pad (self, gegl_pad_get_name (pad)))
508     return;
509 
510   self->pads = g_slist_prepend (self->pads, pad);
511 
512   if (gegl_pad_is_output (pad))
513     self->output_pads = g_slist_prepend (self->output_pads, pad);
514 
515   if (gegl_pad_is_input (pad))
516     self->input_pads = g_slist_prepend (self->input_pads, pad);
517 }
518 
519 void
gegl_node_remove_pad(GeglNode * self,GeglPad * pad)520 gegl_node_remove_pad (GeglNode *self,
521                       GeglPad  *pad)
522 {
523   GeglNode *pad_node;
524 
525   g_return_if_fail (GEGL_IS_NODE (self));
526   g_return_if_fail (GEGL_IS_PAD (pad));
527 
528   self->pads = g_slist_remove (self->pads, pad);
529 
530   if (gegl_pad_is_output (pad))
531     self->output_pads = g_slist_remove (self->output_pads, pad);
532 
533   if (gegl_pad_is_input (pad))
534     self->input_pads = g_slist_remove (self->input_pads, pad);
535 
536   pad_node = gegl_pad_get_node (pad);
537 
538   /* This was a proxy pad, also remove the nop node */
539   if (self != pad_node)
540     gegl_node_remove_child (self, pad_node);
541 
542   g_object_unref (pad);
543 }
544 
545 static gboolean
gegl_node_pads_exist(GeglNode * sink,const gchar * sink_pad_name,GeglNode * source,const gchar * source_pad_name)546 gegl_node_pads_exist (GeglNode    *sink,
547                       const gchar *sink_pad_name,
548                       GeglNode    *source,
549                       const gchar *source_pad_name)
550 {
551   GeglPad *sink_pad;
552 
553   GeglPad *source_pad;
554 
555   if (sink)
556     {
557       g_assert (sink_pad_name);
558       sink_pad = gegl_node_get_pad (sink, sink_pad_name);
559       if (!sink_pad || !gegl_pad_is_input (sink_pad))
560         {
561           g_warning ("%s: Can't find sink property %s of %s", G_STRFUNC,
562                      sink_pad_name, gegl_node_get_debug_name (sink));
563           return FALSE;
564         }
565     }
566 
567   if (source)
568     {
569       g_assert (source_pad_name);
570       source_pad = gegl_node_get_pad (source, source_pad_name);
571       if (!source_pad || !gegl_pad_is_output (source_pad))
572         {
573           g_warning ("%s: Can't find source property %s of %s", G_STRFUNC,
574                      source_pad_name, gegl_node_get_debug_name (source));
575           return FALSE;
576         }
577     }
578 
579   return TRUE;
580 }
581 
582 static GeglConnection *
gegl_node_find_connection(GeglNode * sink,GeglPad * sink_pad)583 gegl_node_find_connection (GeglNode *sink,
584                            GeglPad  *sink_pad)
585 {
586   GSList *list;
587 
588   g_return_val_if_fail (GEGL_IS_NODE (sink), NULL);
589 
590   for (list = sink->priv->source_connections; list; list = g_slist_next (list))
591     {
592       GeglConnection *connection = list->data;
593 
594       if (sink_pad == gegl_connection_get_sink_pad (connection))
595         return connection;
596     }
597 
598   return NULL;
599 }
600 
601 gboolean
gegl_node_connect_to(GeglNode * source,const gchar * source_pad_name,GeglNode * sink,const gchar * sink_pad_name)602 gegl_node_connect_to (GeglNode    *source,
603                       const gchar *source_pad_name,
604                       GeglNode    *sink,
605                       const gchar *sink_pad_name)
606 {
607   return gegl_node_connect_from (sink, sink_pad_name, source, source_pad_name);
608 }
609 
610 /* the implementation of gegl_node_invalidated() can use either GeglRegions
611  * or GeglRectangles (bounding boxes) for calculating the invalidated areas
612  * of the nodes in the graph.  The GeglRegion version is more granular,
613  * invalidating exact areas, but has higher overhead, while the GeglRectangle
614  * version in more coarse, potentially over-invalidating (but never under-
615  * invalidating), but has lower overhead.
616  *
617  * TODO: decide if the higher overhead of the GeglRegion version is worth it.
618  */
619 /* #define GEGL_NODE_INVALIDATED_USE_REGIONS */
620 
621 #ifdef GEGL_NODE_INVALIDATED_USE_REGIONS
622 
623 static gboolean
gegl_node_invalidated_invalidate_node(GeglNode * node,gpointer data)624 gegl_node_invalidated_invalidate_node (GeglNode *node,
625                                        gpointer  data)
626 {
627   GHashTable    *regions = data;
628   GeglRegion    *region  = g_hash_table_lookup (regions, node);
629   GeglRectangle *rects;
630   gint           n_rects;
631   GSList        *iter;
632   gint           i;
633 
634   node->valid_have_rect = FALSE;
635 
636   gegl_region_get_rectangles (region,
637                               &rects, &n_rects);
638 
639   for (i = 0; i < n_rects; i++)
640     {
641       if (node->cache)
642         gegl_cache_invalidate (node->cache, &rects[i]);
643 
644       g_signal_emit (node, gegl_node_signals[INVALIDATED], 0,
645                      &rects[i], NULL);
646     }
647 
648   for (iter = node->priv->sink_connections; iter; iter = g_slist_next (iter))
649     {
650       GeglConnection *connection  = iter->data;
651       GeglNode       *sink_node   = gegl_connection_get_sink_node (connection);
652       GeglPad        *sink_pad    = gegl_connection_get_sink_pad (connection);
653       GeglRegion     *sink_region = g_hash_table_lookup (regions, sink_node);
654 
655       if (! sink_region)
656         {
657           sink_region = gegl_region_new ();
658 
659           g_hash_table_insert (regions, sink_node, sink_region);
660         }
661 
662       if (sink_node->operation)
663         {
664           for (i = 0; i < n_rects; i++)
665             {
666               GeglRectangle invalidated_rect;
667 
668               invalidated_rect = gegl_operation_get_invalidated_by_change (
669                 sink_node->operation,
670                 gegl_pad_get_name (sink_pad), &rects[i]);
671 
672               gegl_region_union_with_rect (sink_region, &invalidated_rect);
673             }
674         }
675       else
676         {
677           gegl_region_union (sink_region, region);
678         }
679     }
680 
681   g_free (rects);
682 
683   return FALSE;
684 }
685 
686 void
gegl_node_invalidated(GeglNode * node,const GeglRectangle * rect,gboolean clear_cache)687 gegl_node_invalidated (GeglNode            *node,
688                        const GeglRectangle *rect,
689                        gboolean             clear_cache)
690 {
691   GHashTable  *regions;
692   GeglVisitor *visitor;
693 
694   g_return_if_fail (GEGL_IS_NODE (node));
695 
696   if (!rect)
697     rect = &node->have_rect;
698 
699   if (node->cache && clear_cache)
700     gegl_buffer_clear (GEGL_BUFFER (node->cache), rect);
701 
702   regions = g_hash_table_new_full (NULL, NULL, NULL,
703                                    (GDestroyNotify) gegl_region_destroy);
704 
705   g_hash_table_insert (regions, node, gegl_region_rectangle (rect));
706 
707   visitor = gegl_callback_visitor_new (gegl_node_invalidated_invalidate_node,
708                                        regions);
709 
710   gegl_visitor_traverse_reverse_topological (visitor,
711                                              gegl_node_get_output_visitable (node));
712 
713   g_object_unref (visitor);
714   g_hash_table_unref (regions);
715 }
716 
717 #else /* ! GEGL_NODE_INVALIDATED_USE_REGIONS */
718 
719 static gboolean
gegl_node_invalidated_invalidate_node(GeglNode * node,gpointer data)720 gegl_node_invalidated_invalidate_node (GeglNode *node,
721                                        gpointer  data)
722 {
723   GHashTable          *rects = data;
724   const GeglRectangle *rect  = g_hash_table_lookup (rects, node);
725   GSList              *iter;
726 
727   node->valid_have_rect = FALSE;
728 
729   if (node->cache)
730     gegl_cache_invalidate (node->cache, rect);
731 
732   g_signal_emit (node, gegl_node_signals[INVALIDATED], 0,
733                  rect, NULL);
734 
735   for (iter = node->priv->sink_connections; iter; iter = g_slist_next (iter))
736     {
737       GeglConnection *connection = iter->data;
738       GeglNode       *sink_node  = gegl_connection_get_sink_node (connection);
739       GeglPad        *sink_pad   = gegl_connection_get_sink_pad (connection);
740       GeglRectangle  *sink_rect  = g_hash_table_lookup (rects, sink_node);
741 
742       if (! sink_rect)
743         {
744           sink_rect = gegl_rectangle_new (0, 0, 0, 0);
745 
746           g_hash_table_insert (rects, sink_node, sink_rect);
747         }
748 
749       if (sink_node->operation)
750         {
751           GeglRectangle invalidated_rect;
752 
753           invalidated_rect = gegl_operation_get_invalidated_by_change (
754             sink_node->operation,
755             gegl_pad_get_name (sink_pad), rect);
756 
757           gegl_rectangle_bounding_box (sink_rect, sink_rect, &invalidated_rect);
758         }
759       else
760         {
761           gegl_rectangle_bounding_box (sink_rect, sink_rect, rect);
762         }
763     }
764 
765   return FALSE;
766 }
767 
768 void
gegl_node_invalidated(GeglNode * node,const GeglRectangle * rect,gboolean clear_cache)769 gegl_node_invalidated (GeglNode            *node,
770                        const GeglRectangle *rect,
771                        gboolean             clear_cache)
772 {
773   GHashTable  *rects;
774   GeglVisitor *visitor;
775 
776   g_return_if_fail (GEGL_IS_NODE (node));
777 
778   if (!rect)
779     rect = &node->have_rect;
780 
781   if (node->cache && clear_cache)
782     gegl_buffer_clear (GEGL_BUFFER (node->cache), rect);
783 
784   rects = g_hash_table_new_full (NULL, NULL, NULL, g_free);
785 
786   g_hash_table_insert (rects, node, g_memdup (rect, sizeof (GeglRectangle)));
787 
788   visitor = gegl_callback_visitor_new (gegl_node_invalidated_invalidate_node,
789                                        rects);
790 
791   gegl_visitor_traverse_reverse_topological (visitor,
792                                              gegl_node_get_output_visitable (node));
793 
794   g_object_unref (visitor);
795   g_hash_table_unref (rects);
796 }
797 
798 #endif /* ! GEGL_NODE_INVALIDATED_USE_REGIONS */
799 
800 static void
gegl_node_source_invalidated(GeglNode * source,GeglPad * destination_pad,const GeglRectangle * rect)801 gegl_node_source_invalidated (GeglNode            *source,
802                               GeglPad             *destination_pad,
803                               const GeglRectangle *rect)
804 {
805   GeglNode      *destination = gegl_pad_get_node (destination_pad);
806   GeglRectangle  dirty_rect;
807 
808   GEGL_NOTE (GEGL_DEBUG_INVALIDATION, "%s.%s is dirtied from %s (%i,%i %i×%i)",
809              gegl_node_get_debug_name (destination), gegl_pad_get_name (destination_pad),
810              gegl_node_get_debug_name (source),
811              rect->x, rect->y,
812              rect->width, rect->height);
813 
814   if (destination->operation)
815     {
816       dirty_rect =
817         gegl_operation_get_invalidated_by_change (destination->operation,
818                                                   gegl_pad_get_name (destination_pad),
819                                                   rect);
820     }
821   else
822     {
823       dirty_rect = *rect;
824     }
825 
826   gegl_node_invalidated (destination, &dirty_rect, FALSE);
827 }
828 
829 static gboolean
gegl_node_has_source_node_equals(GeglNode * node,gpointer potential_source)830 gegl_node_has_source_node_equals (GeglNode *node,
831                                   gpointer  potential_source)
832 {
833   return node == potential_source;
834 }
835 
836 static gboolean
gegl_node_has_source(GeglNode * self,GeglNode * potential_source)837 gegl_node_has_source (GeglNode *self,
838                       GeglNode *potential_source)
839 {
840   GeglVisitor *visitor;
841   gboolean     found;
842 
843   visitor = gegl_callback_visitor_new (gegl_node_has_source_node_equals,
844                                        potential_source);
845 
846   found = gegl_visitor_traverse (visitor, GEGL_VISITABLE (self));
847 
848   g_object_unref (visitor);
849 
850   return found;
851 }
852 
853 gboolean
gegl_node_is_graph(GeglNode * node)854 gegl_node_is_graph (GeglNode *node)
855 {
856   g_return_val_if_fail (node, FALSE);
857   g_return_val_if_fail (GEGL_IS_NODE (node), FALSE);
858   return node->is_graph;
859 }
860 
861 gboolean
gegl_node_connect_from(GeglNode * sink,const gchar * sink_pad_name,GeglNode * source,const gchar * source_pad_name)862 gegl_node_connect_from (GeglNode    *sink,
863                         const gchar *sink_pad_name,
864                         GeglNode    *source,
865                         const gchar *source_pad_name)
866 {
867   GeglNode    *real_sink            = sink;
868   GeglNode    *real_source          = source;
869   const gchar *real_sink_pad_name   = sink_pad_name;
870   const gchar *real_source_pad_name = source_pad_name;
871 
872   g_return_val_if_fail (GEGL_IS_NODE (sink), FALSE);
873   g_return_val_if_fail (sink_pad_name != NULL, FALSE);
874   g_return_val_if_fail (GEGL_IS_NODE (source), FALSE);
875   g_return_val_if_fail (source_pad_name != NULL, FALSE);
876 
877   if (gegl_node_has_source (source, sink))
878     {
879       g_warning ("Construction of loop requested, bailing\n");
880       return FALSE;
881     }
882 
883   /* For graph nodes we implicitly use the proxy nodes */
884   if (sink->is_graph)
885     {
886       real_sink = gegl_node_get_input_proxy (sink, sink_pad_name);
887 
888       /* The name of the input pad of proxynop input nodes is always
889        * "input"
890        */
891       real_sink_pad_name = "input";
892     }
893   if (source->is_graph)
894     {
895       real_source = gegl_node_get_output_proxy (source, source_pad_name);
896 
897       /* The name of the output pad of proxynop output nodes is always
898        * "output"
899        */
900       real_source_pad_name = "output";
901     }
902 
903   if (gegl_node_pads_exist (real_sink, real_sink_pad_name, real_source, real_source_pad_name))
904     {
905       GeglPad        *other_pad;
906       GeglPad        *sink_pad   = gegl_node_get_pad (real_sink, real_sink_pad_name);
907       GeglPad        *source_pad = gegl_node_get_pad (real_source, real_source_pad_name);
908       GeglConnection *connection;
909 
910       other_pad = gegl_pad_get_connected_to (sink_pad);
911       if (source_pad == other_pad)
912         return TRUE;
913 
914       gegl_node_disconnect (real_sink, real_sink_pad_name);
915 
916       connection = gegl_pad_connect (sink_pad, source_pad);
917       gegl_connection_set_sink_node (connection, real_sink);
918       gegl_connection_set_source_node (connection, real_source);
919 
920       real_sink->priv->source_connections = g_slist_prepend (real_sink->priv->source_connections, connection);
921       real_source->priv->sink_connections = g_slist_prepend (real_source->priv->sink_connections, connection);
922 
923       gegl_node_source_invalidated (real_source, sink_pad, &real_source->have_rect);
924 
925       return TRUE;
926     }
927 
928   return FALSE;
929 }
930 
931 gboolean
gegl_node_disconnect(GeglNode * sink,const gchar * sink_pad_name)932 gegl_node_disconnect (GeglNode    *sink,
933                       const gchar *sink_pad_name)
934 {
935   GeglNode    *real_sink          = sink;
936   const gchar *real_sink_pad_name = sink_pad_name;
937 
938   g_return_val_if_fail (GEGL_IS_NODE (sink), FALSE);
939   g_return_val_if_fail (sink_pad_name != NULL, FALSE);
940 
941   /* For graph nodes we implicitly use the proxy nodes */
942   if (sink->is_graph)
943     {
944       real_sink = gegl_node_get_input_proxy (sink, sink_pad_name);
945 
946       /* The name of the input pad of proxynop input nodes is always
947        * "input"
948        */
949       real_sink_pad_name = "input";
950     }
951 
952   if (gegl_node_pads_exist (real_sink, real_sink_pad_name, NULL, NULL))
953     {
954       GeglPad        *sink_pad   = gegl_node_get_pad (real_sink, real_sink_pad_name);
955       GeglConnection *connection = gegl_node_find_connection (real_sink, sink_pad);
956       GeglNode       *source;
957       GeglPad        *source_pad;
958 
959       if (!connection)
960         return FALSE;
961 
962       source_pad = gegl_connection_get_source_pad (connection);
963       source     = gegl_connection_get_source_node (connection);
964 
965       gegl_node_source_invalidated (source, sink_pad, &source->have_rect);
966 
967       gegl_pad_disconnect (sink_pad, source_pad, connection);
968 
969       real_sink->priv->source_connections = g_slist_remove (real_sink->priv->source_connections, connection);
970       source->priv->sink_connections = g_slist_remove (source->priv->sink_connections, connection);
971 
972       gegl_connection_destroy (connection);
973 
974 
975       return TRUE;
976     }
977 
978   return FALSE;
979 }
980 
981 static void
gegl_node_disconnect_sources(GeglNode * self)982 gegl_node_disconnect_sources (GeglNode *self)
983 {
984   while (TRUE)
985     {
986       GeglConnection *connection = g_slist_nth_data (self->priv->source_connections, 0);
987 
988       if (connection)
989         {
990           GeglNode    *sink          = gegl_connection_get_sink_node (connection);
991           GeglPad     *sink_pad      = gegl_connection_get_sink_pad (connection);
992           const gchar *sink_pad_name = gegl_pad_get_name (sink_pad);
993 
994           g_assert (self == sink);
995 
996           gegl_node_disconnect (sink, sink_pad_name);
997         }
998       else
999         break;
1000     }
1001 }
1002 
1003 static void
gegl_node_disconnect_sinks(GeglNode * self)1004 gegl_node_disconnect_sinks (GeglNode *self)
1005 {
1006   while (TRUE)
1007     {
1008       GeglConnection *connection = g_slist_nth_data (self->priv->sink_connections, 0);
1009 
1010       if (connection)
1011         {
1012           GeglNode    *sink          = gegl_connection_get_sink_node (connection);
1013           GeglNode    *source        = gegl_connection_get_source_node (connection);
1014           GeglPad     *sink_pad      = gegl_connection_get_sink_pad (connection);
1015           const gchar *sink_pad_name = gegl_pad_get_name (sink_pad);
1016 
1017           g_assert (self == source);
1018 
1019           gegl_node_disconnect (sink, sink_pad_name);
1020         }
1021       else
1022         break;
1023     }
1024 }
1025 
1026 /**
1027  * gegl_node_num_sinks:
1028  * @self: a #GeglNode.
1029  *
1030  * Gets the number of sinks
1031  *
1032  * Returns: number of sinks
1033  **/
1034 gint
gegl_node_get_num_sinks(GeglNode * self)1035 gegl_node_get_num_sinks (GeglNode *self)
1036 {
1037   g_return_val_if_fail (GEGL_IS_NODE (self), -1);
1038 
1039   return g_slist_length (self->priv->sink_connections);
1040 }
1041 
1042 /**
1043  * gegl_node_get_sinks:
1044  * @self: a #GeglNode.
1045  *
1046  * Gets list of sink connections attached to this self.
1047  *
1048  * Returns: list of sink connections.
1049  **/
1050 GSList *
gegl_node_get_sinks(GeglNode * self)1051 gegl_node_get_sinks (GeglNode *self)
1052 {
1053   g_return_val_if_fail (GEGL_IS_NODE (self), FALSE);
1054 
1055   return self->priv->sink_connections;
1056 }
1057 
1058 void
gegl_node_link(GeglNode * source,GeglNode * sink)1059 gegl_node_link (GeglNode *source,
1060                 GeglNode *sink)
1061 {
1062   g_return_if_fail (GEGL_IS_NODE (source));
1063   g_return_if_fail (GEGL_IS_NODE (sink));
1064 
1065   /* using connect_to is more natural here, but leads to an extra
1066    * function call, perhaps connect_to and connect_from should be swapped?
1067    */
1068   gegl_node_connect_to (source, "output", sink, "input");
1069 }
1070 
1071 void
gegl_node_link_many(GeglNode * source,GeglNode * dest,...)1072 gegl_node_link_many (GeglNode *source,
1073                      GeglNode *dest,
1074                      ...)
1075 {
1076   va_list var_args;
1077 
1078   g_return_if_fail (GEGL_IS_NODE (source));
1079   g_return_if_fail (GEGL_IS_NODE (dest));
1080 
1081   va_start (var_args, dest);
1082   while (dest)
1083     {
1084       gegl_node_link (source, dest);
1085       source = dest;
1086       dest   = va_arg (var_args, GeglNode *);
1087     }
1088   va_end (var_args);
1089 }
1090 
1091 static GeglEvalManager *
gegl_node_get_eval_manager(GeglNode * self)1092 gegl_node_get_eval_manager (GeglNode *self)
1093 {
1094   if (!self->priv->eval_manager)
1095     self->priv->eval_manager = gegl_eval_manager_new (self, "output");
1096   return self->priv->eval_manager;
1097 }
1098 
1099 static GeglBuffer *
gegl_node_apply_roi(GeglNode * self,const GeglRectangle * roi,gint level)1100 gegl_node_apply_roi (GeglNode            *self,
1101                      const GeglRectangle *roi,
1102                      gint                 level)
1103 {
1104   GeglEvalManager *eval_manager = gegl_node_get_eval_manager (self);
1105 
1106   if (roi)
1107     {
1108       return gegl_eval_manager_apply (eval_manager, roi, level);
1109     }
1110   else
1111     {
1112       GeglRectangle node_bbox = gegl_node_get_bounding_box (self);
1113       return gegl_eval_manager_apply (eval_manager, &node_bbox, level);
1114     }
1115 }
1116 
1117 void
gegl_node_blit_buffer(GeglNode * self,GeglBuffer * buffer,const GeglRectangle * roi,gint level,GeglAbyssPolicy abyss_policy)1118 gegl_node_blit_buffer (GeglNode            *self,
1119                        GeglBuffer          *buffer,
1120                        const GeglRectangle *roi,
1121                        gint                 level,
1122                        GeglAbyssPolicy      abyss_policy)
1123 {
1124   // XXX: make use of abyss_policy
1125 
1126   GeglEvalManager *eval_manager;
1127   GeglBuffer      *result;
1128   GeglRectangle    request;
1129 
1130   eval_manager = gegl_node_get_eval_manager (self);
1131 
1132   if (roi)
1133     request = *roi;
1134   else if (buffer)
1135     request = *gegl_buffer_get_extent (buffer);
1136   else
1137     request = gegl_node_get_bounding_box (self);
1138 
1139   result = gegl_eval_manager_apply (eval_manager, &request, level);
1140 
1141   if (result)
1142     {
1143       if (buffer && buffer != result)
1144         gegl_buffer_copy (result, &request, GEGL_ABYSS_NONE, buffer, NULL);
1145       g_object_unref (result);
1146     }
1147 }
1148 
gegl_mipmap_rendering_enabled(void)1149 static inline gboolean gegl_mipmap_rendering_enabled (void)
1150 {
1151   return gegl_config()->mipmap_rendering;
1152 }
1153 
1154 void
gegl_node_blit(GeglNode * self,gdouble scale,const GeglRectangle * roi,const Babl * format,gpointer destination_buf,gint rowstride,GeglBlitFlags flags)1155 gegl_node_blit (GeglNode            *self,
1156                 gdouble              scale,
1157                 const GeglRectangle *roi,
1158                 const Babl          *format,
1159                 gpointer             destination_buf,
1160                 gint                 rowstride,
1161                 GeglBlitFlags        flags)
1162 {
1163   gint interpolation = flags & (GEGL_BUFFER_FILTER_ALL);
1164   flags &= 0xf;
1165 
1166   g_return_if_fail (GEGL_IS_NODE (self));
1167   g_return_if_fail (roi != NULL);
1168 
1169   if (rowstride == GEGL_AUTO_ROWSTRIDE && format)
1170     rowstride = babl_format_get_bytes_per_pixel (format) * roi->width;
1171 
1172   if (flags == 0) // DEFAULT, just render, caching only if graph is explicitly caching itself
1173     {
1174       GeglBuffer *buffer;
1175 
1176       if (scale != 1.0)
1177         {
1178           const GeglRectangle unscaled_roi = _gegl_get_required_for_scale (roi, scale);
1179 
1180           buffer = gegl_node_apply_roi (self, &unscaled_roi,
1181               gegl_mipmap_rendering_enabled()?gegl_level_from_scale (scale):0);
1182         }
1183       else
1184         {
1185           buffer = gegl_node_apply_roi (self, roi, 0);
1186         }
1187       if (buffer && destination_buf)
1188         gegl_buffer_get (buffer, roi, scale, format, destination_buf, rowstride, GEGL_ABYSS_NONE | interpolation);
1189 
1190       g_clear_object (&buffer);
1191     }
1192   else if (flags & GEGL_BLIT_CACHE)
1193     {
1194       GeglCache  *cache;
1195       GeglBuffer *buffer;
1196 
1197       /* make sure we have an output format for the cache */
1198       gegl_eval_manager_prepare (gegl_node_get_eval_manager (self));
1199 
1200       cache  = gegl_node_get_cache (self);
1201       buffer = GEGL_BUFFER (cache);
1202 
1203       if (!(flags & GEGL_BLIT_DIRTY))
1204         {
1205           if (scale != 1.0)
1206             {
1207               const GeglRectangle unscaled_roi = _gegl_get_required_for_scale (roi, scale);
1208               gint  level = gegl_mipmap_rendering_enabled()?gegl_level_from_scale (scale):0;
1209 
1210               gegl_node_blit_buffer (self, buffer, &unscaled_roi, level, GEGL_ABYSS_NONE);
1211               gegl_cache_computed (cache, &unscaled_roi, level);
1212             }
1213           else
1214             {
1215               gegl_node_blit_buffer (self, buffer, roi, 0, GEGL_ABYSS_NONE);
1216               gegl_cache_computed (cache, roi, 0);
1217             }
1218         }
1219 
1220       if (destination_buf && cache)
1221         {
1222           gegl_buffer_get (buffer, roi, scale,
1223                            format, destination_buf, rowstride,
1224                            GEGL_ABYSS_NONE|interpolation);
1225         }
1226     }
1227 }
1228 
1229 static GSList *
gegl_node_get_depends_on(GeglNode * self)1230 gegl_node_get_depends_on (GeglNode *self)
1231 {
1232   GSList *depends_on = NULL;
1233   GSList *llink;
1234 
1235   for (llink = self->priv->source_connections; llink; llink = g_slist_next (llink))
1236     {
1237       GeglConnection *connection = llink->data;
1238       GeglNode       *source_node;
1239 
1240       source_node = gegl_connection_get_source_node (connection);
1241 
1242       depends_on = g_slist_prepend (depends_on, source_node);
1243     }
1244 
1245   return depends_on;
1246 }
1247 
1248 void
gegl_node_dump_depends_on(GeglNode * self)1249 gegl_node_dump_depends_on (GeglNode *self)
1250 {
1251   GSList *depends_on = gegl_node_get_depends_on (self);
1252   GSList *iter       = NULL;
1253 
1254   g_print ("GeglNode %p depends on:\n", self);
1255 
1256   for (iter = depends_on; iter; iter = iter->next)
1257     {
1258       GeglNode *source_node = depends_on->data;
1259       g_print ("  %s\n", gegl_node_get_debug_name (source_node));
1260     }
1261 
1262   g_slist_free (depends_on);
1263 }
1264 
1265 static gboolean
gegl_node_visitable_accept(GeglVisitable * visitable,GeglVisitor * visitor)1266 gegl_node_visitable_accept (GeglVisitable *visitable,
1267                             GeglVisitor   *visitor)
1268 {
1269   return gegl_visitor_visit_node (visitor, (GeglNode *) visitable);
1270 }
1271 
1272 static GSList *
gegl_node_visitable_depends_on(GeglVisitable * visitable)1273 gegl_node_visitable_depends_on (GeglVisitable *visitable)
1274 {
1275   GeglNode *self = GEGL_NODE (visitable);
1276 
1277   return gegl_node_get_depends_on (self);
1278 }
1279 
1280 static void
gegl_node_set_op_class(GeglNode * node,const gchar * op_class,const gchar * first_property,va_list var_args)1281 gegl_node_set_op_class (GeglNode    *node,
1282                         const gchar *op_class,
1283                         const gchar *first_property,
1284                         va_list      var_args)
1285 {
1286   g_return_if_fail (GEGL_IS_NODE (node));
1287   g_return_if_fail (op_class);
1288 
1289   if (op_class && op_class[0] != '\0')
1290     {
1291       GType          type;
1292       GeglOperation *operation;
1293 
1294       type = gegl_operation_gtype_from_name (op_class);
1295 
1296       if (!type)
1297         {
1298           g_warning ("Failed to set operation type %s, using a passthrough op instead", op_class);
1299           if (strcmp (op_class, "gegl:nop"))
1300             {
1301               gegl_node_set_op_class (node, "gegl:nop", NULL, var_args);
1302             }
1303           else
1304             {
1305               g_warning ("The failing op was 'gegl:nop' this means that GEGL was unable to locate any of it's\n"
1306                          "plug-ins. Try making GEGL_PATH point to the directory containing the .so|.dll\n"
1307                          "files with the image processing plug-ins, optionally you could try to make it\n"
1308                          "point to the operations directory of a GEGL sourcetree with a build.");
1309             }
1310           return;
1311         }
1312 
1313       if (node->operation &&
1314           type == G_OBJECT_TYPE (node->operation) &&
1315           first_property)
1316         {
1317           gegl_node_set_valist (node, first_property, var_args);
1318           return;
1319         }
1320 
1321       operation = GEGL_OPERATION (g_object_new_valist (type, first_property,
1322                                                        var_args));
1323       gegl_node_set_operation_object (node, operation);
1324       g_object_unref (operation);
1325     }
1326 }
1327 
1328 static gboolean
gegl_node_invalidate_have_rect(GObject * gobject,gpointer foo,gpointer user_data)1329 gegl_node_invalidate_have_rect (GObject    *gobject,
1330                                 gpointer    foo,
1331                                 gpointer    user_data)
1332 {
1333   GEGL_NODE (user_data)->valid_have_rect = FALSE;
1334   return TRUE;
1335 }
1336 
1337 
1338 static void
gegl_node_property_changed(GObject * gobject,GParamSpec * arg1,gpointer user_data)1339 gegl_node_property_changed (GObject    *gobject,
1340                             GParamSpec *arg1,
1341                             gpointer    user_data)
1342 {
1343   GeglNode *self = GEGL_NODE (user_data);
1344 
1345   if (arg1 != user_data &&
1346       ((arg1 &&
1347         arg1->value_type != GEGL_TYPE_BUFFER) ||
1348        (self->operation && !arg1)))
1349     {
1350       if (self->operation && !arg1)
1351         { /* these means we were called due to a operation change
1352 
1353              FIXME: The logic of this if is not quite intuitive,
1354              perhaps the thing being checked should be slightly different,
1355              or perhaps a bug lurks here?
1356            */
1357           GeglRectangle dirty_rect;
1358 /*        GeglRectangle new_have_rect;*/
1359 
1360           dirty_rect = self->have_rect;
1361           /*new_have_rect = gegl_node_get_bounding_box (self);
1362 
1363              gegl_rectangle_bounding_box (&dirty_rect,
1364                                        &dirty_rect,
1365                                        &new_have_rect);*/
1366 
1367           gegl_node_invalidated (self, &dirty_rect, FALSE);
1368         }
1369       else
1370         {
1371           /* we were called due to a property change */
1372           GeglRectangle dirty_rect;
1373           GeglRectangle new_have_rect;
1374 
1375           dirty_rect    = self->have_rect;
1376           new_have_rect = gegl_node_get_bounding_box (self);
1377 
1378           gegl_rectangle_bounding_box (&dirty_rect,
1379                                        &dirty_rect,
1380                                        &new_have_rect);
1381 
1382           gegl_node_invalidated (self, &dirty_rect, FALSE);
1383         }
1384     }
1385 
1386   if (arg1)
1387     g_object_notify_by_pspec (G_OBJECT (self), arg1);
1388 }
1389 
1390 static void
gegl_node_set_operation_object(GeglNode * self,GeglOperation * operation)1391 gegl_node_set_operation_object (GeglNode      *self,
1392                                 GeglOperation *operation)
1393 {
1394   GeglNode    **consumer_nodes = NULL;
1395   const gchar **consumer_names = NULL;
1396   GeglNode    *input           = NULL;
1397   GeglNode    *aux             = NULL;
1398   GeglNode    *aux2            = NULL;
1399 
1400   g_return_if_fail (GEGL_IS_NODE (self));
1401 
1402   if (!operation)
1403     return;
1404 
1405   g_return_if_fail (GEGL_IS_OPERATION (operation));
1406 
1407   if (gegl_node_has_pad (self, "output"))
1408     gegl_node_get_consumers (self, "output", &consumer_nodes, &consumer_names);
1409 
1410   input = gegl_node_get_producer (self, "input", NULL);
1411   aux   = gegl_node_get_producer (self, "aux", NULL);
1412   aux2  = gegl_node_get_producer (self, "aux2", NULL);
1413 
1414   gegl_node_disconnect_sources (self);
1415   gegl_node_disconnect_sinks (self);
1416 
1417   g_set_object (&self->operation, operation);
1418 
1419   /* Delete all the pads from the previous operation */
1420   while (self->pads)
1421     gegl_node_remove_pad (self, self->pads->data);
1422 
1423   gegl_node_remove_children (self);
1424 
1425   gegl_operation_attach (operation, self);
1426 
1427   /* FIXME: This should handle all input pads instead of just these 3 */
1428   if (input)
1429     gegl_node_connect_from (self, "input", input, "output");
1430   if (aux)
1431     gegl_node_connect_from (self, "aux", aux, "output");
1432   if (aux2)
1433     gegl_node_connect_from (self, "aux2", aux2, "output");
1434 
1435   if (consumer_nodes)
1436     {
1437       for (gint i = 0; consumer_nodes[i]; ++i)
1438         {
1439           GeglNode    *output          = consumer_nodes[i];
1440           const gchar *output_dest_pad = consumer_names[i];
1441 
1442           if (output)
1443             gegl_node_connect_to (self, "output", output, output_dest_pad);
1444         }
1445 
1446       g_free (consumer_nodes);
1447       g_free (consumer_names);
1448     }
1449 
1450   g_signal_connect (G_OBJECT (operation), "notify", G_CALLBACK (gegl_node_invalidate_have_rect), self);
1451   g_signal_connect (G_OBJECT (operation), "notify", G_CALLBACK (gegl_node_property_changed), self);
1452 
1453   gegl_node_update_debug_name (self);
1454 
1455   gegl_node_property_changed (G_OBJECT (operation), (GParamSpec *) NULL, self);
1456 }
1457 
1458 void
gegl_node_set(GeglNode * self,const gchar * first_property_name,...)1459 gegl_node_set (GeglNode    *self,
1460                const gchar *first_property_name,
1461                ...)
1462 {
1463   va_list var_args;
1464 
1465   g_return_if_fail (GEGL_IS_NODE (self));
1466 
1467   va_start (var_args, first_property_name);
1468   gegl_node_set_valist (self, first_property_name, var_args);
1469   va_end (var_args);
1470 }
1471 
1472 void
gegl_node_get(GeglNode * self,const gchar * first_property_name,...)1473 gegl_node_get (GeglNode    *self,
1474                const gchar *first_property_name,
1475                ...)
1476 {
1477   va_list var_args;
1478 
1479   g_return_if_fail (GEGL_IS_NODE (self));
1480   g_return_if_fail (self->is_graph || GEGL_IS_OPERATION (self->operation));
1481 
1482   va_start (var_args, first_property_name);
1483   gegl_node_get_valist (self, first_property_name, var_args);
1484   va_end (var_args);
1485 }
1486 
1487 void
gegl_node_set_valist(GeglNode * self,const gchar * first_property_name,va_list var_args)1488 gegl_node_set_valist (GeglNode    *self,
1489                       const gchar *first_property_name,
1490                       va_list      var_args)
1491 {
1492   const gchar *property_name;
1493 
1494   g_return_if_fail (GEGL_IS_NODE (self));
1495 
1496   g_object_freeze_notify (G_OBJECT (self));
1497 
1498   if (self->operation)
1499     g_object_freeze_notify (G_OBJECT (self->operation));
1500 
1501   property_name = first_property_name;
1502   while (property_name)
1503     {
1504       if (!strcmp (property_name, "operation"))
1505         {
1506           const gchar *op_class;
1507           const gchar *op_first_property;
1508 
1509           op_class          = va_arg (var_args, gchar *);
1510           op_first_property = va_arg (var_args, gchar *);
1511 
1512           if (self->operation)
1513             g_object_thaw_notify (G_OBJECT (self->operation));
1514 
1515           /* pass the following properties as construction properties
1516            * to the operation */
1517           gegl_node_set_op_class (self, op_class, op_first_property, var_args);
1518 
1519           if (self->operation)
1520             g_object_freeze_notify (G_OBJECT (self->operation));
1521 
1522           break;
1523         }
1524       else
1525         {
1526           GValue      value  = { 0, };
1527           GParamSpec *pspec  = NULL;
1528           gchar      *error  = NULL;
1529           GObject    *object = NULL;
1530 
1531           pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self),
1532                                                 property_name);
1533           if (pspec)
1534             {
1535               object = G_OBJECT (self);
1536             }
1537           else if (self->operation)
1538             {
1539               pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self->operation),
1540                                                     property_name);
1541               if (pspec)
1542                 object = G_OBJECT (self->operation);
1543             }
1544 
1545           if (!object)
1546             {
1547               g_warning ("%s is not a valid property of %s",
1548                          property_name,
1549                          gegl_node_get_debug_name (self));
1550               break;
1551             }
1552           else
1553             {
1554               g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1555               G_VALUE_COLLECT (&value, var_args, 0, &error);
1556               if (error)
1557                 {
1558                   g_warning ("%s: %s", G_STRFUNC, error);
1559                   g_free (error);
1560                   g_value_unset (&value);
1561                   break;
1562                 }
1563               g_object_set_property (object, property_name, &value);
1564               g_value_unset (&value);
1565             }
1566         }
1567 
1568       property_name = va_arg (var_args, gchar *);
1569     }
1570 
1571   if (self->operation)
1572     g_object_thaw_notify (G_OBJECT (self->operation));
1573 
1574   g_object_thaw_notify (G_OBJECT (self));
1575 }
1576 
1577 void
gegl_node_get_valist(GeglNode * self,const gchar * first_property_name,va_list var_args)1578 gegl_node_get_valist (GeglNode    *self,
1579                       const gchar *first_property_name,
1580                       va_list      var_args)
1581 {
1582   const gchar *property_name;
1583 
1584   g_return_if_fail (G_IS_OBJECT (self));
1585 
1586   property_name = first_property_name;
1587 
1588   while (property_name)
1589     {
1590       GValue      value = { 0, };
1591       gchar      *error;
1592 
1593       gegl_node_get_property (self, property_name, &value);
1594       if (!G_IS_VALUE (&value))
1595         break;
1596 
1597       G_VALUE_LCOPY (&value, var_args, 0, &error);
1598       if (error)
1599         {
1600           g_warning ("%s: %s", G_STRFUNC, error);
1601           g_free (error);
1602           g_value_unset (&value);
1603           break;
1604         }
1605       g_value_unset (&value);
1606 
1607       property_name = va_arg (var_args, gchar *);
1608     }
1609 }
1610 
1611 void
gegl_node_set_property(GeglNode * self,const gchar * property_name,const GValue * value)1612 gegl_node_set_property (GeglNode     *self,
1613                         const gchar  *property_name,
1614                         const GValue *value)
1615 {
1616   GParamSpec *pspec;
1617 
1618   g_return_if_fail (GEGL_IS_NODE (self));
1619   g_return_if_fail (property_name != NULL);
1620   g_return_if_fail (value != NULL);
1621 
1622   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self), property_name);
1623   if (pspec)
1624     {
1625       g_object_set_property (G_OBJECT (self), property_name, value);
1626       return;
1627     }
1628 
1629   if (self->operation)
1630     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self->operation), property_name);
1631   if (pspec)
1632     {
1633       if (G_IS_PARAM_SPEC_ENUM (pspec) && G_VALUE_HOLDS (value, G_TYPE_STRING))
1634         {
1635           GEnumClass  *enum_class   = G_PARAM_SPEC_ENUM (pspec)->enum_class;
1636           const gchar *value_string = g_value_get_string (value);
1637           GEnumValue  *enum_value   = NULL;
1638 
1639           enum_value = g_enum_get_value_by_name (enum_class, value_string);
1640           if (!enum_value)
1641             enum_value = g_enum_get_value_by_nick (enum_class, value_string);
1642 
1643           if (enum_value)
1644             {
1645               GValue value = G_VALUE_INIT;
1646               g_value_init (&value, G_TYPE_FROM_CLASS (&enum_class->g_type_class));
1647               g_value_set_enum (&value, enum_value->value);
1648               g_object_set_property (G_OBJECT (self->operation), property_name, &value);
1649               g_value_unset (&value);
1650               return;
1651             }
1652 
1653           g_warning ("Could not convert %s to a valid enum value for %s",
1654                      value_string,
1655                      property_name);
1656         }
1657       g_object_set_property (G_OBJECT (self->operation), property_name, value);
1658       return;
1659     }
1660 
1661   g_warning ("%s is not a valid property of %s",
1662              property_name,
1663              gegl_node_get_debug_name (self));
1664 }
1665 
1666 void
gegl_node_get_property(GeglNode * self,const gchar * property_name,GValue * value)1667 gegl_node_get_property (GeglNode    *self,
1668                         const gchar *property_name,
1669                         GValue      *value)
1670 {
1671   GParamSpec *pspec;
1672 
1673   g_return_if_fail (GEGL_IS_NODE (self));
1674   g_return_if_fail (property_name != NULL);
1675   g_return_if_fail (value != NULL);
1676 
1677   /* Unlinke GObject's get_property this function also
1678    * accepts a zero'd GValue and will fill it with the
1679    * correct type automaticaly.
1680    */
1681 
1682   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self), property_name);
1683   if (pspec)
1684     {
1685       if (!G_IS_VALUE (value))
1686         g_value_init (value, pspec->value_type);
1687       g_object_get_property (G_OBJECT (self), property_name, value);
1688       return;
1689     }
1690 
1691   if (self->operation)
1692     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self->operation), property_name);
1693   if (pspec)
1694     {
1695       if (!G_IS_VALUE (value))
1696         g_value_init (value, pspec->value_type);
1697       g_object_get_property (G_OBJECT (self->operation), property_name, value);
1698       return;
1699     }
1700 
1701   g_warning ("%s is not a valid property of %s",
1702              property_name,
1703              gegl_node_get_debug_name (self));
1704 }
1705 
1706 GParamSpec *
gegl_node_find_property(GeglNode * self,const gchar * property_name)1707 gegl_node_find_property (GeglNode    *self,
1708                          const gchar *property_name)
1709 {
1710   GParamSpec *pspec = NULL;
1711 
1712   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
1713   g_return_val_if_fail (property_name != NULL, NULL);
1714 
1715   if (self->operation)
1716     pspec = g_object_class_find_property (
1717       G_OBJECT_GET_CLASS (G_OBJECT (self->operation)), property_name);
1718   if (!pspec)
1719     pspec = g_object_class_find_property (
1720       G_OBJECT_GET_CLASS (G_OBJECT (self)), property_name);
1721   return pspec;
1722 }
1723 
1724 const gchar *
gegl_node_get_operation(const GeglNode * node)1725 gegl_node_get_operation (const GeglNode *node)
1726 {
1727   if (node == NULL)
1728     return NULL;
1729 
1730   if (node->operation == NULL)
1731     {
1732       if (node->is_graph)
1733         return "GraphNode";
1734 
1735       return NULL;
1736     }
1737 
1738   return GEGL_OPERATION_GET_CLASS (node->operation)->name;
1739 }
1740 
1741 GeglOperation *
gegl_node_get_gegl_operation(GeglNode * node)1742 gegl_node_get_gegl_operation (GeglNode *node)
1743 {
1744   if (node == NULL)
1745     return NULL;
1746 
1747   return node->operation;
1748 }
1749 
1750 static void
gegl_node_update_debug_name(GeglNode * node)1751 gegl_node_update_debug_name (GeglNode *node)
1752 {
1753   const gchar  *name = gegl_node_get_name (node);
1754   const gchar  *operation = gegl_node_get_operation (node);
1755   gchar        *new_name = NULL;
1756 
1757   g_return_if_fail (GEGL_IS_NODE (node));
1758 
1759   g_free (node->priv->debug_name);
1760 
1761   if (name && *name)
1762     new_name = g_strdup_printf ("%s '%s' %p", operation ? operation : "(none)", name, node);
1763   else
1764     new_name = g_strdup_printf ("%s %p", operation ? operation : "(none)", node);
1765 
1766   node->priv->debug_name = new_name;
1767 }
1768 
1769 const gchar *
gegl_node_get_debug_name(GeglNode * node)1770 gegl_node_get_debug_name (GeglNode *node)
1771 {
1772   g_return_val_if_fail (GEGL_IS_NODE (node), NULL);
1773 
1774   return node->priv->debug_name;
1775 }
1776 
1777 GeglNode *
gegl_node_get_producer(GeglNode * node,const gchar * pad_name,gchar ** output_pad_name)1778 gegl_node_get_producer (GeglNode     *node,
1779                         const gchar  *pad_name,
1780                         gchar       **output_pad_name)
1781 {
1782   GeglNode *ret;
1783   gpointer pad;
1784 
1785   if (!GEGL_IS_NODE (node))
1786     return NULL;
1787 
1788   /* XXX: there should be public API to test if a node is
1789    * really a graph. So that the user of the API knows
1790    * the internals can be reached through the proxy nops
1791    */
1792   if (node->is_graph)
1793   {
1794     node = gegl_node_get_input_proxy (node, pad_name);
1795     if (!GEGL_IS_NODE (node))
1796       return NULL;
1797     pad_name = "input";
1798   }
1799 
1800   pad = gegl_node_get_pad (node, pad_name);
1801 
1802   if (!pad)
1803     return NULL;
1804   pad = gegl_pad_get_connected_to (pad);
1805   if (!pad)
1806     return NULL;
1807   ret = gegl_pad_get_node (pad);
1808 
1809   if(ret)
1810     {
1811       const gchar *name;
1812       name = gegl_node_get_name (ret);
1813       if (name && !strcmp (name, "proxynop-output"))
1814         {
1815           ret = g_object_get_data (G_OBJECT (ret), "graph");
1816           /* XXX: needs testing whether this returns the correct value
1817            * for non "output" output pads.
1818            */
1819           if (output_pad_name)
1820             *output_pad_name = g_strdup (gegl_pad_get_name (pad));
1821         }
1822       else
1823         {
1824           if (output_pad_name)
1825             *output_pad_name = g_strdup (gegl_pad_get_name (pad));
1826         }
1827     }
1828   return ret;
1829 }
1830 
1831 GeglRectangle
gegl_node_get_bounding_box(GeglNode * self)1832 gegl_node_get_bounding_box (GeglNode *self)
1833 {
1834   if (!self->valid_have_rect)
1835     {
1836       /* We need to construct an evaluation here because we need
1837        * to be sure we use the same logic as the eval manager to
1838        * calculate our bounds. We set our rect explicitly because
1839        * if we're a meta-op the eval manager may not actually
1840        * visit us in prepare.
1841        */
1842 
1843       GeglEvalManager *eval = gegl_eval_manager_new (self, "output");
1844       self->have_rect = gegl_eval_manager_get_bounding_box (eval);
1845       self->valid_have_rect = TRUE;
1846       g_object_unref (eval);
1847     }
1848 
1849   return self->have_rect;
1850 }
1851 
1852 void
gegl_node_process(GeglNode * self)1853 gegl_node_process (GeglNode *self) /* XXX: add level argument?  */
1854 {
1855   GeglProcessor *processor;
1856 
1857   g_return_if_fail (GEGL_IS_NODE (self));
1858 
1859   processor = gegl_node_new_processor (self, NULL);
1860 
1861   while (gegl_processor_work (processor, NULL)) ;
1862   g_object_unref (processor);
1863 }
1864 
1865 GeglNode *
gegl_node_detect(GeglNode * root,gint x,gint y)1866 gegl_node_detect (GeglNode *root,
1867                   gint      x,
1868                   gint      y)
1869 {
1870   if (root)
1871     {
1872       /* make sure the have rects are computed */
1873       /* FIXME: do not call this all the time! */
1874       gegl_node_get_bounding_box (root);
1875 
1876       if (root->operation)
1877         return gegl_operation_detect (root->operation, x, y);
1878       else
1879         {
1880           if (root->is_graph)
1881             {
1882               GeglNode *foo = gegl_node_get_output_proxy (root, "output");
1883               if (foo && foo != root)
1884                 return gegl_node_detect (foo, x, y);
1885             }
1886         }
1887     }
1888   return root;
1889 }
1890 
1891 /* this is a bit hacky, but allows us to insert a node into the graph,
1892  * and avoid the full defined region of the entire graph to change
1893  */
1894 void
gegl_node_insert_before(GeglNode * self,GeglNode * to_be_inserted)1895 gegl_node_insert_before (GeglNode *self,
1896                          GeglNode *to_be_inserted)
1897 {
1898   GeglNode     *other;
1899   GeglRectangle rectangle;
1900 
1901   g_return_if_fail (GEGL_IS_NODE (self));
1902   g_return_if_fail (GEGL_IS_NODE (to_be_inserted));
1903 
1904   other     = gegl_node_get_producer (self, "input", NULL); /*XXX: handle pad name */
1905   rectangle = gegl_node_get_bounding_box (to_be_inserted);
1906 
1907   gegl_node_link_many (other, to_be_inserted, self, NULL);
1908 
1909   /* emit the change ourselves */
1910   gegl_node_invalidated (self, &rectangle, FALSE);
1911 }
1912 
1913 gint
gegl_node_get_consumers(GeglNode * node,const gchar * output_pad,GeglNode *** nodes,const gchar *** pads)1914 gegl_node_get_consumers (GeglNode      *node,
1915                          const gchar   *output_pad,
1916                          GeglNode    ***nodes,
1917                          const gchar ***pads)
1918 {
1919   GSList  *connections;
1920   gint     n_connections;
1921   GeglPad *pad;
1922   gchar  **pasp = NULL;
1923 
1924   g_return_val_if_fail (output_pad != NULL, 0);
1925 
1926   if(node->is_graph)
1927     {
1928       node = gegl_node_get_output_proxy(node, output_pad);
1929       output_pad = "output";
1930     }
1931 
1932   g_return_val_if_fail (GEGL_IS_NODE (node), 0);
1933 
1934   pad = gegl_node_get_pad (node, output_pad);
1935 
1936   if (!pad)
1937     {
1938       g_warning ("%s: no such pad %s for %s",
1939                  G_STRFUNC, output_pad, gegl_node_get_debug_name (node));
1940       return 0;
1941     }
1942 
1943   connections = gegl_pad_get_connections (pad);
1944   {
1945     GSList *iter;
1946     gint    pasp_size = 0;
1947     gint    i;
1948     gint    pasp_pos = 0;
1949 
1950     n_connections = g_slist_length (connections);
1951     pasp_size    += (n_connections + 1) * sizeof (gchar *);
1952 
1953     for (iter = connections; iter; iter = g_slist_next (iter))
1954       {
1955         GeglConnection *connection = iter->data;
1956         GeglPad        *pad        = gegl_connection_get_sink_pad (connection);
1957         pasp_size += strlen (gegl_pad_get_name (pad)) + 1;
1958       }
1959     if (nodes)
1960       *nodes = g_malloc ((n_connections + 1) * sizeof (void *));
1961     if (pads)
1962       {
1963         pasp  = g_malloc (pasp_size);
1964         *pads = (void *) pasp;
1965       }
1966     i        = 0;
1967     pasp_pos = (n_connections + 1) * sizeof (void *);
1968     for (iter = connections; iter; iter = g_slist_next (iter))
1969       {
1970         GeglConnection  *connection = iter->data;
1971         GeglPad                 *pad        = gegl_connection_get_sink_pad (connection);
1972         GeglNode        *node       = gegl_connection_get_sink_node (connection);
1973         const gchar     *pad_name   = gegl_pad_get_name (pad);
1974         const gchar     *name       = gegl_node_get_name(node);
1975 
1976         gchar* proxy_name = g_strconcat("proxynop-", pad_name, NULL);
1977         if(!strcmp(name, proxy_name))
1978           {
1979             node = g_object_get_data(G_OBJECT(node), "graph");
1980             name = gegl_node_get_name(node);
1981           }
1982         else
1983           {
1984           }
1985         g_free (proxy_name);
1986 
1987         if (nodes)
1988           (*nodes)[i] = node;
1989         if (pasp)
1990           {
1991             pasp[i] = ((gchar *) pasp) + pasp_pos;
1992             strcpy (pasp[i], pad_name);
1993           }
1994         pasp_pos += strlen (pad_name) + 1;
1995         i++;
1996       }
1997     if (nodes)
1998       (*nodes)[i] = NULL;
1999     if (pads)
2000       pasp[i] = NULL;
2001   }
2002   return n_connections;
2003 }
2004 
2005 
2006 void
gegl_node_emit_computed(GeglNode * node,const GeglRectangle * rect)2007 gegl_node_emit_computed (GeglNode *node,
2008                          const GeglRectangle *rect)
2009 {
2010   g_signal_emit (node, gegl_node_signals[COMPUTED], 0, rect, NULL, NULL);
2011 }
2012 
2013 gboolean
gegl_node_use_cache(GeglNode * node)2014 gegl_node_use_cache (GeglNode *node)
2015 {
2016   g_return_val_if_fail (GEGL_IS_NODE (node), FALSE);
2017 
2018   switch (node->cache_policy)
2019     {
2020     case GEGL_CACHE_POLICY_AUTO:
2021       if (node->dont_cache)
2022         return FALSE;
2023       else if (node->operation)
2024         return gegl_operation_use_cache (node->operation);
2025       else
2026         return FALSE;
2027 
2028     case GEGL_CACHE_POLICY_NEVER:
2029       return FALSE;
2030 
2031     case GEGL_CACHE_POLICY_ALWAYS:
2032       return TRUE;
2033     }
2034 
2035   g_return_val_if_reached (FALSE);
2036 }
2037 
2038 GeglCache *
gegl_node_get_cache(GeglNode * node)2039 gegl_node_get_cache (GeglNode *node)
2040 {
2041   GeglPad    *pad;
2042   GeglNode   *real_node;
2043   const Babl *format = NULL;
2044   g_return_val_if_fail (GEGL_IS_NODE (node), NULL);
2045 
2046   pad = gegl_node_get_pad (node, "output");
2047   g_return_val_if_fail (pad, NULL);
2048 
2049   real_node = gegl_pad_get_node (pad);
2050 
2051   if (node != real_node)
2052     return gegl_node_get_cache (real_node);
2053 
2054   format = gegl_pad_get_format (pad);
2055 
2056   if (!format)
2057     {
2058       //g_message ("Output of %s has no format", gegl_node_get_debug_name (node));
2059 
2060       format = babl_format ("RGBA float");
2061     }
2062 
2063   if (node->cache && gegl_buffer_get_format ((GeglBuffer *)(node->cache)) != format)
2064     g_clear_object (&node->cache);
2065 
2066   if (node->cache)
2067     return node->cache;
2068 
2069   gegl_node_get_bounding_box (node);
2070 
2071   g_mutex_lock (&node->mutex);
2072 
2073   if (!node->cache)
2074     {
2075       GeglCache *cache;
2076 
2077       cache = g_object_new (
2078         GEGL_TYPE_CACHE,
2079         "format",      format,
2080         "initialized", gegl_operation_context_get_init_output (),
2081         NULL);
2082 
2083       gegl_object_set_has_forked (G_OBJECT (cache));
2084       gegl_buffer_set_extent (GEGL_BUFFER (cache), &node->have_rect);
2085 
2086       g_signal_connect_swapped (G_OBJECT (cache), "computed",
2087                                 (GCallback) gegl_node_emit_computed,
2088                                 node);
2089       node->cache = cache;
2090     }
2091 
2092   g_mutex_unlock (&node->mutex);
2093 
2094   return node->cache;
2095 }
2096 
2097 GeglVisitable *
gegl_node_get_output_visitable(GeglNode * self)2098 gegl_node_get_output_visitable (GeglNode *self)
2099 {
2100   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2101 
2102   return self->output_visitable;
2103 }
2104 
2105 const gchar *
gegl_node_get_name(GeglNode * self)2106 gegl_node_get_name (GeglNode *self)
2107 {
2108   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2109 
2110   return self->priv->name;
2111 }
2112 
2113 void
gegl_node_set_name(GeglNode * self,const gchar * name)2114 gegl_node_set_name (GeglNode    *self,
2115                     const gchar *name)
2116 {
2117   g_return_if_fail (GEGL_IS_NODE (self));
2118 
2119   g_free (self->priv->name);
2120   self->priv->name = g_strdup (name);
2121 
2122   gegl_node_update_debug_name (self);
2123 }
2124 
2125 void
gegl_node_remove_children(GeglNode * self)2126 gegl_node_remove_children (GeglNode *self)
2127 {
2128   g_return_if_fail (GEGL_IS_NODE (self));
2129 
2130   while (TRUE)
2131     {
2132       GeglNode *child = gegl_node_get_nth_child (self, 0);
2133 
2134       if (child && GEGL_IS_NODE (child))
2135         gegl_node_remove_child (self, child);
2136       else
2137         break;
2138     }
2139 }
2140 
2141 GeglNode *
gegl_node_add_child(GeglNode * self,GeglNode * child)2142 gegl_node_add_child (GeglNode *self,
2143                      GeglNode *child)
2144 {
2145   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2146   g_return_val_if_fail (GEGL_IS_NODE (child), NULL);
2147   g_return_val_if_fail (child->priv->parent == NULL, NULL);
2148 
2149   self->priv->children = g_slist_prepend (self->priv->children,
2150                                           g_object_ref (child));
2151   self->is_graph      = TRUE;
2152   child->priv->parent = self;
2153 
2154   child->dont_cache   = self->dont_cache;
2155   child->cache_policy = self->cache_policy;
2156   child->use_opencl   = self->use_opencl;
2157 
2158   return child;
2159 }
2160 
2161 GeglNode *
gegl_node_remove_child(GeglNode * self,GeglNode * child)2162 gegl_node_remove_child (GeglNode *self,
2163                         GeglNode *child)
2164 {
2165   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2166   if (!GEGL_IS_NODE (child))
2167     {
2168       g_print ("%p %s\n", child, G_OBJECT_TYPE_NAME (child));
2169     }
2170   g_return_val_if_fail (GEGL_IS_NODE (child), NULL);
2171 
2172   g_assert (child->priv->parent == self ||
2173             child->priv->parent == NULL);
2174 
2175   self->priv->children = g_slist_remove (self->priv->children, child);
2176 
2177   if (child->priv->parent != NULL)
2178     {
2179       /* if parent isn't set then the node is already in dispose
2180        */
2181       child->priv->parent = NULL;
2182       g_object_unref (child);
2183     }
2184 
2185   if (self->priv->children == NULL)
2186     self->is_graph = FALSE;
2187 
2188   return child;
2189 }
2190 
2191 GeglNode *
gegl_node_get_parent(GeglNode * self)2192 gegl_node_get_parent (GeglNode *self)
2193 {
2194   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2195 
2196   return self->priv->parent;
2197 }
2198 
2199 gint
gegl_node_get_num_children(GeglNode * self)2200 gegl_node_get_num_children (GeglNode *self)
2201 {
2202   g_return_val_if_fail (GEGL_IS_NODE (self), -1);
2203 
2204   return g_slist_length (self->priv->children);
2205 }
2206 
2207 GeglNode *
gegl_node_get_nth_child(GeglNode * self,gint n)2208 gegl_node_get_nth_child (GeglNode *self,
2209                          gint      n)
2210 {
2211   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2212 
2213   return g_slist_nth_data (self->priv->children, n);
2214 }
2215 
2216 /*
2217  * Returns a copy of the graphs internal list of nodes
2218  */
2219 GSList *
gegl_node_get_children(GeglNode * self)2220 gegl_node_get_children (GeglNode *self)
2221 {
2222   g_return_val_if_fail (GEGL_IS_NODE (self), NULL);
2223 
2224   return g_slist_copy (self->priv->children);
2225 }
2226 
2227 /*
2228  *  returns a freshly created node, owned by the graph, and thus freed with it
2229  */
2230 GeglNode *
gegl_node_new_child(GeglNode * parent,const gchar * first_property_name,...)2231 gegl_node_new_child (GeglNode    *parent,
2232                      const gchar *first_property_name,
2233                      ...)
2234 {
2235   GeglNode    *node;
2236   va_list      var_args;
2237   const gchar *name;
2238 
2239   node = g_object_new (GEGL_TYPE_NODE, NULL);
2240   if (parent)
2241     {
2242       gegl_node_add_child (parent, node);
2243     }
2244 
2245   name = first_property_name;
2246   va_start (var_args, first_property_name);
2247   gegl_node_set_valist (node, name, var_args);
2248   va_end (var_args);
2249 
2250   if (parent)
2251     g_object_unref (node);
2252   return node;
2253 }
2254 
2255 GeglNode *
gegl_node_create_child(GeglNode * self,const gchar * operation)2256 gegl_node_create_child (GeglNode    *self,
2257                         const gchar *operation)
2258 {
2259   GeglNode *ret;
2260   g_return_val_if_fail (operation != NULL, NULL);
2261 
2262   ret = gegl_node_new_child (self, "operation", operation, NULL);
2263   if (ret && self)
2264     {
2265       ret->dont_cache   = self->dont_cache;
2266       ret->cache_policy = self->cache_policy;
2267       ret->use_opencl   = self->use_opencl;
2268     }
2269   return ret;
2270 }
2271 
2272 static void
graph_source_invalidated(GeglNode * source,const GeglRectangle * rect,gpointer data)2273 graph_source_invalidated (GeglNode            *source,
2274                           const GeglRectangle *rect,
2275                           gpointer             data)
2276 {
2277   GeglNode      *destination = GEGL_NODE (data);
2278   GeglRectangle  dirty_rect  = *rect;
2279 
2280   GEGL_NOTE (GEGL_DEBUG_INVALIDATION, "graph:%s is dirtied from %s (%i,%i %ix%i)",
2281              gegl_node_get_debug_name (destination),
2282              gegl_node_get_debug_name (source),
2283              rect->x, rect->y,
2284              rect->width, rect->height);
2285 
2286   gegl_node_invalidated (destination, &dirty_rect, FALSE);
2287 }
2288 
2289 
2290 static GeglNode *
gegl_node_get_pad_proxy(GeglNode * node,const gchar * name,gboolean is_graph_input)2291 gegl_node_get_pad_proxy (GeglNode    *node,
2292                          const gchar *name,
2293                          gboolean     is_graph_input)
2294 {
2295   GeglPad *pad = gegl_node_get_pad (node, name);
2296 
2297   if (!pad)
2298     {
2299       GeglNode *nop      = NULL;
2300       GeglPad  *nop_pad  = NULL;
2301       gchar    *nop_name = NULL;
2302 
2303       nop_name = g_strconcat ("proxynop-", name, NULL);
2304       nop      = g_object_new (GEGL_TYPE_NODE, "operation", "gegl:nop", "name", nop_name, NULL);
2305       nop_pad  = gegl_node_get_pad (nop, is_graph_input ? "input" : "output");
2306       g_free (nop_name);
2307 
2308       gegl_node_add_child (node, nop);
2309       g_object_unref (nop); /* our reference is made by the
2310                                gegl_node_add_child call */
2311 
2312       {
2313         GeglPad *new_pad = g_object_new (GEGL_TYPE_PAD, NULL);
2314         gegl_pad_set_param_spec (new_pad, nop_pad->param_spec);
2315         gegl_pad_set_node (new_pad, nop);
2316         gegl_pad_set_name (new_pad, name);
2317         gegl_node_add_pad (node, new_pad);
2318       }
2319 
2320       g_object_set_data (G_OBJECT (nop), "graph", node);
2321 
2322       if (!is_graph_input)
2323         {
2324           g_signal_connect_object (G_OBJECT (nop), "computed",
2325                                    G_CALLBACK (gegl_node_emit_computed), node,
2326                                    G_CONNECT_SWAPPED);
2327           g_signal_connect_object (G_OBJECT (nop), "invalidated",
2328                                    G_CALLBACK (graph_source_invalidated), node,
2329                                    0);
2330         }
2331       return nop;
2332     }
2333   return gegl_pad_get_node (pad);
2334 }
2335 
2336 GeglNode *
gegl_node_get_input_proxy(GeglNode * node,const gchar * name)2337 gegl_node_get_input_proxy (GeglNode    *node,
2338                            const gchar *name)
2339 {
2340   g_return_val_if_fail (GEGL_IS_NODE (node), NULL);
2341 
2342   return gegl_node_get_pad_proxy (node, name, TRUE);
2343 }
2344 
2345 GeglNode *
gegl_node_get_output_proxy(GeglNode * node,const gchar * name)2346 gegl_node_get_output_proxy (GeglNode    *node,
2347                             const gchar *name)
2348 {
2349   g_return_val_if_fail (GEGL_IS_NODE (node), NULL);
2350 
2351   return gegl_node_get_pad_proxy (node, name, FALSE);
2352 }
2353 
2354 GeglNode *
gegl_node_new(void)2355 gegl_node_new (void)
2356 {
2357   return g_object_new (GEGL_TYPE_NODE, NULL);
2358 }
2359 
2360 gboolean
gegl_node_get_passthrough(GeglNode * node)2361 gegl_node_get_passthrough (GeglNode *node)
2362 {
2363   g_return_val_if_fail (GEGL_IS_NODE (node), FALSE);
2364 
2365   return node->passthrough;
2366 }
2367 
2368 void
gegl_node_set_passthrough(GeglNode * node,gboolean passthrough)2369 gegl_node_set_passthrough (GeglNode *node,
2370                            gboolean  passthrough)
2371 {
2372   g_return_if_fail (GEGL_IS_NODE (node));
2373 
2374   if (node->passthrough == passthrough)
2375     return;
2376 
2377   node->passthrough = passthrough;
2378   gegl_node_invalidated (node, NULL, TRUE);
2379 }
2380 
2381 typedef struct Closure {
2382   GeglNode  *node;
2383   gdouble    progress;
2384 } Closure;
2385 
delayed_emission(void * data)2386 static gboolean delayed_emission (void *data)
2387 {
2388   Closure *closure = data;
2389   g_signal_emit (closure->node,
2390                  gegl_node_signals[PROGRESS], 0,
2391                  closure->progress, NULL, NULL);
2392   g_free (closure);
2393   return FALSE;
2394 }
2395 
2396 /* this causes dispatch of the signal on the main thread - if we
2397  * are in the main thread the callback will be directly executed now
2398  * instead of queued (XXX: and if we're on a different thread, this function is
2399  * a nop -- see comment below.)
2400  */
gegl_node_progress(GeglNode * node,gdouble progress,gchar * message)2401 void gegl_node_progress (GeglNode *node,
2402                          gdouble   progress,
2403                          gchar    *message)
2404 {
2405   if (gegl_is_main_thread ())
2406     g_signal_emit (node, gegl_node_signals[PROGRESS], 0, progress, message, NULL);
2407   else
2408   {
2409     /* XXX:  only emit the progress signal from the main thread; otherwise, the
2410      * delayed signal may be emitted after the operation is finished, or,
2411      * indeed, after the node is destroyed.  for auto-threaded operations, each
2412      * thread tracks its progress independently, so reporting the progress of
2413      * the main thread should be a reasonable estimate of the overall progress.
2414      */
2415 #if 0
2416     Closure *closure = g_new0 (Closure, 1);
2417     closure->node = node;
2418     closure->progress = progress;
2419     g_idle_add (delayed_emission, closure);
2420 #else
2421     (void) delayed_emission;
2422 #endif
2423   }
2424 }
2425 
gegl_operation_get_op_version(const char * op_name)2426 const char *gegl_operation_get_op_version (const char *op_name)
2427 {
2428   const gchar *ret = gegl_operation_get_key (op_name, "op-version");
2429   if (!ret)
2430     ret = "0:0";
2431   return ret;
2432 }
2433 
2434