mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-14 20:44:05 +09:00
added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Gradient;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.newdawn.slick.util.Log;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* A processor for the defs node
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class DefsProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("defs")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform transform) throws ParsingException {
|
||||
NodeList patterns = element.getElementsByTagName("pattern");
|
||||
|
||||
for (int i=0;i<patterns.getLength();i++) {
|
||||
Element pattern = (Element) patterns.item(i);
|
||||
NodeList list = pattern.getElementsByTagName("image");
|
||||
if (list.getLength() == 0) {
|
||||
Log.warn("Pattern 1981 does not specify an image. Only image patterns are supported.");
|
||||
continue;
|
||||
}
|
||||
Element image = (Element) list.item(0);
|
||||
|
||||
String patternName = pattern.getAttribute("id");
|
||||
String ref = image.getAttributeNS(Util.XLINK, "href");
|
||||
diagram.addPatternDef(patternName, ref);
|
||||
}
|
||||
|
||||
NodeList linear = element.getElementsByTagName("linearGradient");
|
||||
ArrayList toResolve = new ArrayList();
|
||||
|
||||
for (int i=0;i<linear.getLength();i++) {
|
||||
Element lin = (Element) linear.item(i);
|
||||
String name = lin.getAttribute("id");
|
||||
Gradient gradient = new Gradient(name, false);
|
||||
|
||||
gradient.setTransform(Util.getTransform(lin, "gradientTransform"));
|
||||
|
||||
if (stringLength(lin.getAttribute("x1")) > 0) {
|
||||
gradient.setX1(Float.parseFloat(lin.getAttribute("x1")));
|
||||
}
|
||||
if (stringLength(lin.getAttribute("x2")) > 0) {
|
||||
gradient.setX2(Float.parseFloat(lin.getAttribute("x2")));
|
||||
}
|
||||
if (stringLength(lin.getAttribute("y1")) > 0) {
|
||||
gradient.setY1(Float.parseFloat(lin.getAttribute("y1")));
|
||||
}
|
||||
if (stringLength(lin.getAttribute("y2")) > 0) {
|
||||
gradient.setY2(Float.parseFloat(lin.getAttribute("y2")));
|
||||
}
|
||||
|
||||
String ref = lin.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (stringLength(ref) > 0) {
|
||||
gradient.reference(ref.substring(1));
|
||||
toResolve.add(gradient);
|
||||
} else {
|
||||
NodeList steps = lin.getElementsByTagName("stop");
|
||||
for (int j=0;j<steps.getLength();j++) {
|
||||
Element s = (Element) steps.item(j);
|
||||
float offset = Float.parseFloat(s.getAttribute("offset"));
|
||||
|
||||
String colInt = Util.extractStyle(s.getAttribute("style"),"stop-color");
|
||||
String opaInt = Util.extractStyle(s.getAttribute("style"),"stop-opacity");
|
||||
|
||||
int col = Integer.parseInt(colInt.substring(1), 16);
|
||||
Color stopColor = new Color(col);
|
||||
stopColor.a = Float.parseFloat(opaInt);
|
||||
|
||||
gradient.addStep(offset, stopColor);
|
||||
}
|
||||
|
||||
gradient.getImage();
|
||||
}
|
||||
|
||||
diagram.addGradient(name, gradient);
|
||||
}
|
||||
|
||||
NodeList radial = element.getElementsByTagName("radialGradient");
|
||||
for (int i=0;i<radial.getLength();i++) {
|
||||
Element rad = (Element) radial.item(i);
|
||||
String name = rad.getAttribute("id");
|
||||
Gradient gradient = new Gradient(name, true);
|
||||
|
||||
gradient.setTransform(Util.getTransform(rad, "gradientTransform"));
|
||||
|
||||
if (stringLength(rad.getAttribute("cx")) > 0) {
|
||||
gradient.setX1(Float.parseFloat(rad.getAttribute("cx")));
|
||||
}
|
||||
if (stringLength(rad.getAttribute("cy")) > 0) {
|
||||
gradient.setY1(Float.parseFloat(rad.getAttribute("cy")));
|
||||
}
|
||||
if (stringLength(rad.getAttribute("fx")) > 0) {
|
||||
gradient.setX2(Float.parseFloat(rad.getAttribute("fx")));
|
||||
}
|
||||
if (stringLength(rad.getAttribute("fy")) > 0) {
|
||||
gradient.setY2(Float.parseFloat(rad.getAttribute("fy")));
|
||||
}
|
||||
if (stringLength(rad.getAttribute("r")) > 0) {
|
||||
gradient.setR(Float.parseFloat(rad.getAttribute("r")));
|
||||
}
|
||||
|
||||
String ref = rad.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (stringLength(ref) > 0) {
|
||||
gradient.reference(ref.substring(1));
|
||||
toResolve.add(gradient);
|
||||
} else {
|
||||
NodeList steps = rad.getElementsByTagName("stop");
|
||||
for (int j=0;j<steps.getLength();j++) {
|
||||
Element s = (Element) steps.item(j);
|
||||
float offset = Float.parseFloat(s.getAttribute("offset"));
|
||||
|
||||
String colInt = Util.extractStyle(s.getAttribute("style"),"stop-color");
|
||||
String opaInt = Util.extractStyle(s.getAttribute("style"),"stop-opacity");
|
||||
|
||||
int col = Integer.parseInt(colInt.substring(1), 16);
|
||||
Color stopColor = new Color(col);
|
||||
stopColor.a = Float.parseFloat(opaInt);
|
||||
|
||||
gradient.addStep(offset, stopColor);
|
||||
}
|
||||
|
||||
gradient.getImage();
|
||||
}
|
||||
|
||||
diagram.addGradient(name, gradient);
|
||||
}
|
||||
|
||||
for (int i=0;i<toResolve.size();i++) {
|
||||
((Gradient) toResolve.get(i)).resolve(diagram);
|
||||
((Gradient) toResolve.get(i)).getImage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to cope with null values
|
||||
*
|
||||
* @param value The value to get the length of
|
||||
* @return The length of the string
|
||||
*/
|
||||
private int stringLength(String value) {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value.length();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The description of a module which processes a single XML element from a SVG (inkscape)
|
||||
* document.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public interface ElementProcessor {
|
||||
/**
|
||||
* Process a document extracting all the elements that the processor is
|
||||
* interested in and producing appropriate diagram components for the
|
||||
* element.
|
||||
*
|
||||
* @param loader The loader/context of the parsing
|
||||
* @param element The element to be processed
|
||||
* @param diagram The diagram to be built
|
||||
* @param transform The transform to apply to all elements at this level
|
||||
* @throws ParsingException Indicates an invalid content to an element
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform transform) throws ParsingException;
|
||||
|
||||
/**
|
||||
* Check if this processor handles the element specified
|
||||
*
|
||||
* @param element The element to check
|
||||
* @return True if this processor can handle the given element
|
||||
*/
|
||||
public boolean handles(Element element);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import org.newdawn.slick.geom.Ellipse;
|
||||
import org.newdawn.slick.geom.Shape;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Figure;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Processor for <ellipse> and <path> nodes marked as arcs
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class EllipseProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform t) throws ParsingException {
|
||||
Transform transform = Util.getTransform(element);
|
||||
transform = new Transform(t, transform);
|
||||
|
||||
float x = Util.getFloatAttribute(element,"cx");
|
||||
float y = Util.getFloatAttribute(element,"cy");
|
||||
float rx = Util.getFloatAttribute(element,"rx");
|
||||
float ry = Util.getFloatAttribute(element,"ry");
|
||||
|
||||
Ellipse ellipse = new Ellipse(x,y,rx,ry);
|
||||
Shape shape = ellipse.transform(transform);
|
||||
|
||||
NonGeometricData data = Util.getNonGeometricData(element);
|
||||
data.addAttribute("cx", ""+x);
|
||||
data.addAttribute("cy", ""+y);
|
||||
data.addAttribute("rx", ""+rx);
|
||||
data.addAttribute("ry", ""+ry);
|
||||
|
||||
diagram.addFigure(new Figure(Figure.ELLIPSE, shape, data, transform));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("ellipse")) {
|
||||
return true;
|
||||
}
|
||||
if (element.getNodeName().equals("path")) {
|
||||
if ("arc".equals(element.getAttributeNS(Util.SODIPODI, "type"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* TODO: Document this class
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class GroupProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("g")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**O
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform t) throws ParsingException {
|
||||
Transform transform = Util.getTransform(element);
|
||||
transform = new Transform(t, transform);
|
||||
|
||||
loader.loadChildren(element, transform);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A custom non-geometric data type that can pass back any attribute
|
||||
* on the field.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class InkscapeNonGeometricData extends NonGeometricData {
|
||||
/** The element read from the SVG */
|
||||
private Element element;
|
||||
|
||||
/**
|
||||
* Create a new non-geometric data holder
|
||||
*
|
||||
* @param metaData The metadata provided
|
||||
* @param element The XML element from the SVG document
|
||||
*/
|
||||
public InkscapeNonGeometricData(String metaData, Element element) {
|
||||
super(metaData);
|
||||
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.NonGeometricData#getAttribute(java.lang.String)
|
||||
*/
|
||||
public String getAttribute(String attribute) {
|
||||
String result = super.getAttribute(attribute);
|
||||
if (result == null) {
|
||||
result = element.getAttribute(attribute);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML element that is wrapped by this instance.
|
||||
*
|
||||
* @return The XML element for this instance
|
||||
*/
|
||||
public Element getElement() {
|
||||
return element;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.newdawn.slick.geom.Line;
|
||||
import org.newdawn.slick.geom.Polygon;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Figure;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A processor for the <line> element
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class LineProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* Process the points in a polygon definition
|
||||
*
|
||||
* @param poly The polygon being built
|
||||
* @param element The XML element being read
|
||||
* @param tokens The tokens representing the path
|
||||
* @return The number of points found
|
||||
* @throws ParsingException Indicates an invalid token in the path
|
||||
*/
|
||||
private static int processPoly(Polygon poly, Element element, StringTokenizer tokens) throws ParsingException {
|
||||
int count = 0;
|
||||
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String nextToken = tokens.nextToken();
|
||||
if (nextToken.equals("L")) {
|
||||
continue;
|
||||
}
|
||||
if (nextToken.equals("z")) {
|
||||
break;
|
||||
}
|
||||
if (nextToken.equals("M")) {
|
||||
continue;
|
||||
}
|
||||
if (nextToken.equals("C")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String tokenX = nextToken;
|
||||
String tokenY = tokens.nextToken();
|
||||
|
||||
try {
|
||||
float x = Float.parseFloat(tokenX);
|
||||
float y = Float.parseFloat(tokenY);
|
||||
|
||||
poly.addPoint(x,y);
|
||||
count++;
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(element.getAttribute("id"), "Invalid token in points list", e);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform t) throws ParsingException {
|
||||
Transform transform = Util.getTransform(element);
|
||||
transform = new Transform(t, transform);
|
||||
|
||||
float x1;
|
||||
float y1;
|
||||
float x2;
|
||||
float y2;
|
||||
|
||||
if (element.getNodeName().equals("line")) {
|
||||
x1 = Float.parseFloat(element.getAttribute("x1"));
|
||||
x2 = Float.parseFloat(element.getAttribute("x2"));
|
||||
y1 = Float.parseFloat(element.getAttribute("y1"));
|
||||
y2 = Float.parseFloat(element.getAttribute("y2"));
|
||||
} else {
|
||||
String points = element.getAttribute("d");
|
||||
StringTokenizer tokens = new StringTokenizer(points, ", ");
|
||||
Polygon poly = new Polygon();
|
||||
if (processPoly(poly, element, tokens) == 2) {
|
||||
x1 = poly.getPoint(0)[0];
|
||||
y1 = poly.getPoint(0)[1];
|
||||
x2 = poly.getPoint(1)[0];
|
||||
y2 = poly.getPoint(1)[1];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float[] in = new float[] {x1,y1,x2,y2};
|
||||
float[] out = new float[4];
|
||||
|
||||
transform.transform(in,0,out,0,2);
|
||||
Line line = new Line(out[0],out[1],out[2],out[3]);
|
||||
|
||||
NonGeometricData data = Util.getNonGeometricData(element);
|
||||
data.addAttribute("x1",""+x1);
|
||||
data.addAttribute("x2",""+x2);
|
||||
data.addAttribute("y1",""+y1);
|
||||
data.addAttribute("y2",""+y2);
|
||||
|
||||
diagram.addFigure(new Figure(Figure.LINE, line, data, transform));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("line")) {
|
||||
return true;
|
||||
}
|
||||
if (element.getNodeName().equals("path")) {
|
||||
if (!"arc".equals(element.getAttributeNS(Util.SODIPODI, "type"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.newdawn.slick.geom.Path;
|
||||
import org.newdawn.slick.geom.Shape;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Figure;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A processor for the <polygon> and <path> elements marked as not an arc.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class PathProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* Process the points in a polygon definition
|
||||
*
|
||||
* @param element The XML element being read
|
||||
* @param tokens The tokens representing the path
|
||||
* @return The number of points found
|
||||
* @throws ParsingException Indicates an invalid token in the path
|
||||
*/
|
||||
private static Path processPoly(Element element, StringTokenizer tokens) throws ParsingException {
|
||||
int count = 0;
|
||||
|
||||
ArrayList pts = new ArrayList();
|
||||
boolean moved = false;
|
||||
boolean reasonToBePath = false;
|
||||
Path path = null;
|
||||
|
||||
while (tokens.hasMoreTokens()) {
|
||||
try {
|
||||
String nextToken = tokens.nextToken();
|
||||
if (nextToken.equals("L")) {
|
||||
float x = Float.parseFloat(tokens.nextToken());
|
||||
float y = Float.parseFloat(tokens.nextToken());
|
||||
path.lineTo(x,y);
|
||||
continue;
|
||||
}
|
||||
if (nextToken.equals("z")) {
|
||||
path.close();
|
||||
continue;
|
||||
}
|
||||
if (nextToken.equals("M")) {
|
||||
if (!moved) {
|
||||
moved = true;
|
||||
float x = Float.parseFloat(tokens.nextToken());
|
||||
float y = Float.parseFloat(tokens.nextToken());
|
||||
path = new Path(x,y);
|
||||
continue;
|
||||
}
|
||||
|
||||
reasonToBePath = true;
|
||||
float x = Float.parseFloat(tokens.nextToken());
|
||||
float y = Float.parseFloat(tokens.nextToken());
|
||||
path.startHole(x,y);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (nextToken.equals("C")) {
|
||||
reasonToBePath = true;
|
||||
float cx1 = Float.parseFloat(tokens.nextToken());
|
||||
float cy1 = Float.parseFloat(tokens.nextToken());
|
||||
float cx2 = Float.parseFloat(tokens.nextToken());
|
||||
float cy2 = Float.parseFloat(tokens.nextToken());
|
||||
float x = Float.parseFloat(tokens.nextToken());
|
||||
float y = Float.parseFloat(tokens.nextToken());
|
||||
path.curveTo(x,y,cx1,cy1,cx2,cy2);
|
||||
continue;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(element.getAttribute("id"), "Invalid token in points list", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!reasonToBePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform t) throws ParsingException {
|
||||
Transform transform = Util.getTransform(element);
|
||||
transform = new Transform(t, transform);
|
||||
|
||||
String points = element.getAttribute("points");
|
||||
if (element.getNodeName().equals("path")) {
|
||||
points = element.getAttribute("d");
|
||||
}
|
||||
|
||||
StringTokenizer tokens = new StringTokenizer(points, ", ");
|
||||
Path path = processPoly(element, tokens);
|
||||
NonGeometricData data = Util.getNonGeometricData(element);
|
||||
if (path != null) {
|
||||
Shape shape = path.transform(transform);
|
||||
|
||||
diagram.addFigure(new Figure(Figure.PATH, shape, data, transform));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("path")) {
|
||||
if (!"arc".equals(element.getAttributeNS(Util.SODIPODI, "type"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.newdawn.slick.geom.Polygon;
|
||||
import org.newdawn.slick.geom.Shape;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Figure;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A processor for the <polygon> and <path> elements marked as not an arc.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class PolygonProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* Process the points in a polygon definition
|
||||
*
|
||||
* @param poly The polygon being built
|
||||
* @param element The XML element being read
|
||||
* @param tokens The tokens representing the path
|
||||
* @return The number of points found
|
||||
* @throws ParsingException Indicates an invalid token in the path
|
||||
*/
|
||||
private static int processPoly(Polygon poly, Element element, StringTokenizer tokens) throws ParsingException {
|
||||
int count = 0;
|
||||
|
||||
ArrayList pts = new ArrayList();
|
||||
boolean moved = false;
|
||||
boolean closed = false;
|
||||
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String nextToken = tokens.nextToken();
|
||||
if (nextToken.equals("L")) {
|
||||
continue;
|
||||
}
|
||||
if (nextToken.equals("z")) {
|
||||
closed = true;
|
||||
break;
|
||||
}
|
||||
if (nextToken.equals("M")) {
|
||||
if (!moved) {
|
||||
moved = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (nextToken.equals("C")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String tokenX = nextToken;
|
||||
String tokenY = tokens.nextToken();
|
||||
|
||||
try {
|
||||
float x = Float.parseFloat(tokenX);
|
||||
float y = Float.parseFloat(tokenY);
|
||||
|
||||
poly.addPoint(x,y);
|
||||
count++;
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(element.getAttribute("id"), "Invalid token in points list", e);
|
||||
}
|
||||
}
|
||||
|
||||
poly.setClosed(closed);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform t) throws ParsingException {
|
||||
Transform transform = Util.getTransform(element);
|
||||
transform = new Transform(t, transform);
|
||||
|
||||
String points = element.getAttribute("points");
|
||||
if (element.getNodeName().equals("path")) {
|
||||
points = element.getAttribute("d");
|
||||
}
|
||||
|
||||
StringTokenizer tokens = new StringTokenizer(points, ", ");
|
||||
Polygon poly = new Polygon();
|
||||
int count = processPoly(poly, element, tokens);
|
||||
|
||||
NonGeometricData data = Util.getNonGeometricData(element);
|
||||
if (count > 3) {
|
||||
Shape shape = poly.transform(transform);
|
||||
|
||||
diagram.addFigure(new Figure(Figure.POLYGON, shape, data, transform));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("polygon")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (element.getNodeName().equals("path")) {
|
||||
if (!"arc".equals(element.getAttributeNS(Util.SODIPODI, "type"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import org.newdawn.slick.geom.Rectangle;
|
||||
import org.newdawn.slick.geom.Shape;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Figure;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A processor for the <rect> element.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class RectProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram, Transform t) throws ParsingException {
|
||||
Transform transform = Util.getTransform(element);
|
||||
transform = new Transform(t, transform);
|
||||
|
||||
float width = Float.parseFloat(element.getAttribute("width"));
|
||||
float height = Float.parseFloat(element.getAttribute("height"));
|
||||
float x = Float.parseFloat(element.getAttribute("x"));
|
||||
float y = Float.parseFloat(element.getAttribute("y"));
|
||||
|
||||
Rectangle rect = new Rectangle(x,y,width+1,height+1);
|
||||
Shape shape = rect.transform(transform);
|
||||
|
||||
NonGeometricData data = Util.getNonGeometricData(element);
|
||||
data.addAttribute("width", ""+width);
|
||||
data.addAttribute("height", ""+height);
|
||||
data.addAttribute("x", ""+x);
|
||||
data.addAttribute("y", ""+y);
|
||||
|
||||
diagram.addFigure(new Figure(Figure.RECTANGLE, shape, data, transform));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
if (element.getNodeName().equals("rect")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import org.newdawn.slick.geom.Shape;
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.Diagram;
|
||||
import org.newdawn.slick.svg.Figure;
|
||||
import org.newdawn.slick.svg.Loader;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Processor for the "use", a tag that allows references to other elements
|
||||
* and cloning.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class UseProcessor implements ElementProcessor {
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#handles(org.w3c.dom.Element)
|
||||
*/
|
||||
public boolean handles(Element element) {
|
||||
return element.getNodeName().equals("use");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.svg.inkscape.ElementProcessor#process(org.newdawn.slick.svg.Loader, org.w3c.dom.Element, org.newdawn.slick.svg.Diagram, org.newdawn.slick.geom.Transform)
|
||||
*/
|
||||
public void process(Loader loader, Element element, Diagram diagram,
|
||||
Transform transform) throws ParsingException {
|
||||
|
||||
String ref = element.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
String href = Util.getAsReference(ref);
|
||||
|
||||
Figure referenced = diagram.getFigureByID(href);
|
||||
if (referenced == null) {
|
||||
throw new ParsingException(element, "Unable to locate referenced element: "+href);
|
||||
}
|
||||
|
||||
Transform local = Util.getTransform(element);
|
||||
Transform trans = local.concatenate(referenced.getTransform());
|
||||
|
||||
NonGeometricData data = Util.getNonGeometricData(element);
|
||||
Shape shape = referenced.getShape().transform(trans);
|
||||
data.addAttribute(NonGeometricData.FILL, referenced.getData().getAttribute(NonGeometricData.FILL));
|
||||
data.addAttribute(NonGeometricData.STROKE, referenced.getData().getAttribute(NonGeometricData.STROKE));
|
||||
data.addAttribute(NonGeometricData.OPACITY, referenced.getData().getAttribute(NonGeometricData.OPACITY));
|
||||
data.addAttribute(NonGeometricData.STROKE_WIDTH, referenced.getData().getAttribute(NonGeometricData.STROKE_WIDTH));
|
||||
|
||||
Figure figure = new Figure(referenced.getType(), shape, data, trans);
|
||||
diagram.addFigure(figure);
|
||||
}
|
||||
|
||||
}
|
||||
198
lib/slick-source/org/newdawn/slick/svg/inkscape/Util.java
Normal file
198
lib/slick-source/org/newdawn/slick/svg/inkscape/Util.java
Normal file
@@ -0,0 +1,198 @@
|
||||
package org.newdawn.slick.svg.inkscape;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.newdawn.slick.geom.Transform;
|
||||
import org.newdawn.slick.svg.NonGeometricData;
|
||||
import org.newdawn.slick.svg.ParsingException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A set of utility for processing the SVG documents produced by Inkscape
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class Util {
|
||||
/** The namespace for inkscape */
|
||||
public static final String INKSCAPE = "http://www.inkscape.org/namespaces/inkscape";
|
||||
/** The namespace for sodipodi */
|
||||
public static final String SODIPODI = "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
|
||||
/** The namespace for xlink */
|
||||
public static final String XLINK = "http://www.w3.org/1999/xlink";
|
||||
|
||||
/**
|
||||
* Get the non-geometric data information from an XML element
|
||||
*
|
||||
* @param element The element to be processed
|
||||
* @return The non-geometric data (i.e. stroke, fill, etc)
|
||||
*/
|
||||
static NonGeometricData getNonGeometricData(Element element) {
|
||||
String meta = getMetaData(element);
|
||||
|
||||
NonGeometricData data = new InkscapeNonGeometricData(meta, element);
|
||||
data.addAttribute(NonGeometricData.ID, element.getAttribute("id"));
|
||||
data.addAttribute(NonGeometricData.FILL, getStyle(element, NonGeometricData.FILL));
|
||||
data.addAttribute(NonGeometricData.STROKE, getStyle(element, NonGeometricData.STROKE));
|
||||
data.addAttribute(NonGeometricData.OPACITY, getStyle(element, NonGeometricData.OPACITY));
|
||||
data.addAttribute(NonGeometricData.STROKE_DASHARRAY, getStyle(element, NonGeometricData.STROKE_DASHARRAY));
|
||||
data.addAttribute(NonGeometricData.STROKE_DASHOFFSET, getStyle(element, NonGeometricData.STROKE_DASHOFFSET));
|
||||
data.addAttribute(NonGeometricData.STROKE_MITERLIMIT, getStyle(element, NonGeometricData.STROKE_MITERLIMIT));
|
||||
data.addAttribute(NonGeometricData.STROKE_OPACITY, getStyle(element, NonGeometricData.STROKE_OPACITY));
|
||||
data.addAttribute(NonGeometricData.STROKE_WIDTH, getStyle(element, NonGeometricData.STROKE_WIDTH));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the meta data store within an element either in the label or
|
||||
* id atributes
|
||||
*
|
||||
* @param element The element to be processed
|
||||
* @return The meta data stored
|
||||
*/
|
||||
static String getMetaData(Element element) {
|
||||
String label = element.getAttributeNS(INKSCAPE, "label");
|
||||
if ((label != null) && (!label.equals(""))) {
|
||||
return label;
|
||||
}
|
||||
|
||||
return element.getAttribute("id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style attribute setting for a given style information element (i.e. fill, stroke)
|
||||
*
|
||||
* @param element The element to be processed
|
||||
* @param styleName The name of the attribute to retrieve
|
||||
* @return The style value
|
||||
*/
|
||||
static String getStyle(Element element, String styleName) {
|
||||
String value = element.getAttribute(styleName);
|
||||
|
||||
if ((value != null) && (value.length() > 0)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
String style = element.getAttribute("style");
|
||||
return extractStyle(style, styleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the style value from a Inkscape encoded string
|
||||
*
|
||||
* @param style The style string to be decoded
|
||||
* @param attribute The style attribute to retrieve
|
||||
* @return The value for the given attribute
|
||||
*/
|
||||
static String extractStyle(String style, String attribute) {
|
||||
if (style == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringTokenizer tokens = new StringTokenizer(style,";");
|
||||
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String token = tokens.nextToken();
|
||||
String key = token.substring(0,token.indexOf(':'));
|
||||
if (key.equals(attribute)) {
|
||||
return token.substring(token.indexOf(':')+1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a transform defined in the XML
|
||||
*
|
||||
* @param element The element from which the transform should be read
|
||||
* @return The transform to be applied
|
||||
*/
|
||||
static Transform getTransform(Element element) {
|
||||
return getTransform(element, "transform");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a transform defined in the XML
|
||||
*
|
||||
* @param element The element from which the transform should be read
|
||||
* @param attribute The name of the attribute holding the transform
|
||||
* @return The transform to be applied
|
||||
*/
|
||||
static Transform getTransform(Element element, String attribute) {
|
||||
String str = element.getAttribute(attribute);
|
||||
if (str == null) {
|
||||
return new Transform();
|
||||
}
|
||||
|
||||
if (str.equals("")) {
|
||||
return new Transform();
|
||||
} else if (str.startsWith("translate")) {
|
||||
str = str.substring(0, str.length()-1);
|
||||
str = str.substring("translate(".length());
|
||||
StringTokenizer tokens = new StringTokenizer(str, ", ");
|
||||
float x = Float.parseFloat(tokens.nextToken());
|
||||
float y = Float.parseFloat(tokens.nextToken());
|
||||
|
||||
return Transform.createTranslateTransform(x,y);
|
||||
} else if (str.startsWith("matrix")) {
|
||||
float[] pose = new float[6];
|
||||
str = str.substring(0, str.length()-1);
|
||||
str = str.substring("matrix(".length());
|
||||
StringTokenizer tokens = new StringTokenizer(str, ", ");
|
||||
float[] tr = new float[6];
|
||||
for (int j=0;j<tr.length;j++) {
|
||||
tr[j] = Float.parseFloat(tokens.nextToken());
|
||||
}
|
||||
|
||||
pose[0] = tr[0];
|
||||
pose[1] = tr[2];
|
||||
pose[2] = tr[4];
|
||||
pose[3] = tr[1];
|
||||
pose[4] = tr[3];
|
||||
pose[5] = tr[5];
|
||||
|
||||
return new Transform(pose);
|
||||
}
|
||||
|
||||
return new Transform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a floating point attribute that may appear in either the default or
|
||||
* SODIPODI namespace
|
||||
*
|
||||
* @param element The element from which the attribute should be read
|
||||
* @param attr The attribute to be read
|
||||
* @return The value from the given attribute
|
||||
* @throws ParsingException Indicates the value in the attribute was not a float
|
||||
*/
|
||||
static float getFloatAttribute(Element element, String attr) throws ParsingException {
|
||||
String cx = element.getAttribute(attr);
|
||||
if ((cx == null) || (cx.equals(""))) {
|
||||
cx = element.getAttributeNS(SODIPODI, attr);
|
||||
}
|
||||
|
||||
try {
|
||||
return Float.parseFloat(cx);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(element, "Invalid value for: "+attr, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attribute value as a reference to another entity
|
||||
*
|
||||
* @param value The value to treat as reference
|
||||
* @return The reference part of the attribute value
|
||||
*/
|
||||
public static String getAsReference(String value) {
|
||||
if (value.length() < 2) {
|
||||
return "";
|
||||
}
|
||||
|
||||
value = value.substring(1, value.length());
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user