added combined transforms

This commit is contained in:
hneemann 2018-12-03 22:00:44 +01:00
parent 402a38387f
commit bff8d7ea43

View File

@ -11,6 +11,9 @@ import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import java.awt.*; import java.awt.*;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.HashMap; import java.util.HashMap;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -151,52 +154,97 @@ class Context {
} }
private static void readTransform(Context c, String value) throws SvgException { private static void readTransform(Context c, String value) throws SvgException {
StringTokenizer st = new StringTokenizer(value, "(),"); StreamTokenizer tokenzer = new StreamTokenizer(new StringReader(value));
try {
Transform t; Transform t;
final String trans = st.nextToken(); while (true) {
switch (trans) { final int tok = tokenzer.nextToken();
if (tok == StreamTokenizer.TT_EOF)
break;
if (tok != StreamTokenizer.TT_WORD)
throw new SvgException("invalid transform", null);
switch (tokenzer.sval) {
case "translate": case "translate":
final float x = Float.parseFloat(st.nextToken()); consume(tokenzer, '(');
final float x = readFloat(tokenzer);
float y = 0; float y = 0;
if (st.hasMoreTokens()) if (isComma(tokenzer))
y = Float.parseFloat(st.nextToken()); y = readFloat(tokenzer);
consume(tokenzer, ')');
t = new TransformTranslate(new VectorFloat(x, y)); t = new TransformTranslate(new VectorFloat(x, y));
break; break;
case "scale": case "scale":
final float xs = Float.parseFloat(st.nextToken()); consume(tokenzer, '(');
final float xs = readFloat(tokenzer);
float ys = xs; float ys = xs;
if (st.hasMoreTokens()) if (isComma(tokenzer))
ys = Float.parseFloat(st.nextToken()); ys = readFloat(tokenzer);
consume(tokenzer, ')');
t = new TransformMatrix(xs, 0, 0, ys, 0, 0); t = new TransformMatrix(xs, 0, 0, ys, 0, 0);
break; break;
case "matrix": case "matrix":
final float ma = Float.parseFloat(st.nextToken()); consume(tokenzer, '(');
final float mb = Float.parseFloat(st.nextToken()); final float ma = readFloat(tokenzer);
final float mc = Float.parseFloat(st.nextToken()); consume(tokenzer, ',');
final float mb = readFloat(tokenzer);
consume(tokenzer, ',');
final float mc = readFloat(tokenzer);
consume(tokenzer, ',');
final float md = readFloat(tokenzer);
consume(tokenzer, ',');
final float mx = readFloat(tokenzer);
consume(tokenzer, ',');
final float my = readFloat(tokenzer);
consume(tokenzer, ')');
t = new TransformMatrix( t = new TransformMatrix(
ma, ma,
mc, mc,
mb, mb,
Float.parseFloat(st.nextToken()), md,
Float.parseFloat(st.nextToken()), mx,
Float.parseFloat(st.nextToken())); my);
break; break;
case "rotate": case "rotate":
float w = Float.parseFloat(st.nextToken()); consume(tokenzer, '(');
if (st.hasMoreTokens()) { float w = readFloat(tokenzer);
if (isComma(tokenzer)) {
t = TransformMatrix.rotate(w); t = TransformMatrix.rotate(w);
float xc = Float.parseFloat(st.nextToken()); float xc = readFloat(tokenzer);
float yc = Float.parseFloat(st.nextToken()); consume(tokenzer, ',');
float yc = readFloat(tokenzer);
t = Transform.mul(new TransformTranslate(-xc, -yc), t); t = Transform.mul(new TransformTranslate(-xc, -yc), t);
t = Transform.mul(t, new TransformTranslate(xc, yc)); t = Transform.mul(t, new TransformTranslate(xc, yc));
} else } else
t = TransformMatrix.rotate(w); t = TransformMatrix.rotate(w);
consume(tokenzer, ')');
break; break;
default: default:
throw new SvgException("unknown transform: " + value, null); throw new SvgException("unknown transform: " + value, null);
} }
c.tr = Transform.mul(t, c.tr); c.tr = Transform.mul(t, c.tr);
} }
} catch (IOException e) {
// can never happen
}
}
private static boolean isComma(StreamTokenizer tokenzer) throws IOException {
if (tokenzer.nextToken() == ',')
return true;
tokenzer.pushBack();
return false;
}
private static void consume(StreamTokenizer tokenzer, char c) throws IOException, SvgException {
if (tokenzer.nextToken() != c)
throw new SvgException("expected " + c, null);
}
private static float readFloat(StreamTokenizer tokenzer) throws IOException, SvgException {
if (tokenzer.nextToken() != StreamTokenizer.TT_NUMBER)
throw new SvgException("number expected", null);
return (float) tokenzer.nval;
}
private static Color getColorFromString(String v) { private static Color getColorFromString(String v) {
if (v.equalsIgnoreCase("none")) if (v.equalsIgnoreCase("none"))