浏览代码

svg import fixes and support

Christopher Brown 8 年之前
父节点
当前提交
cae6677d28
共有 1 个文件被更改,包括 45 次插入31 次删除
  1. 45 31
      ext/import-svg.cpp

+ 45 - 31
ext/import-svg.cpp

@@ -52,6 +52,16 @@ static bool readDouble(double &output, const char *&pathDef) {
     return false;
 }
 
+static bool consumeOptionalComma(const char *&pathDef) {
+    while (*pathDef == ' ') {
+        ++pathDef;
+    }
+    if (*pathDef == ',') {
+        ++pathDef;
+    }
+    return true;
+}
+
 static bool buildFromPath(Shape &shape, const char *pathDef) {
     char nodeType;
     Point2 prevNode(0, 0);
@@ -66,79 +76,83 @@ static bool buildFromPath(Shape &shape, const char *pathDef) {
         while (true) {
             switch (nodeType) {
                 case 'M':
-                    REQUIRE(contourStart);
-                    REQUIRE(readCoord(node, pathDef));
-                    startPoint = node;
-                    nodeType = 'L';
-                    break;
                 case 'm':
                     REQUIRE(contourStart);
                     REQUIRE(readCoord(node, pathDef));
-                    node += prevNode;
+                    if (nodeType == 'm') {
+                        node += prevNode;
+                    }
                     startPoint = node;
-                    nodeType = 'l';
+                    --nodeType; // to 'L' or 'l'
                     break;
                 case 'Z':
                 case 'z':
                     if (prevNode != startPoint)
                         contour.addEdge(new LinearSegment(prevNode, startPoint));
+                    prevNode = startPoint;
                     goto NEXT_CONTOUR;
                 case 'L':
-                    REQUIRE(readCoord(node, pathDef));
-                    contour.addEdge(new LinearSegment(prevNode, node));
-                    break;
                 case 'l':
                     REQUIRE(readCoord(node, pathDef));
-                    node += prevNode;
+                    if (nodeType == 'l') {
+                        node += prevNode;
+                    }
                     contour.addEdge(new LinearSegment(prevNode, node));
                     break;
                 case 'H':
-                    REQUIRE(readDouble(node.x, pathDef));
-                    contour.addEdge(new LinearSegment(prevNode, node));
-                    break;
                 case 'h':
                     REQUIRE(readDouble(node.x, pathDef));
-                    node.x += prevNode.x;
+                    if (nodeType == 'h') {
+                        node.x += prevNode.x;
+                    }
                     contour.addEdge(new LinearSegment(prevNode, node));
                     break;
                 case 'V':
-                    REQUIRE(readDouble(node.y, pathDef));
-                    contour.addEdge(new LinearSegment(prevNode, node));
-                    break;
                 case 'v':
                     REQUIRE(readDouble(node.y, pathDef));
-                    node.y += prevNode.y;
+                    if (nodeType == 'v') {
+                        node.y += prevNode.y;
+                    }
                     contour.addEdge(new LinearSegment(prevNode, node));
                     break;
                 case 'Q':
-                    REQUIRE(readCoord(controlPoint[0], pathDef));
-                    REQUIRE(readCoord(node, pathDef));
-                    contour.addEdge(new QuadraticSegment(prevNode, controlPoint[0], node));
-                    break;
                 case 'q':
                     REQUIRE(readCoord(controlPoint[0], pathDef));
+                    consumeOptionalComma(pathDef);
                     REQUIRE(readCoord(node, pathDef));
-                    controlPoint[0] += prevNode;
-                    node += prevNode;
+                    if (nodeType == 'q') {
+                        controlPoint[0] += prevNode;
+                        node += prevNode;
+                    }
                     contour.addEdge(new QuadraticSegment(prevNode, controlPoint[0], node));
                     break;
                 // TODO T, t
                 case 'C':
+                case 'c':
                     REQUIRE(readCoord(controlPoint[0], pathDef));
+                    consumeOptionalComma(pathDef);
                     REQUIRE(readCoord(controlPoint[1], pathDef));
+                    consumeOptionalComma(pathDef);
                     REQUIRE(readCoord(node, pathDef));
+                    if (nodeType == 'c') {
+                        controlPoint[0] += prevNode;
+                        controlPoint[1] += prevNode;
+                        node += prevNode;
+                    }
                     contour.addEdge(new CubicSegment(prevNode, controlPoint[0], controlPoint[1], node));
                     break;
-                case 'c':
-                    REQUIRE(readCoord(controlPoint[0], pathDef));
+                case 'S':
+                case 's':
+                    controlPoint[0] = node * 2 - controlPoint[1];
                     REQUIRE(readCoord(controlPoint[1], pathDef));
+                    consumeOptionalComma(pathDef);
                     REQUIRE(readCoord(node, pathDef));
-                    controlPoint[0] += prevNode;
-                    controlPoint[1] += prevNode;
-                    node += prevNode;
+                    if (nodeType == 's') {
+                        controlPoint[1] += prevNode;
+                        node += prevNode;
+                    }
                     contour.addEdge(new CubicSegment(prevNode, controlPoint[0], controlPoint[1], node));
                     break;
-                // TODO S, s
                 // TODO A, a
                 default:
                     REQUIRE(false);