Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Bicet/33ff29db1bf7600ad35e15c22d5be8c5 to your computer and use it in GitHub Desktop.
Save Bicet/33ff29db1bf7600ad35e15c22d5be8c5 to your computer and use it in GitHub Desktop.

Revisions

  1. @qinshulei qinshulei revised this gist Nov 12, 2015. 1 changed file with 216 additions and 0 deletions.
    216 changes: 216 additions & 0 deletions Vector2Svg.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,216 @@
    /*
    * 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;
    }
    }

    }
  2. @qinshulei qinshulei created this gist Nov 12, 2015.
    29 changes: 29 additions & 0 deletions ConvertAndroidVectorDrawable2png.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@

    转换方法:
    1. Convert Android VectorDrawable to SVG:

    使用附件中的java程序。命令如下:
    ```
    cp Vector2Svg.java path/to/xml_dir
    javac Vector2Svg.java
    java Vector2Svg ./*.xml
    mkdir svg_dir
    mv *.svg svg_dir
    ```
    ./*.xml为目标Android VectorDrawable的xml文件列表
    然后程序会在对应目录生成同名的svg

    2. Convert SVG to PNG:

    最简单的方法是直接使用Ubuntu的图片浏览器打开,然后另存为png

    批量转换:
    ```
    sudo apt-get install librsvg2-bin
    cd svg_dir
    for i in *; do rsvg-convert $i -o `echo $i | sed -e 's/svg$/png/'`; done
    ```

    安装rsvg库,使用rsvg 转换svg到png.

    附件中svg.tgz,是昨天图片的png结果。