[gegl] Added syntactic sugar for graph construction for C
- From: Øyvind Kolås <ok src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gegl] Added syntactic sugar for graph construction for C
- Date: Sun, 22 Nov 2009 21:57:34 +0000 (UTC)
commit 7f00beed5a06c534738e09f68ce595b7a3a30c19
Author: �yvind Kolås <pippin gimp org>
Date: Sun Nov 22 21:48:15 2009 +0000
Added syntactic sugar for graph construction for C
examples/csugar.c | 59 ++++++++++++++++++++
gegl/Makefile.am | 1 +
gegl/gegl-c.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++
gegl/gegl.h | 36 ++++++++++++
4 files changed, 254 insertions(+), 0 deletions(-)
---
diff --git a/examples/csugar.c b/examples/csugar.c
new file mode 100644
index 0000000..a8e403f
--- /dev/null
+++ b/examples/csugar.c
@@ -0,0 +1,59 @@
+#include "config.h"
+#include <gegl.h>
+#include <gegl-plugin.h>
+#include <glib/gprintf.h>
+#include <gobject/gvaluecollector.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+/* Example file illustrating the syntactic sugar for graph
+ * construction in C
+ */
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ GeglNode *gegl, *sink;
+
+ if (argc != 4)
+ {
+ g_print ("Usage: %s <input image> \"string\" <output image>\n\n", argv[0]);
+ return -1;
+ }
+
+ g_thread_init (NULL);
+ gegl_init (&argc, &argv);
+
+ gegl =
+ gegl_graph (
+ sink = gegl_node ("gegl:png-save", "path", argv[3], NULL,
+ gegl_node ("gegl:over", NULL,
+ gegl_node ("gegl:scale",
+ "x", 0.4,
+ "y", 0.4,
+ NULL,
+ gegl_node ("gegl:invert",
+ NULL,
+ gegl_node ("gegl:load",
+ "path", argv[1],
+ NULL
+ ))),
+ gegl_node ("gegl:translate",
+ "x", 50.0,
+ "y", 50.0,
+ NULL,
+ gegl_node ("gegl:dropshadow", "opacity", 1.0, "radius", 3.0, "x", 3.0, "y", 3.0, NULL,
+ gegl_node ("gegl:text",
+ "size", 40.0,
+ "font", "sans bold",
+ "string", argv[2],
+ "color", gegl_color_new("green"),
+ NULL
+ ))))));
+
+ gegl_node_process (sink);
+ g_object_unref (gegl);
+ gegl_exit ();
+ return 0;
+}
diff --git a/gegl/Makefile.am b/gegl/Makefile.am
index 200116e..72d9d55 100644
--- a/gegl/Makefile.am
+++ b/gegl/Makefile.am
@@ -41,6 +41,7 @@ GEGL_public_HEADERS = \
property-types/gegl-curve.h
GEGL_sources = \
+ gegl-c.c \
gegl-config.c \
gegl-cpuaccel.c \
gegl-dot.c \
diff --git a/gegl/gegl-c.c b/gegl/gegl-c.c
new file mode 100644
index 0000000..e7a70c1
--- /dev/null
+++ b/gegl/gegl-c.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 2009 �yvind Kolås
+ */
+
+#include "config.h"
+#include <gegl.h>
+#include <gegl-plugin.h>
+#include <glib/gprintf.h>
+#include <gobject/gvaluecollector.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "graph/gegl-node.h"
+#include "graph/gegl-pad.h"
+
+static void
+gegl_graph_adopt (GeglNode *graph, GeglNode *node)
+{
+ GeglNode *input, *aux;
+
+ gegl_node_add_child (graph, node);
+ g_object_unref (node);
+
+ if ((input = gegl_node_get_producer (node, "input", NULL)))
+ gegl_graph_adopt (graph, input);
+ if ((aux = gegl_node_get_producer (node, "aux", NULL)))
+ gegl_graph_adopt (graph, aux);
+}
+
+GeglNode *
+gegl_graph (GeglNode *node)
+{
+ GeglNode *graph;
+
+ graph = g_object_new (GEGL_TYPE_NODE, NULL);
+ if (gegl_node_get_pad (node, "output"))
+ {
+ GeglNode *outproxynop = gegl_node_get_output_proxy (graph, "output");
+ gegl_node_connect_to (node, "output", outproxynop, "input");
+ }
+ gegl_graph_adopt (graph, node);
+ return graph;
+}
+
+GeglNode *
+gegl_node (const gchar *type,
+ const gchar *firstname,
+ ...)
+{
+ GeglNode *node;
+ GeglOperation *operation;
+ va_list var_args;
+ const gchar *property_name;
+
+ node = g_object_new (GEGL_TYPE_NODE, "operation", type, NULL);
+ g_object_get (G_OBJECT (node), "gegl-operation", &operation, NULL);
+
+ g_object_freeze_notify (G_OBJECT (node));
+ va_start (var_args, firstname);
+ property_name = firstname;
+ while (property_name)
+ {
+ GValue value = { 0, };
+ GParamSpec *pspec = NULL;
+ gchar *error = NULL;
+
+ if (!strcmp (property_name, "name"))
+ {
+ pspec = g_object_class_find_property (
+ G_OBJECT_GET_CLASS (G_OBJECT (node)), property_name);
+
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRFUNC, error);
+ g_free (error);
+ g_value_unset (&value);
+ break;
+ }
+ g_object_set_property (G_OBJECT (node), property_name, &value);
+ g_value_unset (&value);
+ }
+ else
+ {
+ if (operation)
+ {
+ pspec = g_object_class_find_property (
+ G_OBJECT_GET_CLASS (G_OBJECT (operation)), property_name);
+ }
+ if (!pspec)
+ {
+ g_warning ("%s:%s has no property named: '%s'",
+ G_STRFUNC,
+ G_OBJECT_TYPE_NAME (operation), property_name);
+ break;
+ }
+ if (!(pspec->flags & G_PARAM_WRITABLE))
+ {
+ g_warning ("%s: property (%s of operation class '%s' is not writable",
+ G_STRFUNC,
+ pspec->name,
+ G_OBJECT_TYPE_NAME (operation));
+ break;
+ }
+
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRFUNC, error);
+ g_free (error);
+ g_value_unset (&value);
+ break;
+ }
+ g_object_set_property (G_OBJECT (operation), property_name, &value);
+ g_value_unset (&value);
+ }
+
+ property_name = va_arg (var_args, gchar *);
+ }
+ g_object_thaw_notify (G_OBJECT (node));
+
+ /* The input pads checked for are hard-coded, if no output is connected
+ * pass NULL to indicate no connected node.
+ */
+ if (gegl_node_get_pad (node, "input"))
+ {
+ GeglNode *input = va_arg (var_args, GeglNode*);
+
+ if (input)
+ gegl_node_connect_from (node, "input", input, "output");
+ }
+
+ if (gegl_node_get_pad (node, "aux"))
+ {
+ GeglNode *aux = va_arg (var_args, GeglNode*);
+
+ if (aux)
+ gegl_node_connect_from (node, "aux", aux, "output");
+ }
+ va_end (var_args);
+ return node;
+}
diff --git a/gegl/gegl.h b/gegl/gegl.h
index 3e9fa9a..4ef71e9 100644
--- a/gegl/gegl.h
+++ b/gegl/gegl.h
@@ -845,6 +845,42 @@ void gegl_processor_destroy (GeglProcessor *processor);
GeglConfig * gegl_config (void);
+/**
+ * gegl_node:
+ * @op_type: the type of operation to create
+ * @first_property_name:
+ * @...:
+ *
+ * Construct a GEGL node, connecting it to needed input nodes. The
+ * returned node does not have a parent but a single reference it
+ * is meant to be passed to gegl_graph () for gegl_graph () to assume
+ * its ownership. This is syntactic sugar for use from C, similar
+ * conveniences can easily be built externally in other languages.
+ *
+ * gegl_node(op_type, [key, value, [...]], NULL, [input, [aux]])
+ *
+ * Returns a new Gegl node.
+ */
+GeglNode *gegl_node (const gchar *op_type,
+ const gchar *first_property_name,
+ ...);
+
+
+/**
+ * gegl_graph:
+ * @node: the end result of a composition created with gegl_node()
+ *
+ * Creates a GeglNode containing a free floating graph constructed
+ * using gegl_node(). The GeglGraph adopts all the passed in nodes
+ * making it sufficient to unref the resulting graph.
+ *
+ * gegl_graph (gegl_node ("gegl:over", NULL,
+ * gegl_node (..), gegl_node (..)));
+ *
+ * Returns a GeglNode graph.
+ */
+GeglNode *gegl_graph (GeglNode *node);
+
G_END_DECLS
#endif /* __GEGL_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]