[dia] svg: initial support for CSS style for svg-import



commit 9705ca3046e3ebad7d556cfd90d2d6a5ccab7289
Author: Hans Breuer <hans breuer org>
Date:   Sat Aug 3 18:07:29 2013 +0200

    svg: initial support for CSS style for svg-import
    
    The style is a applied to all the basic objects as before, but now
    it can come from a style block, with keys tag.class#id and all
    variations. CSS styled files will now be much closer to the intent
    after loading, but CSS styling is also quite expensive for two reasons:
     - we have to try all the variations of tag.class#id to find if
       there actually is some style (unavoidable)
     - we parse a referenced over and over again (because that was the
       easiest way to get it working)
    See comment on _css_parse_style for major things missing.

 lib/dia_svg.c             |    4 +-
 lib/dia_svg.h             |    3 +-
 plug-ins/svg/svg-import.c |  234 +++++++++++++++++++++++++++++++++++++--------
 3 files changed, 199 insertions(+), 42 deletions(-)
---
diff --git a/lib/dia_svg.c b/lib/dia_svg.c
index f99f42e..5104189 100644
--- a/lib/dia_svg.c
+++ b/lib/dia_svg.c
@@ -53,7 +53,7 @@ void
 dia_svg_style_init(DiaSvgStyle *gs, DiaSvgStyle *parent_style)
 {
   g_return_if_fail (gs);
-  gs->stroke = parent_style ? parent_style->stroke : DIA_SVG_COLOUR_NONE;
+  gs->stroke = parent_style ? parent_style->stroke : DIA_SVG_COLOUR_DEFAULT;
   gs->stroke_opacity = parent_style ? parent_style->stroke_opacity : 1.0;
   gs->line_width = parent_style ? parent_style->line_width : 0.0;
   gs->linestyle = parent_style ? parent_style->linestyle : LINESTYLE_SOLID;
@@ -61,7 +61,7 @@ dia_svg_style_init(DiaSvgStyle *gs, DiaSvgStyle *parent_style)
   /* http://www.w3.org/TR/SVG/painting.html#FillProperty - default black
    * but we still have to see the difference
    */ 
-  gs->fill = parent_style ? parent_style->fill : DIA_SVG_COLOUR_DEFAULT_FILL;
+  gs->fill = parent_style ? parent_style->fill : DIA_SVG_COLOUR_DEFAULT;
   gs->fill_opacity = parent_style ? parent_style->fill_opacity : 1.0;
   gs->linecap = parent_style ? parent_style->linecap : DIA_SVG_LINECAPS_DEFAULT;
   gs->linejoin = parent_style ? parent_style->linejoin : DIA_SVG_LINEJOIN_DEFAULT;
diff --git a/lib/dia_svg.h b/lib/dia_svg.h
index 05a9a47..be53176 100644
--- a/lib/dia_svg.h
+++ b/lib/dia_svg.h
@@ -29,7 +29,8 @@ enum DiaSvgColours
   DIA_SVG_COLOUR_FOREGROUND = -2,
   DIA_SVG_COLOUR_BACKGROUND = -3,
   DIA_SVG_COLOUR_TEXT = -4,
-  DIA_SVG_COLOUR_DEFAULT_FILL = -5
+  /* used for initlaization only */
+  DIA_SVG_COLOUR_DEFAULT = -5
 };
 
 /* these should be changed if they ever cause a conflict */
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index ea03bc0..de83bce 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -50,12 +50,6 @@
 #include "attributes.h"
 
 static gboolean import_svg (xmlDocPtr doc, DiagramData *dia, DiaContext *ctx, void* user_data);
-static GList *read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list);
-static GList *read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list);
-static GList *read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list);
-static GList *read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, char *object_type);
-static GList *read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list);
-static GList *read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, DiaContext *ctx);
 static GPtrArray *make_element_props(real xpos, real ypos, real width, real height);
 
 /* TODO: use existing implementation in dia source */
@@ -282,9 +276,80 @@ use_position (DiaObject *obj, xmlNodePtr node)
     }
 }
 
+/*!
+ * \brief Lookup and apply CSS style
+ *
+ * This is a slow initial version of CSS support. It parse the style
+ * string for every use rather than for every definition. A better/faster
+ * variant might be to parse the style on definition time into a list
+ * of stdprops which simply could be applied in the right order on use.
+ *
+ * Also missing support for:
+ *  - class lists (which would make it even slower)
+ *  - referenced style definitions (e.g. url())
+ *  - fill-rule, overflow, clip, ....
+ *
+ * \ingroup DiaSvg
+ */
+static void
+_css_parse_style (DiaSvgStyle *s, real user_scale,
+                 gchar *tag, gchar *klass, gchar *id,
+                 GHashTable *style_ht)
+{
+  gchar *style = NULL;
+
+  /* always try and apply '*' */
+  style = g_hash_table_lookup (style_ht, "*");
+  if (style) {
+    dia_svg_parse_style_string (s, user_scale, style);
+    style = NULL;
+  }
+
+  /* build the key in order of importance */
+  /* tag.class#id */
+  if (id && klass) {
+    gchar *key = g_strdup_printf ("%s.%s#%s", tag, klass, id);
+
+    style = g_hash_table_lookup (style_ht, key);
+    g_free (key);
+    if (!style) {
+      /* class#id */
+      key = g_strdup_printf (".%s#%s", klass, id);
+      style = g_hash_table_lookup (style_ht, key);
+      g_free (key);
+    }
+  } 
+  if (!style && klass) {
+    gchar *key = g_strdup_printf (".%s", klass);
+    style = g_hash_table_lookup (style_ht, key);
+    g_free (key);
+  }
+  /* apply most specific style from class lookup */
+  if (style) {
+    dia_svg_parse_style_string (s, user_scale, style);
+    style = NULL;
+  }
+
+  /* apply style from id */
+  if (id) {
+    gchar *key = g_strdup_printf ("#%s", id);
+    style = g_hash_table_lookup (style_ht, key);
+    if (style) {
+      dia_svg_parse_style_string (s, user_scale, style);
+    }
+    g_free (key);
+    key = g_strdup_printf ("%s#%s", tag, id);
+    style = g_hash_table_lookup (style_ht, key);
+    if (style) {
+      dia_svg_parse_style_string (s, user_scale, style);
+    }
+  }
+}
+
 /* apply SVG style to object */
 static void
-apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style, gboolean init_fill)
+apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style,
+           GHashTable *style_ht, gboolean init)
 {
       DiaSvgStyle *gs;
       GPtrArray *props;
@@ -307,12 +372,30 @@ apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style, gboolean
       /* SVG defaults */
       dia_svg_style_init (gs, parent_style);
             
+      if (g_hash_table_size (style_ht) > 0) {
+       /* only do all these expensive variants if we have some style at all */
+       xmlChar *id = xmlGetProp (node, (xmlChar *)"id");
+       xmlChar *klass = xmlGetProp (node, (xmlChar *)"class");
+
+       _css_parse_style (gs, user_scale, (gchar *)node->name, (gchar *)klass, (gchar *)id, style_ht);
+
+       if (id)
+         xmlFree (id);
+       if (klass)
+         xmlFree (klass);
+      }
+
       dia_svg_parse_style(node, gs, user_scale);
       props = prop_list_from_descs(svg_style_prop_descs, pdtpp_true);
       g_assert(props->len == 5);
   
       cprop = g_ptr_array_index(props,0);
-      if(gs->stroke == DIA_SVG_COLOUR_NONE) /* transparent */
+      if (gs->stroke == DIA_SVG_COLOUR_DEFAULT) {
+        if (init) /* no stroke */
+         cprop->color_data = get_colour(0xFFFFFF, 0.0);
+       else /* leave it alone */
+         cprop->common.experience |= PXP_NOTSET; /* no overwrite */
+      } else if (gs->stroke == DIA_SVG_COLOUR_NONE) /* transparent */
        cprop->color_data = get_colour(0xFFFFFF, 0.0);
       else if (gs->stroke == DIA_SVG_COLOUR_FOREGROUND)
        cprop->color_data = attributes_get_foreground();
@@ -325,12 +408,17 @@ apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style, gboolean
       rprop->real_data = gs->line_width * scale;
   
       lsprop = g_ptr_array_index(props,2);
-      lsprop->style = gs->linestyle != DIA_SVG_LINESTYLE_DEFAULT ? gs->linestyle : LINESTYLE_SOLID;
+      if (gs->linestyle != DIA_SVG_LINESTYLE_DEFAULT)
+       lsprop->style = gs->linestyle;
+      else if (init)
+       lsprop->style = LINESTYLE_SOLID;
+      else
+       lsprop->common.experience |= PXP_NOTSET; /* no overwrite */
       lsprop->dash = gs->dashlength * scale;
 
       cprop = g_ptr_array_index(props,3);
-      if (gs->fill == DIA_SVG_COLOUR_DEFAULT_FILL) {
-       if (init_fill)
+      if (gs->fill == DIA_SVG_COLOUR_DEFAULT) {
+       if (init)
          cprop->color_data = get_colour(0x000000, gs->fill_opacity); /* black */
        else
          cprop->common.experience |= PXP_NOTSET; /* no overwrite */
@@ -362,7 +450,8 @@ apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style, gboolean
  */
 /* read a path */
 static GList *
-read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, DiaContext *ctx)
+read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
+             GList *list, DiaContext *ctx)
 {
     DiaObjectType *otype;
     DiaObject *new_obj;
@@ -401,7 +490,7 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, DiaContex
        dia_svg_parse_style(node, gs, user_scale);
        if (gs->font)
           dia_font_unref (gs->font);
-       closed = (gs->fill != DIA_SVG_COLOUR_NONE && gs->fill != DIA_SVG_COLOUR_DEFAULT_FILL);
+       closed = (gs->fill != DIA_SVG_COLOUR_NONE && gs->fill != DIA_SVG_COLOUR_DEFAULT);
        /* if we close it here add an explicit line-to */
        if (closed) {
          bp.type = BEZ_LINE_TO;
@@ -456,7 +545,7 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, DiaContex
        if (!closed)
          reset_arrows (new_obj);
        g_free(bcd);
-       apply_style(new_obj, node, parent_style, TRUE);
+       apply_style(new_obj, node, parent_style, style_ht, TRUE);
        list = g_list_append (list, new_obj);
 
         g_array_set_size (bezpoints, 0);
@@ -477,7 +566,7 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, DiaContex
 
 /* read a text */
 static GList *
-read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list) 
+read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht, GList *list) 
 {
     DiaObjectType *otype = object_get_type("Standard - Text");
     DiaObject *new_obj;
@@ -516,6 +605,20 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
       xmlFree(str);
     }
 
+    /* text propety handling is special, don't use apply_style() */
+    if (g_hash_table_size (style_ht) > 0) {
+      /* only do all these expensive variants if we have some style at all */
+      xmlChar *id = xmlGetProp (node, (xmlChar *)"id");
+      xmlChar *klass = xmlGetProp (node, (xmlChar *)"class");
+
+      _css_parse_style (gs, user_scale, (gchar *)node->name, (gchar *)klass, (gchar *)id, style_ht);
+
+      if (id)
+       xmlFree (id);
+      if (klass)
+       xmlFree (klass);
+    }
+
     /* font-size can be given in the style (with absolute unit) or
      * with it's own attribute. The latter is preferred - also by
      * Dia's own export.
@@ -603,7 +706,7 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
       case DIA_SVG_COLOUR_BACKGROUND :
         prop->attr.color = attributes_get_foreground();
        break;
-      case DIA_SVG_COLOUR_DEFAULT_FILL: /* black */
+      case DIA_SVG_COLOUR_DEFAULT: /* black */
        prop->attr.color = get_colour(0x000000, gs->fill_opacity);
        break;
       case DIA_SVG_COLOUR_FOREGROUND :
@@ -625,7 +728,8 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
 
 /* read a polygon or a polyline */
 static GList *
-read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, char *object_type) 
+read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
+             GList *list, char *object_type) 
 {
     DiaObjectType *otype = object_get_type(object_type);
     DiaObject *new_obj;
@@ -678,7 +782,7 @@ read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, char *obj
     new_obj = otype->ops->create(NULL, pcd,
                                 &h1, &h2);
     reset_arrows (new_obj);
-    apply_style(new_obj, node, parent_style, TRUE);
+    apply_style(new_obj, node, parent_style, style_ht, TRUE);
     list = g_list_append (list, new_obj);
     g_free(points);
     g_free(pcd);
@@ -688,7 +792,8 @@ read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, char *obj
 
 /* read an ellipse or circle */
 static GList *
-read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list) 
+read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
+                GHashTable *style_ht, GList *list) 
 {
   xmlChar *str;
   real width = 0.0, height = 0.0;
@@ -745,7 +850,7 @@ read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
     return list;
   new_obj = otype->ops->create(&start, otype->default_user_data,
                                 &h1, &h2);
-  apply_style(new_obj, node, parent_style, TRUE);
+  apply_style(new_obj, node, parent_style, style_ht, TRUE);
 
   props = make_element_props(start.x-(width/2), start.y-(height/2),
                              width, height);
@@ -756,7 +861,8 @@ read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
 
 /* read a line */
 static GList *
-read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list) 
+read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
+             GHashTable *style_ht, GList *list) 
 {
   xmlChar *str;
   DiaObjectType *otype = object_get_type("Standard - Line");
@@ -821,14 +927,15 @@ read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
 
   prop_list_free(props);
 
-  apply_style(new_obj, node, parent_style, TRUE);
+  apply_style(new_obj, node, parent_style, style_ht, TRUE);
 
   return g_list_append (list, new_obj);
 }
 
 /* read a rectangle */
 static GList *
-read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list) 
+read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
+             GHashTable *style_ht, GList *list) 
 {
   xmlChar *str;
   real width = 0.0, height = 0.0;
@@ -920,14 +1027,15 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
   props = make_element_props(start.x,start.y,width,height);
   new_obj->ops->set_props(new_obj, props);
 
-  apply_style(new_obj, node, parent_style, TRUE);
+  apply_style(new_obj, node, parent_style, style_ht, TRUE);
   prop_list_free(props);
 
   return list;
 }
 
 static GList *
-read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, const gchar *filename_svg)
+read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
+              GList *list, const gchar *filename_svg)
 {
   xmlChar *str;
   real x = 0, y = 0, width = 0, height = 0;
@@ -1022,6 +1130,42 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, const gc
   return list;
 }
 
+
+/*!
+ * \brief Parse the CSS style block of the SVG
+ *
+ * 
+ * @node : containing the style
+ * @ht: hash table with style key and style string
+ */
+static void
+read_style (xmlNodePtr node, GHashTable *ht)
+{
+
+  xmlChar *style_type = xmlGetProp (node, (const xmlChar *)"type");
+
+  if (!style_type || xmlStrcmp(style_type, (const xmlChar*)"text/css") == 0) {
+    xmlChar *str = xmlNodeGetContent(node);
+    GRegex *regex = g_regex_new ("\\s*([^\\s+{]+)\\s*{([^}]*)}", G_REGEX_MULTILINE, 0, NULL);
+    GMatchInfo *info;
+
+    g_regex_match (regex, (gchar *)str, 0, &info);
+    while (g_match_info_matches (info)) {
+      /* */
+      gchar *key = g_match_info_fetch (info, 1);
+      gchar *val = g_match_info_fetch (info, 2);
+
+      g_hash_table_insert (ht, key, val);
+      g_match_info_next (info, NULL);
+    }
+    g_match_info_free (info);
+    g_regex_unref (regex);
+
+  }
+  if (style_type)
+    xmlFree (style_type);
+}
+
 /* GFunc for foreach */
 static void
 add_def (gpointer       data,
@@ -1054,6 +1198,7 @@ static GList*
 read_items (xmlNodePtr   startnode, 
            DiaSvgStyle *parent_gs,
            GHashTable  *defs_ht,
+           GHashTable  *style_ht,
            const gchar *filename_svg,
            DiaContext  *ctx)
 {
@@ -1099,7 +1244,7 @@ read_items (xmlNodePtr   startnode,
        xmlFree (trans);
       }
 
-      moreitems = read_items (node->xmlChildrenNode, group_gs, defs_ht, filename_svg, ctx);
+      moreitems = read_items (node->xmlChildrenNode, group_gs, defs_ht, style_ht, filename_svg, ctx);
 
       if (moreitems) {
         DiaObject *group;
@@ -1120,7 +1265,7 @@ read_items (xmlNodePtr   startnode,
       g_free (matrix);
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"symbol")) {
       /* ignore 'viewBox' and 'preserveAspectRatio' */
-      GList *moreitems = read_items (node->xmlChildrenNode, parent_gs, defs_ht, filename_svg, ctx);
+      GList *moreitems = read_items (node->xmlChildrenNode, parent_gs, defs_ht, style_ht, filename_svg, ctx);
 
       /* only one object or create a group */
       if (g_list_length (moreitems) > 1)
@@ -1128,44 +1273,45 @@ read_items (xmlNodePtr   startnode,
       else if (moreitems)
        obj = g_list_last(moreitems)->data;
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"rect")) {
-      items = read_rect_svg(node, parent_gs, items);
+      items = read_rect_svg(node, parent_gs, style_ht, items);
       if (items)
        obj = g_list_last(items)->data;
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"line")) {
-      items = read_line_svg(node, parent_gs, items);
+      items = read_line_svg(node, parent_gs, style_ht, items);
       if (items)
        obj = g_list_last(items)->data;
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"ellipse") || !xmlStrcmp(node->name, (const xmlChar 
*)"circle")) {
-      items = read_ellipse_svg(node, parent_gs, items);
+      items = read_ellipse_svg(node, parent_gs, style_ht, items);
       if (items)
        obj = g_list_last(items)->data;
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"polyline")) {
       /* Uh, oh, no : apparently a fill="" in a group above make this a polygon */
-      items = read_poly_svg(node, parent_gs, items, parent_gs && parent_gs->fill >= 0 ?
+      items = read_poly_svg(node, parent_gs, style_ht, items,
+                           parent_gs && parent_gs->fill >= 0 ?
                             "Standard - Polygon" : "Standard - PolyLine");
       if (items)
        obj = g_list_last(items)->data;
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"polygon")) {
-      items = read_poly_svg(node, parent_gs, items, "Standard - Polygon");
+      items = read_poly_svg(node, parent_gs, style_ht, items, "Standard - Polygon");
       if (items)
        obj = g_list_last(items)->data;
     } else if(!xmlStrcmp(node->name, (const xmlChar *)"text")) {
-      items = read_text_svg(node, parent_gs, items);
+      items = read_text_svg(node, parent_gs, style_ht, items);
       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);
+      items = read_path_svg(node, parent_gs, style_ht, items, ctx);
       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);
+      items = read_image_svg(node, parent_gs, style_ht, items, filename_svg);
       if (items)
        obj = g_list_last(items)->data;
     } else if(!xmlStrcmp(node->name, (const xmlChar *)"defs")) {
       /* everything below must have a name to make a difference */
-      GList *list, *defs = read_items (node->xmlChildrenNode, parent_gs, defs_ht, filename_svg, ctx);
+      GList *list, *defs = read_items (node->xmlChildrenNode, parent_gs, defs_ht, style_ht, filename_svg, 
ctx);
 
       /* Commonly seen in <defs/> are
        *   clipPath, font, filter, linearGradient, mask, marker, pattern, radialGradient, style
@@ -1210,11 +1356,18 @@ read_items (xmlNodePtr   startnode,
          obj = otemp->ops->copy (otemp);
 
          use_position (obj, node);
-         apply_style (obj, node, parent_gs, FALSE);
+         apply_style (obj, node, parent_gs, style_ht, FALSE);
          items = g_list_append (items, obj);
        }
        xmlFree (key);
       }
+    } else if(!xmlStrcmp(node->name, (const xmlChar *)"style")) {
+      /* Prepare the third variant to apply style to the objects.
+       * The final style is similar to what we have in the style
+       * attribute, but we have to do complicated key lookup to
+       * apply styles to the right objects.
+       */
+      read_style (node, style_ht);
     } else if(!xmlStrcmp(node->name, (const xmlChar *)"pattern")) {
       /* Patterns could be considered as groups, too But Dia does not
        * have the facility to apply them (yet?). */
@@ -1227,7 +1380,7 @@ read_items (xmlNodePtr   startnode,
       /* one of the non-grouping elements is <a>, extract possible links */
       xmlChar *href = xmlGetProp (node, (const xmlChar *)"href");
 
-      moreitems = read_items (node->xmlChildrenNode, parent_gs, defs_ht, filename_svg, ctx);
+      moreitems = read_items (node->xmlChildrenNode, parent_gs, defs_ht, style_ht, filename_svg, ctx);
       if (moreitems) {
        if (href) {
          GList *subs;
@@ -1469,7 +1622,10 @@ import_svg (xmlDocPtr doc, DiagramData *dia,
 
   {
     GHashTable *defs_ht = g_hash_table_new (g_str_hash, g_str_equal);
-    items = read_items (root->xmlChildrenNode, NULL, defs_ht, dia_context_get_filename(ctx), ctx);
+    GHashTable *style_ht = g_hash_table_new (g_str_hash, g_str_equal);
+    items = read_items (root->xmlChildrenNode, NULL, defs_ht, style_ht,
+                       dia_context_get_filename(ctx), ctx);
+    g_hash_table_destroy (style_ht);
     g_hash_table_destroy (defs_ht);
   }
   /* Every top level item which is a group with a name/id we are converting


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