Skip to content

Instantly share code, notes, and snippets.

@AtkinsSJ
Created April 6, 2013 18:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AtkinsSJ/5327208 to your computer and use it in GitHub Desktop.
Save AtkinsSJ/5327208 to your computer and use it in GitHub Desktop.
This is a class I've written to grab data from svg files made in Inkscape. (Saved as Inkscape svg, not plain svg) Create an SvgParser, call fromFile() with a file handle to the svg file, and you'll be able to access layers by what you named then in Inkscape, using getLayer(name), then access paths from the Layer with getPath(id), or points with …
package uk.co.samatkins.racing;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.XmlReader;
import com.badlogic.gdx.utils.XmlReader.Element;
import com.badlogic.gdx.math.Vector2;
public class SvgParser {
private HashMap<String, Layer> layers;
public SvgParser() {
layers = new HashMap<String, Layer>();
}
public void fromFile(FileHandle file) throws IOException {
XmlReader reader = new XmlReader();
XmlReader.Element xml;
xml = reader.parse(file);
Array<Element> gs = xml.getChildrenByName("g");
for (Element g : gs ) {
if (g.getAttribute("inkscape:groupmode").equals("layer")) {
Layer l = new Layer(transformToVector(g.getAttribute("transform", "")));
for (int i=0; i<g.getChildCount(); i++) {
Element el = g.getChild(i);
switch (el.getName()) {
case "path":
l.addPath(el.getAttribute("id"), this.svgPathToVertices(el.getAttribute("d")));
break;
case "text":
l.addPoint(el.getAttribute("id"),
new Vector2(Float.parseFloat(el.getAttribute("x")),
Float.parseFloat(el.getAttribute("y"))));
break;
}
}
this.addLayer(g.getAttribute("inkscape:label"), l);
}
}
}
/**
* Takes a path's data, and returns an array of vectors for its vertices.
* @param pathString The 'd' attribute from the svg 'path' element
* @return
*/
private Vector2[] svgPathToVertices(String pathString) {
ArrayList<Vector2> vertexList = new ArrayList<Vector2>();
boolean relativeCoords = false;
// get the path string
String[] pathParts = pathString.split(" ");
for (String s: pathParts) {
if (s.charAt(0) == 'm') {
relativeCoords = true;
} else if (s.charAt(0) == 'M') {
relativeCoords = false;
} else if (s.charAt(0) == 'l') {
relativeCoords = true;
} else if (s.charAt(0) == 'L') {
relativeCoords = false;
} else if (Character.isDigit(s.charAt(0)) || s.charAt(0) == '-') {
String[] coords = s.split(",");
if (vertexList.size() > 0 && relativeCoords) {
Vector2 last = vertexList.get(vertexList.size()-1);
vertexList.add( new Vector2( Float.parseFloat(coords[0]) + last.x, Float.parseFloat(coords[1]) + last.y ) );
} else {
vertexList.add( new Vector2( Float.parseFloat(coords[0]), Float.parseFloat(coords[1]) ) );
}
}
}
Vector2[] v = new Vector2[vertexList.size()];
return vertexList.toArray(v);
}
private void addLayer(String id, Layer layer) {
this.layers.put(id, layer);
}
public Layer getLayer(String id) {
return this.layers.get(id);
}
private Vector2 transformToVector(String transform) {
if (transform.startsWith("translate")) {
String[] parts = transform.substring(10, transform.length()-1).split(",");
return new Vector2(Float.parseFloat(parts[0]), Float.parseFloat(parts[1]));
}
return Vector2.Zero;
}
public class Layer {
private HashMap<String, Vector2[]> paths;
private HashMap<String, Vector2> points;
private Vector2 position;
public Layer(Vector2 offset) {
paths = new HashMap<String, Vector2[]>();
points = new HashMap<String, Vector2>();
position = offset;
}
/**
* Adds the given path to this layer.
* If this layer has a translation, the path is normalised.
* @param id
* @param path
*/
public void addPath(String id, Vector2[] path) {
for (int i=0; i<path.length; i++) {
path[i] = path[i].add(position);
}
this.paths.put(id, path);
}
public Vector2[] getPath(String id) {
return this.paths.get(id);
}
/**
* Adds the given point to this layer.
* If this layer has a translation, the point is normalised.
* @param id
* @param point
*/
public void addPoint(String id, Vector2 point) {
this.points.put(id, point.add(position));
}
public Vector2 getPoint(String id) {
return this.points.get(id);
}
}
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment