Path: blob/master/SLICK_HOME/src/org/newdawn/slick/svg/InkscapeLoader.java
1463 views
package org.newdawn.slick.svg;12import java.io.ByteArrayInputStream;3import java.io.IOException;4import java.io.InputStream;5import java.util.ArrayList;67import javax.xml.parsers.DocumentBuilder;8import javax.xml.parsers.DocumentBuilderFactory;910import org.newdawn.slick.SlickException;11import org.newdawn.slick.geom.Transform;12import org.newdawn.slick.svg.inkscape.DefsProcessor;13import org.newdawn.slick.svg.inkscape.ElementProcessor;14import org.newdawn.slick.svg.inkscape.EllipseProcessor;15import org.newdawn.slick.svg.inkscape.GroupProcessor;16import org.newdawn.slick.svg.inkscape.LineProcessor;17import org.newdawn.slick.svg.inkscape.PathProcessor;18import org.newdawn.slick.svg.inkscape.PolygonProcessor;19import org.newdawn.slick.svg.inkscape.RectProcessor;20import org.newdawn.slick.svg.inkscape.UseProcessor;21import org.newdawn.slick.util.ResourceLoader;22import org.w3c.dom.Document;23import org.w3c.dom.Element;24import org.w3c.dom.NodeList;25import org.xml.sax.EntityResolver;26import org.xml.sax.InputSource;27import org.xml.sax.SAXException;2829/**30* A loader specifically for the SVG that is produced from Inkscape31*32* @author kevin33*/34public class InkscapeLoader implements Loader {35/**36* The number of times to over trigulate to get enough tesselation for37* smooth shading38*/39public static int RADIAL_TRIANGULATION_LEVEL = 1;4041/** The list of XML element processors */42private static ArrayList processors = new ArrayList();4344/** The diagram loaded */45private Diagram diagram;4647static {48addElementProcessor(new RectProcessor());49addElementProcessor(new EllipseProcessor());50addElementProcessor(new PolygonProcessor());51addElementProcessor(new PathProcessor());52addElementProcessor(new LineProcessor());53addElementProcessor(new GroupProcessor());54addElementProcessor(new DefsProcessor());55addElementProcessor(new UseProcessor());56}5758/**59* Add an <code>ElementProcessor</code> which will be passed60* each element read as the Inkscape SVG document is processed.61*62* @param proc The processor to be added63*/64public static void addElementProcessor(ElementProcessor proc) {65processors.add(proc);66}6768/**69* Load a SVG document into a diagram70*71* @param ref72* The reference in the classpath to load the diagram from73* @param offset74* Offset the diagram for the height of the document75* @return The diagram loaded76* @throws SlickException77* Indicates a failure to process the document78*/79public static Diagram load(String ref, boolean offset)80throws SlickException {81return load(ResourceLoader.getResourceAsStream(ref), offset);82}8384/**85* Load a SVG document into a diagram86*87* @param ref88* The reference in the classpath to load the diagram from89* @return The diagram loaded90* @throws SlickException91* Indicates a failure to process the document92*/93public static Diagram load(String ref) throws SlickException {94return load(ResourceLoader.getResourceAsStream(ref), false);95}9697/**98* Load a SVG document into a diagram99*100* @param offset101* Offset the diagram for the height of the document102* @param in103* The input stream from which to read the SVG104* @return The diagram loaded105* @throws SlickException106* Indicates a failure to process the document107*/108public static Diagram load(InputStream in, boolean offset)109throws SlickException {110return new InkscapeLoader().loadDiagram(in, offset);111}112113/**114* Private, you should be using the static method115*/116private InkscapeLoader() {117}118119/**120* Load a SVG document into a diagram121*122* @param in123* The input stream from which to read the SVG124* @return The diagram loaded125* @throws SlickException126* Indicates a failure to process the document127*/128private Diagram loadDiagram(InputStream in) throws SlickException {129return loadDiagram(in, false);130}131132/**133* Load a SVG document into a diagram134*135* @param in136* The input stream from which to read the SVG137* @param offset138* Offset the diagram for the height of the document139* @return The diagram loaded140* @throws SlickException141* Indicates a failure to process the document142*/143private Diagram loadDiagram(InputStream in, boolean offset)144throws SlickException {145try {146DocumentBuilderFactory factory = DocumentBuilderFactory147.newInstance();148factory.setValidating(false);149factory.setNamespaceAware(true);150151DocumentBuilder builder = factory.newDocumentBuilder();152builder.setEntityResolver(new EntityResolver() {153public InputSource resolveEntity(String publicId,154String systemId) throws SAXException, IOException {155return new InputSource(156new ByteArrayInputStream(new byte[0]));157}158});159160Document doc = builder.parse(in);161Element root = doc.getDocumentElement();162163String widthString = root.getAttribute("width");164while (Character.isLetter(widthString165.charAt(widthString.length() - 1))) {166widthString = widthString.substring(0, widthString.length() - 1);167}168169String heightString = root.getAttribute("height");170while (Character.isLetter(heightString171.charAt(heightString.length() - 1))) {172heightString = heightString.substring(0,heightString.length() - 1);173}174175float docWidth = Float.parseFloat(widthString);176float docHeight = Float.parseFloat(heightString);177178diagram = new Diagram(docWidth, docHeight);179if (!offset) {180docHeight = 0;181}182loadChildren(root, Transform183.createTranslateTransform(0, -docHeight));184185return diagram;186} catch (Exception e) {187throw new SlickException("Failed to load inkscape document", e);188}189}190191/**192* @see org.newdawn.slick.svg.Loader#loadChildren(org.w3c.dom.Element,193* org.newdawn.slick.geom.Transform)194*/195public void loadChildren(Element element, Transform t)196throws ParsingException {197NodeList list = element.getChildNodes();198for (int i = 0; i < list.getLength(); i++) {199if (list.item(i) instanceof Element) {200loadElement((Element) list.item(i), t);201}202}203}204205/**206* Load a single element into the diagram207*208* @param element209* The element ot be loaded210* @param t211* The transform to apply to the loaded element from the parent212* @throws ParsingException213* Indicates a failure to parse the element214*/215private void loadElement(Element element, Transform t)216throws ParsingException {217for (int i = 0; i < processors.size(); i++) {218ElementProcessor processor = (ElementProcessor) processors.get(i);219220if (processor.handles(element)) {221processor.process(this, element, diagram, t);222}223}224}225}226227228