[dia] svg: retain current point over path split



commit 71090b449e69271375233415b4a5bcbe48636ecb
Author: Hans Breuer <hans breuer org>
Date:   Sun Aug 7 17:06:54 2011 +0200

    svg: retain current point over path split
    
    SVGs with relative movement produced wrong results, when that
    path was split (e.g. car.svg from Inkscape examples). Now the
    current_point is retained across the splitting loop.
    
    Slightly related: handle a second move command directly after
    the initial one gracefully (there are too many borked SVG generators;))

 lib/dia_svg.c               |   22 +++++++++++++++++++---
 lib/dia_svg.h               |    2 +-
 objects/custom/shape_info.c |    3 ++-
 plug-ins/svg/svg-import.c   |    3 ++-
 4 files changed, 24 insertions(+), 6 deletions(-)
---
diff --git a/lib/dia_svg.c b/lib/dia_svg.c
index 5451498..54f3a26 100644
--- a/lib/dia_svg.c
+++ b/lib/dia_svg.c
@@ -570,6 +570,7 @@ _path_arc(GArray *points, double cpx, double cpy,
  *                 the string was completely parsed.  This should be used for
  *                 calling the function until it is fully parsed.
  * @param closed Whether the path was closed.
+ * @param current_point to retain it over splitting
  * @returns Array of BezPoint objects, or NULL if an error occurred.
  *          The caller is responsible for freeing the array.
  * @bug This function is way too long (324 lines). So dont touch it. please!
@@ -580,7 +581,7 @@ _path_arc(GArray *points, double cpx, double cpy,
  * NOPE: Dia is capable to handle beziers and the file has given us some so WHY should be break it in to pieces ???
  */
 GArray*
-dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed)
+dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed, Point *current_point)
 {
   enum {
     PATH_MOVE, PATH_LINE, PATH_HLINE, PATH_VLINE, PATH_CURVE,
@@ -597,6 +598,10 @@ dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed)
   *closed = FALSE;
   *unparsed = NULL;
 
+  /* when splitting into pieces, we have to maintain current_point accross them */
+  if (current_point)
+    last_point = *current_point;
+
   points = g_array_new(FALSE, FALSE, sizeof(BezPoint));
   g_array_set_size(points, 0);
 
@@ -744,6 +749,10 @@ dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed)
     /* actually parse the path component */
     switch (last_type) {
     case PATH_MOVE:
+#ifndef MULTI_MOVE_BEZIER
+      if (points->len > 1)
+	g_warning ("Only first point should be 'move'");
+#endif
       bez.type = BEZ_MOVE_TO;
       bez.p1.x = g_ascii_strtod(path, &path);
       path_chomp(path);
@@ -756,7 +765,12 @@ dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed)
       last_point = bez.p1;
       last_control = bez.p1;
       last_open = bez.p1;
-      g_array_append_val(points, bez);
+#ifndef MULTI_MOVE_BEZIER
+      if (points->len == 1) /* stupid svg, but we can handle it */
+	g_array_index(points,BezPoint,0) = bez;
+      else
+#endif
+        g_array_append_val(points, bez);
       break;
     case PATH_LINE:
       bez.type = BEZ_LINE_TO;
@@ -917,7 +931,7 @@ dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed)
     path_chomp(path);
 MORETOPARSE:
     if (need_next_element) {
-      /* check if there really is mor to be parsed */
+      /* check if there really is more to be parsed */
       if (path[0] != 0)
 	*unparsed = path;
       break; /* while */
@@ -931,6 +945,8 @@ MORETOPARSE:
   if (points->len < 2) {
     g_array_set_size(points, 0);
   }
+  if (current_point)
+    *current_point = last_point;
   return points;
 }
 
diff --git a/lib/dia_svg.h b/lib/dia_svg.h
index 4588201..0240f4d 100644
--- a/lib/dia_svg.h
+++ b/lib/dia_svg.h
@@ -61,7 +61,7 @@ void dia_svg_style_init (DiaSvgStyle *gs, DiaSvgStyle *parent_style);
 void dia_svg_style_copy (DiaSvgStyle *dest, DiaSvgStyle *src);
 void dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale);
 /* parse the svg sub format for pathes int an array of BezPoint */
-GArray *dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed);
+GArray *dia_svg_parse_path(const gchar *path_str, gchar **unparsed, gboolean *closed, Point *current_point);
 DiaMatrix *dia_svg_parse_transform(const gchar *trans, real scale);
 gchar *dia_svg_from_matrix(const DiaMatrix *matrix, real scale);
 
diff --git a/objects/custom/shape_info.c b/objects/custom/shape_info.c
index f4e457e..443502a 100644
--- a/objects/custom/shape_info.c
+++ b/objects/custom/shape_info.c
@@ -155,9 +155,10 @@ parse_path(ShapeInfo *info, const char *path_str, DiaSvgStyle *s, const char* fi
   GArray *points;
   gchar *pathdata = (gchar *)path_str, *unparsed;
   gboolean closed = FALSE;
+  Point current_point = {0.0, 0.0};
 
   do {
-    points = dia_svg_parse_path (pathdata, &unparsed, &closed);
+    points = dia_svg_parse_path (pathdata, &unparsed, &closed, &current_point);
 
     if (points->len > 0) {
       if (g_array_index(points, BezPoint, 0).type != BEZ_MOVE_TO) {
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 90a58f5..3130fe0 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -305,6 +305,7 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
     gboolean closed = FALSE;
     gint i;
     DiaMatrix *matrix = NULL;
+    Point current_point = {0.0, 0.0};
 
     str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
     if (str) {
@@ -314,7 +315,7 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
 
     pathdata = str = (char *) xmlGetProp(node, (const xmlChar *)"d");
     do {
-      bezpoints = dia_svg_parse_path (pathdata, &unparsed, &closed);
+      bezpoints = dia_svg_parse_path (pathdata, &unparsed, &closed, &current_point);
 
       if (bezpoints && bezpoints->len > 0) {
         if (g_array_index(bezpoints, BezPoint, 0).type != BEZ_MOVE_TO) {



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