⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flatteningpathiterator.java

📁 JAVA基本类源代码,大家可以学习学习!
💻 JAVA
字号:
/* * @(#)FlatteningPathIterator.java	1.15 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.awt.geom;import java.util.*;/** * The <code>FlatteningPathIterator</code> class returns a flattened view of * another {@link PathIterator} object.  Other {@link java.awt.Shape Shape}  * classes can use this class to provide flattening behavior for their paths * without having to perform the interpolation calculations themselves. * * @version 1.6 06/29/98 * @author Jim Graham */public class FlatteningPathIterator implements PathIterator {    static final int GROW_SIZE = 24;	// Multiple of cubic & quad curve size    PathIterator src;			// The source iterator    double squareflat;			// Square of the flatness parameter					// for testing against squared lengths    int limit;				// Maximum number of recursion levels    double hold[] = new double[14];	// The cache of interpolated coords					// Note that this must be long enough					// to store a full cubic segment and					// a relative cubic segment to avoid					// aliasing when copying the coords					// of a curve to the end of the array.					// This is also serendipitously equal					// to the size of a full quad segment					// and 2 relative quad segments.    double curx, cury;			// The ending x,y of the last segment    double movx, movy;			// The x,y of the last move segment    int holdType;			// The type of the curve being held					// for interpolation    int holdEnd;			// The index of the last curve segment					// being held for interpolation    int holdIndex;			// The index of the curve segment					// that was last interpolated.  This					// is the curve segment ready to be					// returned in the next call to					// currentSegment().    int levels[];			// The recursion level at which					// each curve being held in storage					// was generated.    int levelIndex;			// The index of the entry in the					// levels array of the curve segment					// at the holdIndex    boolean done;			// True when iteration is done    /**     * Constructs a new <code>FlatteningPathIterator</code> object that      * flattens a path as it iterates over it.  The iterator does not      * subdivide any curve read from the source iterator to more than      * 10 levels of subdivision which yields a maximum of 1024 line      * segments per curve.     * @param src the original unflattened path being iterated over     * @param flatness the maximum allowable distance between the     * control points and the flattened curve     */    public FlatteningPathIterator(PathIterator src, double flatness) {	this(src, flatness, 10);    }    /**     * Constructs a new <code>FlatteningPathIterator</code> object      * that flattens a path as it iterates over it.     * The <code>limit</code> parameter allows you to control the     * maximum number of recursive subdivisions that the iterator     * can make before it assumes that the curve is flat enough     * without measuring against the <code>flatness</code> parameter.     * The flattened iteration therefore never generates more than     * a maximum of <code>(2^limit)</code> line segments per curve.     * @param src the original unflattened path being iterated over     * @param flatness the maximum allowable distance between the     * control points and the flattened curve     * @param limit the maximum number of recursive subdivisions     * allowed for any curved segment     * @exception <code>IllegalArgumentException</code> if      * 		<code>flatness</code> or <code>limit</code>     *		is less than zero     */    public FlatteningPathIterator(PathIterator src, double flatness,				  int limit) {	if (flatness < 0.0) {	    throw new IllegalArgumentException("flatness must be >= 0");	}	if (limit < 0) {	    throw new IllegalArgumentException("limit must be >= 0");	}	this.src = src;	this.squareflat = flatness * flatness;	this.limit = limit;	this.levels = new int[limit + 1];	// prime the first path segment	next(false);    }    /**     * Returns the flatness of this iterator.     * @return the flatness of this <code>FlatteningPathIterator</code>.     */    public double getFlatness() {	return Math.sqrt(squareflat);    }    /**     * Returns the recursion limit of this iterator.     * @return the recursion limit of this      * <code>FlatteningPathIterator</code>.     */    public int getRecursionLimit() {	return limit;    }    /**     * Returns the winding rule for determining the interior of the     * path.     * @return the winding rule of the original unflattened path being     * iterated over.     * @see PathIterator#WIND_EVEN_ODD     * @see PathIterator#WIND_NON_ZERO     */    public int getWindingRule() {	return src.getWindingRule();    }    /**     * Tests if the iteration is complete.     * @return <code>true</code> if all the segments have     * been read; <code>false</code> otherwise.     */    public boolean isDone() {	return done;    }    /*     * Ensures that the hold array can hold up to (want) more values.     * It is currently holding (hold.length - holdIndex) values.     */    void ensureHoldCapacity(int want) {	if (holdIndex - want < 0) {	    int have = hold.length - holdIndex;	    int newsize = hold.length + GROW_SIZE;	    double newhold[] = new double[newsize];	    System.arraycopy(hold, holdIndex,			     newhold, holdIndex + GROW_SIZE,			     have);	    hold = newhold;	    holdIndex += GROW_SIZE;	    holdEnd += GROW_SIZE;	}    }    /**     * Moves the iterator to the next segment of the path forwards     * along the primary direction of traversal as long as there are     * more points in that direction.     */    public void next() {	next(true);    }    private void next(boolean doNext) {	int level;	if (holdIndex >= holdEnd) {	    if (doNext) {		src.next();	    }	    if (src.isDone()) {		done = true;		return;	    }	    holdType = src.currentSegment(hold);	    levelIndex = 0;	    levels[0] = 0;	}	switch (holdType) {	case SEG_MOVETO:	case SEG_LINETO:	    curx = hold[0];	    cury = hold[1];	    if (holdType == SEG_MOVETO) {		movx = curx;		movy = cury;	    }	    holdIndex = 0;	    holdEnd = 0;	    break;	case SEG_CLOSE:	    curx = movx;	    cury = movy;	    holdIndex = 0;	    holdEnd = 0;	    break;	case SEG_QUADTO:	    if (holdIndex >= holdEnd) {		// Move the coordinates to the end of the array.		holdIndex = hold.length - 6;		holdEnd = hold.length - 2;		hold[holdIndex + 0] = curx;		hold[holdIndex + 1] = cury;		hold[holdIndex + 2] = hold[0];		hold[holdIndex + 3] = hold[1];		hold[holdIndex + 4] = curx = hold[2];		hold[holdIndex + 5] = cury = hold[3];	    }	    level = levels[levelIndex];	    while (level < limit) {		if (QuadCurve2D.getFlatnessSq(hold, holdIndex) < squareflat) {		    break;		}		ensureHoldCapacity(4);		QuadCurve2D.subdivide(hold, holdIndex,				      hold, holdIndex - 4,				      hold, holdIndex);		holdIndex -= 4;		// Now that we have subdivided, we have constructed		// two curves of one depth lower than the original		// curve.  One of those curves is in the place of		// the former curve and one of them is in the next		// set of held coordinate slots.  We now set both		// curves level values to the next higher level.		level++;		levels[levelIndex] = level;		levelIndex++;		levels[levelIndex] = level;	    }	    // This curve segment is flat enough, or it is too deep	    // in recursion levels to try to flatten any more.  The	    // two coordinates at holdIndex+4 and holdIndex+5 now	    // contain the endpoint of the curve which can be the	    // endpoint of an approximating line segment.	    holdIndex += 4;	    levelIndex--;	    break;	case SEG_CUBICTO:	    if (holdIndex >= holdEnd) {		// Move the coordinates to the end of the array.		holdIndex = hold.length - 8;		holdEnd = hold.length - 2;		hold[holdIndex + 0] = curx;		hold[holdIndex + 1] = cury;		hold[holdIndex + 2] = hold[0];		hold[holdIndex + 3] = hold[1];		hold[holdIndex + 4] = hold[2];		hold[holdIndex + 5] = hold[3];		hold[holdIndex + 6] = curx = hold[4];		hold[holdIndex + 7] = cury = hold[5];	    }	    level = levels[levelIndex];	    while (level < limit) {		if (CubicCurve2D.getFlatnessSq(hold, holdIndex) < squareflat) {		    break;		}		ensureHoldCapacity(6);		CubicCurve2D.subdivide(hold, holdIndex,				       hold, holdIndex - 6,				       hold, holdIndex);		holdIndex -= 6;		// Now that we have subdivided, we have constructed		// two curves of one depth lower than the original		// curve.  One of those curves is in the place of		// the former curve and one of them is in the next		// set of held coordinate slots.  We now set both		// curves level values to the next higher level.		level++;		levels[levelIndex] = level;		levelIndex++;		levels[levelIndex] = level;	    }	    // This curve segment is flat enough, or it is too deep	    // in recursion levels to try to flatten any more.  The	    // two coordinates at holdIndex+6 and holdIndex+7 now	    // contain the endpoint of the curve which can be the	    // endpoint of an approximating line segment.	    holdIndex += 6;	    levelIndex--;	    break;	}    }    /**     * Returns the coordinates and type of the current path segment in     * the iteration.     * The return value is the path segment type:     * SEG_MOVETO, SEG_LINETO, or SEG_CLOSE.     * A float array of length 6 must be passed in and can be used to     * store the coordinates of the point(s).     * Each point is stored as a pair of float x,y coordinates.     * SEG_MOVETO and SEG_LINETO types return one point,     * and SEG_CLOSE does not return any points.     * @param coords an array that holds the data returned from     * this method     * @return the path segment type of the current path segment.     * @exception <code>NoSuchElementException</code> if there     *		are no more elements in the flattening path to be     *		returned.     * @see PathIterator#SEG_MOVETO     * @see PathIterator#SEG_LINETO     * @see PathIterator#SEG_CLOSE     */    public int currentSegment(float[] coords) {	if (isDone()) {	    throw new NoSuchElementException("flattening iterator out of bounds");	}	int type = holdType;	if (type != SEG_CLOSE) {	    coords[0] = (float) hold[holdIndex + 0];	    coords[1] = (float) hold[holdIndex + 1];	    if (type != SEG_MOVETO) {		type = SEG_LINETO;	    }	}	return type;    }    /**     * Returns the coordinates and type of the current path segment in     * the iteration.     * The return value is the path segment type:     * SEG_MOVETO, SEG_LINETO, or SEG_CLOSE.     * A double array of length 6 must be passed in and can be used to     * store the coordinates of the point(s).     * Each point is stored as a pair of double x,y coordinates.     * SEG_MOVETO and SEG_LINETO types return one point,     * and SEG_CLOSE does not return any points.     * @param coords an array that holds the data returned from     * this method     * @return the path segment type of the current path segment.     * @exception <code>NoSuchElementException</code> if there     *          are no more elements in the flattening path to be     *          returned.     * @see PathIterator#SEG_MOVETO     * @see PathIterator#SEG_LINETO     * @see PathIterator#SEG_CLOSE     */    public int currentSegment(double[] coords) {	if (isDone()) {	    throw new NoSuchElementException("flattening iterator out of bounds");	}	int type = holdType;	if (type != SEG_CLOSE) {	    coords[0] = hold[holdIndex + 0];	    coords[1] = hold[holdIndex + 1];	    if (type != SEG_MOVETO) {		type = SEG_LINETO;	    }	}	return type;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -