private static SketchDocument importSVG(InputStream stream) throws Exception { SketchDocument sdoc = new SketchDocument(); sdoc.removePage(sdoc.getCurrentPage()); SketchDocument.SketchPage page = sdoc.addPage(); u.p("parsing"); Doc doc = XMLParser.parse(stream); u.p("parsed"); Elem svg = doc.xpathElement("/svg"); for (Elem n : svg.xpath("./*")) { u.p("node = " + n + " " + n.name()); SNode node = loadNode(n); if (node != null) page.add(node); } return sdoc; }
private static void parseFill(SShape shape, Elem root) { if (!root.hasAttr("fill")) { shape.setFillPaint(FlatColor.BLACK); return; } String sfill = root.attr("fill"); if (sfill.equals("none")) { shape.setFillPaint(null); return; } if (sfill.startsWith("#")) { shape.setFillPaint(new FlatColor(sfill)); return; } u.p("trouble parsing fill: " + sfill); }
private static void parseStroke(SShape shape, Elem root) { if (!root.hasAttr("stroke")) { shape.setStrokeWidth(1); shape.setStrokePaint(null); } String sstroke = root.attr("stroke"); if (sstroke.equals("none")) { shape.setStrokePaint(null); } if (sstroke.startsWith("#")) { shape.setStrokePaint(new FlatColor(sstroke)); } if (!root.hasAttr("stroke-width")) { shape.setStrokeWidth(1); } else { String sstrokeWidth = root.attr("stroke-width"); double strokeWidth = Double.parseDouble(sstrokeWidth); shape.setStrokeWidth(strokeWidth); } }
private static SNode loadNode(Elem root) throws Exception { u.p("loading SVG element: " + root.name()); if ("g".equals(root.name())) { SGroup g = new SGroup(); for (Elem n : root.xpath("./*")) { SNode nn = loadNode(n); if (nn != null) g.addAll(false, nn); } g.normalize(); return g; } if ("rect".equals(root.name())) { SRect rect = new SRect(); rect.setX(Double.parseDouble(root.attr("x"))); rect.setY(Double.parseDouble(root.attr("y"))); parseFill(rect, root); parseStroke(rect, root); rect.setWidth(Double.parseDouble(root.attr("width"))); rect.setHeight(Double.parseDouble(root.attr("height"))); return rect; } if ("line".equals(root.name())) { SPoly poly = new SPoly(); double x1 = Double.parseDouble(root.attr("x1")); double y1 = Double.parseDouble(root.attr("y1")); double x2 = Double.parseDouble(root.attr("x2")); double y2 = Double.parseDouble(root.attr("y2")); poly.addPoint(new Point2D.Double(x1, y1)); poly.addPoint(new Point2D.Double(x2, y2)); poly.setClosed(false); parseFill(poly, root); parseStroke(poly, root); return poly; } if ("polygon".equals(root.name()) || "polyline".equals(root.name())) { String pointsString = root.attr("points"); String[] points = pointsString.split("\\s"); SPoly poly = new SPoly(); for (String pt : points) { if (pt != null && pt.trim().equals("")) continue; String[] xy = pt.split(","); poly.addPoint(new Point2D.Double(Double.parseDouble(xy[0]), Double.parseDouble(xy[1]))); } // the polygon is closed, poly lines aren't poly.setClosed("polygon".equals(root.name())); parseFill(poly, root); parseStroke(poly, root); return poly; } if ("path".equals(root.name())) { return parsePathNode(root); } Exception ex = new Exception("unrecognized SVG element: " + root.name()); u.p(ex); return null; }
private static SNode parsePathNode(Elem root) throws IOException { SPath path = new SPath(); String d = root.attr("d"); PushbackReader read = new PushbackReader(new StringReader(d)); int count = 0; double x = 0; double y = 0; SPath.PathPoint prev = null; boolean go = true; while (go) { count++; char ch = (char) read.read(); if (ch == -1) break; double x1, x2, y1, y2; u.p("ch = " + ch); switch (ch) { // absolute move case 'M': x = readDouble(read); y = readDouble(read); prev = path.moveTo(x, y); continue; // relative vertical lineto case 'v': y += readDouble(read); prev = path.lineTo(x, y); continue; // absolute vertical lineto case 'V': y = readDouble(read); prev = path.lineTo(x, y); continue; // relative horiz lineto case 'h': x += readDouble(read); prev = path.lineTo(x, y); continue; case 'H': x = readDouble(read); prev = path.lineTo(x, y); continue; // relative lineto case 'l': x += readDouble(read); y += readDouble(read); prev = path.lineTo(x, y); continue; case 'L': x = readDouble(read); y = readDouble(read); prev = path.lineTo(x, y); continue; // relative cubic curve case 'c': x1 = x + readDouble(read); y1 = y + readDouble(read); x2 = x + readDouble(read); y2 = y + readDouble(read); x += readDouble(read); y += readDouble(read); prev = path.curveTo(prev, x1, y1, x2, y2, x, y); continue; // relative shorthand curve case 's': x2 = x + readDouble(read); y2 = y + readDouble(read); x += readDouble(read); y += readDouble(read); double dx = prev.x - prev.cx1; double dy = prev.y - prev.cy1; double rx = prev.x + dx; double ry = prev.y + dy; prev = path.curveTo(prev, rx, ry, x2, y2, x, y); continue; // absolute cubic curve case 'C': x1 = readDouble(read); y1 = readDouble(read); x2 = readDouble(read); y2 = readDouble(read); x = readDouble(read); y = readDouble(read); prev = path.curveTo(prev, x1, y1, x2, y2, x, y); continue; case 'z': path.close(); break; case ' ': continue; case '\n': continue; // end of string case (char) -1: go = false; break; default: u.p("unrecognized character! " + ch + " " + ((int) ch)); go = false; break; } } parseFill(path, root); parseStroke(path, root); return path; }