[dia] svg: activate viewBox interpretation again on import



commit 4e9c7a06758a361df2353630cd41d160563c0f39
Author: Hans Breuer <hans breuer org>
Date:   Sun Aug 25 18:48:02 2013 +0200

    svg: activate viewBox interpretation again on import
    
    Now it is also applied on non-root svg elements defining a local
    viewport. It is only used if we are _not_ importing shapes,
    restricting otherwise was a mistake when shape import was added.
    With the current shape set it was triggered very seldom , because
    there are only 14 out of >700 shapes defining width, height and
    viewBox.

 plug-ins/svg/svg-import.c |  130 ++++++++++++++++++++++++++++++++------------
 1 files changed, 94 insertions(+), 36 deletions(-)
---
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 836b460..961aa69 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -1155,6 +1155,64 @@ add_def (gpointer       data,
 }
 
 /*!
+ * \brief Parse and set global user scale
+ *
+ * This function is modifying the global user scale. If it's effect
+ * should be temporary user_scale needs to be saved before.
+ *
+ * @param node  element containing the viewBox attribute
+ * @param mat   out parameter for optional matrix transform
+ */
+static void
+_node_read_viewbox (xmlNodePtr root, DiaMatrix **mat)
+{
+  xmlChar *swidth = xmlGetProp(root, (const xmlChar *)"width");
+  xmlChar *sheight = xmlGetProp(root, (const xmlChar *)"height");
+  xmlChar *sviewbox = xmlGetProp(root, (const xmlChar *)"viewBox");
+
+  if (swidth && sheight && sviewbox) {
+    real width = get_value_as_cm ((const char *)swidth, NULL);
+    real height = get_value_as_cm ((const char *)sheight, NULL);
+    gint x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+      
+    if (4 == sscanf ((const char *)sviewbox, "%d %d %d %d", &x1, &y1, &x2, &y2)) {
+      real xs, ys;
+      g_debug ("viewBox(%d %d %d %d) = (%f,%f)\n", x1, y1, x2, y2, width, height);
+      /* some basic sanity check */
+      if (x2 > x1 && y2 > y1 && width > 0 && height > 0) {
+       xs = ((real)x2 - x1) / width;
+       ys = ((real)y2 - y1) / height;
+       /* plausibility check, strictly speaking these are not required to be the same 
+        * /or/ are they and Dia is writting a bogus viewBox?
+        */
+       if (fabs((fabs (xs/ys) - 1.0) < 0.1) && fabs((fabs (ys/xs) - 1.0) < 0.1)) {
+         user_scale = xs;
+         g_debug ("viewBox(%d %d %d %d) scaling (%f,%f) -> %f\n", x1, y1, x2, y2, xs, ys, user_scale);
+       } else {
+         /* the bigger the scale the smaller the objects */
+         user_scale = MAX(xs, ys);
+#if 0 /* need to think about - might fly with preserveAspectRatio handling */
+         if (mat) {
+           DiaMatrix *m = g_new0 (DiaMatrix, 1);
+           m->xx = xs > ys ? xs/ys : 1.0;
+           m->yy = ys > xs ? ys/xs : 1.0;
+           *mat = m;
+         }
+#endif
+       }
+      }
+    }
+  }
+
+  if (swidth)
+    xmlFree (swidth);
+  if (sheight)
+    xmlFree (sheight);
+  if (sviewbox)
+    xmlFree (sviewbox);
+}
+
+/*!
  * Fill a GList* with objects which is to be put in a
  * diagram or a group by the caller. 
  * Can be called recusively to allow groups in groups.
@@ -1358,6 +1416,40 @@ read_items (xmlNodePtr   startnode,
     } 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?). */
+    } else if(!xmlStrcmp(node->name, (const xmlChar *)"svg")) {
+      /* A subsequent svg node is truned into a group to simplify offseting
+       * it and maybe later honor additional attributes like viewBox, width,
+       * height and preserveAspectRatio with clipping and scaling
+       */
+      GList *moreitems;
+      Point pos;
+      /* put the global user scale on the stack */
+      real user_scale_prev = user_scale;
+      DiaMatrix *matrix = NULL;
+
+      _node_read_viewbox (node, &matrix);
+
+      pos.x = _node_get_real (node, "x", 0.0);
+      pos.y = _node_get_real (node, "y", 0.0);
+      moreitems = read_items (node->xmlChildrenNode, parent_gs, defs_ht, style_ht, filename_svg, ctx);
+      if (moreitems) {
+        DiaObject *group;
+
+       if (matrix) /* eats list and matrix */
+         group = group_create_with_matrix (moreitems, matrix);
+       else
+         group = group_create (moreitems);
+       /* remember for meta */
+       obj = group;
+       if (pos.x != 0.0 || pos.y != 0.0) {
+         pos.x += obj->position.x;
+         pos.y += obj->position.y;
+         obj->ops->move (obj, &pos);
+       }
+        items = g_list_append (items, group);
+      }
+      /* restore scale */
+      user_scale = user_scale_prev;
     } else {
       /* everything else is treated like a group _without grouping_, i.e. we dive
        * into unknown stuff. This allows to import stuff generated by 'dot' with
@@ -1570,42 +1662,8 @@ import_svg (xmlDocPtr doc, DiagramData *dia,
     user_scale = DEFAULT_SVG_SCALE;
 
   /* if the svg root element contains width, height and viewBox calculate our user scale from it */
-  if (shape_root)
-  {
-    xmlChar *swidth = xmlGetProp(root, (const xmlChar *)"width");
-    xmlChar *sheight = xmlGetProp(root, (const xmlChar *)"height");
-    xmlChar *sviewbox = xmlGetProp(root, (const xmlChar *)"viewBox");
-
-    if (swidth && sheight && sviewbox) {
-      real width = get_value_as_cm ((const char *)swidth, NULL);
-      real height = get_value_as_cm ((const char *)sheight, NULL);
-      gint x1 = 0, y1 = 0, x2 = 0, y2 = 0;
-      
-      if (4 == sscanf ((const char *)sviewbox, "%d %d %d %d", &x1, &y1, &x2, &y2)) {
-        real xs, ys;
-       g_debug ("viewBox(%d %d %d %d) = (%f,%f)\n", x1, y1, x2, y2, width, height);
-        /* some basic sanity check */
-       if (x2 > x1 && y2 > y1 && width > 0 && height > 0) {
-         xs = ((real)x2 - x1) / width;
-         ys = ((real)y2 - y1) / height;
-         /* plausibility check, strictly speaking these are not required to be the same 
-              * /or/ are they and Dia is writting a bogus viewBox?
-              */
-         if (fabs((fabs (xs/ys) - 1.0) < 0.1)) {
-           user_scale = xs;
-           g_debug ("viewBox(%d %d %d %d) scaling (%f,%f) -> %f\n", x1, y1, x2, y2, xs, ys, user_scale);
-         }
-        }
-      }
-    }
-    
-    if (swidth)
-      xmlFree (swidth);
-    if (sheight)
-      xmlFree (sheight);
-    if (sviewbox)
-      xmlFree (sviewbox);
-  }
+  if (!shape_root)
+    _node_read_viewbox (root, NULL);
 
   {
     GHashTable *defs_ht = g_hash_table_new (g_str_hash, g_str_equal);


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