| 
          /* | 
        
        
           | 
           * Copyright (C) 2015. Jared Rummler <[email protected]> | 
        
        
           | 
           * | 
        
        
           | 
           * Licensed under the Apache License, Version 2.0 (the "License"); | 
        
        
           | 
           * you may not use this file except in compliance with the License. | 
        
        
           | 
           * You may obtain a copy of the License at | 
        
        
           | 
           * | 
        
        
           | 
           *      http://www.apache.org/licenses/LICENSE-2.0 | 
        
        
           | 
           * | 
        
        
           | 
           * Unless required by applicable law or agreed to in writing, software | 
        
        
           | 
           * distributed under the License is distributed on an "AS IS" BASIS, | 
        
        
           | 
           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
        
        
           | 
           * See the License for the specific language governing permissions and | 
        
        
           | 
           * limitations under the License. | 
        
        
           | 
           * | 
        
        
           | 
           */ | 
        
        
           | 
          
 | 
        
        
           | 
          import org.w3c.dom.Document; | 
        
        
           | 
          import org.w3c.dom.Element; | 
        
        
           | 
          import org.w3c.dom.NamedNodeMap; | 
        
        
           | 
          import org.w3c.dom.Node; | 
        
        
           | 
          import org.w3c.dom.NodeList; | 
        
        
           | 
          import org.xml.sax.SAXException; | 
        
        
           | 
          
 | 
        
        
           | 
          import java.io.File; | 
        
        
           | 
          import java.io.IOException; | 
        
        
           | 
          import java.util.ArrayList; | 
        
        
           | 
          import java.util.List; | 
        
        
           | 
          
 | 
        
        
           | 
          import javax.xml.parsers.DocumentBuilderFactory; | 
        
        
           | 
          import javax.xml.parsers.ParserConfigurationException; | 
        
        
           | 
          import javax.xml.transform.OutputKeys; | 
        
        
           | 
          import javax.xml.transform.Transformer; | 
        
        
           | 
          import javax.xml.transform.TransformerFactory; | 
        
        
           | 
          import javax.xml.transform.dom.DOMSource; | 
        
        
           | 
          import javax.xml.transform.stream.StreamResult; | 
        
        
           | 
          
 | 
        
        
           | 
          public class Vector2Svg { | 
        
        
           | 
          
 | 
        
        
           | 
            public static void main(String[] args) { | 
        
        
           | 
              if (args == null || args.length == 0 || args[0].equals("--help")) { | 
        
        
           | 
                printUsage(); | 
        
        
           | 
                return; | 
        
        
           | 
              } | 
        
        
           | 
              for (String path : args) { | 
        
        
           | 
                Vector2Svg converter = new Vector2Svg(new File(path)); | 
        
        
           | 
                if (!converter.createSvg()) { | 
        
        
           | 
                  System.out.println("Error creating SVG from " + path); | 
        
        
           | 
                } | 
        
        
           | 
              } | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private static void printUsage() { | 
        
        
           | 
              File jarFile = | 
        
        
           | 
                  new File(Vector2Svg.class.getProtectionDomain().getCodeSource().getLocation().getPath()); | 
        
        
           | 
              System.out.println("Convert Android VectorDrawable XML resource file to SVG"); | 
        
        
           | 
              System.out.println(); | 
        
        
           | 
              System.out.println(String.format("Usage: java -jar %s [FILE]...", jarFile.getName())); | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private final File source; | 
        
        
           | 
            private final File destination; | 
        
        
           | 
          
 | 
        
        
           | 
            public Vector2Svg(File source) { | 
        
        
           | 
              this(source, new File(source.getParent(), source.getName().replaceFirst("[.][^.]+$", ".svg"))); | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            public Vector2Svg(File source, File destination) { | 
        
        
           | 
              this.source = source; | 
        
        
           | 
              this.destination = destination; | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            public boolean createSvg() { | 
        
        
           | 
              try { | 
        
        
           | 
                AndroidVectorDrawable drawable = getDrawable(); | 
        
        
           | 
                Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); | 
        
        
           | 
                Element svg = doc.createElement("svg"); | 
        
        
           | 
                svg.setAttribute("viewBox", String.format("0 0 %.1f %.1f", drawable.width, drawable.height)); | 
        
        
           | 
                for (Group group : drawable.groups) { | 
        
        
           | 
                  Element g = doc.createElement("g"); | 
        
        
           | 
                  for (VectorPath path : group.paths) { | 
        
        
           | 
                    Element child = doc.createElement("path"); | 
        
        
           | 
                    if (path.fillColor != null) { | 
        
        
           | 
                      child.setAttribute("fill", path.fillColor); | 
        
        
           | 
                    } | 
        
        
           | 
                    child.setAttribute("d", path.pathData); | 
        
        
           | 
                    g.appendChild(child); | 
        
        
           | 
                  } | 
        
        
           | 
                  svg.appendChild(g); | 
        
        
           | 
                } | 
        
        
           | 
                for (VectorPath path : drawable.paths) { | 
        
        
           | 
                  Element child = doc.createElement("path"); | 
        
        
           | 
                  if (path.fillColor != null) { | 
        
        
           | 
                    child.setAttribute("fill", path.fillColor); | 
        
        
           | 
                  } | 
        
        
           | 
                  child.setAttribute("d", path.pathData); | 
        
        
           | 
                  svg.appendChild(child); | 
        
        
           | 
                } | 
        
        
           | 
                doc.appendChild(svg); | 
        
        
           | 
                TransformerFactory transformerFactory = TransformerFactory.newInstance(); | 
        
        
           | 
                Transformer transformer = transformerFactory.newTransformer(); | 
        
        
           | 
                DOMSource source = new DOMSource(doc); | 
        
        
           | 
                StreamResult result = new StreamResult(destination); | 
        
        
           | 
                transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | 
        
        
           | 
                transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); | 
        
        
           | 
                transformer.transform(source, result); | 
        
        
           | 
                return true; | 
        
        
           | 
              } catch (Exception e) { | 
        
        
           | 
                return false; | 
        
        
           | 
              } | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private AndroidVectorDrawable getDrawable() | 
        
        
           | 
                throws ParserConfigurationException, IOException, SAXException { | 
        
        
           | 
              Document xml = | 
        
        
           | 
                  DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(source); | 
        
        
           | 
              xml.getDocumentElement().normalize(); | 
        
        
           | 
              Node vector = xml.getElementsByTagName("vector").item(0); | 
        
        
           | 
              NamedNodeMap attributes = vector.getAttributes(); | 
        
        
           | 
              NodeList children = vector.getChildNodes(); | 
        
        
           | 
          
 | 
        
        
           | 
              double width = 0; | 
        
        
           | 
              double height = 0; | 
        
        
           | 
              for (int i = 0; i < attributes.getLength(); i++) { | 
        
        
           | 
                if (attributes.item(i).getNodeName().equals("android:viewportHeight")) { | 
        
        
           | 
                  height = Double.parseDouble(attributes.item(i).getNodeValue()); | 
        
        
           | 
                } else if (attributes.item(i).getNodeName().equals("android:viewportWidth")) { | 
        
        
           | 
                  width = Double.parseDouble(attributes.item(i).getNodeValue()); | 
        
        
           | 
                } | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              List<VectorPath> paths = new ArrayList<>(); | 
        
        
           | 
              List<Group> groups = new ArrayList<>(); | 
        
        
           | 
          
 | 
        
        
           | 
              for (int i = 0; i < children.getLength(); i++) { | 
        
        
           | 
                Node item = children.item(i); | 
        
        
           | 
                if (item.getNodeName().equals("group")) { | 
        
        
           | 
                  List<VectorPath> groupPaths = new ArrayList<>(); | 
        
        
           | 
                  for (int j = 0; j < item.getChildNodes().getLength(); j++) { | 
        
        
           | 
                    VectorPath path = getVectorPathFromNode(item.getChildNodes().item(j)); | 
        
        
           | 
                    if (path != null) { | 
        
        
           | 
                      groupPaths.add(path); | 
        
        
           | 
                    } | 
        
        
           | 
                  } | 
        
        
           | 
                  if (!groupPaths.isEmpty()) { | 
        
        
           | 
                    groups.add(new Group(groupPaths)); | 
        
        
           | 
                  } | 
        
        
           | 
                } else { | 
        
        
           | 
                  VectorPath path = getVectorPathFromNode(item); | 
        
        
           | 
                  if (path != null) { | 
        
        
           | 
                    paths.add(path); | 
        
        
           | 
                  } | 
        
        
           | 
                } | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              return new AndroidVectorDrawable(paths, groups, width, height); | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private VectorPath getVectorPathFromNode(Node item) { | 
        
        
           | 
              if (item.getNodeName().equals("path")) { | 
        
        
           | 
                String pathData = null; | 
        
        
           | 
                String fillColor = null; | 
        
        
           | 
                for (int j = 0; j < item.getAttributes().getLength(); j++) { | 
        
        
           | 
                  Node node = item.getAttributes().item(j); | 
        
        
           | 
                  String name = node.getNodeName(); | 
        
        
           | 
                  String value = node.getNodeValue(); | 
        
        
           | 
                  if (name.equals("android:pathData")) { | 
        
        
           | 
                    pathData = value; | 
        
        
           | 
                  } else if (name.equals("android:fillColor") && value.startsWith("#")) { | 
        
        
           | 
                    fillColor = value; | 
        
        
           | 
                  } | 
        
        
           | 
                } | 
        
        
           | 
                if (pathData != null) { | 
        
        
           | 
                  return new VectorPath(pathData, fillColor); | 
        
        
           | 
                } | 
        
        
           | 
              } | 
        
        
           | 
              return null; | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private class VectorPath { | 
        
        
           | 
          
 | 
        
        
           | 
              private String pathData; | 
        
        
           | 
              private String fillColor; | 
        
        
           | 
          
 | 
        
        
           | 
              private VectorPath(String pathData, String fillColor) { | 
        
        
           | 
                this.pathData = pathData; | 
        
        
           | 
                this.fillColor = fillColor; | 
        
        
           | 
              } | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private class Group { | 
        
        
           | 
          
 | 
        
        
           | 
              private final List<VectorPath> paths; | 
        
        
           | 
          
 | 
        
        
           | 
              public Group(List<VectorPath> paths) { | 
        
        
           | 
                this.paths = paths; | 
        
        
           | 
              } | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
            private class AndroidVectorDrawable { | 
        
        
           | 
          
 | 
        
        
           | 
              private final List<VectorPath> paths; | 
        
        
           | 
              private final List<Group> groups; | 
        
        
           | 
              private final double height; | 
        
        
           | 
              private final double width; | 
        
        
           | 
          
 | 
        
        
           | 
              private AndroidVectorDrawable(List<VectorPath> paths, List<Group> groups, | 
        
        
           | 
                                            double width, double height) { | 
        
        
           | 
                this.paths = paths; | 
        
        
           | 
                this.groups = groups; | 
        
        
           | 
                this.height = height; | 
        
        
           | 
                this.width = width; | 
        
        
           | 
              } | 
        
        
           | 
            } | 
        
        
           | 
          
 | 
        
        
           | 
          } |