[gegl] graph: add GeglNodeOutputVisitable



commit ac50d9539eaf71e927ea726facabd0a6d6efe1da
Author: Ell <ell_se yahoo com>
Date:   Thu Nov 9 15:48:37 2017 -0500

    graph: add GeglNodeOutputVisitable
    
    Add GeglNodeOutputVisitable -- an adapter class for GeglNode,
    turning it into a GeglVisitable that returns its sinks, rather than
    its sources, upon GeglVisitable::depends_on(), allowing to traverse
    the graph in the output direction.

 gegl/graph/Makefile.am                  |   28 +++---
 gegl/graph/gegl-node-output-visitable.c |  158 +++++++++++++++++++++++++++++++
 gegl/graph/gegl-node-output-visitable.h |   60 ++++++++++++
 3 files changed, 233 insertions(+), 13 deletions(-)
---
diff --git a/gegl/graph/Makefile.am b/gegl/graph/Makefile.am
index 9992065..6cc76c1 100644
--- a/gegl/graph/Makefile.am
+++ b/gegl/graph/Makefile.am
@@ -24,20 +24,22 @@ noinst_LTLIBRARIES = libgraph.la
 #libgraph_public_HEADERS = #
 
 libgraph_la_SOURCES = \
-       gegl-connection.c       \
-       gegl-node.c             \
-       gegl-pad.c              \
-       gegl-visitor.c          \
-       gegl-callback-visitor.c \
-       gegl-visitable.c        \
+       gegl-connection.c               \
+       gegl-node.c                     \
+       gegl-pad.c                      \
+       gegl-visitor.c                  \
+       gegl-callback-visitor.c         \
+       gegl-visitable.c                \
+       gegl-node-output-visitable.c    \
        \
-       gegl-connection.h       \
-       gegl-node.h             \
-       gegl-node-private.h     \
-       gegl-pad.h              \
-       gegl-visitor.h          \
-       gegl-callback-visitor.h \
-       gegl-visitable.h
+       gegl-connection.h               \
+       gegl-node.h                     \
+       gegl-node-private.h             \
+       gegl-pad.h                      \
+       gegl-visitor.h                  \
+       gegl-callback-visitor.h         \
+       gegl-visitable.h                \
+       gegl-node-output-visitable.h
 
 #libgraph_la_SOURCES = $(libgraph_sources) $(libgraph_public_HEADERS)
 
diff --git a/gegl/graph/gegl-node-output-visitable.c b/gegl/graph/gegl-node-output-visitable.c
new file mode 100644
index 0000000..be164be
--- /dev/null
+++ b/gegl/graph/gegl-node-output-visitable.c
@@ -0,0 +1,158 @@
+/* This file is part of GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2017 Ell
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gegl-types-internal.h"
+
+#include "gegl.h"
+#include "gegl-connection.h"
+#include "gegl-node-output-visitable.h"
+#include "gegl-node-private.h"
+#include "gegl-pad.h"
+#include "gegl-visitable.h"
+#include "gegl-visitor.h"
+
+
+static void                      gegl_node_output_visitable_class_init           
(GeglNodeOutputVisitableClass *klass);
+static void                      gegl_node_output_visitable_init                 (GeglNodeOutputVisitable    
  *self);
+static void                      gegl_node_output_visitable_finalize             (GObject                    
  *object);
+static void                      gegl_node_output_visitable_visitable_iface_init (gpointer                   
   ginterface,
+                                                                                  gpointer                   
   interface_data);
+static gboolean                  gegl_node_output_visitable_visitable_accept     (GeglVisitable              
  *visitable,
+                                                                                  GeglVisitor                
  *visitor);
+static GSList                  * gegl_node_output_visitable_visitable_depends_on (GeglVisitable              
  *visitable);
+
+static GeglNodeOutputVisitable * _gegl_node_output_visitable_new                 (GeglNode                   
  *node);
+
+
+G_DEFINE_TYPE_WITH_CODE (GeglNodeOutputVisitable, gegl_node_output_visitable, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GEGL_TYPE_VISITABLE,
+                                                gegl_node_output_visitable_visitable_iface_init))
+
+
+static void
+gegl_node_output_visitable_class_init (GeglNodeOutputVisitableClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gegl_node_output_visitable_finalize;
+}
+
+static void
+gegl_node_output_visitable_init (GeglNodeOutputVisitable *self)
+{
+  self->node       = NULL;
+  self->visitables = NULL;
+}
+
+static void
+gegl_node_output_visitable_visitable_iface_init (gpointer ginterface,
+                                                 gpointer interface_data)
+{
+  GeglVisitableClass *visitable_class = ginterface;
+
+  visitable_class->accept     = gegl_node_output_visitable_visitable_accept;
+  visitable_class->depends_on = gegl_node_output_visitable_visitable_depends_on;
+}
+
+static void
+gegl_node_output_visitable_finalize (GObject *object)
+{
+  GeglNodeOutputVisitable *self = GEGL_NODE_OUTPUT_VISITABLE (object);
+
+  if (self->is_root)
+    g_hash_table_unref (self->visitables);
+
+  G_OBJECT_CLASS (gegl_node_output_visitable_parent_class)->finalize (object);
+}
+
+static gboolean
+gegl_node_output_visitable_visitable_accept (GeglVisitable *visitable,
+                                             GeglVisitor   *visitor)
+{
+  GeglNodeOutputVisitable *self = GEGL_NODE_OUTPUT_VISITABLE (visitable);
+
+  return gegl_visitor_visit_node (visitor, self->node);
+}
+
+static GSList *
+gegl_node_output_visitable_visitable_depends_on (GeglVisitable *visitable)
+{
+  GeglNodeOutputVisitable *self         = GEGL_NODE_OUTPUT_VISITABLE (visitable);
+  GSList                  *dependencies = NULL;
+  GSList                  *iter;
+
+  for (iter = gegl_node_get_sinks (self->node); iter; iter = g_slist_next (iter))
+    {
+      GeglConnection          *connection = iter->data;
+      GeglNode                *sink_node;
+      GeglNodeOutputVisitable *sink_visitable;
+
+      sink_node = gegl_connection_get_sink_node (connection);
+
+      sink_visitable = g_hash_table_lookup (self->visitables, sink_node);
+
+      if (! sink_visitable)
+        {
+          sink_visitable = _gegl_node_output_visitable_new (sink_node);
+
+          /* don't ref 'visitables'; the root visitable owns it */
+          sink_visitable->visitables = self->visitables;
+
+          g_hash_table_insert (self->visitables, sink_node, sink_visitable);
+        }
+
+      dependencies = g_slist_prepend (dependencies, sink_visitable);
+    }
+
+  return dependencies;
+}
+
+GeglNodeOutputVisitable *
+_gegl_node_output_visitable_new (GeglNode *node)
+{
+  GeglNodeOutputVisitable *self;
+
+  self = g_object_new (GEGL_TYPE_NODE_OUTPUT_VISITABLE, NULL);
+
+  /* don't ref 'node', since we might be called during its destruction */
+  self->node       = node;
+
+  self->is_root    = FALSE;
+  self->visitables = NULL;
+
+  return self;
+}
+
+GeglVisitable *
+gegl_node_output_visitable_new (GeglNode *node)
+{
+  GeglNodeOutputVisitable *self;
+
+  g_return_val_if_fail (GEGL_IS_NODE (node), NULL);
+
+  self = _gegl_node_output_visitable_new (node);
+
+  self->is_root    = TRUE;
+  self->visitables = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
+
+  return GEGL_VISITABLE (self);
+}
diff --git a/gegl/graph/gegl-node-output-visitable.h b/gegl/graph/gegl-node-output-visitable.h
new file mode 100644
index 0000000..54e3328
--- /dev/null
+++ b/gegl/graph/gegl-node-output-visitable.h
@@ -0,0 +1,60 @@
+/* This file is part of GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2017 Ell
+ */
+
+#ifndef __GEGL_NODE_OUTPUT_VISITABLE_H__
+#define __GEGL_NODE_OUTPUT_VISITABLE_H__
+
+G_BEGIN_DECLS
+
+
+#define GEGL_TYPE_NODE_OUTPUT_VISITABLE            (gegl_node_output_visitable_get_type ())
+#define GEGL_NODE_OUTPUT_VISITABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEGL_TYPE_NODE_OUTPUT_VISITABLE, GeglNodeOutputVisitable))
+#define GEGL_NODE_OUTPUT_VISITABLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
GEGL_TYPE_NODE_OUTPUT_VISITABLE, GeglNodeOutputVisitableClass))
+#define GEGL_IS_NODE_OUTPUT_VISITABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEGL_TYPE_NODE_OUTPUT_VISITABLE))
+#define GEGL_IS_NODE_OUTPUT_VISITABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
GEGL_TYPE_NODE_OUTPUT_VISITABLE))
+#define GEGL_NODE_OUTPUT_VISITABLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
GEGL_TYPE_NODE_OUTPUT_VISITABLE, GeglNodeOutputVisitableClass))
+
+
+typedef struct _GeglNodeOutputVisitable      GeglNodeOutputVisitable;
+typedef struct _GeglNodeOutputVisitableClass GeglNodeOutputVisitableClass;
+
+struct _GeglNodeOutputVisitable
+{
+  GObject     parent_instance;
+
+  GeglNode   *node;
+
+  /*< private >*/
+  gboolean    is_root;
+  GHashTable *visitables;
+};
+
+struct _GeglNodeOutputVisitableClass
+{
+  GObjectClass  parent_class;
+};
+
+
+GType           gegl_node_output_visitable_get_type (void) G_GNUC_CONST;
+
+GeglVisitable * gegl_node_output_visitable_new      (GeglNode *node);
+
+
+G_END_DECLS
+
+#endif /* __GEGL_NODE_OUTPUT_VISITABLE_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]