diff options
Diffstat (limited to 'libjava/java/awt')
-rw-r--r-- | libjava/java/awt/geom/GeneralPath.java | 298 |
1 files changed, 205 insertions, 93 deletions
diff --git a/libjava/java/awt/geom/GeneralPath.java b/libjava/java/awt/geom/GeneralPath.java index 6c1b578f..05d98c7 100644 --- a/libjava/java/awt/geom/GeneralPath.java +++ b/libjava/java/awt/geom/GeneralPath.java @@ -1,5 +1,5 @@ /* GeneralPath.java -- represents a shape built from subpaths - Copyright (C) 2002 Free Software Foundation + Copyright (C) 2002, 2003 Free Software Foundation This file is part of GNU Classpath. @@ -128,7 +128,7 @@ public final class GeneralPath implements Shape, Cloneable float x3, float y3) { ensureSize(index + 6); - types[index >> 1] = PathIterator.SEG_QUADTO; + types[index >> 1] = PathIterator.SEG_CUBICTO; points[index++] = x1; points[index++] = y1; points[index++] = x2; @@ -148,40 +148,69 @@ public final class GeneralPath implements Shape, Cloneable { append(s.getPathIterator(null), connect); } - public void append(PathIterator i, boolean connect) + + + /** + * Appends the segments of a PathIterator to this GeneralPath. + * Optionally, the initial {@link PathIterator#SEG_MOVETO} segment + * of the appended path is changed into a {@link + * PathIterator#SEG_LINETO} segment. + * + * @param iter the PathIterator specifying which segments shall be + * appended. + * + * @param connect <code>true</code> for substituting the initial + * {@link PathIterator#SEG_MOVETO} segment by a {@link + * PathIterator#SEG_LINETO}, or <code>false</code> for not + * performing any substitution. If this GeneralPath is currently + * empty, <code>connect</code> is assumed to be <code>false</code>, + * thus leaving the initial {@link PathIterator#SEG_MOVETO} + * unchanged. + */ + public void append(PathIterator iter, boolean connect) { + // A bad implementation of this method had caused Classpath bug #6076. float[] f = new float[6]; - while (! i.isDone()) + while (!iter.isDone()) + { + switch (iter.currentSegment(f)) { - int result = i.currentSegment(f); - switch (result) - { - case PathIterator.SEG_MOVETO: - if (! connect) - { - moveTo(f[0], f[1]); - break; - } - if (subpath >= 0 && f[0] == points[subpath] - && f[1] == points[subpath + 1]) - break; - // Fallthrough. - case PathIterator.SEG_LINETO: - lineTo(f[0], f[1]); - break; - case PathIterator.SEG_QUADTO: - quadTo(f[0], f[1], f[2], f[3]); - break; - case PathIterator.SEG_CUBICTO: - curveTo(f[0], f[1], f[2], f[3], f[4], f[5]); - break; - default: - closePath(); - } - connect = false; + case PathIterator.SEG_MOVETO: + if (!connect || (index == 0)) + { + moveTo(f[0], f[1]); + break; + } + + if ((index >= 2) && (types[(index - 2) >> 2] == PathIterator.SEG_CLOSE) + && (f[0] == points[index - 2]) && (f[1] == points[index - 1])) + break; + + // Fall through. + + case PathIterator.SEG_LINETO: + lineTo(f[0], f[1]); + break; + + case PathIterator.SEG_QUADTO: + quadTo(f[0], f[1], f[2], f[3]); + break; + + case PathIterator.SEG_CUBICTO: + curveTo(f[0], f[1], f[2], f[3], f[4], f[5]); + break; + + case PathIterator.SEG_CLOSE: + closePath(); + break; } + + connect = false; + iter.next(); + } } + public int getWindingRule() { return rule; @@ -197,7 +226,7 @@ public final class GeneralPath implements Shape, Cloneable { if (subpath < 0) return null; - return new Point2D.Float(points[subpath], points[subpath + 1]); + return new Point2D.Float(points[index - 2], points[index - 1]); } public void reset() { @@ -254,80 +283,163 @@ public final class GeneralPath implements Shape, Cloneable { return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } - public PathIterator getPathIterator(final AffineTransform at) + + + /** + * A PathIterator that iterates over the segments of a GeneralPath. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + private static class GeneralPathIterator + implements PathIterator { - return new PathIterator() + /** + * The number of coordinate values for each segment type. + */ + private static final int[] NUM_COORDS = { - int current = 0; + /* 0: SEG_MOVETO */ 2, + /* 1: SEG_LINETO */ 2, + /* 2: SEG_QUADTO */ 4, + /* 3: SEG_CUBICTO */ 6, + /* 4: SEG_CLOSE */ 0 + }; - public int getWindingRule() - { - return rule; - } - public boolean isDone() - { - return current >= index; - } + /** + * The GeneralPath whose segments are being iterated. + */ + private final GeneralPath path; - public void next() - { - current++; - } - public int currentSegment(float[] coords) + /** + * The affine transformation used to transform coordinates. + */ + private final AffineTransform transform; + + + /** + * The current position of the iterator. + */ + private int pos; + + + /** + * Constructs a new iterator for enumerating the segments of a + * GeneralPath. + * + * @param at an affine transformation for projecting the returned + * points, or <code>null</code> to return the original points + * without any mapping. + */ + GeneralPathIterator(GeneralPath path, AffineTransform transform) + { + this.path = path; + this.transform = transform; + } + + + /** + * Returns the current winding rule of the GeneralPath. + */ + public int getWindingRule() + { + return path.rule; + } + + + /** + * Determines whether the iterator has reached the last segment in + * the path. + */ + public boolean isDone() + { + return pos >= path.index; + } + + + /** + * Advances the iterator position by one segment. + */ + public void next() + { + int seg; + + /* Increment pos by the number of coordinate values. Note that + * we store two values even for a SEG_CLOSE segment, which is + * why we increment pos at least by 2. + */ + seg = path.types[pos >> 1]; + if (seg == SEG_CLOSE) + pos += 2; + else + pos += NUM_COORDS[seg]; + } + + + /** + * Returns the current segment in float coordinates. + */ + public int currentSegment(float[] coords) + { + int seg, numCoords; + + seg = path.types[pos >> 1]; + numCoords = NUM_COORDS[seg]; + if (numCoords > 0) { - if (current >= index) - return SEG_CLOSE; - int result = types[current >> 1]; - int i = 0; - if (result == 3) - { - coords[i++] = points[current++]; - coords[i++] = points[current++]; - } - if (result == 2) - { - coords[i++] = points[current++]; - coords[i++] = points[current++]; - } - if (result < 2) - { - coords[i++] = points[current++]; - coords[i++] = points[current++]; - if (at != null) - at.transform(coords, 0, coords, 0, result == 0 ? 1 : result); - } - return result; + if (transform == null) + System.arraycopy(path.points, pos, coords, 0, numCoords); + else + transform.transform(/* src */ path.points, /* srcOffset */ pos, + /* dest */ coords, /* destOffset */ 0, + /* numPoints */ numCoords >> 1); } + return seg; + } + + + /** + * Returns the current segment in double coordinates. + */ + public int currentSegment(double[] coords) + { + int seg, numCoords; - public int currentSegment(double[] coords) + seg = path.types[pos >> 1]; + numCoords = NUM_COORDS[seg]; + if (numCoords > 0) { - if (current >= index) - return SEG_CLOSE; - int result = types[current >> 1]; - int i = 0; - if (result == 3) - { - coords[i++] = points[current++]; - coords[i++] = points[current++]; - } - if (result == 2) - { - coords[i++] = points[current++]; - coords[i++] = points[current++]; - } - if (result < 2) - { - coords[i++] = points[current++]; - coords[i++] = points[current++]; - if (at != null) - at.transform(coords, 0, coords, 0, result == 0 ? 1 : result); - } - return result; + if (transform == null) + { + // System.arraycopy throws an exception if the source and destination + // array are not of the same primitive type. + for (int i = 0; i < numCoords; i++) + coords[i] = (double) path.points[pos + i]; + } + else + transform.transform(/* src */ path.points, /* srcOffset */ pos, + /* dest */ coords, /* destOffset */ 0, + /* numPoints */ numCoords >> 1); } - }; + return seg; + } + } + + + /** + * Creates a PathIterator for iterating along the segments of this path. + * + * @param at an affine transformation for projecting the returned + * points, or <code>null</code> to let the created iterator return + * the original points without any mapping. + */ + public PathIterator getPathIterator(AffineTransform at) + { + return new GeneralPathIterator(this, at); } + + public PathIterator getPathIterator(AffineTransform at, double flatness) { return new FlatteningPathIterator(getPathIterator(at), flatness); |