FileDocCategorySizeDatePackage
FlatteningPathIterator.javaAPI DocAndroid 1.5 API11367Wed May 06 22:41:54 BST 2009java.awt.geom

FlatteningPathIterator

public class FlatteningPathIterator extends Object implements PathIterator
The 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.
since
Android 1.0

Fields Summary
private static final int
BUFFER_SIZE
The default points buffer size.
private static final int
BUFFER_LIMIT
The default curve subdivision limit.
private static final int
BUFFER_CAPACITY
The points buffer capacity.
int
bufType
The type of current segment to be flat.
int
bufLimit
The curve subdivision limit.
int
bufSize
The current points buffer size.
int
bufIndex
The inner cursor position in points buffer.
int
bufSubdiv
The current subdivision count.
double[]
buf
The points buffer.
boolean
bufEmpty
The indicator of empty points buffer.
PathIterator
p
The source PathIterator.
double
flatness
The flatness of new path.
double
flatness2
The square of flatness.
double
px
The x coordinate of previous path segment.
double
py
The y coordinate of previous path segment.
double[]
coords
The 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.

param
path the path iterator of the original curve.
param
flatness the flattening factor that indicates how far the flat path is allowed to be from the actual curve in order to decide when to stop dividing the path into smaller and smaller segments.
throws
IllegalArgumentException if the flatness is less than zero.
throws
NullPointerException if the path is null.


                                                                                                                                                                                                   
         
        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.

param
path the path iterator of the original curve.
param
flatness the flattening factor that indicates how far the flat path is allowed to be from the actual curve in order to decide when to stop dividing the path into smaller and smaller segments.
param
limit the maximum number of flat segments to divide each curve into.
throws
IllegalArgumentException if the flatness or limit is less than zero.
throws
NullPointerException if the path is null.

        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 intcurrentSegment(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 intcurrentSegment(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;
    
voidevaluate()
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 doublegetFlatness()
Gets the flattening factor.

return
the flattening factor.

        return flatness;
    
public intgetRecursionLimit()
Gets the maximum number of subdivisions per curved segment.

return
the maximum number of subdivisions per curved segment.

        return bufLimit;
    
public intgetWindingRule()

        return p.getWindingRule();
    
public booleanisDone()

        return bufEmpty && p.isDone();
    
public voidnext()

        if (bufEmpty) {
            p.next();
        }