[dia] svg: layer import/export via named groups <g id="LayerName"></g>
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] svg: layer import/export via named groups <g id="LayerName"></g>
- Date: Wed, 3 Oct 2012 20:02:00 +0000 (UTC)
commit 647ce815ced916b0b35ad7a3f7618e32783ea0dd
Author: Hans Breuer <hans breuer org>
Date: Sat Sep 29 20:24:27 2012 +0200
svg: layer import/export via named groups <g id="LayerName"></g>
Export: overwriting DiaRenderer::draw_layer() to wrap every layer's
objects into their own named group. This seems to be the common way to
transport layer information via SVG.
Import: Every top level item which is a group with a name/id we are converting
back to a layer. This is consistent with our SVG export and does
also work with layers from Sodipodi/Inkscape/iDraw/...
plug-ins/svg/render_svg.c | 35 +++++++++++++++++++++++++++++++++++
plug-ins/svg/svg-import.c | 35 ++++++++++++++++++++++++++++++++---
2 files changed, 67 insertions(+), 3 deletions(-)
---
diff --git a/plug-ins/svg/render_svg.c b/plug-ins/svg/render_svg.c
index 029a0ad..fc25afd 100644
--- a/plug-ins/svg/render_svg.c
+++ b/plug-ins/svg/render_svg.c
@@ -83,6 +83,10 @@ GType svg_renderer_get_type (void) G_GNUC_CONST;
static DiaSvgRenderer *new_svg_renderer(DiagramData *data, const char *filename);
+static void draw_layer (DiaRenderer *self,
+ Layer *layer,
+ gboolean active,
+ Rectangle *update);
static void draw_object (DiaRenderer *renderer,
DiaObject *object,
DiaMatrix *matrix);
@@ -201,6 +205,7 @@ svg_renderer_class_init (SvgRendererClass *klass)
renderer_class->begin_render = begin_render;
renderer_class->end_render = end_render;
+ renderer_class->draw_layer = draw_layer;
renderer_class->draw_object = draw_object;
renderer_class->draw_rounded_rect = draw_rounded_rect;
renderer_class->fill_rounded_rect = fill_rounded_rect;
@@ -271,6 +276,36 @@ new_svg_renderer(DiagramData *data, const char *filename)
}
/*!
+ * \brief Wrap every layer into it's own group
+ * This method intercepts DiaRenderer::draw_layer() to wrap every layer's
+ * object into their own named group. This seems to be the common way to
+ * transport layer information via SVG.
+ * \memberof SvgRenderer
+ */
+static void
+draw_layer (DiaRenderer *self,
+ Layer *layer,
+ gboolean active,
+ Rectangle *update)
+{
+ DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self);
+ SvgRenderer *svg_renderer = SVG_RENDERER (self);
+ xmlNodePtr layer_group;
+
+ g_queue_push_tail (svg_renderer->parents, renderer->root);
+
+ /* modifying the root pointer so everything below us gets into the new node */
+ renderer->root = layer_group = xmlNewNode (renderer->svg_name_space, (const xmlChar *)"g");
+
+ if (layer->name)
+ xmlSetProp(renderer->root, (const xmlChar *)"id", (xmlChar *) layer->name);
+
+ DIA_RENDERER_CLASS (parent_class)->draw_layer (self, layer, active, update);
+
+ renderer->root = g_queue_pop_tail (svg_renderer->parents);
+ xmlAddChild (renderer->root, layer_group);
+}
+/*!
* \brief Wrap every object in \<g\>\</g\> and apply transformation
*
* We could try to be smart and count the objects we using for the object.
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 405c942..e6e1753 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -945,6 +945,10 @@ read_items (xmlNodePtr startnode,
for (node = startnode; node != NULL; node = node->next) {
+ /* Points to the *first* object created by this node (used to be the last one).
+ * Dia may split a single SVG element into multiple DiaObjects. If so these objects
+ * should be grouped or at least inherit all the same node properties
+ */
DiaObject *obj = NULL;
if (xmlIsBlankNode(node)) continue;
@@ -1022,9 +1026,11 @@ read_items (xmlNodePtr startnode,
if (items)
obj = g_list_last(items)->data;
} else if(!xmlStrcmp(node->name, (const xmlChar *)"path")) {
+ /* the path element might be split into multiple objects */
+ int first = g_list_length (items);
items = read_path_svg(node, parent_gs, items, ctx);
- if (items)
- obj = g_list_last(items)->data;
+ if (items && g_list_nth(items, first))
+ obj = g_list_nth(items, first)->data;
} else if(!xmlStrcmp(node->name, (const xmlChar *)"image")) {
items = read_image_svg(node, parent_gs, items, filename_svg);
if (items)
@@ -1096,6 +1102,7 @@ read_items (xmlNodePtr startnode,
dia_object_set_meta (sub, "url", (char *)href);
}
}
+ obj = moreitems->data;
items = g_list_concat (items, moreitems);
}
if (href)
@@ -1210,10 +1217,32 @@ import_svg(const gchar *filename, DiagramData *dia, DiaContext *ctx, void* user_
items = read_items (root->xmlChildrenNode, NULL, defs_ht, filename, ctx);
g_hash_table_destroy (defs_ht);
}
+ /* Every top level item which is a group with a name/id we are converting
+ * back to a layer. This is consistent with our SVG export and does
+ * also work with layers from Sodipodi/Inkscape/iDraw/...
+ */
for (item = items; item != NULL; item = g_list_next (item)) {
DiaObject *obj = (DiaObject *)item->data;
- layer_add_object(dia->active_layer, obj);
+ gchar *name = NULL;
+
+ if (IS_GROUP(obj) && ((name = dia_object_get_meta (obj, "id")) != NULL)) {
+ DiaObject *group = (DiaObject *)item->data;
+ /* new_layer() is taking ownership of the name */
+ Layer *layer = new_layer (g_strdup (name), dia);
+
+ /* layer_add_objects() is taking ownership of the list */
+ layer_add_objects (layer, g_list_copy (group_objects (group)));
+ data_add_layer (dia, layer);
+ group_destroy_shallow (group);
+ g_free (name);
+ } else {
+ /* Just as before: throw it in the active layer */
+ DiaObject *obj = (DiaObject *)item->data;
+ layer_add_object(dia->active_layer, obj);
+ }
+
}
+
g_list_free (items);
xmlFreeDoc(doc);
/* set 'display' setting */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]