|
Packit |
bc1512 |
/* This file is part of GEGL
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is free software; you can redistribute it and/or
|
|
Packit |
bc1512 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License as published by the Free Software Foundation; either
|
|
Packit |
bc1512 |
* version 3 of the License, or (at your option) any later version.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is distributed in the hope that it will be useful,
|
|
Packit |
bc1512 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
bc1512 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
bc1512 |
* Lesser General Public License for more details.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Copyright 2006 Øyvind Kolås
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
#include "config.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include <glib.h>
|
|
Packit |
bc1512 |
#include <glib-object.h>
|
|
Packit |
bc1512 |
#include <stdlib.h>
|
|
Packit |
bc1512 |
#include <stdio.h>
|
|
Packit |
bc1512 |
#include <string.h>
|
|
Packit |
bc1512 |
#include <limits.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl.h"
|
|
Packit |
bc1512 |
#include "gegl-types-internal.h"
|
|
Packit |
bc1512 |
#include "graph/gegl-node.h"
|
|
Packit |
bc1512 |
#include "graph/gegl-pad.h"
|
|
Packit |
bc1512 |
#include "operation/gegl-operation.h"
|
|
Packit |
bc1512 |
#include "property-types/gegl-color.h"
|
|
Packit |
bc1512 |
#include "property-types/gegl-curve.h"
|
|
Packit |
bc1512 |
#include "property-types/gegl-path.h"
|
|
Packit |
bc1512 |
#include "property-types/gegl-paramspecs.h"
|
|
Packit |
bc1512 |
#include "gegl-instrument.h"
|
|
Packit |
bc1512 |
#include "gegl-xml.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#ifdef G_OS_WIN32
|
|
Packit |
bc1512 |
#define realpath(a, b) _fullpath (b, a, _MAX_PATH)
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
typedef struct _ParseData ParseData;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
enum
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
STATE_NONE = 0,
|
|
Packit |
bc1512 |
STATE_TREE_NORMAL,
|
|
Packit |
bc1512 |
STATE_TREE_FIRST_CHILD
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
struct _ParseData
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint state;
|
|
Packit |
bc1512 |
const gchar *path_root;
|
|
Packit |
bc1512 |
GeglNode *gegl;
|
|
Packit |
bc1512 |
gchar *param;/*< the param we are setting (NULL when not in <param></param>) */
|
|
Packit |
bc1512 |
GeglNode *iter; /*< the iterator we're either connecting to input|aux of
|
|
Packit |
bc1512 |
depending on context */
|
|
Packit |
bc1512 |
GList *parent;/*< a stack of parents, as we are recursing into aux
|
|
Packit |
bc1512 |
branches */
|
|
Packit |
bc1512 |
GeglCurve *curve;/*< the curve whose points we are parsing */
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
GHashTable *ids;
|
|
Packit |
bc1512 |
GList *refs;
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Search a paired attribute name/value arrays for an entry with a specific
|
|
Packit |
bc1512 |
* name, return the value or null if not found.
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
static const gchar *name2val (const gchar **attribute_names,
|
|
Packit |
bc1512 |
const gchar **attribute_values,
|
|
Packit |
bc1512 |
const gchar *name)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
while (*attribute_names)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (!strcmp (*attribute_names, name))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return *attribute_values;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
attribute_names++;
|
|
Packit |
bc1512 |
attribute_values++;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
return NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void param_set (ParseData *pd,
|
|
Packit |
bc1512 |
GeglNode *new,
|
|
Packit |
bc1512 |
const gchar *param_name,
|
|
Packit |
bc1512 |
const gchar *param_value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (!strcmp (param_name, "name"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_object_set (new, param_name, param_value, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (param_name, "id"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_hash_table_insert (pd->ids, g_strdup (param_value), new);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (param_name, "ref"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
pd->refs = g_list_append (pd->refs, new);
|
|
Packit |
bc1512 |
goto set_clone_prop_as_well;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (strcmp (param_name, "operation") &&
|
|
Packit |
bc1512 |
strcmp (param_name, "type"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglOperation *operation;
|
|
Packit |
bc1512 |
GParamSpec *paramspec;
|
|
Packit |
bc1512 |
set_clone_prop_as_well:
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
operation = new->operation;
|
|
Packit |
bc1512 |
paramspec = g_object_class_find_property (G_OBJECT_GET_CLASS (operation), param_name);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!paramspec)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("property %s not found for %s",
|
|
Packit |
bc1512 |
param_name, gegl_node_get_debug_name (new));
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (g_type_is_a (G_PARAM_SPEC_TYPE (paramspec),
|
|
Packit |
bc1512 |
GEGL_TYPE_PARAM_FILE_PATH))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *buf;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (g_path_is_absolute (param_value))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, param_value, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar * absolute_path;
|
|
Packit |
bc1512 |
if (pd->path_root)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
buf = g_strdup_printf ("%s/%s", pd->path_root, param_value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
buf = g_strdup_printf ("./%s", param_value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
absolute_path = realpath (buf, NULL);
|
|
Packit |
bc1512 |
g_free (buf);
|
|
Packit |
bc1512 |
if (absolute_path)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, absolute_path, NULL);
|
|
Packit |
bc1512 |
free (absolute_path);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("Unable to obtain absolute path for parameter %s\n",
|
|
Packit |
bc1512 |
param_name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == G_TYPE_INT)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, atoi (param_value), NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == G_TYPE_FLOAT ||
|
|
Packit |
bc1512 |
paramspec->value_type == G_TYPE_DOUBLE)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, g_ascii_strtod (param_value, NULL), NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == G_TYPE_STRING)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, param_value, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == G_TYPE_BOOLEAN)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (!strcmp (param_value, "true") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "TRUE") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "YES") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "yes") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "y") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "Y") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "1") ||
|
|
Packit |
bc1512 |
!strcmp (param_value, "on"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, TRUE, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, FALSE, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (g_type_is_a (paramspec->value_type, G_TYPE_ENUM))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GEnumClass *eclass = g_type_class_peek (paramspec->value_type);
|
|
Packit |
bc1512 |
GEnumValue *evalue = g_enum_get_value_by_nick (eclass, param_value);
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, evalue->value, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == GEGL_TYPE_COLOR)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglColor *color = g_object_new (GEGL_TYPE_COLOR,
|
|
Packit |
bc1512 |
"string", param_value,
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, color, NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_unref (color);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == GEGL_TYPE_CURVE)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (pd->curve)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, pd->curve, NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_unref (pd->curve);
|
|
Packit |
bc1512 |
pd->curve = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (paramspec->value_type == GEGL_TYPE_PATH)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglPath *path = gegl_path_new ();
|
|
Packit |
bc1512 |
gegl_path_parse_string (path, param_value);
|
|
Packit |
bc1512 |
gegl_node_set (new, param_name, path, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("operation desired unknown parapspec type for %s",
|
|
Packit |
bc1512 |
param_name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Check that the attributes for ELEMENT include an attribute of name NAME,
|
|
Packit |
bc1512 |
* and store it in the variable of the same name. Else report an error.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* eg: { collect_attribute (value, 'key'); }
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
#define collect_attribute(NAME, ELEMENT) \
|
|
Packit |
bc1512 |
{ \
|
|
Packit |
bc1512 |
const gchar *__value = name2val (a, v, (G_STRINGIFY (NAME))); \
|
|
Packit |
bc1512 |
if (!__value) \
|
|
Packit |
bc1512 |
{ \
|
|
Packit |
bc1512 |
*error = g_error_new (G_MARKUP_ERROR, \
|
|
Packit |
bc1512 |
G_MARKUP_ERROR_MISSING_ATTRIBUTE, \
|
|
Packit |
bc1512 |
"Expected attribute '%s' in element '%s'", \
|
|
Packit |
bc1512 |
(G_STRINGIFY (NAME)), \
|
|
Packit |
bc1512 |
(ELEMENT)); \
|
|
Packit |
bc1512 |
return; \
|
|
Packit |
bc1512 |
} \
|
|
Packit |
bc1512 |
else \
|
|
Packit |
bc1512 |
{ \
|
|
Packit |
bc1512 |
(NAME) = __value; \
|
|
Packit |
bc1512 |
} \
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void start_element (GMarkupParseContext *context,
|
|
Packit |
bc1512 |
const gchar *element_name,
|
|
Packit |
bc1512 |
const gchar **attribute_names,
|
|
Packit |
bc1512 |
const gchar **attribute_values,
|
|
Packit |
bc1512 |
gpointer user_data,
|
|
Packit |
bc1512 |
GError **error)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar **a = attribute_names;
|
|
Packit |
bc1512 |
const gchar **v = attribute_values;
|
|
Packit |
bc1512 |
ParseData *pd = user_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!strcmp (element_name, "gegl") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "image"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglNode *new = g_object_new (GEGL_TYPE_NODE, "operation", "gegl:nop", NULL);
|
|
Packit |
bc1512 |
if (pd->gegl == NULL)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
pd->gegl = new;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
pd->state = STATE_TREE_NORMAL;
|
|
Packit |
bc1512 |
pd->parent = g_list_prepend (pd->parent, new);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_node_get_output_proxy (new, "output"); /* creates the pad if it doesn't exist */
|
|
Packit |
bc1512 |
if (pd->iter)
|
|
Packit |
bc1512 |
gegl_node_connect_from (pd->iter, "input", new, "output");
|
|
Packit |
bc1512 |
pd->iter = gegl_node_get_output_proxy (new, "output");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "graph"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/*NYI*/
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "params"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/*g_warning ("go a param set");*/
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "param"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar *name;
|
|
Packit |
bc1512 |
if (pd->param != NULL)
|
|
Packit |
bc1512 |
g_warning ("eek, haven't cleared previous param");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
collect_attribute (name, "param");
|
|
Packit |
bc1512 |
pd->param = g_strdup (name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "curve"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar *ymin, *ymax;
|
|
Packit |
bc1512 |
if (pd->curve != NULL)
|
|
Packit |
bc1512 |
g_warning ("we haven't cleared previous curve");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
collect_attribute (ymin, "curve");
|
|
Packit |
bc1512 |
collect_attribute (ymax, "curve");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
pd->curve = gegl_curve_new (g_ascii_strtod (ymin, NULL),
|
|
Packit |
bc1512 |
g_ascii_strtod (ymax, NULL));
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "curve-point"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (!pd->curve)
|
|
Packit |
bc1512 |
g_warning ("curve not instantiated");
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar *x, *y;
|
|
Packit |
bc1512 |
collect_attribute (x, "curve-point");
|
|
Packit |
bc1512 |
collect_attribute (y, "curve-point");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_curve_add_point (pd->curve,
|
|
Packit |
bc1512 |
g_ascii_strtod (x, NULL),
|
|
Packit |
bc1512 |
g_ascii_strtod (y, NULL));
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "link") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "links") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "stack") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "launcher") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "launchers") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "source") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "destination"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* ignore */
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglNode *new;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!strcmp (element_name, "clone"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
new = gegl_node_new_child (pd->gegl,
|
|
Packit |
bc1512 |
"operation", "gegl:clone",
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "layer"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
new = gegl_node_new_child (pd->gegl,
|
|
Packit |
bc1512 |
"operation", "gegl:layer",
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "node"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar *operation;
|
|
Packit |
bc1512 |
collect_attribute (operation, "node");
|
|
Packit |
bc1512 |
new = gegl_node_new_child (pd->gegl, "operation", operation, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "filter"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar *type;
|
|
Packit |
bc1512 |
collect_attribute (type, "filter");
|
|
Packit |
bc1512 |
new = gegl_node_new_child (pd->gegl, "operation", type, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
new = gegl_node_new_child (pd->gegl,
|
|
Packit |
bc1512 |
"operation", element_name,
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Could not instance an appropriate node */
|
|
Packit |
bc1512 |
if (!new)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
*error = g_error_new (G_MARKUP_ERROR,
|
|
Packit |
bc1512 |
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
|
Packit |
bc1512 |
"Could not instantiate operation '%s'",
|
|
Packit |
bc1512 |
element_name);
|
|
Packit |
bc1512 |
return;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (*a)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
param_set (pd, new, *a, *v);
|
|
Packit |
bc1512 |
a++;
|
|
Packit |
bc1512 |
v++;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (pd->state == STATE_TREE_FIRST_CHILD)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_connect_from (pd->iter, "aux", new, "output");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (pd->iter)
|
|
Packit |
bc1512 |
gegl_node_connect_from (pd->iter, "input", new, "output");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
pd->parent = g_list_prepend (pd->parent, new);
|
|
Packit |
bc1512 |
pd->state = STATE_TREE_FIRST_CHILD;
|
|
Packit |
bc1512 |
pd->iter = new;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void text (GMarkupParseContext *context,
|
|
Packit |
bc1512 |
const gchar *text,
|
|
Packit |
bc1512 |
gsize text_len,
|
|
Packit |
bc1512 |
gpointer user_data,
|
|
Packit |
bc1512 |
GError **error)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ParseData *pd = user_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (pd->param && pd->iter && !pd->curve)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
param_set (pd, pd->iter, pd->param, text);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Called for close tags </foo> */
|
|
Packit |
bc1512 |
static void end_element (GMarkupParseContext *context,
|
|
Packit |
bc1512 |
const gchar *element_name,
|
|
Packit |
bc1512 |
gpointer user_data,
|
|
Packit |
bc1512 |
GError **error)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ParseData *pd = user_data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!strcmp (element_name, "gegl") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "image"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/*ignored*/
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "tree") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "layers"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (gegl_node_get_pad (pd->iter, "input"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gegl_node_connect_from (pd->iter, "input",
|
|
Packit |
bc1512 |
gegl_node_get_input_proxy (GEGL_NODE (pd->parent->data), "input"),
|
|
Packit |
bc1512 |
"output");
|
|
Packit |
bc1512 |
pd->iter = gegl_node_get_input_proxy (GEGL_NODE (pd->parent->data),
|
|
Packit |
bc1512 |
"input");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
pd->iter = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
pd->parent = g_list_delete_link (pd->parent, pd->parent);
|
|
Packit |
bc1512 |
pd->state = STATE_TREE_NORMAL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "graph"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/*NYI*/
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "param"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_free (pd->param);
|
|
Packit |
bc1512 |
pd->param = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "curve"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_assert (pd->param && pd->iter);
|
|
Packit |
bc1512 |
param_set (pd, pd->iter, pd->param, NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (!strcmp (element_name, "link") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "links") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "launcher") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "launchers") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "source") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "destination") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "stack") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "params") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "curve-point"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* ignore */
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (1 ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "node") ||
|
|
Packit |
bc1512 |
!strcmp (element_name, "filter"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
pd->iter = pd->parent->data;
|
|
Packit |
bc1512 |
pd->parent = g_list_delete_link (pd->parent, pd->parent);
|
|
Packit |
bc1512 |
pd->state = STATE_TREE_NORMAL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Called on error, including one set by other
|
|
Packit |
bc1512 |
* methods in the vtable. The GError should not be freed.
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
static void error (GMarkupParseContext *context,
|
|
Packit |
bc1512 |
GError *error,
|
|
Packit |
bc1512 |
gpointer user_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint line_number;
|
|
Packit |
bc1512 |
gint char_number;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
Packit |
bc1512 |
g_warning ("XML Parse error %i:%i: %s",
|
|
Packit |
bc1512 |
line_number, char_number, error->message);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static GMarkupParser parser = {
|
|
Packit |
bc1512 |
start_element,
|
|
Packit |
bc1512 |
end_element,
|
|
Packit |
bc1512 |
text,
|
|
Packit |
bc1512 |
NULL,
|
|
Packit |
bc1512 |
error
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void each_ref (gpointer value,
|
|
Packit |
bc1512 |
gpointer user_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ParseData *pd = user_data;
|
|
Packit |
bc1512 |
GeglNode *dest_node = value;
|
|
Packit |
bc1512 |
gchar *ref;
|
|
Packit |
bc1512 |
GeglNode *source_node;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_node_get (dest_node, "ref", &ref, NULL);
|
|
Packit |
bc1512 |
source_node = g_hash_table_lookup (pd->ids, ref);
|
|
Packit |
bc1512 |
g_free (ref);
|
|
Packit |
bc1512 |
gegl_node_connect_from (dest_node, "input", source_node, "output");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
GeglNode *gegl_node_new_from_xml (const gchar *xmldata,
|
|
Packit |
bc1512 |
const gchar *path_root)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
glong time = gegl_ticks ();
|
|
Packit |
bc1512 |
ParseData pd = { 0, };
|
|
Packit |
bc1512 |
GMarkupParseContext *context;
|
|
Packit |
bc1512 |
gboolean success = FALSE;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_return_val_if_fail (xmldata != NULL, NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
pd.ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
Packit |
bc1512 |
pd.refs = NULL;
|
|
Packit |
bc1512 |
pd.path_root = path_root;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_list_free (pd.refs);
|
|
Packit |
bc1512 |
context = g_markup_parse_context_new (&parser, 0, &pd, NULL);
|
|
Packit |
bc1512 |
success = g_markup_parse_context_parse (context,
|
|
Packit |
bc1512 |
xmldata,
|
|
Packit |
bc1512 |
strlen (xmldata),
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
if (success)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* connect clones */
|
|
Packit |
bc1512 |
g_list_foreach (pd.refs, each_ref, &pd;;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (pd.gegl)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_object_unref (pd.gegl);
|
|
Packit |
bc1512 |
pd.gegl = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_list_free (pd.refs);
|
|
Packit |
bc1512 |
g_list_free (pd.parent);
|
|
Packit |
bc1512 |
g_markup_parse_context_free (context);
|
|
Packit |
bc1512 |
g_hash_table_destroy (pd.ids);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
time = gegl_ticks () - time;
|
|
Packit |
bc1512 |
gegl_instrument ("gegl", "gegl_parse_xml", time);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return success ? GEGL_NODE (pd.gegl) : NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
GeglNode *
|
|
Packit |
bc1512 |
gegl_node_new_from_file (const gchar *path)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglNode *node = NULL;
|
|
Packit |
bc1512 |
GError *err = NULL;
|
|
Packit |
bc1512 |
gchar *script;
|
|
Packit |
bc1512 |
gchar *path_root;
|
|
Packit |
bc1512 |
gchar *dirname;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (path);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
dirname = g_path_get_dirname (path);
|
|
Packit |
bc1512 |
path_root = realpath (dirname, NULL);
|
|
Packit |
bc1512 |
if (!path_root)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
goto cleanup;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_file_get_contents (path, &script, NULL, &err;;
|
|
Packit |
bc1512 |
if (err != NULL)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("Unable to read file: %s", err->message);
|
|
Packit |
bc1512 |
g_error_free (err);
|
|
Packit |
bc1512 |
goto cleanup;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
node = gegl_node_new_from_xml (script, path_root);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cleanup:
|
|
Packit |
bc1512 |
g_free (path_root);
|
|
Packit |
bc1512 |
g_free (dirname);
|
|
Packit |
bc1512 |
return node;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/****/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#define ind do { gint i; for (i = 0; i < indent; i++) g_string_append (ss->buf, " "); } while (0)
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
typedef struct _SerializeState SerializeState;
|
|
Packit |
bc1512 |
struct _SerializeState
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GString *buf;
|
|
Packit |
bc1512 |
const gchar *path_root;
|
|
Packit |
bc1512 |
gint clone_count;
|
|
Packit |
bc1512 |
GHashTable *clones;
|
|
Packit |
bc1512 |
gboolean terse;
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
free_clone_id (gpointer key,
|
|
Packit |
bc1512 |
gpointer value,
|
|
Packit |
bc1512 |
gpointer user_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_free (value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_attr (GString *buf,
|
|
Packit |
bc1512 |
const gchar *key,
|
|
Packit |
bc1512 |
const gchar *value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_assert (key);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *text = g_markup_escape_text (value, -1);
|
|
Packit |
bc1512 |
gchar *p;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_string_append_c (buf, ' ');
|
|
Packit |
bc1512 |
g_string_append (buf, key);
|
|
Packit |
bc1512 |
g_string_append_c (buf, '=');
|
|
Packit |
bc1512 |
g_string_append_c (buf, '\'');
|
|
Packit |
bc1512 |
for (p = text; *p; p++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (*p == '\n')
|
|
Packit |
bc1512 |
g_string_append (buf, "
");
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
g_string_append_c (buf, *p);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
g_string_append_c (buf, '\'');
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (text);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_param_start (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
const gchar *key)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_assert (key);
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
g_string_append (ss->buf, key);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "'>");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_param_text (SerializeState *ss,
|
|
Packit |
bc1512 |
const gchar *value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *text;
|
|
Packit |
bc1512 |
/*gchar *p;*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (value);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Why isn't this used here??? */
|
|
Packit |
bc1512 |
text = g_markup_escape_text (value, -1);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_string_append (ss->buf, value);
|
|
Packit |
bc1512 |
/*for (p=text;*p;p++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (*p=='\n')
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "
");
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
g_string_append_c (ss->buf, *p);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
}*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (text);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_param_end (SerializeState *ss)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "</param>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_param (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
const gchar *key,
|
|
Packit |
bc1512 |
const gchar *value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_assert (key);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_param_start (ss, indent, key);
|
|
Packit |
bc1512 |
xml_param_text (ss, value);
|
|
Packit |
bc1512 |
xml_param_end (ss);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_curve_point (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
gfloat x,
|
|
Packit |
bc1512 |
gfloat y)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar str[64];
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), x);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, str);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "' y='");
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), y);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, str);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "'/>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
xml_curve (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
GeglCurve *curve)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
|
Packit |
bc1512 |
gdouble min_y, max_y;
|
|
Packit |
bc1512 |
guint num_points = gegl_curve_num_points (curve);
|
|
Packit |
bc1512 |
guint i;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_curve_get_y_bounds (curve, &min_y, &max_y);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), min_y);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, str);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "' ymax='");
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), max_y);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, str);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "'>\n");
|
|
Packit |
bc1512 |
for (i = 0; i < num_points; ++i)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gdouble x, y;
|
|
Packit |
bc1512 |
gegl_curve_get_point (curve, i, &x, &y);
|
|
Packit |
bc1512 |
xml_curve_point (ss, indent + 2, x, y);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "</curve>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
serialize_properties (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
GeglNode *node)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GParamSpec **properties;
|
|
Packit |
bc1512 |
guint n_properties;
|
|
Packit |
bc1512 |
gboolean got_a_param = FALSE;
|
|
Packit |
bc1512 |
gint i;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
properties = gegl_operation_list_properties (gegl_node_get_operation (node),
|
|
Packit |
bc1512 |
&n_properties);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i = 0; i < n_properties; i++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (strcmp (properties[i]->name, "input") &&
|
|
Packit |
bc1512 |
strcmp (properties[i]->name, "output") &&
|
|
Packit |
bc1512 |
strcmp (properties[i]->name, "aux"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (!got_a_param)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "<params>\n");
|
|
Packit |
bc1512 |
got_a_param = TRUE;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (g_type_is_a (G_PARAM_SPEC_TYPE (properties[i]),
|
|
Packit |
bc1512 |
GEGL_TYPE_PARAM_FILE_PATH))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *value;
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (ss->path_root &&
|
|
Packit |
bc1512 |
!strncmp (ss->path_root, value, strlen (ss->path_root)))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, &value[strlen (ss->path_root) + 1]);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == G_TYPE_FLOAT)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gfloat value;
|
|
Packit |
bc1512 |
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), value);
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, str);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == G_TYPE_DOUBLE)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gdouble value;
|
|
Packit |
bc1512 |
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), value);
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, str);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == G_TYPE_INT)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint value;
|
|
Packit |
bc1512 |
gchar str[64];
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
g_snprintf (str, sizeof (str), "%i", value);
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, str);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == G_TYPE_BOOLEAN)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gboolean value;
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
if (value)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, "true");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, "false");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == G_TYPE_STRING)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *value;
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, value);
|
|
Packit |
bc1512 |
g_free (value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (g_type_is_a (properties[i]->value_type, G_TYPE_ENUM))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GEnumClass *eclass = g_type_class_peek (properties[i]->value_type);
|
|
Packit |
bc1512 |
GEnumValue *evalue;
|
|
Packit |
bc1512 |
gint value;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &value, NULL);
|
|
Packit |
bc1512 |
evalue = g_enum_get_value (eclass, value);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, evalue->value_nick);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == GEGL_TYPE_COLOR)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglColor *color;
|
|
Packit |
bc1512 |
gchar *value;
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &color, NULL);
|
|
Packit |
bc1512 |
g_object_get (color, "string", &value, NULL);
|
|
Packit |
bc1512 |
g_object_unref (color);
|
|
Packit |
bc1512 |
xml_param (ss, indent + 2, properties[i]->name, value);
|
|
Packit |
bc1512 |
g_free (value);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == GEGL_TYPE_CURVE)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglCurve *curve;
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &curve, NULL);
|
|
Packit |
bc1512 |
xml_param_start (ss, indent + 2, properties[i]->name);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "\n");
|
|
Packit |
bc1512 |
xml_curve (ss, indent + 4, curve);
|
|
Packit |
bc1512 |
indent += 2; ind; indent -= 2; xml_param_end (ss);
|
|
Packit |
bc1512 |
g_object_unref (curve);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (properties[i]->value_type == GEGL_TYPE_PATH)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *svg_path;
|
|
Packit |
bc1512 |
GeglPath *path;
|
|
Packit |
bc1512 |
gegl_node_get (node, properties[i]->name, &path, NULL);
|
|
Packit |
bc1512 |
xml_param_start (ss, indent + 2, properties[i]->name);
|
|
Packit |
bc1512 |
svg_path = gegl_path_to_string (path);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, svg_path);
|
|
Packit |
bc1512 |
xml_param_end (ss);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_unref (path);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("%s: serialization of %s properties not implemented",
|
|
Packit |
bc1512 |
properties[i]->name, g_type_name (properties[i]->value_type));
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (got_a_param)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "</params>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
g_free (properties);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
serialize_layer (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
GeglNode *layer)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *name;
|
|
Packit |
bc1512 |
gchar *src;
|
|
Packit |
bc1512 |
gchar *composite_op;
|
|
Packit |
bc1512 |
gdouble x;
|
|
Packit |
bc1512 |
gdouble y;
|
|
Packit |
bc1512 |
gdouble opacity;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_node_get (layer, "name", &name,
|
|
Packit |
bc1512 |
"src", &src,
|
|
Packit |
bc1512 |
"x", &x,
|
|
Packit |
bc1512 |
"y", &y,
|
|
Packit |
bc1512 |
"opacity", &opacity,
|
|
Packit |
bc1512 |
"composite_op", &composite_op,
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
if (name[0])
|
|
Packit |
bc1512 |
g_string_append_printf (ss->buf, " name='%s'", name);
|
|
Packit |
bc1512 |
if (x != 0.0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), x);
|
|
Packit |
bc1512 |
g_string_append_printf (ss->buf, " x='%s'", str);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
if (y != 0.0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), y);
|
|
Packit |
bc1512 |
g_string_append_printf (ss->buf, " y='%s'", str);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
if (opacity != 1.0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar str[G_ASCII_DTOSTR_BUF_SIZE];
|
|
Packit |
bc1512 |
g_ascii_dtostr (str, sizeof(str), opacity);
|
|
Packit |
bc1512 |
g_string_append_printf (ss->buf, " opacity='%s'", str);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
if (src[0])
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (ss->path_root &&
|
|
Packit |
bc1512 |
!strncmp (ss->path_root, src, strlen (ss->path_root)))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_string_append_printf (ss->buf, " src='%s'", &src[strlen (ss->path_root) + 1]);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_string_append_printf (ss->buf, " src='%s'", src);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "/>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
add_stack (SerializeState *ss,
|
|
Packit |
bc1512 |
gint indent,
|
|
Packit |
bc1512 |
GeglNode *head)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/*ind; g_string_append (ss->buf, "<stack>\n");
|
|
Packit |
bc1512 |
indent+=2;*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (GEGL_IS_NODE (head))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglNode *iter = head;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (iter)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglPad *input, *aux;
|
|
Packit |
bc1512 |
const gchar *id = NULL;
|
|
Packit |
bc1512 |
gchar *class;
|
|
Packit |
bc1512 |
gegl_node_get (iter, "operation", &class, NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
input = gegl_node_get_pad (iter, "input");
|
|
Packit |
bc1512 |
aux = gegl_node_get_pad (iter, "aux");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (gegl_node_get_num_sinks (iter) > 1)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const gchar *new_id = g_hash_table_lookup (ss->clones, iter);
|
|
Packit |
bc1512 |
if (new_id)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
g_string_append (ss->buf, new_id);
|
|
Packit |
bc1512 |
g_string_append (ss->buf, "'/>\n");
|
|
Packit |
bc1512 |
return; /* terminate the stack, the cloned part is already
|
|
Packit |
bc1512 |
serialized */
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar temp_id[64];
|
|
Packit |
bc1512 |
g_snprintf (temp_id, sizeof (temp_id),
|
|
Packit |
bc1512 |
"clone%i", ss->clone_count++);
|
|
Packit |
bc1512 |
id = g_strdup (temp_id);
|
|
Packit |
bc1512 |
g_hash_table_insert (ss->clones, iter, (gchar *) id);
|
|
Packit |
bc1512 |
/* the allocation is freed by the hash table */
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (class)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (!strcmp (class, "layer"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
serialize_layer (ss, indent, iter);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (aux &&
|
|
Packit |
bc1512 |
gegl_pad_get_connected_to (aux))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglPad *source_pad;
|
|
Packit |
bc1512 |
GeglNode *source_node;
|
|
Packit |
bc1512 |
source_pad = gegl_pad_get_connected_to (aux);
|
|
Packit |
bc1512 |
source_node = gegl_pad_get_node (source_pad);
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglNode *graph = g_object_get_data (G_OBJECT (source_node),
|
|
Packit |
bc1512 |
"graph");
|
|
Packit |
bc1512 |
if (graph)
|
|
Packit |
bc1512 |
source_node = graph;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *class;
|
|
Packit |
bc1512 |
gchar *name;
|
|
Packit |
bc1512 |
gegl_node_get (iter, "operation", &class,
|
|
Packit |
bc1512 |
"name", &name,
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
if (name[0])
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_attr (ss->buf, "name", name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
xml_attr (ss->buf, "operation", class);
|
|
Packit |
bc1512 |
if (id != NULL)
|
|
Packit |
bc1512 |
xml_attr (ss->buf, "id", id);
|
|
Packit |
bc1512 |
g_free (name);
|
|
Packit |
bc1512 |
g_free (class);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_string_append (ss->buf, ">\n");
|
|
Packit |
bc1512 |
serialize_properties (ss, indent + 4, iter);
|
|
Packit |
bc1512 |
add_stack (ss, indent + 4, source_node);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "</node>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (strcmp (class, "gegl:nop") &&
|
|
Packit |
bc1512 |
strcmp (class, "gegl:clone"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gchar *class;
|
|
Packit |
bc1512 |
gchar *name;
|
|
Packit |
bc1512 |
gegl_node_get (iter, "operation", &class,
|
|
Packit |
bc1512 |
"name", &name,
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
if (name[0])
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
xml_attr (ss->buf, "name", name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
xml_attr (ss->buf, "operation", class);
|
|
Packit |
bc1512 |
if (id != NULL)
|
|
Packit |
bc1512 |
xml_attr (ss->buf, "id", id);
|
|
Packit |
bc1512 |
g_free (name);
|
|
Packit |
bc1512 |
g_free (class);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_string_append (ss->buf, ">\n");
|
|
Packit |
bc1512 |
serialize_properties (ss, indent + 4, iter);
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "</node>\n");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
id = NULL;
|
|
Packit |
bc1512 |
if (input)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglPad *source_pad;
|
|
Packit |
bc1512 |
source_pad = gegl_pad_get_connected_to (input);
|
|
Packit |
bc1512 |
if (source_pad)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglNode *source_node = gegl_pad_get_node (source_pad);
|
|
Packit |
bc1512 |
GeglNode *graph = g_object_get_data (G_OBJECT (source_node),
|
|
Packit |
bc1512 |
"graph");
|
|
Packit |
bc1512 |
if (graph)
|
|
Packit |
bc1512 |
source_node = graph;
|
|
Packit |
bc1512 |
iter = source_node;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
iter = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
iter = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (class);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
/*indent-=2;
|
|
Packit |
bc1512 |
ind; g_string_append (ss->buf, "<stack>\n");*/
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gchar *
|
|
Packit |
bc1512 |
gegl_node_to_xml (GeglNode *gegl,
|
|
Packit |
bc1512 |
const gchar *path_root)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
SerializeState ss;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
ss.buf = g_string_new ("");
|
|
Packit |
bc1512 |
ss.path_root = path_root;
|
|
Packit |
bc1512 |
ss.clone_count = 0;
|
|
Packit |
bc1512 |
ss.clones = g_hash_table_new (NULL, NULL);
|
|
Packit |
bc1512 |
ss.terse = FALSE;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl = gegl_node_get_output_proxy (gegl, "output");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_string_append (ss.buf, "\n");
|
|
Packit |
bc1512 |
g_string_append (ss.buf, "<gegl>\n");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
add_stack (&ss, 2, gegl);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_string_append (ss.buf, "</gegl>\n");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_hash_table_foreach (ss.clones, free_clone_id, NULL);
|
|
Packit |
bc1512 |
g_hash_table_destroy (ss.clones);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return g_string_free (ss.buf, FALSE);
|
|
Packit |
bc1512 |
}
|