added the path commands q, Q, t, T, s, S to the PolygonParser

This commit is contained in:
hneemann 2018-11-27 15:22:01 +01:00
parent a119caeba3
commit c245cf9c7f
3 changed files with 96 additions and 7 deletions

View File

@ -76,7 +76,7 @@ public class Polygon implements Iterable<VectorInterface> {
} }
/** /**
* Adds a new bezier line to the polygon. * Adds a new cubic bezier curve to the polygon.
* *
* @param c1 the first control point to add * @param c1 the first control point to add
* @param c2 the second control point to add * @param c2 the second control point to add
@ -84,6 +84,8 @@ public class Polygon implements Iterable<VectorInterface> {
* @return this for chained calls * @return this for chained calls
*/ */
public Polygon add(VectorInterface c1, VectorInterface c2, VectorInterface p) { public Polygon add(VectorInterface c1, VectorInterface c2, VectorInterface p) {
if (points.size() == 0)
throw new RuntimeException("cubic bezier curve is not allowed to be the first path element");
isBezierStart.add(points.size()); isBezierStart.add(points.size());
points.add(c1); points.add(c1);
points.add(c2); points.add(c2);

View File

@ -18,6 +18,8 @@ public class PolygonParser {
private float value; private float value;
private float x; private float x;
private float y; private float y;
private VectorInterface lastQuadraticControlPoint;
private VectorInterface lastCubicControlPoint;
/** /**
* Creates a new instance * Creates a new instance
@ -126,47 +128,76 @@ public class PolygonParser {
switch (command) { switch (command) {
case 'M': case 'M':
p.add(nextVector()); p.add(nextVector());
clearControl();
break; break;
case 'm': case 'm':
p.add(nextVectorInc()); p.add(nextVectorInc());
clearControl();
break; break;
case 'V': case 'V':
y = nextValue(); y = nextValue();
p.add(new VectorFloat(x, y)); p.add(getCurrent());
clearControl();
break; break;
case 'v': case 'v':
y += nextValue(); y += nextValue();
p.add(new VectorFloat(x, y)); p.add(getCurrent());
clearControl();
break; break;
case 'H': case 'H':
x = nextValue(); x = nextValue();
p.add(new VectorFloat(x, y)); p.add(getCurrent());
clearControl();
break; break;
case 'h': case 'h':
x += nextValue(); x += nextValue();
p.add(new VectorFloat(x, y)); p.add(getCurrent());
clearControl();
break; break;
case 'l': case 'l':
p.add(nextVectorInc()); p.add(nextVectorInc());
clearControl();
break; break;
case 'L': case 'L':
p.add(nextVector()); p.add(nextVector());
clearControl();
break; break;
case 'c': case 'c':
p.add(nextVectorRel(), nextVectorRel(), nextVectorInc()); p.add(nextVectorRel(), setLastC3(nextVectorRel()), nextVectorInc());
break; break;
case 'C': case 'C':
p.add(nextVector(), nextVector(), nextVector()); p.add(nextVector(), setLastC3(nextVector()), nextVector());
break;
case 'q':
addQuadratic(p, getCurrent(), setLastC2(nextVectorRel()), nextVectorInc());
break;
case 'Q':
addQuadratic(p, getCurrent(), setLastC2(nextVector()), nextVector());
break;
case 's':
addCubicWithReflect(p, getCurrent(), setLastC3(nextVectorRel()), nextVectorInc());
break;
case 'S':
addCubicWithReflect(p, getCurrent(), setLastC3(nextVector()), nextVector());
break;
case 't':
addQuadraticWithReflect(p, getCurrent(), nextVectorInc());
break;
case 'T':
addQuadraticWithReflect(p, getCurrent(), nextVector());
break; break;
case 'a': case 'a':
addArc(p, nextVectorInc(), nextValue(), nextValue() != 0, nextValue() != 0, nextVectorInc()); addArc(p, nextVectorInc(), nextValue(), nextValue() != 0, nextValue() != 0, nextVectorInc());
clearControl();
break; break;
case 'A': case 'A':
addArc(p, nextVector(), nextValue(), nextValue() != 0, nextValue() != 0, nextVector()); addArc(p, nextVector(), nextValue(), nextValue() != 0, nextValue() != 0, nextVector());
clearControl();
break; break;
case 'Z': case 'Z':
case 'z': case 'z':
p.setClosed(true); p.setClosed(true);
clearControl();
break; break;
default: default:
throw new ParserException("unsupported path command " + command); throw new ParserException("unsupported path command " + command);
@ -175,10 +206,58 @@ public class PolygonParser {
return p; return p;
} }
private VectorInterface getCurrent() {
return new VectorFloat(x, y);
}
private VectorInterface setLastC2(VectorInterface p) {
lastQuadraticControlPoint = p;
lastCubicControlPoint = null;
return p;
}
private VectorInterface setLastC3(VectorInterface p) {
lastCubicControlPoint = p;
lastQuadraticControlPoint = null;
return p;
}
private void clearControl() {
lastQuadraticControlPoint = null;
lastCubicControlPoint = null;
}
private VectorInterface getLastC2() {
if (lastQuadraticControlPoint == null)
return getCurrent();
return lastQuadraticControlPoint;
}
private VectorInterface getLastC3() {
if (lastCubicControlPoint == null)
return getCurrent();
return lastCubicControlPoint;
}
private void addArc(Polygon p, VectorFloat rad, float rot, boolean large, boolean sweep, VectorFloat pos) { private void addArc(Polygon p, VectorFloat rad, float rot, boolean large, boolean sweep, VectorFloat pos) {
p.add(pos); p.add(pos);
} }
private void addQuadratic(Polygon poly, VectorInterface start, VectorInterface c, VectorInterface p) {
c = c.mul(2.0f / 3);
poly.add(start.mul(1f / 3).add(c), p.mul(1f / 3).add(c), p);
}
private void addQuadraticWithReflect(Polygon poly, VectorInterface start, VectorInterface p) {
VectorInterface c = start.add(start.sub(getLastC2()));
addQuadratic(poly, start, setLastC2(c), p);
}
private void addCubicWithReflect(Polygon poly, VectorInterface start, VectorInterface c2, VectorInterface p) {
VectorInterface c1 = start.add(start.sub(getLastC3()));
poly.add(c1, c2, p);
}
/** /**
* The parser exception * The parser exception
*/ */

View File

@ -54,6 +54,14 @@ public interface VectorInterface {
*/ */
VectorInterface div(int d); VectorInterface div(int d);
/**
* Creates a new vector which has the value this*m
*
* @param m m
* @return this*m
*/
VectorFloat mul(float m);
/** /**
* Creates a new vector which has the value this-a * Creates a new vector which has the value this-a
* *