[dia] svg: parse font-* and text-* also as attributes



commit e785c0a1dd6684a6f9f02409fa2f4a307f32d847
Author: Hans Breuer <hans breuer org>
Date:   Sun Aug 4 11:25:10 2013 +0200

    svg: parse font-* and text-* also as attributes
    
    Small code restructuring to support more attributes with
    only small code duplication. Related changes to the order
    of <text/> vs. <tspan/> style parsing and some more matrix
    usage when interpreting <text/>.

 lib/dia_svg.c             |  134 +++++++++++++++++++++++++++-----------------
 plug-ins/svg/svg-import.c |   19 ++++---
 2 files changed, 93 insertions(+), 60 deletions(-)
---
diff --git a/lib/dia_svg.c b/lib/dia_svg.c
index 5c3df71..2cab789 100644
--- a/lib/dia_svg.c
+++ b/lib/dia_svg.c
@@ -333,7 +333,66 @@ _parse_linecap (DiaSvgStyle *s, const char *val)
     s->linecap = DIA_SVG_LINECAPS_DEFAULT;
 }
 
-/*
+/*!
+ * \brief Given any of the three parameters adjust the font
+ * @param s      Dia SVG style to modify
+ * @param family comma-separated list of family names
+ * @param style  font slant string
+ * @param weight font weight string
+ */
+static void
+_style_adjust_font (DiaSvgStyle *s, const char *family, const char *style, const char *weight)
+{
+    if (s->font)
+      dia_font_unref (s->font);
+    /* given font_height is bogus, especially if not given at all
+     * or without unit ... see bug 665648 about invalid CSS
+     */
+    s->font = dia_font_new_from_style(DIA_FONT_SANS, s->font_height > 0 ? s->font_height : 1.0);
+    if (family) {
+      /* SVG allows a list of families here, also there is some stange formatting 
+       * seen, like 'Arial'. If the given family name can not be resolved by 
+       * Pango it complaints loudly with g_warning().
+       */
+      gchar **families = g_strsplit(family, ",", -1);
+      int i = 0;
+      gboolean found = FALSE;
+      while (!found && families[i]) {
+       const gchar *chomped = g_strchomp (g_strdelimit(families[i], "'", ' '));
+       PangoFont *loaded;
+        dia_font_set_any_family(s->font, chomped);
+       loaded = pango_context_load_font(dia_font_get_context(),
+                                        dia_font_get_description(s->font));
+       if (loaded) {
+         g_object_unref(loaded);
+         found = TRUE;
+       }
+       ++i;
+      }
+      if (!found)
+       dia_font_set_any_family(s->font, "sans");
+      g_strfreev(families);
+    }
+    if (style) {
+      dia_font_set_slant_from_string(s->font,style);
+    }
+    if (weight) {
+      dia_font_set_weight_from_string(s->font,weight);
+    }
+}
+
+static void
+_parse_text_align(DiaSvgStyle *s, const gchar *ptr)
+{
+  if (!strncmp(ptr, "start", 5))
+    s->alignment = ALIGN_LEFT;
+  else if (!strncmp(ptr, "end", 3))
+    s->alignment = ALIGN_RIGHT;
+  else if (!strncmp(ptr, "middle", 6))
+    s->alignment = ALIGN_CENTER;
+}
+
+/*!
  * \brief Parse SVG/CSS style string
  *
  * Parse as much information from the given style string as Dia can handle.
@@ -426,13 +485,8 @@ dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str)
     } else if (!strncmp("text-anchor:", ptr, 12)) {
       ptr += 12;
       while ((ptr[0] != '\0') && g_ascii_isspace(ptr[0])) ptr++;
-      if (!strncmp(ptr, "start", 5))
-       s->alignment = ALIGN_LEFT;
-      else if (!strncmp(ptr, "end", 3))
-       s->alignment = ALIGN_RIGHT;
-      else if (!strncmp(ptr, "middle", 6))
-       s->alignment = ALIGN_CENTER;
 
+      _parse_text_align(s, ptr);
     } else if (!strncmp("stroke-width:", ptr, 13)) {
       ptr += 13;
       s->line_width = g_ascii_strtod(ptr, &ptr);
@@ -525,45 +579,11 @@ dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str)
   }
 
   if (family || style || weight) {
-    if (s->font)
-      dia_font_unref (s->font);
-    /* given font_height is bogus, especially if not given at all
-     * or without unit ... see bug 665648 about invalid CSS
-     */
-    s->font = dia_font_new_from_style(DIA_FONT_SANS, s->font_height > 0 ? s->font_height : 1.0);
-    if (family) {
-      /* SVG allows a list of families here, also there is some stange formatting 
-       * seen, like 'Arial'. If the given family name can not be resolved by 
-       * Pango it complaints loudly with g_warning().
-       */
-      gchar **families = g_strsplit(family, ",", -1);
-      int i = 0;
-      gboolean found = FALSE;
-      while (!found && families[i]) {
-       const gchar *chomped = g_strchomp (g_strdelimit(families[i], "'", ' '));
-       PangoFont *loaded;
-        dia_font_set_any_family(s->font, chomped);
-       loaded = pango_context_load_font(dia_font_get_context(),
-                                        dia_font_get_description(s->font));
-       if (loaded) {
-         g_object_unref(loaded);
-         found = TRUE;
-       }
-       ++i;
-      }
-      if (!found)
-       dia_font_set_any_family(s->font, "sans");
-      g_strfreev(families);
-      g_free(family);
-    }
-    if (style) {
-      dia_font_set_slant_from_string(s->font,style);
-      g_free(style);
-    }
-    if (weight) {
-      dia_font_set_weight_from_string(s->font,weight);
-      g_free(weight);
-    }
+    _style_adjust_font (s, family, style, weight);
+
+    g_free(family);
+    g_free(style);
+    g_free(weight);
   }
 }
 
@@ -661,14 +681,24 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
   }
   str = xmlGetProp(node, (const xmlChar *)"text-anchor");
   if (str) {
-    if (xmlStrcmp(str, (const xmlChar*)"middle") == 0)
-      s->alignment = ALIGN_CENTER;
-    else if (xmlStrcmp(str, (const xmlChar*)"end") == 0)
-      s->alignment = ALIGN_RIGHT;
-    else if (xmlStrcmp(str, (const xmlChar*)"start") == 0)
-      s->alignment = ALIGN_LEFT;
+    _parse_text_align (s, (const gchar*)str);
     xmlFree(str);
   }
+  {
+    xmlChar *family = xmlGetProp(node, (const xmlChar *)"font-family");
+    xmlChar *slant  = xmlGetProp(node, (const xmlChar *)"font-style");
+    xmlChar *weight = xmlGetProp(node, (const xmlChar *)"font-weight");
+    if (family || slant || weight) {
+      _style_adjust_font (s, (gchar *)family, (gchar *)slant, (gchar *)weight);
+
+      if (family)
+        xmlFree(family);
+      if (slant)
+        xmlFree(slant);
+      if (weight)
+        xmlFree(weight);
+    }
+  }
 }
 
 /*!
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index ea59d8f..a64ee2f 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -651,6 +651,9 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
       xmlFree(str);
     }
 
+    /* parse from <text/> before looking at the first <tspan/> */
+    dia_svg_parse_style(node, gs, user_scale);    
+
     {
       xmlNode *tspan = node->children;
       GString *paragraph = g_string_sized_new(512);
@@ -659,8 +662,8 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
           xmlChar *line = xmlNodeGetContent(tspan);
           if (any_tspan) /* every other line needs separation */
            g_string_append(paragraph, "\n");
-         else /* only first time */
-           dia_svg_parse_style(tspan, gs, user_scale);
+         else /* only first time - with bogus, experimental division of user scale */
+           dia_svg_parse_style(tspan, gs, matrix ? user_scale / matrix->yy : user_scale);
           g_string_append(paragraph, (gchar*)line);
          xmlFree(line);
           any_tspan = TRUE;
@@ -675,11 +678,8 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
       str = xmlNodeGetContent(node);
     }
     if(str || multiline) {
-      if (matrix) {
-        /* TODO: transform the text, too - when it is supported */
+      if (matrix)
        transform_point (&point, matrix);
-       g_free (matrix);
-      }
       new_obj = otype->ops->create(&point, otype->default_user_data,
                                 &h1, &h2);
       list = g_list_append (list, new_obj);
@@ -687,7 +687,6 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
       props = prop_list_from_descs(svg_text_prop_descs, pdtpp_true);
       g_assert(props->len == 1);
 
-      dia_svg_parse_style(node, gs, user_scale);    
       if(gs->font == NULL) {
        gs->font = dia_font_new_from_legacy_name("Courier");
       }
@@ -704,7 +703,9 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
       if (font_height > 0.0) {
         /* font-size should be the line-height according to SVG spec,
         * but see node_set_text_style() - round-trip first */
-       real font_scale = dia_font_get_height (prop->attr.font) / dia_font_get_size (prop->attr.font); 
+       real font_scale = dia_font_get_height (prop->attr.font) / dia_font_get_size (prop->attr.font);
+       if (matrix) /* ToDo: more text transform */
+         font_scale /= matrix->yy;
         prop->attr.height = font_height * font_scale;
       } else
         prop->attr.height = gs->font_height;
@@ -729,10 +730,12 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
       }
       new_obj->ops->set_props(new_obj, props);
       prop_list_free(props);
+
     }
     if (gs->font)
       dia_font_unref (gs->font);
     g_free(gs);
+    g_free(matrix);
 
     return list;
 }


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