/*
* @(#)SerializedPathIterator.java
*
* $Date: 2014-03-13 09:15:48 +0100 (Cs, 13 márc. 2014) $
*
* Copyright (c) 2011 by Jeremy Wood.
* All rights reserved.
*
* The copyright of this software is owned by Jeremy Wood.
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* Jeremy Wood. For details see accompanying license terms.
*
* This software is probably, but not necessarily, discussed here:
* https://javagraphics.java.net/
*
* That site should also contain the most recent official version
* of this software. (See the SVN repository for more details.)
*/
package com.bric.geom;
import java.awt.geom.PathIterator;
/** A PathIterator that parses serialized shape info.
*/
class SerializedPathIterator implements PathIterator {
char[] c;
int ctr = 0;
double[] data = new double[6];
int currentSegment = -1;
int windingRule;
public SerializedPathIterator(String s,int windingRule) {
if(!(windingRule==PathIterator.WIND_EVEN_ODD || windingRule==PathIterator.WIND_NON_ZERO))
throw new IllegalArgumentException("The winding rule must be PathIterator.WIND_NON_ZERO or PathIterator.WIND_EVEN_ODD");
c = s.toCharArray();
this.windingRule = windingRule;
next();
}
public int getWindingRule() {
return windingRule;
}
protected void consumeWhiteSpace(boolean expectingWhiteSpace) {
if(ctr>=c.length) {
ctr = c.length+2;
return;
}
char ch = c[ctr];
if(Character.isWhitespace(ch)==false) {
if(expectingWhiteSpace==false)
return;
throw new ParserException("expected whitespace", ctr, 1);
}
while(true) {
ctr++;
if(ctr>=c.length) {
ctr = c.length+2;
return;
}
ch = c[ctr];
if(Character.isWhitespace(ch)==false) {
return;
}
}
}
public void next() {
consumeWhiteSpace(false);
if(ctr>=c.length) {
ctr = c.length+2;
return;
}
int terms;
char k = c[ctr];
switch(k) {
case 'm':
case 'M':
currentSegment = PathIterator.SEG_MOVETO;
terms = 2;
break;
case 'l':
case 'L':
currentSegment = PathIterator.SEG_LINETO;
terms = 2;
break;
case 'q':
case 'Q':
currentSegment = PathIterator.SEG_QUADTO;
terms = 4;
break;
case 'c':
case 'C':
currentSegment = PathIterator.SEG_CUBICTO;
terms = 6;
break;
case 'z':
case 'Z':
currentSegment = PathIterator.SEG_CLOSE;
terms = 0;
break;
default:
throw new ParserException("Unrecognized character in shape data: \'"+c[ctr]+"\'", ctr, 1);
}
ctr++;
if(terms>0) {
parseTerms(terms);
} else {
if(ctr<c.length) {
if(Character.isWhitespace( c[ctr] )==false)
throw new ParserException("expected whitespace after z", ctr, 1);
}
}
}
class ParserException extends RuntimeException {
private static final long serialVersionUID = 1L;
ParserException(String msg,int ptr,int length) {
super(msg);
System.err.println("\""+(new String(c))+"\"");
StringBuffer sb = new StringBuffer();
for(int a = 0; a<ptr+1; a++) {
sb.append(' ');
}
for(int a = 0; a<length; a++) {
sb.append('^');
}
System.err.println(sb);
}
}
protected void parseTerms(int terms) {
for(int a = 0; a<terms; a++) {
data[a] = parseTerm();
}
}
protected double parseTerm() {
consumeWhiteSpace(true);
int i = ctr;
while(i<c.length && (Character.isWhitespace(c[i])==false) ) {
i++;
}
String string = new String(c, ctr, i-ctr);
try {
return Double.parseDouble( string );
} catch(RuntimeException e) {
//just constructing this prints data to System.err:
ParserException e2 = new ParserException(e.getMessage(), ctr, i-ctr);
throw e2;
} finally {
ctr = i;
}
}
public int currentSegment(double[] d) {
d[0] = data[0];
d[1] = data[1];
d[2] = data[2];
d[3] = data[3];
d[4] = data[4];
d[5] = data[5];
return currentSegment;
}
public int currentSegment(float[] f) {
f[0] = (float)data[0];
f[1] = (float)data[1];
f[2] = (float)data[2];
f[3] = (float)data[3];
f[4] = (float)data[4];
f[5] = (float)data[5];
return currentSegment;
}
public boolean isDone() {
return ctr>c.length+1;
}
}