FlatteningPathIteratorpublic class FlatteningPathIterator extends Object implements PathIteratorThe Class FlatteningPathIterator takes a PathIterator for traversing a curved
shape and flattens it by estimating the curve as a series of line segments.
The flattening factor indicates how far the estimating line segments are
allowed to be from the actual curve: the FlatteningPathIterator will keep
dividing each curved segment into smaller and smaller flat segments until
either the segments are within the flattening factor of the curve or until
the buffer limit is reached. |
Fields Summary |
---|
private static final int | BUFFER_SIZEThe default points buffer size. | private static final int | BUFFER_LIMITThe default curve subdivision limit. | private static final int | BUFFER_CAPACITYThe points buffer capacity. | int | bufTypeThe type of current segment to be flat. | int | bufLimitThe curve subdivision limit. | int | bufSizeThe current points buffer size. | int | bufIndexThe inner cursor position in points buffer. | int | bufSubdivThe current subdivision count. | double[] | bufThe points buffer. | boolean | bufEmptyThe indicator of empty points buffer. | PathIterator | pThe source PathIterator. | double | flatnessThe flatness of new path. | double | flatness2The square of flatness. | double | pxThe x coordinate of previous path segment. | double | pyThe y coordinate of previous path segment. | double[] | coordsThe temporary buffer for getting points from PathIterator. |
Constructors Summary |
---|
public FlatteningPathIterator(PathIterator path, double flatness)Instantiates a new flattening path iterator given the path iterator for a
(possibly) curved path and a flattening factor which indicates how close
together the points on the curve should be chosen. The buffer limit
defaults to 16 which means that each curve will be divided into no more
than 16 segments regardless of the flattening factor.
this(path, flatness, BUFFER_LIMIT);
| public FlatteningPathIterator(PathIterator path, double flatness, int limit)Instantiates a new flattening path iterator given the path iterator for a
(possibly) curved path and a flattening factor and a buffer limit. The
FlatteningPathIterator will keep dividing each curved segment into
smaller and smaller flat segments until either the segments are within
the flattening factor of the curve or until the buffer limit is reached.
if (flatness < 0.0) {
// awt.206=Flatness is less then zero
throw new IllegalArgumentException(Messages.getString("awt.206")); //$NON-NLS-1$
}
if (limit < 0) {
// awt.207=Limit is less then zero
throw new IllegalArgumentException(Messages.getString("awt.207")); //$NON-NLS-1$
}
if (path == null) {
// awt.208=Path is null
throw new NullPointerException(Messages.getString("awt.208")); //$NON-NLS-1$
}
this.p = path;
this.flatness = flatness;
this.flatness2 = flatness * flatness;
this.bufLimit = limit;
this.bufSize = Math.min(bufLimit, BUFFER_SIZE);
this.buf = new double[bufSize];
this.bufIndex = bufSize;
|
Methods Summary |
---|
public int | currentSegment(double[] coords)
if (isDone()) {
// awt.4B=Iterator out of bounds
throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
}
evaluate();
int type = bufType;
if (type != SEG_CLOSE) {
coords[0] = px;
coords[1] = py;
if (type != SEG_MOVETO) {
type = SEG_LINETO;
}
}
return type;
| public int | currentSegment(float[] coords)
if (isDone()) {
// awt.4B=Iterator out of bounds
throw new NoSuchElementException(Messages.getString("awt.4Bx")); //$NON-NLS-1$
}
evaluate();
int type = bufType;
if (type != SEG_CLOSE) {
coords[0] = (float)px;
coords[1] = (float)py;
if (type != SEG_MOVETO) {
type = SEG_LINETO;
}
}
return type;
| void | evaluate()Calculates flat path points for current segment of the source shape. Line
segment is flat by itself. Flatness of quad and cubic curves evaluated by
getFlatnessSq() method. Curves subdivided until current flatness is
bigger than user defined and subdivision limit isn't exhausted. Single
source segment translated to series of buffer points. The less flatness
the bigger series. Every currentSegment() call extract one point from the
buffer. When series completed evaluate() takes next source shape segment.
if (bufEmpty) {
bufType = p.currentSegment(coords);
}
switch (bufType) {
case SEG_MOVETO:
case SEG_LINETO:
px = coords[0];
py = coords[1];
break;
case SEG_QUADTO:
if (bufEmpty) {
bufIndex -= 6;
buf[bufIndex + 0] = px;
buf[bufIndex + 1] = py;
System.arraycopy(coords, 0, buf, bufIndex + 2, 4);
bufSubdiv = 0;
}
while (bufSubdiv < bufLimit) {
if (QuadCurve2D.getFlatnessSq(buf, bufIndex) < flatness2) {
break;
}
// Realloc buffer
if (bufIndex <= 4) {
double tmp[] = new double[bufSize + BUFFER_CAPACITY];
System.arraycopy(buf, bufIndex, tmp, bufIndex + BUFFER_CAPACITY, bufSize
- bufIndex);
buf = tmp;
bufSize += BUFFER_CAPACITY;
bufIndex += BUFFER_CAPACITY;
}
QuadCurve2D.subdivide(buf, bufIndex, buf, bufIndex - 4, buf, bufIndex);
bufIndex -= 4;
bufSubdiv++;
}
bufIndex += 4;
px = buf[bufIndex];
py = buf[bufIndex + 1];
bufEmpty = (bufIndex == bufSize - 2);
if (bufEmpty) {
bufIndex = bufSize;
bufType = SEG_LINETO;
} else {
bufSubdiv--;
}
break;
case SEG_CUBICTO:
if (bufEmpty) {
bufIndex -= 8;
buf[bufIndex + 0] = px;
buf[bufIndex + 1] = py;
System.arraycopy(coords, 0, buf, bufIndex + 2, 6);
bufSubdiv = 0;
}
while (bufSubdiv < bufLimit) {
if (CubicCurve2D.getFlatnessSq(buf, bufIndex) < flatness2) {
break;
}
// Realloc buffer
if (bufIndex <= 6) {
double tmp[] = new double[bufSize + BUFFER_CAPACITY];
System.arraycopy(buf, bufIndex, tmp, bufIndex + BUFFER_CAPACITY, bufSize
- bufIndex);
buf = tmp;
bufSize += BUFFER_CAPACITY;
bufIndex += BUFFER_CAPACITY;
}
CubicCurve2D.subdivide(buf, bufIndex, buf, bufIndex - 6, buf, bufIndex);
bufIndex -= 6;
bufSubdiv++;
}
bufIndex += 6;
px = buf[bufIndex];
py = buf[bufIndex + 1];
bufEmpty = (bufIndex == bufSize - 2);
if (bufEmpty) {
bufIndex = bufSize;
bufType = SEG_LINETO;
} else {
bufSubdiv--;
}
break;
}
| public double | getFlatness()Gets the flattening factor.
return flatness;
| public int | getRecursionLimit()Gets the maximum number of subdivisions per curved segment.
return bufLimit;
| public int | getWindingRule()
return p.getWindingRule();
| public boolean | isDone()
return bufEmpty && p.isDone();
| public void | next()
if (bufEmpty) {
p.next();
}
|
|