]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGShapeWithPassthruSupport.java
Generate tidier SVG from diagrams
[simantics/platform.git] / bundles / org.simantics.diagram.svg / src / org / simantics / diagram / svg / export / SVGShapeWithPassthruSupport.java
diff --git a/bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGShapeWithPassthruSupport.java b/bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGShapeWithPassthruSupport.java
new file mode 100644 (file)
index 0000000..584bcf5
--- /dev/null
@@ -0,0 +1,101 @@
+package org.simantics.diagram.svg.export;
+
+import java.awt.Shape;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGShape;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.scenegraph.utils.SVGPassthruShape;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+public class SVGShapeWithPassthruSupport extends SVGShape {
+       private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+       
+       public SVGShapeWithPassthruSupport(SVGGeneratorContext generatorCtx) {
+               super(generatorCtx);
+               dbf.setValidating(false);
+               dbf.setExpandEntityReferences(false);
+               try {
+                       dbf.setFeature("http://xml.org/sax/features/namespaces", false);
+                       dbf.setFeature("http://xml.org/sax/features/validation", false);
+                       dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
+                       dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+               } catch (ParserConfigurationException e) {
+                       Logger.defaultLogError(e);
+               }
+       }
+
+       public Element toSVG(Shape shape) {
+               if (shape instanceof SVGPassthruShape) {
+                       String source = ((SVGPassthruShape) shape).getSource();
+                       
+                       try {
+                               
+                               Document owner = generatorContext.getDOMFactory();
+
+                               @SuppressWarnings("unchecked")
+                               Map<String, String> defsMap = (Map<String, String>)owner.getUserData("defs-map");
+                               if (defsMap == null) {
+                                       defsMap = new HashMap<String, String>();
+                                       owner.setUserData("defs-map", defsMap, null);
+                               }
+                               
+                               synchronized (defsMap) {
+                                       String symbolId = defsMap.get(source);
+                                       if (symbolId == null) {
+                                               symbolId = "S" + defsMap.size();
+                                               defsMap.put(source, symbolId);
+                                               
+                                               DocumentBuilder db = dbf.newDocumentBuilder();
+                                               
+                                               Document doc = db.parse(new ByteArrayInputStream(source.getBytes("UTF-8")));
+                                               Node node = doc.getDocumentElement();
+                                               Node localNode = owner.importNode(node, true);
+
+                                               if (localNode instanceof Element) {
+                                                       Element g = generatorContext.getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG);
+                                                       Element e = (Element)localNode;
+                                                       e.setAttribute("id", symbolId);
+                                                       g.appendChild(localNode);
+                                                       return g;
+                                               } else {
+                                                       return null;
+                                               }
+                                       } else {
+                                               Element element = owner.createElement("use");
+                                               element.setAttribute("xlink:href", "#" + symbolId);
+                                               return element;
+                                       }
+                               }
+                       } catch (UnsupportedEncodingException e) {
+                               Logger.defaultLogError(e);
+                               return null;
+                       } catch (IOException e) {
+                               Logger.defaultLogError(e);
+                               return null;
+                       } catch (ParserConfigurationException e) {
+                               Logger.defaultLogError(e);
+                               return null;
+                       } catch (SAXException e) {
+                               Logger.defaultLogError(e);
+                               return null;
+                       }
+               } else {
+                       return super.toSVG(shape);
+               }
+               
+       }
+       
+}