You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ay...@apache.org on 2007/06/13 17:05:32 UTC
svn commit: r546906 - in /harmony/enhanced/classlib/trunk/modules/awt/src:
main/java/common/java/awt/geom/Area.java
test/api/java/common/java/awt/geom/AreaTest.java
Author: ayza
Date: Wed Jun 13 08:05:17 2007
New Revision: 546906
URL: http://svn.apache.org/viewvc?view=rev&rev=546906
Log:
java.awt.geom.Area implementation from HARMONY-1476
Modified:
harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java
harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java
Modified: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java?view=diff&rev=546906&r1=546905&r2=546906
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java (original)
+++ harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java Wed Jun 13 08:05:17 2007
@@ -14,199 +14,1287 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @author Denis M. Kishenko
- * @version $Revision$
- */
package java.awt.geom;
import java.awt.Rectangle;
import java.awt.Shape;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Rectangle2D;
import java.util.NoSuchElementException;
+import org.apache.harmony.awt.gl.Crossing;
+import org.apache.harmony.awt.internal.CrossingHelper;
+import org.apache.harmony.awt.internal.CurveCrossingHelper;
+import org.apache.harmony.awt.internal.GeometryUtil;
+import org.apache.harmony.awt.internal.IntersectPoint;
import org.apache.harmony.awt.internal.nls.Messages;
+
public class Area implements Shape, Cloneable {
/**
- * The source Shape object
+ * the coordinates array of the shape vertices
*/
- Shape s;
-
- private static class NullIterator implements PathIterator {
-
- NullIterator() {
- }
-
- public int getWindingRule() {
- return WIND_NON_ZERO;
- }
-
- public boolean isDone() {
- return true;
- }
+ private double coords[] = new double[20];
+
+ /**
+ * the coordinates quantity
+ */
+ private int coordsSize = 0;
+
+ /**
+ * the rules array for the drawing of the shape edges
+ */
+ private int rules[] = new int[10];
+
+ /**
+ * the rules quantity
+ */
+ private int rulesSize = 0;
+
+ /**
+ * offsets[i] - index in array of coords and i - index in array of rules
+ */
+ private int offsets[] = new int[10];
+
+ /**
+ * the quantity of MOVETO rule occurences
+ */
+ private int moveToCount = 0;
+
+ /**
+ * true if the shape is polygon
+ */
+ private boolean isPolygonal = true;
+
+ public Area() {
+ }
+
+ public Area(Shape s) {
+ double segmentCoords[] = new double[6];
+ double lastMoveX = 0.0;
+ double lastMoveY = 0.0;
+ int rulesIndex = 0;
+ int coordsIndex = 0;
+
+ for (PathIterator pi = s.getPathIterator(null);
+ !pi.isDone(); pi.next()) {
+ coords = adjustSize(coords, coordsIndex + 6);
+ rules = adjustSize(rules, rulesIndex + 1);
+ offsets = adjustSize(offsets, rulesIndex + 1);
+ rules[rulesIndex] = pi.currentSegment(segmentCoords);
+ offsets[rulesIndex] = coordsIndex;
+
+ switch (rules[rulesIndex]) {
+ case PathIterator.SEG_MOVETO:
+ coords[coordsIndex++] = segmentCoords[0];
+ coords[coordsIndex++] = segmentCoords[1];
+ lastMoveX = segmentCoords[0];
+ lastMoveY = segmentCoords[1];
+ ++moveToCount;
+ break;
+ case PathIterator.SEG_LINETO:
+ if ((segmentCoords[0] != lastMoveX) ||
+ (segmentCoords[1] != lastMoveY)) {
+ coords[coordsIndex++] = segmentCoords[0];
+ coords[coordsIndex++] = segmentCoords[1];
+ } else {
+ --rulesIndex;
+ }
+ break;
+ case PathIterator.SEG_QUADTO:
+ System.arraycopy(segmentCoords, 0, coords, coordsIndex, 4);
+ coordsIndex += 4;
+ isPolygonal = false;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ System.arraycopy(segmentCoords, 0, coords, coordsIndex, 6);
+ coordsIndex += 6;
+ isPolygonal = false;
+ break;
+ case PathIterator.SEG_CLOSE:
+ break;
+ }
+ ++rulesIndex;
+ }
+
+ if ((rulesIndex != 0) &&
+ (rules[rulesIndex - 1] != PathIterator.SEG_CLOSE)) {
+ rules[rulesIndex] = PathIterator.SEG_CLOSE;
+ offsets[rulesIndex] = coordsSize;
+ }
+
+ rulesSize = rulesIndex;
+ coordsSize = coordsIndex;
+ }
+
+ public boolean contains(double x, double y) {
+ return !isEmpty() &&
+ containsExact(x, y) > 0;
+ }
+
+ public boolean contains(double x, double y, double width, double height) {
+ int crossCount = Crossing.intersectPath(getPathIterator(null), x, y,
+ width, height);
+ return crossCount != Crossing.CROSSING &&
+ Crossing.isInsideEvenOdd(crossCount);
+ }
+
+ public boolean contains(Point2D p) {
+ return contains(p.getX(), p.getY());
+ }
+
+ public boolean contains(Rectangle2D r) {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ public boolean equals(Area obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ Area area = (Area)clone();
+ area.subtract(obj);
+ return area.isEmpty();
+ }
+
+ public boolean intersects(double x, double y, double width, double height) {
+ if ((width <= 0.0) || (height <= 0.0)) {
+ return false;
+ } else if (!getBounds2D().intersects(x, y, width, height)) {
+ return false;
+ }
+
+ int crossCount = Crossing.intersectShape(this, x, y, width, height);
+ return Crossing.isInsideEvenOdd(crossCount);
+ }
+
+ public boolean intersects(Rectangle2D r) {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ public Rectangle getBounds() {
+ return getBounds2D().getBounds();
+ }
+
+ public Rectangle2D getBounds2D() {
+ double maxX = coords[0];
+ double maxY = coords[1];
+ double minX = coords[0];
+ double minY = coords[1];
+
+ for (int i = 0; i < coordsSize;) {
+ minX = Math.min(minX, coords[i]);
+ maxX = Math.max(maxX, coords[i++]);
+ minY = Math.min(minY, coords[i]);
+ maxY = Math.max(maxY, coords[i++]);
+ }
+
+ return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
+ }
+
+ public PathIterator getPathIterator(AffineTransform t) {
+ return new AreaPathIterator(this, t);
+ }
+
+ public PathIterator getPathIterator(AffineTransform t, double flatness) {
+ return new FlatteningPathIterator(getPathIterator(t), flatness);
+ }
+
+ public boolean isEmpty() {
+ return (rulesSize == 0) && (coordsSize == 0);
+ }
+
+ public boolean isPolygonal() {
+ return isPolygonal;
+ }
+
+ public boolean isRectangular() {
+ return (isPolygonal) && (rulesSize <= 5) && (coordsSize <= 8) &&
+ (coords[1] == coords[3]) && (coords[7] == coords[5]) &&
+ (coords[0] == coords[6]) && (coords[2] == coords[4]);
+ }
+
+ public boolean isSingular() {
+ return (moveToCount <= 1);
+ }
+
+ public void reset() {
+ coordsSize = 0;
+ rulesSize = 0;
+ }
+
+ public void transform(AffineTransform t) {
+ copy(new Area(t.createTransformedShape(this)), this);
+ }
+
+ public Area createTransformedArea(AffineTransform t) {
+ return new Area(t.createTransformedShape(this));
+ }
+
+ public Object clone() {
+ Area area = new Area();
+ copy(this, area);
+ return area;
+ }
+
+ public void add(Area area) {
+ if (isPolygonal() && area.isPolygonal()) {
+ addPolygon(area);
+ } else {
+ addCurvePolygon(area);
+ }
+ }
+
+ public void intersect(Area area) {
+ if (isPolygonal() && area.isPolygonal()) {
+ intersectPolygon(area);
+ } else {
+ intersectCurvePolygon(area);
+ }
+ }
+
+ public void subtract(Area area) {
+ if (isPolygonal() && area.isPolygonal()) {
+ subtractPolygon(area);
+ } else {
+ subtractCurvePolygon(area);
+ }
+ }
+
+ public void exclusiveOr(Area area) {
+ Area a = (Area) clone();
+ a.intersect(area);
+ add(area);
+ subtract(a);
+ }
+
+ private void addCurvePolygon(Area area) {
+ CurveCrossingHelper crossHelper = new CurveCrossingHelper(
+ new double[][] { coords, area.coords },
+ new int[] { coordsSize, area.coordsSize },
+ new int[][] { rules, area.rules },
+ new int[] { rulesSize, area.rulesSize },
+ new int[][] { offsets, area.offsets });
+ IntersectPoint[] intersectPoints = crossHelper.findCrossing();
+
+ if (intersectPoints.length == 0) {
+ if (area.contains(getBounds2D())) {
+ copy(area, this);
+ } else if (!contains(area.getBounds2D())) {
+ coords = adjustSize(coords, coordsSize + area.coordsSize);
+ System.arraycopy(area.coords, 0, coords, coordsSize,
+ area.coordsSize);
+ coordsSize += area.coordsSize;
+ rules = adjustSize(rules, rulesSize + area.rulesSize);
+ System.arraycopy(area.rules, 0, rules, rulesSize,
+ area.rulesSize);
+ rulesSize += area.rulesSize;
+ offsets = adjustSize(offsets, rulesSize + area.rulesSize);
+ System.arraycopy(area.offsets, 0, offsets, rulesSize,
+ area.rulesSize);
+ }
+
+ return;
+ }
+
+ double[] resultCoords = new double[coordsSize + area.coordsSize +
+ intersectPoints.length];
+ int[] resultRules = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int[] resultOffsets = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int resultCoordPos = 0;
+ int resultRulesPos = 0;
+ boolean isCurrentArea = true;
+
+ IntersectPoint point = intersectPoints[0];
+ resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+
+ do {
+ resultCoords[resultCoordPos++] = point.getX();
+ resultCoords[resultCoordPos++] = point.getY();
+ int curIndex = point.getEndIndex(true);
+
+ if (curIndex < 0) {
+ isCurrentArea = !isCurrentArea;
+ } else if (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) > 0) {
+ isCurrentArea = false;
+ } else {
+ isCurrentArea = true;
+ }
- public void next() {
- // nothing
- }
+ IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
+ point,
+ isCurrentArea);
+ double[] coords = (isCurrentArea) ? this.coords : area.coords;
+ int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
+ int[] rules = (isCurrentArea) ? this.rules : area.rules;
+ int offset = point.getRuleIndex(isCurrentArea);
+ boolean isCopyUntilZero = false;
+
+ if ((point.getRuleIndex(isCurrentArea) >
+ nextPoint.getRuleIndex(isCurrentArea))) {
+ int rulesSize = (isCurrentArea) ? this.rulesSize :
+ area.rulesSize;
+ resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
+ rules, offsets,
+ resultRules,
+ resultOffsets,
+ resultCoords, coords,
+ resultRulesPos,
+ resultCoordPos,
+ point, isCurrentArea,
+ false, 0);
+ resultRulesPos += rulesSize - offset - 1;
+ offset = 1;
+ isCopyUntilZero = true;
+ }
+
+ int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
+
+ if (isCopyUntilZero) {
+ offset = 0;
+ }
+
+ resultCoordPos = includeCoordsAndRules(offset, length, rules,
+ offsets, resultRules,
+ resultOffsets, resultCoords,
+ coords, resultRulesPos,
+ resultCoordPos, point,
+ isCurrentArea, true, 0);
+ resultRulesPos += length - offset;
+ point = nextPoint;
+ } while (point != intersectPoints[0]);
+
+ resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
+ resultOffsets[resultRulesPos - 1] = resultCoordPos;
+ this.coords = resultCoords;
+ this.rules = resultRules;
+ this.offsets = resultOffsets;
+ this.coordsSize = resultCoordPos;
+ this.rulesSize = resultRulesPos;
+ }
+
+ private void addPolygon(Area area) {
+ CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
+ area.coords },
+ new int[] {coordsSize,
+ area.coordsSize });
+ IntersectPoint[] intersectPoints = crossHelper.findCrossing();
+
+ if (intersectPoints.length == 0) {
+ if (area.contains(getBounds2D())) {
+ copy(area, this);
+ } else if (!contains(area.getBounds2D())) {
+ coords = adjustSize(coords, coordsSize + area.coordsSize);
+ System.arraycopy(area.coords, 0, coords, coordsSize,
+ area.coordsSize);
+ coordsSize += area.coordsSize;
+ rules = adjustSize(rules, rulesSize + area.rulesSize);
+ System.arraycopy(area.rules, 0, rules, rulesSize,
+ area.rulesSize);
+ rulesSize += area.rulesSize;
+ offsets = adjustSize(offsets, rulesSize + area.rulesSize);
+ System.arraycopy(area.offsets, 0, offsets, rulesSize,
+ area.rulesSize);
+ }
+ return;
+ }
+
+ double[] resultCoords = new double[coordsSize + area.coordsSize +
+ intersectPoints.length];
+ int[] resultRules = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int[] resultOffsets = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int resultCoordPos = 0;
+ int resultRulesPos = 0;
+ boolean isCurrentArea = true;
+
+ IntersectPoint point = intersectPoints[0];
+ resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+
+ do {
+ resultCoords[resultCoordPos++] = point.getX();
+ resultCoords[resultCoordPos++] = point.getY();
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos - 2;
+ int curIndex = point.getEndIndex(true);
+ if (curIndex < 0) {
+ isCurrentArea = !isCurrentArea;
+ } else if (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) > 0) {
+ isCurrentArea = false;
+ } else {
+ isCurrentArea = true;
+ }
- public int currentSegment(double[] coords) {
- // awt.4B=Iterator out of bounds
- throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
- }
+ IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
+ point,
+ isCurrentArea);
+ double[] coords = (isCurrentArea) ? this.coords : area.coords;
+ int offset = 2 * point.getEndIndex(isCurrentArea);
+
+ if (nextPoint.getBegIndex(isCurrentArea) <
+ point.getEndIndex(isCurrentArea)) {
+ int coordSize = (isCurrentArea) ? this.coordsSize :
+ area.coordsSize;
+ int length = coordSize - offset;
+ System.arraycopy(coords, offset,
+ resultCoords, resultCoordPos, length);
+
+ for (int i = 0; i < length / 2; i++) {
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+ resultCoordPos += 2;
+ }
+
+ offset = 0;
+ }
+
+ int length = 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2;
+ System.arraycopy(coords, offset,
+ resultCoords, resultCoordPos, length);
+
+ for (int i = 0; i < length / 2; i++) {
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+ resultCoordPos += 2;
+ }
- public int currentSegment(float[] coords) {
- // awt.4B=Iterator out of bounds
- throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+ point = nextPoint;
+ } while (point != intersectPoints[0]);
+
+ resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
+ resultOffsets[resultRulesPos - 1] = resultCoordPos;
+ coords = resultCoords;
+ rules = resultRules;
+ offsets = resultOffsets;
+ coordsSize = resultCoordPos;
+ rulesSize = resultRulesPos;
+ }
+
+ private void intersectCurvePolygon(Area area) {
+ CurveCrossingHelper crossHelper = new CurveCrossingHelper(
+ new double[][] {coords, area.coords },
+ new int[] { coordsSize, area.coordsSize },
+ new int[][] { rules, area.rules },
+ new int[] { rulesSize, area.rulesSize },
+ new int[][] { offsets, area.offsets });
+ IntersectPoint[] intersectPoints = crossHelper.findCrossing();
+
+ if (intersectPoints.length == 0) {
+ if (contains(area.getBounds2D())) {
+ copy(area, this);
+ } else if (!area.contains(getBounds2D())) {
+ reset();
+ }
+ return;
+ }
+
+ double[] resultCoords = new double[coordsSize + area.coordsSize +
+ intersectPoints.length];
+ int[] resultRules = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int[] resultOffsets = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int resultCoordPos = 0;
+ int resultRulesPos = 0;
+ boolean isCurrentArea = true;
+
+ IntersectPoint point = intersectPoints[0];
+ IntersectPoint nextPoint = intersectPoints[0];
+ resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+
+ do {
+ resultCoords[resultCoordPos++] = point.getX();
+ resultCoords[resultCoordPos++] = point.getY();
+
+ int curIndex = point.getEndIndex(true);
+ if ((curIndex < 0) || (area.containsExact(
+ coords[2 * curIndex], coords[2 * curIndex + 1]) == 0)) {
+ isCurrentArea = !isCurrentArea;
+ } else if (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) > 0) {
+ isCurrentArea = true;
+ } else {
+ isCurrentArea = false;
+ }
+
+ nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
+ double[] coords = (isCurrentArea) ? this.coords : area.coords;
+ int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
+ int[] rules = (isCurrentArea) ? this.rules : area.rules;
+ int offset = point.getRuleIndex(isCurrentArea);
+ boolean isCopyUntilZero = false;
+
+ if (point.getRuleIndex(isCurrentArea) >
+ nextPoint.getRuleIndex(isCurrentArea)) {
+ int rulesSize = (isCurrentArea) ? this.rulesSize :
+ area.rulesSize;
+ resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
+ rules, offsets,
+ resultRules,
+ resultOffsets,
+ resultCoords, coords,
+ resultRulesPos,
+ resultCoordPos, point,
+ isCurrentArea, false,
+ 1);
+ resultRulesPos += rulesSize - offset - 1;
+ offset = 1;
+ isCopyUntilZero = true;
+ }
+
+ int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
+
+ if (isCopyUntilZero) {
+ offset = 0;
+ isCopyUntilZero = false;
+ }
+ if ((length == offset) &&
+ (nextPoint.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
+ (nextPoint.getRule(isCurrentArea) != PathIterator.SEG_CLOSE) &&
+ (point.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
+ (point.getRule(isCurrentArea) != PathIterator.SEG_CLOSE)) {
+
+ isCopyUntilZero = true;
+ length++;
+ }
+
+ resultCoordPos = includeCoordsAndRules(offset, length, rules,
+ offsets, resultRules,
+ resultOffsets, resultCoords,
+ coords, resultRulesPos,
+ resultCoordPos, nextPoint,
+ isCurrentArea, true, 1);
+ resultRulesPos = ((length <= offset) || (isCopyUntilZero)) ?
+ resultRulesPos + 1 : resultRulesPos + length;
+
+ point = nextPoint;
+ } while (point != intersectPoints[0]);
+
+ if (resultRules[resultRulesPos - 1] == PathIterator.SEG_LINETO) {
+ resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
+ } else {
+ resultCoords[resultCoordPos++] = nextPoint.getX();
+ resultCoords[resultCoordPos++] = nextPoint.getY();
+ resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
}
+
+ resultOffsets[resultRulesPos - 1] = resultCoordPos;
+ coords = resultCoords;
+ rules = resultRules;
+ offsets = resultOffsets;
+ coordsSize = resultCoordPos;
+ rulesSize = resultRulesPos;
+ }
+
+ private void intersectPolygon(Area area) {
+ CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
+ area.coords },
+ new int[] { coordsSize,
+ area.coordsSize });
+ IntersectPoint[] intersectPoints = crossHelper.findCrossing();
+
+ if (intersectPoints.length == 0) {
+ if (contains(area.getBounds2D())) {
+ copy(area, this);
+ } else if (!area.contains(getBounds2D())) {
+ reset();
+ }
+ return;
+ }
+
+ double[] resultCoords = new double[coordsSize + area.coordsSize +
+ intersectPoints.length];
+ int[] resultRules = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int[] resultOffsets = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int resultCoordPos = 0;
+ int resultRulesPos = 0;
+ boolean isCurrentArea = true;
+
+ IntersectPoint point = intersectPoints[0];
+ resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+
+ do {
+ resultCoords[resultCoordPos++] = point.getX();
+ resultCoords[resultCoordPos++] = point.getY();
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos - 2;
+ int curIndex = point.getEndIndex(true);
+
+ if ((curIndex < 0) ||
+ (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) == 0)) {
+ isCurrentArea = !isCurrentArea;
+ } else if (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) > 0) {
+ isCurrentArea = true;
+ } else {
+ isCurrentArea = false;
+ }
- }
-
- public Area() {
- }
+ IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
+ point,
+ isCurrentArea);
+ double[] coords = (isCurrentArea) ? this.coords : area.coords;
+ int offset = 2 * point.getEndIndex(isCurrentArea);
+ if ((offset >= 0) &&
+ (nextPoint.getBegIndex(isCurrentArea) <
+ point.getEndIndex(isCurrentArea))) {
+ int coordSize = (isCurrentArea) ? this.coordsSize :
+ area.coordsSize;
+ int length = coordSize - offset;
+ System.arraycopy(coords, offset,
+ resultCoords, resultCoordPos, length);
+
+ for (int i = 0; i < length / 2; i++) {
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+ resultCoordPos += 2;
+ }
+
+ offset = 0;
+ }
+
+ if (offset >= 0) {
+ int length = 2 * nextPoint.getBegIndex(isCurrentArea) -
+ offset + 2;
+ System.arraycopy(coords, offset,
+ resultCoords, resultCoordPos, length);
+
+ for (int i = 0; i < length / 2; i++) {
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+ resultCoordPos += 2;
+ }
+ }
- public Area(Shape s) {
- if (s == null) {
- throw new NullPointerException();
- }
- this.s = s;
- }
+ point = nextPoint;
+ } while (point != intersectPoints[0]);
+
+ resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
+ resultOffsets[resultRulesPos - 1] = resultCoordPos;
+ coords = resultCoords;
+ rules = resultRules;
+ offsets = resultOffsets;
+ coordsSize = resultCoordPos;
+ rulesSize = resultRulesPos;
+ }
+
+ private void subtractCurvePolygon(Area area) {
+ CurveCrossingHelper crossHelper = new CurveCrossingHelper(
+ new double[][] { coords, area.coords },
+ new int[] { coordsSize, area.coordsSize },
+ new int[][] { rules, area.rules },
+ new int[] { rulesSize, area.rulesSize },
+ new int[][] { offsets, area.offsets });
+ IntersectPoint[] intersectPoints = crossHelper.findCrossing();
+
+ if (intersectPoints.length == 0 && contains(area.getBounds2D())) {
+ copy(area, this);
+ return;
+ }
+
+ double[] resultCoords = new double[coordsSize + area.coordsSize +
+ intersectPoints.length];
+ int[] resultRules = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int[] resultOffsets = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int resultCoordPos = 0;
+ int resultRulesPos = 0;
+ boolean isCurrentArea = true;
+
+ IntersectPoint point = intersectPoints[0];
+ resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+
+ do {
+ resultCoords[resultCoordPos++] = point.getX();
+ resultCoords[resultCoordPos++] = point.getY();
+ int curIndex = offsets[point.getRuleIndex(true)] % coordsSize;
+
+ if (area.containsExact(coords[curIndex],
+ coords[curIndex + 1]) == 0) {
+ isCurrentArea = !isCurrentArea;
+ } else if (area.containsExact(coords[curIndex],
+ coords[curIndex + 1]) > 0) {
+ isCurrentArea = false;
+ } else {
+ isCurrentArea = true;
+ }
+
+ IntersectPoint nextPoint = (isCurrentArea) ?
+ getNextIntersectPoint(intersectPoints, point,
+ isCurrentArea):
+ getPrevIntersectPoint(intersectPoints, point,
+ isCurrentArea);
+ double[] coords = (isCurrentArea) ? this.coords : area.coords;
+ int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
+ int[] rules = (isCurrentArea) ? this.rules : area.rules;
+ int offset = (isCurrentArea) ? point.getRuleIndex(isCurrentArea) :
+ nextPoint.getRuleIndex(isCurrentArea);
+ boolean isCopyUntilZero = false;
+
+ if (((isCurrentArea) &&
+ (point.getRuleIndex(isCurrentArea) >
+ nextPoint.getRuleIndex(isCurrentArea))) ||
+ ((!isCurrentArea) &&
+ (nextPoint.getRuleIndex(isCurrentArea) >
+ nextPoint.getRuleIndex(isCurrentArea)))) {
+
+ int rulesSize = (isCurrentArea) ? this.rulesSize :
+ area.rulesSize;
+ resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
+ rules, offsets,
+ resultRules,
+ resultOffsets,
+ resultCoords, coords,
+ resultRulesPos,
+ resultCoordPos, point,
+ isCurrentArea, false,
+ 2);
+ resultRulesPos += rulesSize - offset - 1;
+ offset = 1;
+ isCopyUntilZero = true;
+ }
+
+ int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
+
+ if (isCopyUntilZero) {
+ offset = 0;
+ isCopyUntilZero = false;
+ }
+
+ resultCoordPos = includeCoordsAndRules(offset, length, rules,
+ offsets, resultRules,
+ resultOffsets, resultCoords,
+ coords, resultRulesPos,
+ resultCoordPos, point,
+ isCurrentArea, true, 2);
+
+ if ((length == offset) &&
+ ((rules[offset] == PathIterator.SEG_QUADTO) ||
+ (rules[offset] == PathIterator.SEG_CUBICTO))) {
+
+ resultRulesPos++;
+ } else {
+ resultRulesPos = (length < offset || isCopyUntilZero) ?
+ resultRulesPos + 1 : resultRulesPos + length - offset;
+ }
+
+ point = nextPoint;
+ } while (point != intersectPoints[0]);
+
+ resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
+ resultOffsets[resultRulesPos - 1] = resultCoordPos;
+ coords = resultCoords;
+ rules = resultRules;
+ offsets = resultOffsets;
+ coordsSize = resultCoordPos;
+ rulesSize = resultRulesPos;
+ }
+
+ private void subtractPolygon(Area area) {
+ CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
+ area.coords },
+ new int[] { coordsSize,
+ area.coordsSize });
+ IntersectPoint[] intersectPoints = crossHelper.findCrossing();
+
+ if ((intersectPoints.length == 0) && (contains(area.getBounds2D()))) {
+ copy(area, this);
+ return;
+ }
+
+ double[] resultCoords = new double[coordsSize + area.coordsSize +
+ intersectPoints.length];
+ int[] resultRules = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int[] resultOffsets = new int[rulesSize + area.rulesSize +
+ intersectPoints.length];
+ int resultCoordPos = 0;
+ int resultRulesPos = 0;
+ boolean isCurrentArea = true;
+ int count = 0;
- public boolean contains(double x, double y) {
- return s == null ? false : s.contains(x, y);
- }
+ IntersectPoint point = intersectPoints[0];
+ resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+
+ do {
+ resultCoords[resultCoordPos++] = point.getX();
+ resultCoords[resultCoordPos++] = point.getY();
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos - 2;
+ int curIndex = point.getEndIndex(true);
+
+ if ((curIndex < 0) ||
+ (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) > 0)) {
+ isCurrentArea = !isCurrentArea;
+ } else if (area.containsExact(coords[2 * curIndex],
+ coords[2 * curIndex + 1]) > 0) {
+ isCurrentArea = false;
+ } else {
+ isCurrentArea = true;
+ }
- public boolean contains(double x, double y, double width, double height) {
- return s == null ? false : s.contains(x, y, width, height);
- }
+ IntersectPoint nextPoint = (isCurrentArea) ?
+ getNextIntersectPoint(intersectPoints, point, isCurrentArea):
+ getPrevIntersectPoint(intersectPoints, point, isCurrentArea);
+ double[] coords = (isCurrentArea) ? this.coords : area.coords;
+
+ int offset = (isCurrentArea) ? 2 * point.getEndIndex(isCurrentArea):
+ 2 * nextPoint.getEndIndex(isCurrentArea);
+
+ if ((offset > 0) &&
+ (((isCurrentArea) &&
+ (nextPoint.getBegIndex(isCurrentArea) <
+ point.getEndIndex(isCurrentArea))) ||
+ ((!isCurrentArea) &&
+ (nextPoint.getEndIndex(isCurrentArea) <
+ nextPoint.getBegIndex(isCurrentArea))))) {
+
+ int coordSize = (isCurrentArea) ? this.coordsSize :
+ area.coordsSize;
+ int length = coordSize - offset;
+
+ if (isCurrentArea) {
+ System.arraycopy(coords, offset,
+ resultCoords, resultCoordPos, length);
+ } else {
+ double[] temp = new double[length];
+ System.arraycopy(coords, offset, temp, 0, length);
+ reverseCopy(temp);
+ System.arraycopy(temp, 0,
+ resultCoords, resultCoordPos, length);
+ }
+
+ for (int i = 0; i < length / 2; i++) {
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+ resultCoordPos += 2;
+ }
+
+ offset = 0;
+ }
+
+ if (offset >= 0) {
+ int length = (isCurrentArea) ?
+ 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2:
+ 2 * point.getBegIndex(isCurrentArea) - offset + 2;
+
+ if (isCurrentArea) {
+ System.arraycopy(coords, offset,
+ resultCoords, resultCoordPos, length);
+ } else {
+ double[] temp = new double[length];
+ System.arraycopy(coords, offset, temp, 0, length);
+ reverseCopy(temp);
+ System.arraycopy(temp, 0,
+ resultCoords, resultCoordPos, length);
+ }
+
+ for (int i = 0; i < length / 2; i++) {
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos;
+ resultCoordPos += 2;
+ }
+ }
- public boolean contains(Point2D p) {
- if (p == null) {
- throw new NullPointerException();
+ point = nextPoint;
+ count++;
+ } while (point != intersectPoints[0] && count <= intersectPoints.length);
+
+ if (count > intersectPoints.length) {
+ reset();
+ } else {
+ resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
+ resultOffsets[resultRulesPos - 1] = resultCoordPos;
+ coords = resultCoords;
+ rules = resultRules;
+ offsets = resultOffsets;
+ coordsSize = resultCoordPos;
+ rulesSize = resultRulesPos;
}
- return s == null ? false : s.contains(p);
- }
-
- public boolean contains(Rectangle2D r) {
- if (r == null) {
- throw new NullPointerException();
+ }
+
+ private IntersectPoint getNextIntersectPoint(IntersectPoint[] iPoints,
+ IntersectPoint isectPoint,
+ boolean isCurrentArea) {
+
+ int endIndex = isectPoint.getEndIndex(isCurrentArea);
+ if (endIndex < 0) {
+ return iPoints[Math.abs(endIndex) - 1];
+ }
+
+ IntersectPoint firstIsectPoint = null;
+ IntersectPoint nextIsectPoint = null;
+ for (IntersectPoint point : iPoints) {
+ int begIndex = point.getBegIndex(isCurrentArea);
+
+ if (begIndex >= 0) {
+ if (firstIsectPoint == null) {
+ firstIsectPoint = point;
+ } else if (begIndex < firstIsectPoint
+ .getBegIndex(isCurrentArea)) {
+ firstIsectPoint = point;
+ }
+ }
+
+ if (endIndex <= begIndex) {
+ if (nextIsectPoint == null) {
+ nextIsectPoint = point;
+ } else if (begIndex <
+ nextIsectPoint.getBegIndex(isCurrentArea)) {
+ nextIsectPoint = point;
+ }
+ }
+ }
+
+ return (nextIsectPoint != null) ? nextIsectPoint : firstIsectPoint;
+ }
+
+ private IntersectPoint getPrevIntersectPoint(IntersectPoint[] iPoints,
+ IntersectPoint isectPoint,
+ boolean isCurrentArea) {
+
+ int begIndex = isectPoint.getBegIndex(isCurrentArea);
+
+ if (begIndex < 0) {
+ return iPoints[Math.abs(begIndex) - 1];
+ }
+
+ IntersectPoint firstIsectPoint = null;
+ IntersectPoint predIsectPoint = null;
+ for (IntersectPoint point : iPoints) {
+ int endIndex = point.getEndIndex(isCurrentArea);
+
+ if (endIndex >= 0) {
+ if (firstIsectPoint == null) {
+ firstIsectPoint = point;
+ } else if (endIndex < firstIsectPoint
+ .getEndIndex(isCurrentArea)) {
+ firstIsectPoint = point;
+ }
+ }
+
+ if (endIndex <= begIndex) {
+ if (predIsectPoint == null) {
+ predIsectPoint = point;
+ } else if (endIndex >
+ predIsectPoint.getEndIndex(isCurrentArea)) {
+ predIsectPoint = point;
+ }
+ }
+ }
+
+ return (predIsectPoint != null) ? predIsectPoint : firstIsectPoint;
+ }
+
+
+ private int includeCoordsAndRules(int offset, int length, int[] rules,
+ int[] offsets, int[] resultRules,
+ int[] resultOffsets, double[] resultCoords,
+ double[] coords, int resultRulesPos,
+ int resultCoordPos, IntersectPoint point,
+ boolean isCurrentArea, boolean way,
+ int operation) {
+
+ double[] temp = new double[8 * length];
+ int coordsCount = 0;
+ boolean isMoveIndex = true;
+ boolean isMoveLength = true;
+ boolean additional = false;
+
+ if (length <= offset) {
+ for (int i = resultRulesPos; i < resultRulesPos + 1; i++) {
+ resultRules[i] = PathIterator.SEG_LINETO;
+ }
+ } else {
+ int j = resultRulesPos;
+ for (int i = offset; i < length; i++) {
+ resultRules[j++] = PathIterator.SEG_LINETO;
+ }
+ }
+
+ if ((length == offset) &&
+ ((rules[offset] == PathIterator.SEG_QUADTO) ||
+ (rules[offset] == PathIterator.SEG_CUBICTO))) {
+ length++;
+ additional = true;
+ }
+ for (int i = offset; i < length; i++) {
+ int index = offsets[i];
+
+ if (!isMoveIndex) {
+ index -= 2;
+ }
+
+ if (!isMoveLength) {
+ length++;
+ isMoveLength = true;
+ }
+
+ switch (rules[i]) {
+ case PathIterator.SEG_MOVETO:
+ isMoveIndex = false;
+ isMoveLength = false;
+ break;
+ case PathIterator.SEG_LINETO:
+ case PathIterator.SEG_CLOSE:
+ resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
+ resultOffsets[resultRulesPos++] = resultCoordPos + 2;
+ boolean isLeft = CrossingHelper.compare(coords[index],
+ coords[index + 1], point.getX(), point.getY()) > 0;
+
+ if (way || !isLeft) {
+ temp[coordsCount++] = coords[index];
+ temp[coordsCount++] = coords[index + 1];
+ }
+ break;
+ case PathIterator.SEG_QUADTO:
+ resultRules[resultRulesPos] = PathIterator.SEG_QUADTO;
+ resultOffsets[resultRulesPos++] = resultCoordPos + 4;
+ double[] coefs = new double[] { coords[index - 2],
+ coords[index - 1], coords[index], coords[index + 1],
+ coords[index + 2], coords[index + 3] };
+ isLeft = CrossingHelper.compare(coords[index - 2],
+ coords[index - 1], point.getX(), point.getY()) > 0;
+
+ if ((!additional) && (operation == 0 || operation == 2)) {
+ isLeft = !isLeft;
+ way = false;
+ }
+ GeometryUtil
+ .subQuad(coefs, point.getParam(isCurrentArea), isLeft);
+
+ if (way || isLeft) {
+ temp[coordsCount++] = coefs[2];
+ temp[coordsCount++] = coefs[3];
+ } else {
+ System.arraycopy(coefs, 2, temp, coordsCount, 4);
+ coordsCount += 4;
+ }
+ break;
+ case PathIterator.SEG_CUBICTO:
+ resultRules[resultRulesPos] = PathIterator.SEG_CUBICTO;
+ resultOffsets[resultRulesPos++] = resultCoordPos + 6;
+ coefs = new double[] {coords[index - 2], coords[index - 1],
+ coords[index], coords[index + 1],
+ coords[index + 2], coords[index + 3],
+ coords[index + 4], coords[index + 5] };
+ isLeft = CrossingHelper.compare(coords[index - 2],
+ coords[index - 1], point.getX(), point.getY()) > 0;
+ GeometryUtil.subCubic(coefs, point.getParam(isCurrentArea),
+ !isLeft);
+
+ if (isLeft) {
+ System.arraycopy(coefs, 2, temp, coordsCount, 6);
+ coordsCount += 6;
+ } else {
+ System.arraycopy(coefs, 2, temp, coordsCount, 4);
+ coordsCount += 4;
+ }
+ break;
+ }
+ }
+
+ if (operation == 2 && !isCurrentArea && coordsCount > 2) {
+ reverseCopy(temp);
+ System.arraycopy(temp, 0, resultCoords, resultCoordPos, coordsCount);
+ } else {
+ System.arraycopy(temp, 0, resultCoords, resultCoordPos, coordsCount);
+ }
+
+ return (resultCoordPos + coordsCount);
+ }
+
+ // the method check up the array size and necessarily increases it.
+ private static double[] adjustSize(double[] array, int newSize) {
+ if (newSize <= array.length) {
+ return array;
+ }
+ double[] newArray = new double[2 * newSize];
+ System.arraycopy(array, 0, newArray, 0, array.length);
+ return newArray;
+ }
+
+ private static int[] adjustSize(int[] array, int newSize) {
+ if (newSize <= array.length) {
+ return array;
+ }
+ int[] newArray = new int[2 * newSize];
+ System.arraycopy(array, 0, newArray, 0, array.length);
+ return newArray;
+ }
+
+ private void copy(Area src, Area dst) {
+ dst.coordsSize = src.coordsSize;
+ dst.coords = src.coords.clone();
+ dst.rulesSize = src.rulesSize;
+ dst.rules = src.rules.clone();
+ dst.moveToCount = src.moveToCount;
+ dst.offsets = src.offsets.clone();
+ }
+
+ private int containsExact(double x, double y) {
+ PathIterator pi = getPathIterator(null);
+ int crossCount = Crossing.crossPath(pi, x, y);
+
+ if (Crossing.isInsideEvenOdd(crossCount)) {
+ return 1;
}
- return s == null ? false : s.contains(r);
- }
- public boolean equals(Area obj) throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public boolean intersects(double x, double y, double width, double height) {
- return s == null ? false : s.intersects(x, y, width, height);
- }
-
- public boolean intersects(Rectangle2D r) {
- if (r == null) {
- throw new NullPointerException();
+ double[] segmentCoords = new double[6];
+ double[] resultPoints = new double[6];
+ int rule;
+ double curX = -1;
+ double curY = -1;
+ double moveX = -1;
+ double moveY = -1;
+
+ for (pi = getPathIterator(null); !pi.isDone(); pi.next()) {
+ rule = pi.currentSegment(segmentCoords);
+ switch (rule) {
+ case PathIterator.SEG_MOVETO:
+ moveX = curX = segmentCoords[0];
+ moveY = curY = segmentCoords[1];
+ break;
+ case PathIterator.SEG_LINETO:
+ if (GeometryUtil.intersectLines(curX, curY,
+ segmentCoords[0], segmentCoords[1], x, y, x, y,
+ resultPoints) != 0) {
+ return 0;
+ }
+ curX = segmentCoords[0];
+ curY = segmentCoords[1];
+ break;
+ case PathIterator.SEG_QUADTO:
+ if (GeometryUtil.intersectLineAndQuad(x, y, x, y,
+ curX, curY, segmentCoords[0], segmentCoords[1],
+ segmentCoords[2], segmentCoords[3],
+ resultPoints) > 0) {
+ return 0;
+ }
+ curX = segmentCoords[2];
+ curY = segmentCoords[3];
+ break;
+ case PathIterator.SEG_CUBICTO:
+ if (GeometryUtil.intersectLineAndCubic(x, y, x, y,
+ curX, curY, segmentCoords[0], segmentCoords[1],
+ segmentCoords[2], segmentCoords[3], segmentCoords[4],
+ segmentCoords[5], resultPoints) > 0) {
+ return 0;
+ }
+ curX = segmentCoords[4];
+ curY = segmentCoords[5];
+ break;
+ case PathIterator.SEG_CLOSE:
+ if (GeometryUtil.intersectLines(curX, curY, moveX, moveY,
+ x, y, x, y, resultPoints) != 0) {
+ return 0;
+ }
+ curX = moveX;
+ curY = moveY;
+ break;
+ }
}
- return s == null ? false : s.intersects(r);
- }
-
- public Rectangle getBounds() {
- return s == null ? new Rectangle() : s.getBounds();
+ return -1;
}
- public Rectangle2D getBounds2D() {
- return s == null ? new Rectangle2D.Double(): s.getBounds2D();
- }
-
- public PathIterator getPathIterator(AffineTransform t) {
- return s == null ? new NullIterator() : s.getPathIterator(t);
- }
-
- public PathIterator getPathIterator(AffineTransform t, double flatness) {
- return s == null ? new NullIterator() : s.getPathIterator(t, flatness);
- }
-
- public void add(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public void exclusiveOr(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- /**
- * Extract Rectangle2D from the source shape
- * @return a Rectangle2D object if the source shape is rectangle, or null if shape is empty or not rectangle.
- */
- Rectangle2D extractRectangle() {
- if (s == null) {
- return null;
- }
- float[] points = new float[12];
- int count = 0;
- PathIterator p = s.getPathIterator(null);
- float[] coords = new float[6];
- while(!p.isDone()) {
- int type = p.currentSegment(coords);
- if (count > 12 || type == PathIterator.SEG_QUADTO || type == PathIterator.SEG_CUBICTO) {
- return null;
- }
- points[count++] = coords[0];
- points[count++] = coords[1];
- p.next();
- }
- if (points[0] == points[6] && points[6] == points[8] && points[2] == points[4] &&
- points[1] == points[3] && points[3] == points[9] && points[5] == points[7])
- {
- return new Rectangle2D.Float(points[0], points[1], points[2] - points[0], points[7] - points[1]);
- }
- return null;
+ private void reverseCopy(double[] coords) {
+ double[] temp = new double[coords.length];
+ System.arraycopy(coords, 0, temp, 0, coords.length);
+
+ for (int i = 0; i < coords.length;) {
+ coords[i] = temp[coords.length - i - 2];
+ coords[i + 1] = temp[coords.length - i - 1];
+ i = i + 2;
+ }
}
- public void intersect(Area area) {
- Rectangle2D src1 = extractRectangle();
- Rectangle2D src2 = area.extractRectangle();
- if (src1 != null && src2 != null) {
- Rectangle2D.intersect(src1, src2, (Rectangle2D)s);
- }
- }
-
- public void subtract(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public boolean isEmpty() throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public boolean isPolygonal() throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public boolean isRectangular() throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public boolean isSingular() throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public void reset() throws org.apache.harmony.luni.util.NotImplementedException {
- throw new RuntimeException("Not implemented"); //$NON-NLS-1$
- }
-
- public void transform(AffineTransform t) {
- s = t.createTransformedShape(s);
- }
-
- public Area createTransformedArea(AffineTransform t) {
- return s == null ? new Area() : new Area(t.createTransformedShape(s));
- }
-
- @Override
- public Object clone() {
- return new Area(this);
- }
+ // the internal class implements PathIterator
+ private class AreaPathIterator implements PathIterator {
-}
+ AffineTransform t;
+ Area area;
+ int curRuleIndex = 0;
+ int curCoordIndex = 0;
+
+ AreaPathIterator(Area area) {
+ this(area, null);
+ }
+
+ AreaPathIterator(Area area, AffineTransform t) {
+ this.area = area;
+ this.t = t;
+ }
+
+ public int getWindingRule() {
+ return WIND_EVEN_ODD;
+ }
+
+ public boolean isDone() {
+ return curRuleIndex >= rulesSize;
+ }
+
+ public void next() {
+ switch (rules[curRuleIndex]) {
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ curCoordIndex += 2;
+ break;
+ case PathIterator.SEG_QUADTO:
+ curCoordIndex += 4;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ curCoordIndex += 6;
+ break;
+ }
+ curRuleIndex++;
+ }
+
+ public int currentSegment(double[] c) {
+ if (isDone()) {
+ throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+ }
+ switch (rules[curRuleIndex]) {
+ case PathIterator.SEG_CUBICTO:
+ c[4] = coords[curCoordIndex + 4];
+ c[5] = coords[curCoordIndex + 5];
+ case PathIterator.SEG_QUADTO:
+ c[2] = coords[curCoordIndex + 2];
+ c[3] = coords[curCoordIndex + 3];
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ c[0] = coords[curCoordIndex];
+ c[1] = coords[curCoordIndex + 1];
+ }
+ return rules[curRuleIndex];
+ }
+
+ public int currentSegment(float[] c) {
+ double[] doubleCoords = new double[6];
+ int rule = currentSegment(doubleCoords);
+
+ for (int i = 0; i < 6; i++) {
+ c[i] = (float) doubleCoords[i];
+ }
+ return rule;
+ }
+ }
+}
\ No newline at end of file
Modified: harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java?view=diff&rev=546906&r1=546905&r2=546906
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java Wed Jun 13 08:05:17 2007
@@ -45,54 +45,126 @@
}
public void testContainsPoint() {
- // Regression test HARMONY-1404
try {
- Area a = new Area();
- a.contains((Point2D)null);
- fail("Expected NPE");
- } catch (NullPointerException e) {
- // expected
- }
- }
+ Area area = new Area(new Ellipse2D.Double(200, 300, 400, 200));
+ assertTrue(area.contains(250, 350));
+ assertFalse(area.contains(200, 300));
+ assertFalse(area.contains(50, 50));
+
+ assertTrue(area.contains(new Point2D.Double(500, 400)));
+ assertFalse(area.contains(new Point2D.Double(700, 400)));
+
+ // Regression test HARMONY-1404
+ Area emptyArea = new Area();
+ emptyArea.contains((Point2D)null);
+ fail("Expected NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
- public void testContainsRect() {
- // Regression test HARMONY-1404
- try {
- Area a = new Area();
- a.contains((Rectangle2D)null);
- fail("Expected NPE");
- } catch (NullPointerException e) {
- // expected
- }
- }
+ public void testContainsRect() {
+ // Regression test HARMONY-1476
+ GeneralPath path = new GeneralPath();
+ path.moveTo(100, 500);
+ path.lineTo(400, 100);
+ path.lineTo(700, 500);
+ path.closePath();
+
+ Area area = new Area(path);
+ assertTrue(area.contains(new Rectangle2D.Double(300, 400, 100, 50)));
+ assertFalse(area.contains(new Rectangle2D.Double(50, 400, 700, 50)));
+
+ GeneralPath path1 = new GeneralPath();
+ path1.moveTo(400, 500);
+ path1.quadTo(200, 200, 400, 100);
+ path1.quadTo(600, 200, 400, 500);
+ path1.closePath();
+
+ Area area1 = new Area(path1);
+ assertTrue(area1.contains(350, 200, 50, 50));
+ assertFalse(area1.contains(100, 50, 600, 500));
+
+ // Regression test HARMONY-1404
+ try {
+ Area emptyArea = new Area();
+ emptyArea.contains((Rectangle2D)null);
+ fail("Expected NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
- public void testIntersectsRect() {
- // Regression test HARMONY-1404
- try {
- Area a = new Area();
- a.intersects((Rectangle2D)null);
- fail("Expected NPE");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- public void testGetPathIterator() {
- // Regression test HARMONY-1860
- Area a = new Area();
- PathIterator path = a.getPathIterator(null);
- checkPathRule(path, PathIterator.WIND_NON_ZERO);
- checkPathDone(path, true);
- }
-
- public void testCreateTransformedArea() {
- // Regression test HARMONY-1880
- AffineTransform t = AffineTransform.getScaleInstance(2, 3);
- Area a1 = new Area();
- Area a2 = a1.createTransformedArea(t);
- PathIterator path = a2.getPathIterator(null);
- checkPathRule(path, PathIterator.WIND_NON_ZERO);
- checkPathDone(path, true);
- }
+ public void testIntersectsRect() {
+ // Regression test HARMONY-1476
+ GeneralPath path = new GeneralPath();
+ path.moveTo(100, 500);
+ path.lineTo(400, 100);
+ path.lineTo(700, 500);
+ path.closePath();
+
+ Area area = new Area(path);
+ assertTrue(area.intersects(new Rectangle2D.Double(300, 400, 100, 50)));
+ assertFalse(area.intersects(new Rectangle2D.Double(50, 50, 50, 50)));
+
+ GeneralPath path1 = new GeneralPath();
+ path1.moveTo(400, 500);
+ path1.quadTo(200, 200, 400, 100);
+ path1.quadTo(600, 200, 400, 500);
+ path1.closePath();
+
+ Area area1 = new Area(path1);
+ assertTrue(area1.intersects(350, 200, 50, 50));
+ assertFalse(area1.intersects(500, 50, 100, 50));
+
+ // Regression test HARMONY-1404
+ try {
+ Area emptyArea = new Area();
+ emptyArea.intersects((Rectangle2D)null);
+ fail("Expected NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testIsRectangle() {
+ // Regression test HARMONY-1476
+ Area area = new Area(new Rectangle2D.Double(200, 300, 400, 150));
+ assertTrue(area.isRectangular());
+
+ GeneralPath path = new GeneralPath();
+ path.moveTo(200, 300);
+ path.lineTo(600, 300);
+ path.lineTo(600, 450);
+ path.lineTo(200, 450);
+ path.closePath();
+
+ Area area1 = new Area(path);
+ assertTrue(area1.isRectangular());
+
+ Area area2 = new Area(new Ellipse2D.Double(200, 300, 400, 150));
+ assertFalse(area2.isRectangular());
+ }
+
+ public void testGetPathIterator() {
+ // Regression test HARMONY-1860
+ Area a = new Area();
+ PathIterator path = a.getPathIterator(null);
+ checkPathRule(path, PathIterator.WIND_EVEN_ODD);
+ checkPathDone(path, true);
+ }
+
+ public void testCreateTransformedArea() {
+ // Regression test HARMONY-1880
+ AffineTransform t = AffineTransform.getScaleInstance(2, 3);
+ Area a1 = new Area();
+ Area a2 = a1.createTransformedArea(t);
+ PathIterator path = a2.getPathIterator(null);
+ checkPathRule(path, PathIterator.WIND_EVEN_ODD);
+ checkPathDone(path, true);
+ }
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AreaTest.class);
+ }
}
Re: [classli][awt] compile errors
Posted by Tim Ellison <t....@gmail.com>.
Alexei Zakharov wrote:
> Thanks gentlemen,
>
> I probably should sleep more - forgot to add few source files indeed.
> Sorry for this. Should be fixed after 547195.
No worries -- we've all done it :-)
Tim
Re: [classli][awt] compile errors
Posted by Alexei Zakharov <al...@gmail.com>.
Thanks gentlemen,
I probably should sleep more - forgot to add few source files indeed.
Sorry for this. Should be fixed after 547195.
Regards,
Alexei
2007/6/14, Tim Ellison <t....@gmail.com>:
> Gregory Shimansky wrote:
> > Tim Ellison wrote:
> >> I've rolled back this commit since it produces a number of compile time
> >> errors in AWT.
> >
> > It looks like some files from the original patch in HARMONY-1476 weren't
> > committed, so compilation failed. I was going to try to add them, but I
> > think it is better if Alexei does it himself.
>
> I agree. This is not blocking anything else, so we'll let him have a
> second run at it ;-)
>
> Regards,
> Tim
Re: [classli][awt] compile errors
Posted by Tim Ellison <t....@gmail.com>.
Gregory Shimansky wrote:
> Tim Ellison wrote:
>> I've rolled back this commit since it produces a number of compile time
>> errors in AWT.
>
> It looks like some files from the original patch in HARMONY-1476 weren't
> committed, so compilation failed. I was going to try to add them, but I
> think it is better if Alexei does it himself.
I agree. This is not blocking anything else, so we'll let him have a
second run at it ;-)
Regards,
Tim
Re: [classli][awt] compile errors
Posted by Gregory Shimansky <gs...@apache.org>.
Tim Ellison wrote:
> I've rolled back this commit since it produces a number of compile time
> errors in AWT.
It looks like some files from the original patch in HARMONY-1476 weren't
committed, so compilation failed. I was going to try to add them, but I
think it is better if Alexei does it himself.
> ayza@apache.org wrote:
>> Author: ayza
>> Date: Wed Jun 13 08:05:17 2007
>> New Revision: 546906
>>
>> URL: http://svn.apache.org/viewvc?view=rev&rev=546906
>> Log:
>> java.awt.geom.Area implementation from HARMONY-1476
>>
>> Modified:
>> harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java
>> harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java
>>
>> Modified: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java
>> URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java?view=diff&rev=546906&r1=546905&r2=546906
>> ==============================================================================
>> --- harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java (original)
>> +++ harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java Wed Jun 13 08:05:17 2007
>> @@ -14,199 +14,1287 @@
>> * See the License for the specific language governing permissions and
>> * limitations under the License.
>> */
>> -/**
>> - * @author Denis M. Kishenko
>> - * @version $Revision$
>> - */
>> package java.awt.geom;
>>
>> import java.awt.Rectangle;
>> import java.awt.Shape;
>> -import java.awt.geom.PathIterator;
>> -import java.awt.geom.Rectangle2D;
>> import java.util.NoSuchElementException;
>>
>> +import org.apache.harmony.awt.gl.Crossing;
>> +import org.apache.harmony.awt.internal.CrossingHelper;
>> +import org.apache.harmony.awt.internal.CurveCrossingHelper;
>> +import org.apache.harmony.awt.internal.GeometryUtil;
>> +import org.apache.harmony.awt.internal.IntersectPoint;
>> import org.apache.harmony.awt.internal.nls.Messages;
>>
>> +
>> public class Area implements Shape, Cloneable {
>>
>> /**
>> - * The source Shape object
>> + * the coordinates array of the shape vertices
>> */
>> - Shape s;
>> -
>> - private static class NullIterator implements PathIterator {
>> -
>> - NullIterator() {
>> - }
>> -
>> - public int getWindingRule() {
>> - return WIND_NON_ZERO;
>> - }
>> -
>> - public boolean isDone() {
>> - return true;
>> - }
>> + private double coords[] = new double[20];
>> +
>> + /**
>> + * the coordinates quantity
>> + */
>> + private int coordsSize = 0;
>> +
>> + /**
>> + * the rules array for the drawing of the shape edges
>> + */
>> + private int rules[] = new int[10];
>> +
>> + /**
>> + * the rules quantity
>> + */
>> + private int rulesSize = 0;
>> +
>> + /**
>> + * offsets[i] - index in array of coords and i - index in array of rules
>> + */
>> + private int offsets[] = new int[10];
>> +
>> + /**
>> + * the quantity of MOVETO rule occurences
>> + */
>> + private int moveToCount = 0;
>> +
>> + /**
>> + * true if the shape is polygon
>> + */
>> + private boolean isPolygonal = true;
>> +
>> + public Area() {
>> + }
>> +
>> + public Area(Shape s) {
>> + double segmentCoords[] = new double[6];
>> + double lastMoveX = 0.0;
>> + double lastMoveY = 0.0;
>> + int rulesIndex = 0;
>> + int coordsIndex = 0;
>> +
>> + for (PathIterator pi = s.getPathIterator(null);
>> + !pi.isDone(); pi.next()) {
>> + coords = adjustSize(coords, coordsIndex + 6);
>> + rules = adjustSize(rules, rulesIndex + 1);
>> + offsets = adjustSize(offsets, rulesIndex + 1);
>> + rules[rulesIndex] = pi.currentSegment(segmentCoords);
>> + offsets[rulesIndex] = coordsIndex;
>> +
>> + switch (rules[rulesIndex]) {
>> + case PathIterator.SEG_MOVETO:
>> + coords[coordsIndex++] = segmentCoords[0];
>> + coords[coordsIndex++] = segmentCoords[1];
>> + lastMoveX = segmentCoords[0];
>> + lastMoveY = segmentCoords[1];
>> + ++moveToCount;
>> + break;
>> + case PathIterator.SEG_LINETO:
>> + if ((segmentCoords[0] != lastMoveX) ||
>> + (segmentCoords[1] != lastMoveY)) {
>> + coords[coordsIndex++] = segmentCoords[0];
>> + coords[coordsIndex++] = segmentCoords[1];
>> + } else {
>> + --rulesIndex;
>> + }
>> + break;
>> + case PathIterator.SEG_QUADTO:
>> + System.arraycopy(segmentCoords, 0, coords, coordsIndex, 4);
>> + coordsIndex += 4;
>> + isPolygonal = false;
>> + break;
>> + case PathIterator.SEG_CUBICTO:
>> + System.arraycopy(segmentCoords, 0, coords, coordsIndex, 6);
>> + coordsIndex += 6;
>> + isPolygonal = false;
>> + break;
>> + case PathIterator.SEG_CLOSE:
>> + break;
>> + }
>> + ++rulesIndex;
>> + }
>> +
>> + if ((rulesIndex != 0) &&
>> + (rules[rulesIndex - 1] != PathIterator.SEG_CLOSE)) {
>> + rules[rulesIndex] = PathIterator.SEG_CLOSE;
>> + offsets[rulesIndex] = coordsSize;
>> + }
>> +
>> + rulesSize = rulesIndex;
>> + coordsSize = coordsIndex;
>> + }
>> +
>> + public boolean contains(double x, double y) {
>> + return !isEmpty() &&
>> + containsExact(x, y) > 0;
>> + }
>> +
>> + public boolean contains(double x, double y, double width, double height) {
>> + int crossCount = Crossing.intersectPath(getPathIterator(null), x, y,
>> + width, height);
>> + return crossCount != Crossing.CROSSING &&
>> + Crossing.isInsideEvenOdd(crossCount);
>> + }
>> +
>> + public boolean contains(Point2D p) {
>> + return contains(p.getX(), p.getY());
>> + }
>> +
>> + public boolean contains(Rectangle2D r) {
>> + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
>> + }
>> +
>> + public boolean equals(Area obj) {
>> + if (this == obj) {
>> + return true;
>> + }
>> +
>> + if (obj == null) {
>> + return false;
>> + }
>> +
>> + Area area = (Area)clone();
>> + area.subtract(obj);
>> + return area.isEmpty();
>> + }
>> +
>> + public boolean intersects(double x, double y, double width, double height) {
>> + if ((width <= 0.0) || (height <= 0.0)) {
>> + return false;
>> + } else if (!getBounds2D().intersects(x, y, width, height)) {
>> + return false;
>> + }
>> +
>> + int crossCount = Crossing.intersectShape(this, x, y, width, height);
>> + return Crossing.isInsideEvenOdd(crossCount);
>> + }
>> +
>> + public boolean intersects(Rectangle2D r) {
>> + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
>> + }
>> +
>> + public Rectangle getBounds() {
>> + return getBounds2D().getBounds();
>> + }
>> +
>> + public Rectangle2D getBounds2D() {
>> + double maxX = coords[0];
>> + double maxY = coords[1];
>> + double minX = coords[0];
>> + double minY = coords[1];
>> +
>> + for (int i = 0; i < coordsSize;) {
>> + minX = Math.min(minX, coords[i]);
>> + maxX = Math.max(maxX, coords[i++]);
>> + minY = Math.min(minY, coords[i]);
>> + maxY = Math.max(maxY, coords[i++]);
>> + }
>> +
>> + return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
>> + }
>> +
>> + public PathIterator getPathIterator(AffineTransform t) {
>> + return new AreaPathIterator(this, t);
>> + }
>> +
>> + public PathIterator getPathIterator(AffineTransform t, double flatness) {
>> + return new FlatteningPathIterator(getPathIterator(t), flatness);
>> + }
>> +
>> + public boolean isEmpty() {
>> + return (rulesSize == 0) && (coordsSize == 0);
>> + }
>> +
>> + public boolean isPolygonal() {
>> + return isPolygonal;
>> + }
>> +
>> + public boolean isRectangular() {
>> + return (isPolygonal) && (rulesSize <= 5) && (coordsSize <= 8) &&
>> + (coords[1] == coords[3]) && (coords[7] == coords[5]) &&
>> + (coords[0] == coords[6]) && (coords[2] == coords[4]);
>> + }
>> +
>> + public boolean isSingular() {
>> + return (moveToCount <= 1);
>> + }
>> +
>> + public void reset() {
>> + coordsSize = 0;
>> + rulesSize = 0;
>> + }
>> +
>> + public void transform(AffineTransform t) {
>> + copy(new Area(t.createTransformedShape(this)), this);
>> + }
>> +
>> + public Area createTransformedArea(AffineTransform t) {
>> + return new Area(t.createTransformedShape(this));
>> + }
>> +
>> + public Object clone() {
>> + Area area = new Area();
>> + copy(this, area);
>> + return area;
>> + }
>> +
>> + public void add(Area area) {
>> + if (isPolygonal() && area.isPolygonal()) {
>> + addPolygon(area);
>> + } else {
>> + addCurvePolygon(area);
>> + }
>> + }
>> +
>> + public void intersect(Area area) {
>> + if (isPolygonal() && area.isPolygonal()) {
>> + intersectPolygon(area);
>> + } else {
>> + intersectCurvePolygon(area);
>> + }
>> + }
>> +
>> + public void subtract(Area area) {
>> + if (isPolygonal() && area.isPolygonal()) {
>> + subtractPolygon(area);
>> + } else {
>> + subtractCurvePolygon(area);
>> + }
>> + }
>> +
>> + public void exclusiveOr(Area area) {
>> + Area a = (Area) clone();
>> + a.intersect(area);
>> + add(area);
>> + subtract(a);
>> + }
>> +
>> + private void addCurvePolygon(Area area) {
>> + CurveCrossingHelper crossHelper = new CurveCrossingHelper(
>> + new double[][] { coords, area.coords },
>> + new int[] { coordsSize, area.coordsSize },
>> + new int[][] { rules, area.rules },
>> + new int[] { rulesSize, area.rulesSize },
>> + new int[][] { offsets, area.offsets });
>> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
>> +
>> + if (intersectPoints.length == 0) {
>> + if (area.contains(getBounds2D())) {
>> + copy(area, this);
>> + } else if (!contains(area.getBounds2D())) {
>> + coords = adjustSize(coords, coordsSize + area.coordsSize);
>> + System.arraycopy(area.coords, 0, coords, coordsSize,
>> + area.coordsSize);
>> + coordsSize += area.coordsSize;
>> + rules = adjustSize(rules, rulesSize + area.rulesSize);
>> + System.arraycopy(area.rules, 0, rules, rulesSize,
>> + area.rulesSize);
>> + rulesSize += area.rulesSize;
>> + offsets = adjustSize(offsets, rulesSize + area.rulesSize);
>> + System.arraycopy(area.offsets, 0, offsets, rulesSize,
>> + area.rulesSize);
>> + }
>> +
>> + return;
>> + }
>> +
>> + double[] resultCoords = new double[coordsSize + area.coordsSize +
>> + intersectPoints.length];
>> + int[] resultRules = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int resultCoordPos = 0;
>> + int resultRulesPos = 0;
>> + boolean isCurrentArea = true;
>> +
>> + IntersectPoint point = intersectPoints[0];
>> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> +
>> + do {
>> + resultCoords[resultCoordPos++] = point.getX();
>> + resultCoords[resultCoordPos++] = point.getY();
>> + int curIndex = point.getEndIndex(true);
>> +
>> + if (curIndex < 0) {
>> + isCurrentArea = !isCurrentArea;
>> + } else if (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) > 0) {
>> + isCurrentArea = false;
>> + } else {
>> + isCurrentArea = true;
>> + }
>>
>> - public void next() {
>> - // nothing
>> - }
>> + IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
>> + point,
>> + isCurrentArea);
>> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
>> + int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
>> + int[] rules = (isCurrentArea) ? this.rules : area.rules;
>> + int offset = point.getRuleIndex(isCurrentArea);
>> + boolean isCopyUntilZero = false;
>> +
>> + if ((point.getRuleIndex(isCurrentArea) >
>> + nextPoint.getRuleIndex(isCurrentArea))) {
>> + int rulesSize = (isCurrentArea) ? this.rulesSize :
>> + area.rulesSize;
>> + resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
>> + rules, offsets,
>> + resultRules,
>> + resultOffsets,
>> + resultCoords, coords,
>> + resultRulesPos,
>> + resultCoordPos,
>> + point, isCurrentArea,
>> + false, 0);
>> + resultRulesPos += rulesSize - offset - 1;
>> + offset = 1;
>> + isCopyUntilZero = true;
>> + }
>> +
>> + int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
>> +
>> + if (isCopyUntilZero) {
>> + offset = 0;
>> + }
>> +
>> + resultCoordPos = includeCoordsAndRules(offset, length, rules,
>> + offsets, resultRules,
>> + resultOffsets, resultCoords,
>> + coords, resultRulesPos,
>> + resultCoordPos, point,
>> + isCurrentArea, true, 0);
>> + resultRulesPos += length - offset;
>> + point = nextPoint;
>> + } while (point != intersectPoints[0]);
>> +
>> + resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
>> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
>> + this.coords = resultCoords;
>> + this.rules = resultRules;
>> + this.offsets = resultOffsets;
>> + this.coordsSize = resultCoordPos;
>> + this.rulesSize = resultRulesPos;
>> + }
>> +
>> + private void addPolygon(Area area) {
>> + CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
>> + area.coords },
>> + new int[] {coordsSize,
>> + area.coordsSize });
>> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
>> +
>> + if (intersectPoints.length == 0) {
>> + if (area.contains(getBounds2D())) {
>> + copy(area, this);
>> + } else if (!contains(area.getBounds2D())) {
>> + coords = adjustSize(coords, coordsSize + area.coordsSize);
>> + System.arraycopy(area.coords, 0, coords, coordsSize,
>> + area.coordsSize);
>> + coordsSize += area.coordsSize;
>> + rules = adjustSize(rules, rulesSize + area.rulesSize);
>> + System.arraycopy(area.rules, 0, rules, rulesSize,
>> + area.rulesSize);
>> + rulesSize += area.rulesSize;
>> + offsets = adjustSize(offsets, rulesSize + area.rulesSize);
>> + System.arraycopy(area.offsets, 0, offsets, rulesSize,
>> + area.rulesSize);
>> + }
>> + return;
>> + }
>> +
>> + double[] resultCoords = new double[coordsSize + area.coordsSize +
>> + intersectPoints.length];
>> + int[] resultRules = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int resultCoordPos = 0;
>> + int resultRulesPos = 0;
>> + boolean isCurrentArea = true;
>> +
>> + IntersectPoint point = intersectPoints[0];
>> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> +
>> + do {
>> + resultCoords[resultCoordPos++] = point.getX();
>> + resultCoords[resultCoordPos++] = point.getY();
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos - 2;
>> + int curIndex = point.getEndIndex(true);
>> + if (curIndex < 0) {
>> + isCurrentArea = !isCurrentArea;
>> + } else if (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) > 0) {
>> + isCurrentArea = false;
>> + } else {
>> + isCurrentArea = true;
>> + }
>>
>> - public int currentSegment(double[] coords) {
>> - // awt.4B=Iterator out of bounds
>> - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
>> - }
>> + IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
>> + point,
>> + isCurrentArea);
>> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
>> + int offset = 2 * point.getEndIndex(isCurrentArea);
>> +
>> + if (nextPoint.getBegIndex(isCurrentArea) <
>> + point.getEndIndex(isCurrentArea)) {
>> + int coordSize = (isCurrentArea) ? this.coordsSize :
>> + area.coordsSize;
>> + int length = coordSize - offset;
>> + System.arraycopy(coords, offset,
>> + resultCoords, resultCoordPos, length);
>> +
>> + for (int i = 0; i < length / 2; i++) {
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> + resultCoordPos += 2;
>> + }
>> +
>> + offset = 0;
>> + }
>> +
>> + int length = 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2;
>> + System.arraycopy(coords, offset,
>> + resultCoords, resultCoordPos, length);
>> +
>> + for (int i = 0; i < length / 2; i++) {
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> + resultCoordPos += 2;
>> + }
>>
>> - public int currentSegment(float[] coords) {
>> - // awt.4B=Iterator out of bounds
>> - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
>> + point = nextPoint;
>> + } while (point != intersectPoints[0]);
>> +
>> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
>> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
>> + coords = resultCoords;
>> + rules = resultRules;
>> + offsets = resultOffsets;
>> + coordsSize = resultCoordPos;
>> + rulesSize = resultRulesPos;
>> + }
>> +
>> + private void intersectCurvePolygon(Area area) {
>> + CurveCrossingHelper crossHelper = new CurveCrossingHelper(
>> + new double[][] {coords, area.coords },
>> + new int[] { coordsSize, area.coordsSize },
>> + new int[][] { rules, area.rules },
>> + new int[] { rulesSize, area.rulesSize },
>> + new int[][] { offsets, area.offsets });
>> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
>> +
>> + if (intersectPoints.length == 0) {
>> + if (contains(area.getBounds2D())) {
>> + copy(area, this);
>> + } else if (!area.contains(getBounds2D())) {
>> + reset();
>> + }
>> + return;
>> + }
>> +
>> + double[] resultCoords = new double[coordsSize + area.coordsSize +
>> + intersectPoints.length];
>> + int[] resultRules = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int resultCoordPos = 0;
>> + int resultRulesPos = 0;
>> + boolean isCurrentArea = true;
>> +
>> + IntersectPoint point = intersectPoints[0];
>> + IntersectPoint nextPoint = intersectPoints[0];
>> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> +
>> + do {
>> + resultCoords[resultCoordPos++] = point.getX();
>> + resultCoords[resultCoordPos++] = point.getY();
>> +
>> + int curIndex = point.getEndIndex(true);
>> + if ((curIndex < 0) || (area.containsExact(
>> + coords[2 * curIndex], coords[2 * curIndex + 1]) == 0)) {
>> + isCurrentArea = !isCurrentArea;
>> + } else if (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) > 0) {
>> + isCurrentArea = true;
>> + } else {
>> + isCurrentArea = false;
>> + }
>> +
>> + nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
>> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
>> + int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
>> + int[] rules = (isCurrentArea) ? this.rules : area.rules;
>> + int offset = point.getRuleIndex(isCurrentArea);
>> + boolean isCopyUntilZero = false;
>> +
>> + if (point.getRuleIndex(isCurrentArea) >
>> + nextPoint.getRuleIndex(isCurrentArea)) {
>> + int rulesSize = (isCurrentArea) ? this.rulesSize :
>> + area.rulesSize;
>> + resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
>> + rules, offsets,
>> + resultRules,
>> + resultOffsets,
>> + resultCoords, coords,
>> + resultRulesPos,
>> + resultCoordPos, point,
>> + isCurrentArea, false,
>> + 1);
>> + resultRulesPos += rulesSize - offset - 1;
>> + offset = 1;
>> + isCopyUntilZero = true;
>> + }
>> +
>> + int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
>> +
>> + if (isCopyUntilZero) {
>> + offset = 0;
>> + isCopyUntilZero = false;
>> + }
>> + if ((length == offset) &&
>> + (nextPoint.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
>> + (nextPoint.getRule(isCurrentArea) != PathIterator.SEG_CLOSE) &&
>> + (point.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
>> + (point.getRule(isCurrentArea) != PathIterator.SEG_CLOSE)) {
>> +
>> + isCopyUntilZero = true;
>> + length++;
>> + }
>> +
>> + resultCoordPos = includeCoordsAndRules(offset, length, rules,
>> + offsets, resultRules,
>> + resultOffsets, resultCoords,
>> + coords, resultRulesPos,
>> + resultCoordPos, nextPoint,
>> + isCurrentArea, true, 1);
>> + resultRulesPos = ((length <= offset) || (isCopyUntilZero)) ?
>> + resultRulesPos + 1 : resultRulesPos + length;
>> +
>> + point = nextPoint;
>> + } while (point != intersectPoints[0]);
>> +
>> + if (resultRules[resultRulesPos - 1] == PathIterator.SEG_LINETO) {
>> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
>> + } else {
>> + resultCoords[resultCoordPos++] = nextPoint.getX();
>> + resultCoords[resultCoordPos++] = nextPoint.getY();
>> + resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
>> }
>> +
>> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
>> + coords = resultCoords;
>> + rules = resultRules;
>> + offsets = resultOffsets;
>> + coordsSize = resultCoordPos;
>> + rulesSize = resultRulesPos;
>> + }
>> +
>> + private void intersectPolygon(Area area) {
>> + CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
>> + area.coords },
>> + new int[] { coordsSize,
>> + area.coordsSize });
>> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
>> +
>> + if (intersectPoints.length == 0) {
>> + if (contains(area.getBounds2D())) {
>> + copy(area, this);
>> + } else if (!area.contains(getBounds2D())) {
>> + reset();
>> + }
>> + return;
>> + }
>> +
>> + double[] resultCoords = new double[coordsSize + area.coordsSize +
>> + intersectPoints.length];
>> + int[] resultRules = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int resultCoordPos = 0;
>> + int resultRulesPos = 0;
>> + boolean isCurrentArea = true;
>> +
>> + IntersectPoint point = intersectPoints[0];
>> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> +
>> + do {
>> + resultCoords[resultCoordPos++] = point.getX();
>> + resultCoords[resultCoordPos++] = point.getY();
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos - 2;
>> + int curIndex = point.getEndIndex(true);
>> +
>> + if ((curIndex < 0) ||
>> + (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) == 0)) {
>> + isCurrentArea = !isCurrentArea;
>> + } else if (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) > 0) {
>> + isCurrentArea = true;
>> + } else {
>> + isCurrentArea = false;
>> + }
>>
>> - }
>> -
>> - public Area() {
>> - }
>> + IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
>> + point,
>> + isCurrentArea);
>> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
>> + int offset = 2 * point.getEndIndex(isCurrentArea);
>> + if ((offset >= 0) &&
>> + (nextPoint.getBegIndex(isCurrentArea) <
>> + point.getEndIndex(isCurrentArea))) {
>> + int coordSize = (isCurrentArea) ? this.coordsSize :
>> + area.coordsSize;
>> + int length = coordSize - offset;
>> + System.arraycopy(coords, offset,
>> + resultCoords, resultCoordPos, length);
>> +
>> + for (int i = 0; i < length / 2; i++) {
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> + resultCoordPos += 2;
>> + }
>> +
>> + offset = 0;
>> + }
>> +
>> + if (offset >= 0) {
>> + int length = 2 * nextPoint.getBegIndex(isCurrentArea) -
>> + offset + 2;
>> + System.arraycopy(coords, offset,
>> + resultCoords, resultCoordPos, length);
>> +
>> + for (int i = 0; i < length / 2; i++) {
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> + resultCoordPos += 2;
>> + }
>> + }
>>
>> - public Area(Shape s) {
>> - if (s == null) {
>> - throw new NullPointerException();
>> - }
>> - this.s = s;
>> - }
>> + point = nextPoint;
>> + } while (point != intersectPoints[0]);
>> +
>> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
>> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
>> + coords = resultCoords;
>> + rules = resultRules;
>> + offsets = resultOffsets;
>> + coordsSize = resultCoordPos;
>> + rulesSize = resultRulesPos;
>> + }
>> +
>> + private void subtractCurvePolygon(Area area) {
>> + CurveCrossingHelper crossHelper = new CurveCrossingHelper(
>> + new double[][] { coords, area.coords },
>> + new int[] { coordsSize, area.coordsSize },
>> + new int[][] { rules, area.rules },
>> + new int[] { rulesSize, area.rulesSize },
>> + new int[][] { offsets, area.offsets });
>> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
>> +
>> + if (intersectPoints.length == 0 && contains(area.getBounds2D())) {
>> + copy(area, this);
>> + return;
>> + }
>> +
>> + double[] resultCoords = new double[coordsSize + area.coordsSize +
>> + intersectPoints.length];
>> + int[] resultRules = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int resultCoordPos = 0;
>> + int resultRulesPos = 0;
>> + boolean isCurrentArea = true;
>> +
>> + IntersectPoint point = intersectPoints[0];
>> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> +
>> + do {
>> + resultCoords[resultCoordPos++] = point.getX();
>> + resultCoords[resultCoordPos++] = point.getY();
>> + int curIndex = offsets[point.getRuleIndex(true)] % coordsSize;
>> +
>> + if (area.containsExact(coords[curIndex],
>> + coords[curIndex + 1]) == 0) {
>> + isCurrentArea = !isCurrentArea;
>> + } else if (area.containsExact(coords[curIndex],
>> + coords[curIndex + 1]) > 0) {
>> + isCurrentArea = false;
>> + } else {
>> + isCurrentArea = true;
>> + }
>> +
>> + IntersectPoint nextPoint = (isCurrentArea) ?
>> + getNextIntersectPoint(intersectPoints, point,
>> + isCurrentArea):
>> + getPrevIntersectPoint(intersectPoints, point,
>> + isCurrentArea);
>> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
>> + int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
>> + int[] rules = (isCurrentArea) ? this.rules : area.rules;
>> + int offset = (isCurrentArea) ? point.getRuleIndex(isCurrentArea) :
>> + nextPoint.getRuleIndex(isCurrentArea);
>> + boolean isCopyUntilZero = false;
>> +
>> + if (((isCurrentArea) &&
>> + (point.getRuleIndex(isCurrentArea) >
>> + nextPoint.getRuleIndex(isCurrentArea))) ||
>> + ((!isCurrentArea) &&
>> + (nextPoint.getRuleIndex(isCurrentArea) >
>> + nextPoint.getRuleIndex(isCurrentArea)))) {
>> +
>> + int rulesSize = (isCurrentArea) ? this.rulesSize :
>> + area.rulesSize;
>> + resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
>> + rules, offsets,
>> + resultRules,
>> + resultOffsets,
>> + resultCoords, coords,
>> + resultRulesPos,
>> + resultCoordPos, point,
>> + isCurrentArea, false,
>> + 2);
>> + resultRulesPos += rulesSize - offset - 1;
>> + offset = 1;
>> + isCopyUntilZero = true;
>> + }
>> +
>> + int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
>> +
>> + if (isCopyUntilZero) {
>> + offset = 0;
>> + isCopyUntilZero = false;
>> + }
>> +
>> + resultCoordPos = includeCoordsAndRules(offset, length, rules,
>> + offsets, resultRules,
>> + resultOffsets, resultCoords,
>> + coords, resultRulesPos,
>> + resultCoordPos, point,
>> + isCurrentArea, true, 2);
>> +
>> + if ((length == offset) &&
>> + ((rules[offset] == PathIterator.SEG_QUADTO) ||
>> + (rules[offset] == PathIterator.SEG_CUBICTO))) {
>> +
>> + resultRulesPos++;
>> + } else {
>> + resultRulesPos = (length < offset || isCopyUntilZero) ?
>> + resultRulesPos + 1 : resultRulesPos + length - offset;
>> + }
>> +
>> + point = nextPoint;
>> + } while (point != intersectPoints[0]);
>> +
>> + resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
>> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
>> + coords = resultCoords;
>> + rules = resultRules;
>> + offsets = resultOffsets;
>> + coordsSize = resultCoordPos;
>> + rulesSize = resultRulesPos;
>> + }
>> +
>> + private void subtractPolygon(Area area) {
>> + CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
>> + area.coords },
>> + new int[] { coordsSize,
>> + area.coordsSize });
>> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
>> +
>> + if ((intersectPoints.length == 0) && (contains(area.getBounds2D()))) {
>> + copy(area, this);
>> + return;
>> + }
>> +
>> + double[] resultCoords = new double[coordsSize + area.coordsSize +
>> + intersectPoints.length];
>> + int[] resultRules = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
>> + intersectPoints.length];
>> + int resultCoordPos = 0;
>> + int resultRulesPos = 0;
>> + boolean isCurrentArea = true;
>> + int count = 0;
>>
>> - public boolean contains(double x, double y) {
>> - return s == null ? false : s.contains(x, y);
>> - }
>> + IntersectPoint point = intersectPoints[0];
>> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> +
>> + do {
>> + resultCoords[resultCoordPos++] = point.getX();
>> + resultCoords[resultCoordPos++] = point.getY();
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos - 2;
>> + int curIndex = point.getEndIndex(true);
>> +
>> + if ((curIndex < 0) ||
>> + (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) > 0)) {
>> + isCurrentArea = !isCurrentArea;
>> + } else if (area.containsExact(coords[2 * curIndex],
>> + coords[2 * curIndex + 1]) > 0) {
>> + isCurrentArea = false;
>> + } else {
>> + isCurrentArea = true;
>> + }
>>
>> - public boolean contains(double x, double y, double width, double height) {
>> - return s == null ? false : s.contains(x, y, width, height);
>> - }
>> + IntersectPoint nextPoint = (isCurrentArea) ?
>> + getNextIntersectPoint(intersectPoints, point, isCurrentArea):
>> + getPrevIntersectPoint(intersectPoints, point, isCurrentArea);
>> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
>> +
>> + int offset = (isCurrentArea) ? 2 * point.getEndIndex(isCurrentArea):
>> + 2 * nextPoint.getEndIndex(isCurrentArea);
>> +
>> + if ((offset > 0) &&
>> + (((isCurrentArea) &&
>> + (nextPoint.getBegIndex(isCurrentArea) <
>> + point.getEndIndex(isCurrentArea))) ||
>> + ((!isCurrentArea) &&
>> + (nextPoint.getEndIndex(isCurrentArea) <
>> + nextPoint.getBegIndex(isCurrentArea))))) {
>> +
>> + int coordSize = (isCurrentArea) ? this.coordsSize :
>> + area.coordsSize;
>> + int length = coordSize - offset;
>> +
>> + if (isCurrentArea) {
>> + System.arraycopy(coords, offset,
>> + resultCoords, resultCoordPos, length);
>> + } else {
>> + double[] temp = new double[length];
>> + System.arraycopy(coords, offset, temp, 0, length);
>> + reverseCopy(temp);
>> + System.arraycopy(temp, 0,
>> + resultCoords, resultCoordPos, length);
>> + }
>> +
>> + for (int i = 0; i < length / 2; i++) {
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> + resultCoordPos += 2;
>> + }
>> +
>> + offset = 0;
>> + }
>> +
>> + if (offset >= 0) {
>> + int length = (isCurrentArea) ?
>> + 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2:
>> + 2 * point.getBegIndex(isCurrentArea) - offset + 2;
>> +
>> + if (isCurrentArea) {
>> + System.arraycopy(coords, offset,
>> + resultCoords, resultCoordPos, length);
>> + } else {
>> + double[] temp = new double[length];
>> + System.arraycopy(coords, offset, temp, 0, length);
>> + reverseCopy(temp);
>> + System.arraycopy(temp, 0,
>> + resultCoords, resultCoordPos, length);
>> + }
>> +
>> + for (int i = 0; i < length / 2; i++) {
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos;
>> + resultCoordPos += 2;
>> + }
>> + }
>>
>> - public boolean contains(Point2D p) {
>> - if (p == null) {
>> - throw new NullPointerException();
>> + point = nextPoint;
>> + count++;
>> + } while (point != intersectPoints[0] && count <= intersectPoints.length);
>> +
>> + if (count > intersectPoints.length) {
>> + reset();
>> + } else {
>> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
>> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
>> + coords = resultCoords;
>> + rules = resultRules;
>> + offsets = resultOffsets;
>> + coordsSize = resultCoordPos;
>> + rulesSize = resultRulesPos;
>> }
>> - return s == null ? false : s.contains(p);
>> - }
>> -
>> - public boolean contains(Rectangle2D r) {
>> - if (r == null) {
>> - throw new NullPointerException();
>> + }
>> +
>> + private IntersectPoint getNextIntersectPoint(IntersectPoint[] iPoints,
>> + IntersectPoint isectPoint,
>> + boolean isCurrentArea) {
>> +
>> + int endIndex = isectPoint.getEndIndex(isCurrentArea);
>> + if (endIndex < 0) {
>> + return iPoints[Math.abs(endIndex) - 1];
>> + }
>> +
>> + IntersectPoint firstIsectPoint = null;
>> + IntersectPoint nextIsectPoint = null;
>> + for (IntersectPoint point : iPoints) {
>> + int begIndex = point.getBegIndex(isCurrentArea);
>> +
>> + if (begIndex >= 0) {
>> + if (firstIsectPoint == null) {
>> + firstIsectPoint = point;
>> + } else if (begIndex < firstIsectPoint
>> + .getBegIndex(isCurrentArea)) {
>> + firstIsectPoint = point;
>> + }
>> + }
>> +
>> + if (endIndex <= begIndex) {
>> + if (nextIsectPoint == null) {
>> + nextIsectPoint = point;
>> + } else if (begIndex <
>> + nextIsectPoint.getBegIndex(isCurrentArea)) {
>> + nextIsectPoint = point;
>> + }
>> + }
>> + }
>> +
>> + return (nextIsectPoint != null) ? nextIsectPoint : firstIsectPoint;
>> + }
>> +
>> + private IntersectPoint getPrevIntersectPoint(IntersectPoint[] iPoints,
>> + IntersectPoint isectPoint,
>> + boolean isCurrentArea) {
>> +
>> + int begIndex = isectPoint.getBegIndex(isCurrentArea);
>> +
>> + if (begIndex < 0) {
>> + return iPoints[Math.abs(begIndex) - 1];
>> + }
>> +
>> + IntersectPoint firstIsectPoint = null;
>> + IntersectPoint predIsectPoint = null;
>> + for (IntersectPoint point : iPoints) {
>> + int endIndex = point.getEndIndex(isCurrentArea);
>> +
>> + if (endIndex >= 0) {
>> + if (firstIsectPoint == null) {
>> + firstIsectPoint = point;
>> + } else if (endIndex < firstIsectPoint
>> + .getEndIndex(isCurrentArea)) {
>> + firstIsectPoint = point;
>> + }
>> + }
>> +
>> + if (endIndex <= begIndex) {
>> + if (predIsectPoint == null) {
>> + predIsectPoint = point;
>> + } else if (endIndex >
>> + predIsectPoint.getEndIndex(isCurrentArea)) {
>> + predIsectPoint = point;
>> + }
>> + }
>> + }
>> +
>> + return (predIsectPoint != null) ? predIsectPoint : firstIsectPoint;
>> + }
>> +
>> +
>> + private int includeCoordsAndRules(int offset, int length, int[] rules,
>> + int[] offsets, int[] resultRules,
>> + int[] resultOffsets, double[] resultCoords,
>> + double[] coords, int resultRulesPos,
>> + int resultCoordPos, IntersectPoint point,
>> + boolean isCurrentArea, boolean way,
>> + int operation) {
>> +
>> + double[] temp = new double[8 * length];
>> + int coordsCount = 0;
>> + boolean isMoveIndex = true;
>> + boolean isMoveLength = true;
>> + boolean additional = false;
>> +
>> + if (length <= offset) {
>> + for (int i = resultRulesPos; i < resultRulesPos + 1; i++) {
>> + resultRules[i] = PathIterator.SEG_LINETO;
>> + }
>> + } else {
>> + int j = resultRulesPos;
>> + for (int i = offset; i < length; i++) {
>> + resultRules[j++] = PathIterator.SEG_LINETO;
>> + }
>> + }
>> +
>> + if ((length == offset) &&
>> + ((rules[offset] == PathIterator.SEG_QUADTO) ||
>> + (rules[offset] == PathIterator.SEG_CUBICTO))) {
>> + length++;
>> + additional = true;
>> + }
>> + for (int i = offset; i < length; i++) {
>> + int index = offsets[i];
>> +
>> + if (!isMoveIndex) {
>> + index -= 2;
>> + }
>> +
>> + if (!isMoveLength) {
>> + length++;
>> + isMoveLength = true;
>> + }
>> +
>> + switch (rules[i]) {
>> + case PathIterator.SEG_MOVETO:
>> + isMoveIndex = false;
>> + isMoveLength = false;
>> + break;
>> + case PathIterator.SEG_LINETO:
>> + case PathIterator.SEG_CLOSE:
>> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos + 2;
>> + boolean isLeft = CrossingHelper.compare(coords[index],
>> + coords[index + 1], point.getX(), point.getY()) > 0;
>> +
>> + if (way || !isLeft) {
>> + temp[coordsCount++] = coords[index];
>> + temp[coordsCount++] = coords[index + 1];
>> + }
>> + break;
>> + case PathIterator.SEG_QUADTO:
>> + resultRules[resultRulesPos] = PathIterator.SEG_QUADTO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos + 4;
>> + double[] coefs = new double[] { coords[index - 2],
>> + coords[index - 1], coords[index], coords[index + 1],
>> + coords[index + 2], coords[index + 3] };
>> + isLeft = CrossingHelper.compare(coords[index - 2],
>> + coords[index - 1], point.getX(), point.getY()) > 0;
>> +
>> + if ((!additional) && (operation == 0 || operation == 2)) {
>> + isLeft = !isLeft;
>> + way = false;
>> + }
>> + GeometryUtil
>> + .subQuad(coefs, point.getParam(isCurrentArea), isLeft);
>> +
>> + if (way || isLeft) {
>> + temp[coordsCount++] = coefs[2];
>> + temp[coordsCount++] = coefs[3];
>> + } else {
>> + System.arraycopy(coefs, 2, temp, coordsCount, 4);
>> + coordsCount += 4;
>> + }
>> + break;
>> + case PathIterator.SEG_CUBICTO:
>> + resultRules[resultRulesPos] = PathIterator.SEG_CUBICTO;
>> + resultOffsets[resultRulesPos++] = resultCoordPos + 6;
>> + coefs = new double[] {coords[index - 2], coords[index - 1],
>> + coords[index], coords[index + 1],
>> + coords[index + 2], coords[index + 3],
>> + coords[index + 4], coords[index + 5] };
>> + isLeft = CrossingHelper.compare(coords[index - 2],
>> + coords[index - 1], point.getX(), point.getY()) > 0;
>> + GeometryUtil.subCubic(coefs, point.getParam(isCurrentArea),
>> + !isLeft);
>> +
>> + if (isLeft) {
>> + System.arraycopy(coefs, 2, temp, coordsCount, 6);
>> + coordsCount += 6;
>> + } else {
>> + System.arraycopy(coefs, 2, temp, coordsCount, 4);
>> + coordsCount += 4;
>> + }
>> + break;
>> + }
>> + }
>> +
>> + if (operation == 2 && !isCurrentArea && coordsCount > 2) {
>> + reverseCopy(temp);
>> + System.arraycopy(temp, 0, resultCoords, resultCoordPos, coordsCount);
>> + } else {
>> + System.arraycopy(temp, 0, resultCoords, resultCoordPos, coordsCount);
>> + }
>> +
>> + return (resultCoordPos + coordsCount);
>> + }
>> +
>> + // the method check up the array size and necessarily increases it.
>> + private static double[] adjustSize(double[] array, int newSize) {
>> + if (newSize <= array.length) {
>> + return array;
>> + }
>> + double[] newArray = new double[2 * newSize];
>> + System.arraycopy(array, 0, newArray, 0, array.length);
>> + return newArray;
>> + }
>> +
>> + private static int[] adjustSize(int[] array, int newSize) {
>> + if (newSize <= array.length) {
>> + return array;
>> + }
>> + int[] newArray = new int[2 * newSize];
>> + System.arraycopy(array, 0, newArray, 0, array.length);
>> + return newArray;
>> + }
>> +
>> + private void copy(Area src, Area dst) {
>> + dst.coordsSize = src.coordsSize;
>> + dst.coords = src.coords.clone();
>> + dst.rulesSize = src.rulesSize;
>> + dst.rules = src.rules.clone();
>> + dst.moveToCount = src.moveToCount;
>> + dst.offsets = src.offsets.clone();
>> + }
>> +
>> + private int containsExact(double x, double y) {
>> + PathIterator pi = getPathIterator(null);
>> + int crossCount = Crossing.crossPath(pi, x, y);
>> +
>> + if (Crossing.isInsideEvenOdd(crossCount)) {
>> + return 1;
>> }
>> - return s == null ? false : s.contains(r);
>> - }
>>
>> - public boolean equals(Area obj) throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public boolean intersects(double x, double y, double width, double height) {
>> - return s == null ? false : s.intersects(x, y, width, height);
>> - }
>> -
>> - public boolean intersects(Rectangle2D r) {
>> - if (r == null) {
>> - throw new NullPointerException();
>> + double[] segmentCoords = new double[6];
>> + double[] resultPoints = new double[6];
>> + int rule;
>> + double curX = -1;
>> + double curY = -1;
>> + double moveX = -1;
>> + double moveY = -1;
>> +
>> + for (pi = getPathIterator(null); !pi.isDone(); pi.next()) {
>> + rule = pi.currentSegment(segmentCoords);
>> + switch (rule) {
>> + case PathIterator.SEG_MOVETO:
>> + moveX = curX = segmentCoords[0];
>> + moveY = curY = segmentCoords[1];
>> + break;
>> + case PathIterator.SEG_LINETO:
>> + if (GeometryUtil.intersectLines(curX, curY,
>> + segmentCoords[0], segmentCoords[1], x, y, x, y,
>> + resultPoints) != 0) {
>> + return 0;
>> + }
>> + curX = segmentCoords[0];
>> + curY = segmentCoords[1];
>> + break;
>> + case PathIterator.SEG_QUADTO:
>> + if (GeometryUtil.intersectLineAndQuad(x, y, x, y,
>> + curX, curY, segmentCoords[0], segmentCoords[1],
>> + segmentCoords[2], segmentCoords[3],
>> + resultPoints) > 0) {
>> + return 0;
>> + }
>> + curX = segmentCoords[2];
>> + curY = segmentCoords[3];
>> + break;
>> + case PathIterator.SEG_CUBICTO:
>> + if (GeometryUtil.intersectLineAndCubic(x, y, x, y,
>> + curX, curY, segmentCoords[0], segmentCoords[1],
>> + segmentCoords[2], segmentCoords[3], segmentCoords[4],
>> + segmentCoords[5], resultPoints) > 0) {
>> + return 0;
>> + }
>> + curX = segmentCoords[4];
>> + curY = segmentCoords[5];
>> + break;
>> + case PathIterator.SEG_CLOSE:
>> + if (GeometryUtil.intersectLines(curX, curY, moveX, moveY,
>> + x, y, x, y, resultPoints) != 0) {
>> + return 0;
>> + }
>> + curX = moveX;
>> + curY = moveY;
>> + break;
>> + }
>> }
>> - return s == null ? false : s.intersects(r);
>> - }
>> -
>> - public Rectangle getBounds() {
>> - return s == null ? new Rectangle() : s.getBounds();
>> + return -1;
>> }
>>
>> - public Rectangle2D getBounds2D() {
>> - return s == null ? new Rectangle2D.Double(): s.getBounds2D();
>> - }
>> -
>> - public PathIterator getPathIterator(AffineTransform t) {
>> - return s == null ? new NullIterator() : s.getPathIterator(t);
>> - }
>> -
>> - public PathIterator getPathIterator(AffineTransform t, double flatness) {
>> - return s == null ? new NullIterator() : s.getPathIterator(t, flatness);
>> - }
>> -
>> - public void add(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public void exclusiveOr(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - /**
>> - * Extract Rectangle2D from the source shape
>> - * @return a Rectangle2D object if the source shape is rectangle, or null if shape is empty or not rectangle.
>> - */
>> - Rectangle2D extractRectangle() {
>> - if (s == null) {
>> - return null;
>> - }
>> - float[] points = new float[12];
>> - int count = 0;
>> - PathIterator p = s.getPathIterator(null);
>> - float[] coords = new float[6];
>> - while(!p.isDone()) {
>> - int type = p.currentSegment(coords);
>> - if (count > 12 || type == PathIterator.SEG_QUADTO || type == PathIterator.SEG_CUBICTO) {
>> - return null;
>> - }
>> - points[count++] = coords[0];
>> - points[count++] = coords[1];
>> - p.next();
>> - }
>> - if (points[0] == points[6] && points[6] == points[8] && points[2] == points[4] &&
>> - points[1] == points[3] && points[3] == points[9] && points[5] == points[7])
>> - {
>> - return new Rectangle2D.Float(points[0], points[1], points[2] - points[0], points[7] - points[1]);
>> - }
>> - return null;
>> + private void reverseCopy(double[] coords) {
>> + double[] temp = new double[coords.length];
>> + System.arraycopy(coords, 0, temp, 0, coords.length);
>> +
>> + for (int i = 0; i < coords.length;) {
>> + coords[i] = temp[coords.length - i - 2];
>> + coords[i + 1] = temp[coords.length - i - 1];
>> + i = i + 2;
>> + }
>> }
>>
>> - public void intersect(Area area) {
>> - Rectangle2D src1 = extractRectangle();
>> - Rectangle2D src2 = area.extractRectangle();
>> - if (src1 != null && src2 != null) {
>> - Rectangle2D.intersect(src1, src2, (Rectangle2D)s);
>> - }
>> - }
>> -
>> - public void subtract(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public boolean isEmpty() throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public boolean isPolygonal() throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public boolean isRectangular() throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public boolean isSingular() throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public void reset() throws org.apache.harmony.luni.util.NotImplementedException {
>> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
>> - }
>> -
>> - public void transform(AffineTransform t) {
>> - s = t.createTransformedShape(s);
>> - }
>> -
>> - public Area createTransformedArea(AffineTransform t) {
>> - return s == null ? new Area() : new Area(t.createTransformedShape(s));
>> - }
>> -
>> - @Override
>> - public Object clone() {
>> - return new Area(this);
>> - }
>> + // the internal class implements PathIterator
>> + private class AreaPathIterator implements PathIterator {
>>
>> -}
>> + AffineTransform t;
>> + Area area;
>> + int curRuleIndex = 0;
>> + int curCoordIndex = 0;
>> +
>> + AreaPathIterator(Area area) {
>> + this(area, null);
>> + }
>> +
>> + AreaPathIterator(Area area, AffineTransform t) {
>> + this.area = area;
>> + this.t = t;
>> + }
>> +
>> + public int getWindingRule() {
>> + return WIND_EVEN_ODD;
>> + }
>> +
>> + public boolean isDone() {
>> + return curRuleIndex >= rulesSize;
>> + }
>> +
>> + public void next() {
>> + switch (rules[curRuleIndex]) {
>> + case PathIterator.SEG_MOVETO:
>> + case PathIterator.SEG_LINETO:
>> + curCoordIndex += 2;
>> + break;
>> + case PathIterator.SEG_QUADTO:
>> + curCoordIndex += 4;
>> + break;
>> + case PathIterator.SEG_CUBICTO:
>> + curCoordIndex += 6;
>> + break;
>> + }
>> + curRuleIndex++;
>> + }
>> +
>> + public int currentSegment(double[] c) {
>> + if (isDone()) {
>> + throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
>> + }
>> + switch (rules[curRuleIndex]) {
>> + case PathIterator.SEG_CUBICTO:
>> + c[4] = coords[curCoordIndex + 4];
>> + c[5] = coords[curCoordIndex + 5];
>> + case PathIterator.SEG_QUADTO:
>> + c[2] = coords[curCoordIndex + 2];
>> + c[3] = coords[curCoordIndex + 3];
>> + case PathIterator.SEG_MOVETO:
>> + case PathIterator.SEG_LINETO:
>> + c[0] = coords[curCoordIndex];
>> + c[1] = coords[curCoordIndex + 1];
>> + }
>> + return rules[curRuleIndex];
>> + }
>> +
>> + public int currentSegment(float[] c) {
>> + double[] doubleCoords = new double[6];
>> + int rule = currentSegment(doubleCoords);
>> +
>> + for (int i = 0; i < 6; i++) {
>> + c[i] = (float) doubleCoords[i];
>> + }
>> + return rule;
>> + }
>> + }
>> +}
>> \ No newline at end of file
>>
>> Modified: harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java
>> URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java?view=diff&rev=546906&r1=546905&r2=546906
>> ==============================================================================
>> --- harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java (original)
>> +++ harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java Wed Jun 13 08:05:17 2007
>> @@ -45,54 +45,126 @@
>> }
>>
>> public void testContainsPoint() {
>> - // Regression test HARMONY-1404
>> try {
>> - Area a = new Area();
>> - a.contains((Point2D)null);
>> - fail("Expected NPE");
>> - } catch (NullPointerException e) {
>> - // expected
>> - }
>> - }
>> + Area area = new Area(new Ellipse2D.Double(200, 300, 400, 200));
>> + assertTrue(area.contains(250, 350));
>> + assertFalse(area.contains(200, 300));
>> + assertFalse(area.contains(50, 50));
>> +
>> + assertTrue(area.contains(new Point2D.Double(500, 400)));
>> + assertFalse(area.contains(new Point2D.Double(700, 400)));
>> +
>> + // Regression test HARMONY-1404
>> + Area emptyArea = new Area();
>> + emptyArea.contains((Point2D)null);
>> + fail("Expected NPE");
>> + } catch (NullPointerException e) {
>> + // expected
>> + }
>> + }
>>
>> - public void testContainsRect() {
>> - // Regression test HARMONY-1404
>> - try {
>> - Area a = new Area();
>> - a.contains((Rectangle2D)null);
>> - fail("Expected NPE");
>> - } catch (NullPointerException e) {
>> - // expected
>> - }
>> - }
>> + public void testContainsRect() {
>> + // Regression test HARMONY-1476
>> + GeneralPath path = new GeneralPath();
>> + path.moveTo(100, 500);
>> + path.lineTo(400, 100);
>> + path.lineTo(700, 500);
>> + path.closePath();
>> +
>> + Area area = new Area(path);
>> + assertTrue(area.contains(new Rectangle2D.Double(300, 400, 100, 50)));
>> + assertFalse(area.contains(new Rectangle2D.Double(50, 400, 700, 50)));
>> +
>> + GeneralPath path1 = new GeneralPath();
>> + path1.moveTo(400, 500);
>> + path1.quadTo(200, 200, 400, 100);
>> + path1.quadTo(600, 200, 400, 500);
>> + path1.closePath();
>> +
>> + Area area1 = new Area(path1);
>> + assertTrue(area1.contains(350, 200, 50, 50));
>> + assertFalse(area1.contains(100, 50, 600, 500));
>> +
>> + // Regression test HARMONY-1404
>> + try {
>> + Area emptyArea = new Area();
>> + emptyArea.contains((Rectangle2D)null);
>> + fail("Expected NPE");
>> + } catch (NullPointerException e) {
>> + // expected
>> + }
>> + }
>>
>> - public void testIntersectsRect() {
>> - // Regression test HARMONY-1404
>> - try {
>> - Area a = new Area();
>> - a.intersects((Rectangle2D)null);
>> - fail("Expected NPE");
>> - } catch (NullPointerException e) {
>> - // expected
>> - }
>> - }
>> -
>> - public void testGetPathIterator() {
>> - // Regression test HARMONY-1860
>> - Area a = new Area();
>> - PathIterator path = a.getPathIterator(null);
>> - checkPathRule(path, PathIterator.WIND_NON_ZERO);
>> - checkPathDone(path, true);
>> - }
>> -
>> - public void testCreateTransformedArea() {
>> - // Regression test HARMONY-1880
>> - AffineTransform t = AffineTransform.getScaleInstance(2, 3);
>> - Area a1 = new Area();
>> - Area a2 = a1.createTransformedArea(t);
>> - PathIterator path = a2.getPathIterator(null);
>> - checkPathRule(path, PathIterator.WIND_NON_ZERO);
>> - checkPathDone(path, true);
>> - }
>> + public void testIntersectsRect() {
>> + // Regression test HARMONY-1476
>> + GeneralPath path = new GeneralPath();
>> + path.moveTo(100, 500);
>> + path.lineTo(400, 100);
>> + path.lineTo(700, 500);
>> + path.closePath();
>> +
>> + Area area = new Area(path);
>> + assertTrue(area.intersects(new Rectangle2D.Double(300, 400, 100, 50)));
>> + assertFalse(area.intersects(new Rectangle2D.Double(50, 50, 50, 50)));
>> +
>> + GeneralPath path1 = new GeneralPath();
>> + path1.moveTo(400, 500);
>> + path1.quadTo(200, 200, 400, 100);
>> + path1.quadTo(600, 200, 400, 500);
>> + path1.closePath();
>> +
>> + Area area1 = new Area(path1);
>> + assertTrue(area1.intersects(350, 200, 50, 50));
>> + assertFalse(area1.intersects(500, 50, 100, 50));
>> +
>> + // Regression test HARMONY-1404
>> + try {
>> + Area emptyArea = new Area();
>> + emptyArea.intersects((Rectangle2D)null);
>> + fail("Expected NPE");
>> + } catch (NullPointerException e) {
>> + // expected
>> + }
>> + }
>> +
>> + public void testIsRectangle() {
>> + // Regression test HARMONY-1476
>> + Area area = new Area(new Rectangle2D.Double(200, 300, 400, 150));
>> + assertTrue(area.isRectangular());
>> +
>> + GeneralPath path = new GeneralPath();
>> + path.moveTo(200, 300);
>> + path.lineTo(600, 300);
>> + path.lineTo(600, 450);
>> + path.lineTo(200, 450);
>> + path.closePath();
>> +
>> + Area area1 = new Area(path);
>> + assertTrue(area1.isRectangular());
>> +
>> + Area area2 = new Area(new Ellipse2D.Double(200, 300, 400, 150));
>> + assertFalse(area2.isRectangular());
>> + }
>> +
>> + public void testGetPathIterator() {
>> + // Regression test HARMONY-1860
>> + Area a = new Area();
>> + PathIterator path = a.getPathIterator(null);
>> + checkPathRule(path, PathIterator.WIND_EVEN_ODD);
>> + checkPathDone(path, true);
>> + }
>> +
>> + public void testCreateTransformedArea() {
>> + // Regression test HARMONY-1880
>> + AffineTransform t = AffineTransform.getScaleInstance(2, 3);
>> + Area a1 = new Area();
>> + Area a2 = a1.createTransformedArea(t);
>> + PathIterator path = a2.getPathIterator(null);
>> + checkPathRule(path, PathIterator.WIND_EVEN_ODD);
>> + checkPathDone(path, true);
>> + }
>>
>> + public static void main(String[] args) {
>> + junit.textui.TestRunner.run(AreaTest.class);
>> + }
>> }
>>
>>
>>
>
--
Gregory
[classli][awt] compile errors (was: svn commit: r546906 - in /harmony/enhanced/classlib/trunk/modules/awt/src:
main/java/common/java/awt/geom/Area.java test/api/java/common/java/awt/geom/AreaTest.java)
Posted by Tim Ellison <t....@gmail.com>.
I've rolled back this commit since it produces a number of compile time
errors in AWT.
Regards,
Tim
ayza@apache.org wrote:
> Author: ayza
> Date: Wed Jun 13 08:05:17 2007
> New Revision: 546906
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=546906
> Log:
> java.awt.geom.Area implementation from HARMONY-1476
>
> Modified:
> harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java
> harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java
>
> Modified: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java
> URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java?view=diff&rev=546906&r1=546905&r2=546906
> ==============================================================================
> --- harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java (original)
> +++ harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/java/awt/geom/Area.java Wed Jun 13 08:05:17 2007
> @@ -14,199 +14,1287 @@
> * See the License for the specific language governing permissions and
> * limitations under the License.
> */
> -/**
> - * @author Denis M. Kishenko
> - * @version $Revision$
> - */
> package java.awt.geom;
>
> import java.awt.Rectangle;
> import java.awt.Shape;
> -import java.awt.geom.PathIterator;
> -import java.awt.geom.Rectangle2D;
> import java.util.NoSuchElementException;
>
> +import org.apache.harmony.awt.gl.Crossing;
> +import org.apache.harmony.awt.internal.CrossingHelper;
> +import org.apache.harmony.awt.internal.CurveCrossingHelper;
> +import org.apache.harmony.awt.internal.GeometryUtil;
> +import org.apache.harmony.awt.internal.IntersectPoint;
> import org.apache.harmony.awt.internal.nls.Messages;
>
> +
> public class Area implements Shape, Cloneable {
>
> /**
> - * The source Shape object
> + * the coordinates array of the shape vertices
> */
> - Shape s;
> -
> - private static class NullIterator implements PathIterator {
> -
> - NullIterator() {
> - }
> -
> - public int getWindingRule() {
> - return WIND_NON_ZERO;
> - }
> -
> - public boolean isDone() {
> - return true;
> - }
> + private double coords[] = new double[20];
> +
> + /**
> + * the coordinates quantity
> + */
> + private int coordsSize = 0;
> +
> + /**
> + * the rules array for the drawing of the shape edges
> + */
> + private int rules[] = new int[10];
> +
> + /**
> + * the rules quantity
> + */
> + private int rulesSize = 0;
> +
> + /**
> + * offsets[i] - index in array of coords and i - index in array of rules
> + */
> + private int offsets[] = new int[10];
> +
> + /**
> + * the quantity of MOVETO rule occurences
> + */
> + private int moveToCount = 0;
> +
> + /**
> + * true if the shape is polygon
> + */
> + private boolean isPolygonal = true;
> +
> + public Area() {
> + }
> +
> + public Area(Shape s) {
> + double segmentCoords[] = new double[6];
> + double lastMoveX = 0.0;
> + double lastMoveY = 0.0;
> + int rulesIndex = 0;
> + int coordsIndex = 0;
> +
> + for (PathIterator pi = s.getPathIterator(null);
> + !pi.isDone(); pi.next()) {
> + coords = adjustSize(coords, coordsIndex + 6);
> + rules = adjustSize(rules, rulesIndex + 1);
> + offsets = adjustSize(offsets, rulesIndex + 1);
> + rules[rulesIndex] = pi.currentSegment(segmentCoords);
> + offsets[rulesIndex] = coordsIndex;
> +
> + switch (rules[rulesIndex]) {
> + case PathIterator.SEG_MOVETO:
> + coords[coordsIndex++] = segmentCoords[0];
> + coords[coordsIndex++] = segmentCoords[1];
> + lastMoveX = segmentCoords[0];
> + lastMoveY = segmentCoords[1];
> + ++moveToCount;
> + break;
> + case PathIterator.SEG_LINETO:
> + if ((segmentCoords[0] != lastMoveX) ||
> + (segmentCoords[1] != lastMoveY)) {
> + coords[coordsIndex++] = segmentCoords[0];
> + coords[coordsIndex++] = segmentCoords[1];
> + } else {
> + --rulesIndex;
> + }
> + break;
> + case PathIterator.SEG_QUADTO:
> + System.arraycopy(segmentCoords, 0, coords, coordsIndex, 4);
> + coordsIndex += 4;
> + isPolygonal = false;
> + break;
> + case PathIterator.SEG_CUBICTO:
> + System.arraycopy(segmentCoords, 0, coords, coordsIndex, 6);
> + coordsIndex += 6;
> + isPolygonal = false;
> + break;
> + case PathIterator.SEG_CLOSE:
> + break;
> + }
> + ++rulesIndex;
> + }
> +
> + if ((rulesIndex != 0) &&
> + (rules[rulesIndex - 1] != PathIterator.SEG_CLOSE)) {
> + rules[rulesIndex] = PathIterator.SEG_CLOSE;
> + offsets[rulesIndex] = coordsSize;
> + }
> +
> + rulesSize = rulesIndex;
> + coordsSize = coordsIndex;
> + }
> +
> + public boolean contains(double x, double y) {
> + return !isEmpty() &&
> + containsExact(x, y) > 0;
> + }
> +
> + public boolean contains(double x, double y, double width, double height) {
> + int crossCount = Crossing.intersectPath(getPathIterator(null), x, y,
> + width, height);
> + return crossCount != Crossing.CROSSING &&
> + Crossing.isInsideEvenOdd(crossCount);
> + }
> +
> + public boolean contains(Point2D p) {
> + return contains(p.getX(), p.getY());
> + }
> +
> + public boolean contains(Rectangle2D r) {
> + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
> + }
> +
> + public boolean equals(Area obj) {
> + if (this == obj) {
> + return true;
> + }
> +
> + if (obj == null) {
> + return false;
> + }
> +
> + Area area = (Area)clone();
> + area.subtract(obj);
> + return area.isEmpty();
> + }
> +
> + public boolean intersects(double x, double y, double width, double height) {
> + if ((width <= 0.0) || (height <= 0.0)) {
> + return false;
> + } else if (!getBounds2D().intersects(x, y, width, height)) {
> + return false;
> + }
> +
> + int crossCount = Crossing.intersectShape(this, x, y, width, height);
> + return Crossing.isInsideEvenOdd(crossCount);
> + }
> +
> + public boolean intersects(Rectangle2D r) {
> + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
> + }
> +
> + public Rectangle getBounds() {
> + return getBounds2D().getBounds();
> + }
> +
> + public Rectangle2D getBounds2D() {
> + double maxX = coords[0];
> + double maxY = coords[1];
> + double minX = coords[0];
> + double minY = coords[1];
> +
> + for (int i = 0; i < coordsSize;) {
> + minX = Math.min(minX, coords[i]);
> + maxX = Math.max(maxX, coords[i++]);
> + minY = Math.min(minY, coords[i]);
> + maxY = Math.max(maxY, coords[i++]);
> + }
> +
> + return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
> + }
> +
> + public PathIterator getPathIterator(AffineTransform t) {
> + return new AreaPathIterator(this, t);
> + }
> +
> + public PathIterator getPathIterator(AffineTransform t, double flatness) {
> + return new FlatteningPathIterator(getPathIterator(t), flatness);
> + }
> +
> + public boolean isEmpty() {
> + return (rulesSize == 0) && (coordsSize == 0);
> + }
> +
> + public boolean isPolygonal() {
> + return isPolygonal;
> + }
> +
> + public boolean isRectangular() {
> + return (isPolygonal) && (rulesSize <= 5) && (coordsSize <= 8) &&
> + (coords[1] == coords[3]) && (coords[7] == coords[5]) &&
> + (coords[0] == coords[6]) && (coords[2] == coords[4]);
> + }
> +
> + public boolean isSingular() {
> + return (moveToCount <= 1);
> + }
> +
> + public void reset() {
> + coordsSize = 0;
> + rulesSize = 0;
> + }
> +
> + public void transform(AffineTransform t) {
> + copy(new Area(t.createTransformedShape(this)), this);
> + }
> +
> + public Area createTransformedArea(AffineTransform t) {
> + return new Area(t.createTransformedShape(this));
> + }
> +
> + public Object clone() {
> + Area area = new Area();
> + copy(this, area);
> + return area;
> + }
> +
> + public void add(Area area) {
> + if (isPolygonal() && area.isPolygonal()) {
> + addPolygon(area);
> + } else {
> + addCurvePolygon(area);
> + }
> + }
> +
> + public void intersect(Area area) {
> + if (isPolygonal() && area.isPolygonal()) {
> + intersectPolygon(area);
> + } else {
> + intersectCurvePolygon(area);
> + }
> + }
> +
> + public void subtract(Area area) {
> + if (isPolygonal() && area.isPolygonal()) {
> + subtractPolygon(area);
> + } else {
> + subtractCurvePolygon(area);
> + }
> + }
> +
> + public void exclusiveOr(Area area) {
> + Area a = (Area) clone();
> + a.intersect(area);
> + add(area);
> + subtract(a);
> + }
> +
> + private void addCurvePolygon(Area area) {
> + CurveCrossingHelper crossHelper = new CurveCrossingHelper(
> + new double[][] { coords, area.coords },
> + new int[] { coordsSize, area.coordsSize },
> + new int[][] { rules, area.rules },
> + new int[] { rulesSize, area.rulesSize },
> + new int[][] { offsets, area.offsets });
> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
> +
> + if (intersectPoints.length == 0) {
> + if (area.contains(getBounds2D())) {
> + copy(area, this);
> + } else if (!contains(area.getBounds2D())) {
> + coords = adjustSize(coords, coordsSize + area.coordsSize);
> + System.arraycopy(area.coords, 0, coords, coordsSize,
> + area.coordsSize);
> + coordsSize += area.coordsSize;
> + rules = adjustSize(rules, rulesSize + area.rulesSize);
> + System.arraycopy(area.rules, 0, rules, rulesSize,
> + area.rulesSize);
> + rulesSize += area.rulesSize;
> + offsets = adjustSize(offsets, rulesSize + area.rulesSize);
> + System.arraycopy(area.offsets, 0, offsets, rulesSize,
> + area.rulesSize);
> + }
> +
> + return;
> + }
> +
> + double[] resultCoords = new double[coordsSize + area.coordsSize +
> + intersectPoints.length];
> + int[] resultRules = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int resultCoordPos = 0;
> + int resultRulesPos = 0;
> + boolean isCurrentArea = true;
> +
> + IntersectPoint point = intersectPoints[0];
> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> +
> + do {
> + resultCoords[resultCoordPos++] = point.getX();
> + resultCoords[resultCoordPos++] = point.getY();
> + int curIndex = point.getEndIndex(true);
> +
> + if (curIndex < 0) {
> + isCurrentArea = !isCurrentArea;
> + } else if (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) > 0) {
> + isCurrentArea = false;
> + } else {
> + isCurrentArea = true;
> + }
>
> - public void next() {
> - // nothing
> - }
> + IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
> + point,
> + isCurrentArea);
> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
> + int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
> + int[] rules = (isCurrentArea) ? this.rules : area.rules;
> + int offset = point.getRuleIndex(isCurrentArea);
> + boolean isCopyUntilZero = false;
> +
> + if ((point.getRuleIndex(isCurrentArea) >
> + nextPoint.getRuleIndex(isCurrentArea))) {
> + int rulesSize = (isCurrentArea) ? this.rulesSize :
> + area.rulesSize;
> + resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
> + rules, offsets,
> + resultRules,
> + resultOffsets,
> + resultCoords, coords,
> + resultRulesPos,
> + resultCoordPos,
> + point, isCurrentArea,
> + false, 0);
> + resultRulesPos += rulesSize - offset - 1;
> + offset = 1;
> + isCopyUntilZero = true;
> + }
> +
> + int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
> +
> + if (isCopyUntilZero) {
> + offset = 0;
> + }
> +
> + resultCoordPos = includeCoordsAndRules(offset, length, rules,
> + offsets, resultRules,
> + resultOffsets, resultCoords,
> + coords, resultRulesPos,
> + resultCoordPos, point,
> + isCurrentArea, true, 0);
> + resultRulesPos += length - offset;
> + point = nextPoint;
> + } while (point != intersectPoints[0]);
> +
> + resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
> + this.coords = resultCoords;
> + this.rules = resultRules;
> + this.offsets = resultOffsets;
> + this.coordsSize = resultCoordPos;
> + this.rulesSize = resultRulesPos;
> + }
> +
> + private void addPolygon(Area area) {
> + CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
> + area.coords },
> + new int[] {coordsSize,
> + area.coordsSize });
> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
> +
> + if (intersectPoints.length == 0) {
> + if (area.contains(getBounds2D())) {
> + copy(area, this);
> + } else if (!contains(area.getBounds2D())) {
> + coords = adjustSize(coords, coordsSize + area.coordsSize);
> + System.arraycopy(area.coords, 0, coords, coordsSize,
> + area.coordsSize);
> + coordsSize += area.coordsSize;
> + rules = adjustSize(rules, rulesSize + area.rulesSize);
> + System.arraycopy(area.rules, 0, rules, rulesSize,
> + area.rulesSize);
> + rulesSize += area.rulesSize;
> + offsets = adjustSize(offsets, rulesSize + area.rulesSize);
> + System.arraycopy(area.offsets, 0, offsets, rulesSize,
> + area.rulesSize);
> + }
> + return;
> + }
> +
> + double[] resultCoords = new double[coordsSize + area.coordsSize +
> + intersectPoints.length];
> + int[] resultRules = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int resultCoordPos = 0;
> + int resultRulesPos = 0;
> + boolean isCurrentArea = true;
> +
> + IntersectPoint point = intersectPoints[0];
> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> +
> + do {
> + resultCoords[resultCoordPos++] = point.getX();
> + resultCoords[resultCoordPos++] = point.getY();
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos - 2;
> + int curIndex = point.getEndIndex(true);
> + if (curIndex < 0) {
> + isCurrentArea = !isCurrentArea;
> + } else if (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) > 0) {
> + isCurrentArea = false;
> + } else {
> + isCurrentArea = true;
> + }
>
> - public int currentSegment(double[] coords) {
> - // awt.4B=Iterator out of bounds
> - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
> - }
> + IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
> + point,
> + isCurrentArea);
> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
> + int offset = 2 * point.getEndIndex(isCurrentArea);
> +
> + if (nextPoint.getBegIndex(isCurrentArea) <
> + point.getEndIndex(isCurrentArea)) {
> + int coordSize = (isCurrentArea) ? this.coordsSize :
> + area.coordsSize;
> + int length = coordSize - offset;
> + System.arraycopy(coords, offset,
> + resultCoords, resultCoordPos, length);
> +
> + for (int i = 0; i < length / 2; i++) {
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> + resultCoordPos += 2;
> + }
> +
> + offset = 0;
> + }
> +
> + int length = 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2;
> + System.arraycopy(coords, offset,
> + resultCoords, resultCoordPos, length);
> +
> + for (int i = 0; i < length / 2; i++) {
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> + resultCoordPos += 2;
> + }
>
> - public int currentSegment(float[] coords) {
> - // awt.4B=Iterator out of bounds
> - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
> + point = nextPoint;
> + } while (point != intersectPoints[0]);
> +
> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
> + coords = resultCoords;
> + rules = resultRules;
> + offsets = resultOffsets;
> + coordsSize = resultCoordPos;
> + rulesSize = resultRulesPos;
> + }
> +
> + private void intersectCurvePolygon(Area area) {
> + CurveCrossingHelper crossHelper = new CurveCrossingHelper(
> + new double[][] {coords, area.coords },
> + new int[] { coordsSize, area.coordsSize },
> + new int[][] { rules, area.rules },
> + new int[] { rulesSize, area.rulesSize },
> + new int[][] { offsets, area.offsets });
> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
> +
> + if (intersectPoints.length == 0) {
> + if (contains(area.getBounds2D())) {
> + copy(area, this);
> + } else if (!area.contains(getBounds2D())) {
> + reset();
> + }
> + return;
> + }
> +
> + double[] resultCoords = new double[coordsSize + area.coordsSize +
> + intersectPoints.length];
> + int[] resultRules = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int resultCoordPos = 0;
> + int resultRulesPos = 0;
> + boolean isCurrentArea = true;
> +
> + IntersectPoint point = intersectPoints[0];
> + IntersectPoint nextPoint = intersectPoints[0];
> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> +
> + do {
> + resultCoords[resultCoordPos++] = point.getX();
> + resultCoords[resultCoordPos++] = point.getY();
> +
> + int curIndex = point.getEndIndex(true);
> + if ((curIndex < 0) || (area.containsExact(
> + coords[2 * curIndex], coords[2 * curIndex + 1]) == 0)) {
> + isCurrentArea = !isCurrentArea;
> + } else if (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) > 0) {
> + isCurrentArea = true;
> + } else {
> + isCurrentArea = false;
> + }
> +
> + nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
> + int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
> + int[] rules = (isCurrentArea) ? this.rules : area.rules;
> + int offset = point.getRuleIndex(isCurrentArea);
> + boolean isCopyUntilZero = false;
> +
> + if (point.getRuleIndex(isCurrentArea) >
> + nextPoint.getRuleIndex(isCurrentArea)) {
> + int rulesSize = (isCurrentArea) ? this.rulesSize :
> + area.rulesSize;
> + resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
> + rules, offsets,
> + resultRules,
> + resultOffsets,
> + resultCoords, coords,
> + resultRulesPos,
> + resultCoordPos, point,
> + isCurrentArea, false,
> + 1);
> + resultRulesPos += rulesSize - offset - 1;
> + offset = 1;
> + isCopyUntilZero = true;
> + }
> +
> + int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
> +
> + if (isCopyUntilZero) {
> + offset = 0;
> + isCopyUntilZero = false;
> + }
> + if ((length == offset) &&
> + (nextPoint.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
> + (nextPoint.getRule(isCurrentArea) != PathIterator.SEG_CLOSE) &&
> + (point.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
> + (point.getRule(isCurrentArea) != PathIterator.SEG_CLOSE)) {
> +
> + isCopyUntilZero = true;
> + length++;
> + }
> +
> + resultCoordPos = includeCoordsAndRules(offset, length, rules,
> + offsets, resultRules,
> + resultOffsets, resultCoords,
> + coords, resultRulesPos,
> + resultCoordPos, nextPoint,
> + isCurrentArea, true, 1);
> + resultRulesPos = ((length <= offset) || (isCopyUntilZero)) ?
> + resultRulesPos + 1 : resultRulesPos + length;
> +
> + point = nextPoint;
> + } while (point != intersectPoints[0]);
> +
> + if (resultRules[resultRulesPos - 1] == PathIterator.SEG_LINETO) {
> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
> + } else {
> + resultCoords[resultCoordPos++] = nextPoint.getX();
> + resultCoords[resultCoordPos++] = nextPoint.getY();
> + resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
> }
> +
> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
> + coords = resultCoords;
> + rules = resultRules;
> + offsets = resultOffsets;
> + coordsSize = resultCoordPos;
> + rulesSize = resultRulesPos;
> + }
> +
> + private void intersectPolygon(Area area) {
> + CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
> + area.coords },
> + new int[] { coordsSize,
> + area.coordsSize });
> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
> +
> + if (intersectPoints.length == 0) {
> + if (contains(area.getBounds2D())) {
> + copy(area, this);
> + } else if (!area.contains(getBounds2D())) {
> + reset();
> + }
> + return;
> + }
> +
> + double[] resultCoords = new double[coordsSize + area.coordsSize +
> + intersectPoints.length];
> + int[] resultRules = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int resultCoordPos = 0;
> + int resultRulesPos = 0;
> + boolean isCurrentArea = true;
> +
> + IntersectPoint point = intersectPoints[0];
> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> +
> + do {
> + resultCoords[resultCoordPos++] = point.getX();
> + resultCoords[resultCoordPos++] = point.getY();
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos - 2;
> + int curIndex = point.getEndIndex(true);
> +
> + if ((curIndex < 0) ||
> + (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) == 0)) {
> + isCurrentArea = !isCurrentArea;
> + } else if (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) > 0) {
> + isCurrentArea = true;
> + } else {
> + isCurrentArea = false;
> + }
>
> - }
> -
> - public Area() {
> - }
> + IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints,
> + point,
> + isCurrentArea);
> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
> + int offset = 2 * point.getEndIndex(isCurrentArea);
> + if ((offset >= 0) &&
> + (nextPoint.getBegIndex(isCurrentArea) <
> + point.getEndIndex(isCurrentArea))) {
> + int coordSize = (isCurrentArea) ? this.coordsSize :
> + area.coordsSize;
> + int length = coordSize - offset;
> + System.arraycopy(coords, offset,
> + resultCoords, resultCoordPos, length);
> +
> + for (int i = 0; i < length / 2; i++) {
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> + resultCoordPos += 2;
> + }
> +
> + offset = 0;
> + }
> +
> + if (offset >= 0) {
> + int length = 2 * nextPoint.getBegIndex(isCurrentArea) -
> + offset + 2;
> + System.arraycopy(coords, offset,
> + resultCoords, resultCoordPos, length);
> +
> + for (int i = 0; i < length / 2; i++) {
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> + resultCoordPos += 2;
> + }
> + }
>
> - public Area(Shape s) {
> - if (s == null) {
> - throw new NullPointerException();
> - }
> - this.s = s;
> - }
> + point = nextPoint;
> + } while (point != intersectPoints[0]);
> +
> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
> + coords = resultCoords;
> + rules = resultRules;
> + offsets = resultOffsets;
> + coordsSize = resultCoordPos;
> + rulesSize = resultRulesPos;
> + }
> +
> + private void subtractCurvePolygon(Area area) {
> + CurveCrossingHelper crossHelper = new CurveCrossingHelper(
> + new double[][] { coords, area.coords },
> + new int[] { coordsSize, area.coordsSize },
> + new int[][] { rules, area.rules },
> + new int[] { rulesSize, area.rulesSize },
> + new int[][] { offsets, area.offsets });
> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
> +
> + if (intersectPoints.length == 0 && contains(area.getBounds2D())) {
> + copy(area, this);
> + return;
> + }
> +
> + double[] resultCoords = new double[coordsSize + area.coordsSize +
> + intersectPoints.length];
> + int[] resultRules = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int resultCoordPos = 0;
> + int resultRulesPos = 0;
> + boolean isCurrentArea = true;
> +
> + IntersectPoint point = intersectPoints[0];
> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> +
> + do {
> + resultCoords[resultCoordPos++] = point.getX();
> + resultCoords[resultCoordPos++] = point.getY();
> + int curIndex = offsets[point.getRuleIndex(true)] % coordsSize;
> +
> + if (area.containsExact(coords[curIndex],
> + coords[curIndex + 1]) == 0) {
> + isCurrentArea = !isCurrentArea;
> + } else if (area.containsExact(coords[curIndex],
> + coords[curIndex + 1]) > 0) {
> + isCurrentArea = false;
> + } else {
> + isCurrentArea = true;
> + }
> +
> + IntersectPoint nextPoint = (isCurrentArea) ?
> + getNextIntersectPoint(intersectPoints, point,
> + isCurrentArea):
> + getPrevIntersectPoint(intersectPoints, point,
> + isCurrentArea);
> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
> + int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
> + int[] rules = (isCurrentArea) ? this.rules : area.rules;
> + int offset = (isCurrentArea) ? point.getRuleIndex(isCurrentArea) :
> + nextPoint.getRuleIndex(isCurrentArea);
> + boolean isCopyUntilZero = false;
> +
> + if (((isCurrentArea) &&
> + (point.getRuleIndex(isCurrentArea) >
> + nextPoint.getRuleIndex(isCurrentArea))) ||
> + ((!isCurrentArea) &&
> + (nextPoint.getRuleIndex(isCurrentArea) >
> + nextPoint.getRuleIndex(isCurrentArea)))) {
> +
> + int rulesSize = (isCurrentArea) ? this.rulesSize :
> + area.rulesSize;
> + resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize,
> + rules, offsets,
> + resultRules,
> + resultOffsets,
> + resultCoords, coords,
> + resultRulesPos,
> + resultCoordPos, point,
> + isCurrentArea, false,
> + 2);
> + resultRulesPos += rulesSize - offset - 1;
> + offset = 1;
> + isCopyUntilZero = true;
> + }
> +
> + int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
> +
> + if (isCopyUntilZero) {
> + offset = 0;
> + isCopyUntilZero = false;
> + }
> +
> + resultCoordPos = includeCoordsAndRules(offset, length, rules,
> + offsets, resultRules,
> + resultOffsets, resultCoords,
> + coords, resultRulesPos,
> + resultCoordPos, point,
> + isCurrentArea, true, 2);
> +
> + if ((length == offset) &&
> + ((rules[offset] == PathIterator.SEG_QUADTO) ||
> + (rules[offset] == PathIterator.SEG_CUBICTO))) {
> +
> + resultRulesPos++;
> + } else {
> + resultRulesPos = (length < offset || isCopyUntilZero) ?
> + resultRulesPos + 1 : resultRulesPos + length - offset;
> + }
> +
> + point = nextPoint;
> + } while (point != intersectPoints[0]);
> +
> + resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
> + coords = resultCoords;
> + rules = resultRules;
> + offsets = resultOffsets;
> + coordsSize = resultCoordPos;
> + rulesSize = resultRulesPos;
> + }
> +
> + private void subtractPolygon(Area area) {
> + CrossingHelper crossHelper = new CrossingHelper(new double[][] {coords,
> + area.coords },
> + new int[] { coordsSize,
> + area.coordsSize });
> + IntersectPoint[] intersectPoints = crossHelper.findCrossing();
> +
> + if ((intersectPoints.length == 0) && (contains(area.getBounds2D()))) {
> + copy(area, this);
> + return;
> + }
> +
> + double[] resultCoords = new double[coordsSize + area.coordsSize +
> + intersectPoints.length];
> + int[] resultRules = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int[] resultOffsets = new int[rulesSize + area.rulesSize +
> + intersectPoints.length];
> + int resultCoordPos = 0;
> + int resultRulesPos = 0;
> + boolean isCurrentArea = true;
> + int count = 0;
>
> - public boolean contains(double x, double y) {
> - return s == null ? false : s.contains(x, y);
> - }
> + IntersectPoint point = intersectPoints[0];
> + resultRules[resultRulesPos] = PathIterator.SEG_MOVETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> +
> + do {
> + resultCoords[resultCoordPos++] = point.getX();
> + resultCoords[resultCoordPos++] = point.getY();
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos - 2;
> + int curIndex = point.getEndIndex(true);
> +
> + if ((curIndex < 0) ||
> + (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) > 0)) {
> + isCurrentArea = !isCurrentArea;
> + } else if (area.containsExact(coords[2 * curIndex],
> + coords[2 * curIndex + 1]) > 0) {
> + isCurrentArea = false;
> + } else {
> + isCurrentArea = true;
> + }
>
> - public boolean contains(double x, double y, double width, double height) {
> - return s == null ? false : s.contains(x, y, width, height);
> - }
> + IntersectPoint nextPoint = (isCurrentArea) ?
> + getNextIntersectPoint(intersectPoints, point, isCurrentArea):
> + getPrevIntersectPoint(intersectPoints, point, isCurrentArea);
> + double[] coords = (isCurrentArea) ? this.coords : area.coords;
> +
> + int offset = (isCurrentArea) ? 2 * point.getEndIndex(isCurrentArea):
> + 2 * nextPoint.getEndIndex(isCurrentArea);
> +
> + if ((offset > 0) &&
> + (((isCurrentArea) &&
> + (nextPoint.getBegIndex(isCurrentArea) <
> + point.getEndIndex(isCurrentArea))) ||
> + ((!isCurrentArea) &&
> + (nextPoint.getEndIndex(isCurrentArea) <
> + nextPoint.getBegIndex(isCurrentArea))))) {
> +
> + int coordSize = (isCurrentArea) ? this.coordsSize :
> + area.coordsSize;
> + int length = coordSize - offset;
> +
> + if (isCurrentArea) {
> + System.arraycopy(coords, offset,
> + resultCoords, resultCoordPos, length);
> + } else {
> + double[] temp = new double[length];
> + System.arraycopy(coords, offset, temp, 0, length);
> + reverseCopy(temp);
> + System.arraycopy(temp, 0,
> + resultCoords, resultCoordPos, length);
> + }
> +
> + for (int i = 0; i < length / 2; i++) {
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> + resultCoordPos += 2;
> + }
> +
> + offset = 0;
> + }
> +
> + if (offset >= 0) {
> + int length = (isCurrentArea) ?
> + 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2:
> + 2 * point.getBegIndex(isCurrentArea) - offset + 2;
> +
> + if (isCurrentArea) {
> + System.arraycopy(coords, offset,
> + resultCoords, resultCoordPos, length);
> + } else {
> + double[] temp = new double[length];
> + System.arraycopy(coords, offset, temp, 0, length);
> + reverseCopy(temp);
> + System.arraycopy(temp, 0,
> + resultCoords, resultCoordPos, length);
> + }
> +
> + for (int i = 0; i < length / 2; i++) {
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos;
> + resultCoordPos += 2;
> + }
> + }
>
> - public boolean contains(Point2D p) {
> - if (p == null) {
> - throw new NullPointerException();
> + point = nextPoint;
> + count++;
> + } while (point != intersectPoints[0] && count <= intersectPoints.length);
> +
> + if (count > intersectPoints.length) {
> + reset();
> + } else {
> + resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
> + resultOffsets[resultRulesPos - 1] = resultCoordPos;
> + coords = resultCoords;
> + rules = resultRules;
> + offsets = resultOffsets;
> + coordsSize = resultCoordPos;
> + rulesSize = resultRulesPos;
> }
> - return s == null ? false : s.contains(p);
> - }
> -
> - public boolean contains(Rectangle2D r) {
> - if (r == null) {
> - throw new NullPointerException();
> + }
> +
> + private IntersectPoint getNextIntersectPoint(IntersectPoint[] iPoints,
> + IntersectPoint isectPoint,
> + boolean isCurrentArea) {
> +
> + int endIndex = isectPoint.getEndIndex(isCurrentArea);
> + if (endIndex < 0) {
> + return iPoints[Math.abs(endIndex) - 1];
> + }
> +
> + IntersectPoint firstIsectPoint = null;
> + IntersectPoint nextIsectPoint = null;
> + for (IntersectPoint point : iPoints) {
> + int begIndex = point.getBegIndex(isCurrentArea);
> +
> + if (begIndex >= 0) {
> + if (firstIsectPoint == null) {
> + firstIsectPoint = point;
> + } else if (begIndex < firstIsectPoint
> + .getBegIndex(isCurrentArea)) {
> + firstIsectPoint = point;
> + }
> + }
> +
> + if (endIndex <= begIndex) {
> + if (nextIsectPoint == null) {
> + nextIsectPoint = point;
> + } else if (begIndex <
> + nextIsectPoint.getBegIndex(isCurrentArea)) {
> + nextIsectPoint = point;
> + }
> + }
> + }
> +
> + return (nextIsectPoint != null) ? nextIsectPoint : firstIsectPoint;
> + }
> +
> + private IntersectPoint getPrevIntersectPoint(IntersectPoint[] iPoints,
> + IntersectPoint isectPoint,
> + boolean isCurrentArea) {
> +
> + int begIndex = isectPoint.getBegIndex(isCurrentArea);
> +
> + if (begIndex < 0) {
> + return iPoints[Math.abs(begIndex) - 1];
> + }
> +
> + IntersectPoint firstIsectPoint = null;
> + IntersectPoint predIsectPoint = null;
> + for (IntersectPoint point : iPoints) {
> + int endIndex = point.getEndIndex(isCurrentArea);
> +
> + if (endIndex >= 0) {
> + if (firstIsectPoint == null) {
> + firstIsectPoint = point;
> + } else if (endIndex < firstIsectPoint
> + .getEndIndex(isCurrentArea)) {
> + firstIsectPoint = point;
> + }
> + }
> +
> + if (endIndex <= begIndex) {
> + if (predIsectPoint == null) {
> + predIsectPoint = point;
> + } else if (endIndex >
> + predIsectPoint.getEndIndex(isCurrentArea)) {
> + predIsectPoint = point;
> + }
> + }
> + }
> +
> + return (predIsectPoint != null) ? predIsectPoint : firstIsectPoint;
> + }
> +
> +
> + private int includeCoordsAndRules(int offset, int length, int[] rules,
> + int[] offsets, int[] resultRules,
> + int[] resultOffsets, double[] resultCoords,
> + double[] coords, int resultRulesPos,
> + int resultCoordPos, IntersectPoint point,
> + boolean isCurrentArea, boolean way,
> + int operation) {
> +
> + double[] temp = new double[8 * length];
> + int coordsCount = 0;
> + boolean isMoveIndex = true;
> + boolean isMoveLength = true;
> + boolean additional = false;
> +
> + if (length <= offset) {
> + for (int i = resultRulesPos; i < resultRulesPos + 1; i++) {
> + resultRules[i] = PathIterator.SEG_LINETO;
> + }
> + } else {
> + int j = resultRulesPos;
> + for (int i = offset; i < length; i++) {
> + resultRules[j++] = PathIterator.SEG_LINETO;
> + }
> + }
> +
> + if ((length == offset) &&
> + ((rules[offset] == PathIterator.SEG_QUADTO) ||
> + (rules[offset] == PathIterator.SEG_CUBICTO))) {
> + length++;
> + additional = true;
> + }
> + for (int i = offset; i < length; i++) {
> + int index = offsets[i];
> +
> + if (!isMoveIndex) {
> + index -= 2;
> + }
> +
> + if (!isMoveLength) {
> + length++;
> + isMoveLength = true;
> + }
> +
> + switch (rules[i]) {
> + case PathIterator.SEG_MOVETO:
> + isMoveIndex = false;
> + isMoveLength = false;
> + break;
> + case PathIterator.SEG_LINETO:
> + case PathIterator.SEG_CLOSE:
> + resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
> + resultOffsets[resultRulesPos++] = resultCoordPos + 2;
> + boolean isLeft = CrossingHelper.compare(coords[index],
> + coords[index + 1], point.getX(), point.getY()) > 0;
> +
> + if (way || !isLeft) {
> + temp[coordsCount++] = coords[index];
> + temp[coordsCount++] = coords[index + 1];
> + }
> + break;
> + case PathIterator.SEG_QUADTO:
> + resultRules[resultRulesPos] = PathIterator.SEG_QUADTO;
> + resultOffsets[resultRulesPos++] = resultCoordPos + 4;
> + double[] coefs = new double[] { coords[index - 2],
> + coords[index - 1], coords[index], coords[index + 1],
> + coords[index + 2], coords[index + 3] };
> + isLeft = CrossingHelper.compare(coords[index - 2],
> + coords[index - 1], point.getX(), point.getY()) > 0;
> +
> + if ((!additional) && (operation == 0 || operation == 2)) {
> + isLeft = !isLeft;
> + way = false;
> + }
> + GeometryUtil
> + .subQuad(coefs, point.getParam(isCurrentArea), isLeft);
> +
> + if (way || isLeft) {
> + temp[coordsCount++] = coefs[2];
> + temp[coordsCount++] = coefs[3];
> + } else {
> + System.arraycopy(coefs, 2, temp, coordsCount, 4);
> + coordsCount += 4;
> + }
> + break;
> + case PathIterator.SEG_CUBICTO:
> + resultRules[resultRulesPos] = PathIterator.SEG_CUBICTO;
> + resultOffsets[resultRulesPos++] = resultCoordPos + 6;
> + coefs = new double[] {coords[index - 2], coords[index - 1],
> + coords[index], coords[index + 1],
> + coords[index + 2], coords[index + 3],
> + coords[index + 4], coords[index + 5] };
> + isLeft = CrossingHelper.compare(coords[index - 2],
> + coords[index - 1], point.getX(), point.getY()) > 0;
> + GeometryUtil.subCubic(coefs, point.getParam(isCurrentArea),
> + !isLeft);
> +
> + if (isLeft) {
> + System.arraycopy(coefs, 2, temp, coordsCount, 6);
> + coordsCount += 6;
> + } else {
> + System.arraycopy(coefs, 2, temp, coordsCount, 4);
> + coordsCount += 4;
> + }
> + break;
> + }
> + }
> +
> + if (operation == 2 && !isCurrentArea && coordsCount > 2) {
> + reverseCopy(temp);
> + System.arraycopy(temp, 0, resultCoords, resultCoordPos, coordsCount);
> + } else {
> + System.arraycopy(temp, 0, resultCoords, resultCoordPos, coordsCount);
> + }
> +
> + return (resultCoordPos + coordsCount);
> + }
> +
> + // the method check up the array size and necessarily increases it.
> + private static double[] adjustSize(double[] array, int newSize) {
> + if (newSize <= array.length) {
> + return array;
> + }
> + double[] newArray = new double[2 * newSize];
> + System.arraycopy(array, 0, newArray, 0, array.length);
> + return newArray;
> + }
> +
> + private static int[] adjustSize(int[] array, int newSize) {
> + if (newSize <= array.length) {
> + return array;
> + }
> + int[] newArray = new int[2 * newSize];
> + System.arraycopy(array, 0, newArray, 0, array.length);
> + return newArray;
> + }
> +
> + private void copy(Area src, Area dst) {
> + dst.coordsSize = src.coordsSize;
> + dst.coords = src.coords.clone();
> + dst.rulesSize = src.rulesSize;
> + dst.rules = src.rules.clone();
> + dst.moveToCount = src.moveToCount;
> + dst.offsets = src.offsets.clone();
> + }
> +
> + private int containsExact(double x, double y) {
> + PathIterator pi = getPathIterator(null);
> + int crossCount = Crossing.crossPath(pi, x, y);
> +
> + if (Crossing.isInsideEvenOdd(crossCount)) {
> + return 1;
> }
> - return s == null ? false : s.contains(r);
> - }
>
> - public boolean equals(Area obj) throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public boolean intersects(double x, double y, double width, double height) {
> - return s == null ? false : s.intersects(x, y, width, height);
> - }
> -
> - public boolean intersects(Rectangle2D r) {
> - if (r == null) {
> - throw new NullPointerException();
> + double[] segmentCoords = new double[6];
> + double[] resultPoints = new double[6];
> + int rule;
> + double curX = -1;
> + double curY = -1;
> + double moveX = -1;
> + double moveY = -1;
> +
> + for (pi = getPathIterator(null); !pi.isDone(); pi.next()) {
> + rule = pi.currentSegment(segmentCoords);
> + switch (rule) {
> + case PathIterator.SEG_MOVETO:
> + moveX = curX = segmentCoords[0];
> + moveY = curY = segmentCoords[1];
> + break;
> + case PathIterator.SEG_LINETO:
> + if (GeometryUtil.intersectLines(curX, curY,
> + segmentCoords[0], segmentCoords[1], x, y, x, y,
> + resultPoints) != 0) {
> + return 0;
> + }
> + curX = segmentCoords[0];
> + curY = segmentCoords[1];
> + break;
> + case PathIterator.SEG_QUADTO:
> + if (GeometryUtil.intersectLineAndQuad(x, y, x, y,
> + curX, curY, segmentCoords[0], segmentCoords[1],
> + segmentCoords[2], segmentCoords[3],
> + resultPoints) > 0) {
> + return 0;
> + }
> + curX = segmentCoords[2];
> + curY = segmentCoords[3];
> + break;
> + case PathIterator.SEG_CUBICTO:
> + if (GeometryUtil.intersectLineAndCubic(x, y, x, y,
> + curX, curY, segmentCoords[0], segmentCoords[1],
> + segmentCoords[2], segmentCoords[3], segmentCoords[4],
> + segmentCoords[5], resultPoints) > 0) {
> + return 0;
> + }
> + curX = segmentCoords[4];
> + curY = segmentCoords[5];
> + break;
> + case PathIterator.SEG_CLOSE:
> + if (GeometryUtil.intersectLines(curX, curY, moveX, moveY,
> + x, y, x, y, resultPoints) != 0) {
> + return 0;
> + }
> + curX = moveX;
> + curY = moveY;
> + break;
> + }
> }
> - return s == null ? false : s.intersects(r);
> - }
> -
> - public Rectangle getBounds() {
> - return s == null ? new Rectangle() : s.getBounds();
> + return -1;
> }
>
> - public Rectangle2D getBounds2D() {
> - return s == null ? new Rectangle2D.Double(): s.getBounds2D();
> - }
> -
> - public PathIterator getPathIterator(AffineTransform t) {
> - return s == null ? new NullIterator() : s.getPathIterator(t);
> - }
> -
> - public PathIterator getPathIterator(AffineTransform t, double flatness) {
> - return s == null ? new NullIterator() : s.getPathIterator(t, flatness);
> - }
> -
> - public void add(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public void exclusiveOr(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - /**
> - * Extract Rectangle2D from the source shape
> - * @return a Rectangle2D object if the source shape is rectangle, or null if shape is empty or not rectangle.
> - */
> - Rectangle2D extractRectangle() {
> - if (s == null) {
> - return null;
> - }
> - float[] points = new float[12];
> - int count = 0;
> - PathIterator p = s.getPathIterator(null);
> - float[] coords = new float[6];
> - while(!p.isDone()) {
> - int type = p.currentSegment(coords);
> - if (count > 12 || type == PathIterator.SEG_QUADTO || type == PathIterator.SEG_CUBICTO) {
> - return null;
> - }
> - points[count++] = coords[0];
> - points[count++] = coords[1];
> - p.next();
> - }
> - if (points[0] == points[6] && points[6] == points[8] && points[2] == points[4] &&
> - points[1] == points[3] && points[3] == points[9] && points[5] == points[7])
> - {
> - return new Rectangle2D.Float(points[0], points[1], points[2] - points[0], points[7] - points[1]);
> - }
> - return null;
> + private void reverseCopy(double[] coords) {
> + double[] temp = new double[coords.length];
> + System.arraycopy(coords, 0, temp, 0, coords.length);
> +
> + for (int i = 0; i < coords.length;) {
> + coords[i] = temp[coords.length - i - 2];
> + coords[i + 1] = temp[coords.length - i - 1];
> + i = i + 2;
> + }
> }
>
> - public void intersect(Area area) {
> - Rectangle2D src1 = extractRectangle();
> - Rectangle2D src2 = area.extractRectangle();
> - if (src1 != null && src2 != null) {
> - Rectangle2D.intersect(src1, src2, (Rectangle2D)s);
> - }
> - }
> -
> - public void subtract(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public boolean isEmpty() throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public boolean isPolygonal() throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public boolean isRectangular() throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public boolean isSingular() throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public void reset() throws org.apache.harmony.luni.util.NotImplementedException {
> - throw new RuntimeException("Not implemented"); //$NON-NLS-1$
> - }
> -
> - public void transform(AffineTransform t) {
> - s = t.createTransformedShape(s);
> - }
> -
> - public Area createTransformedArea(AffineTransform t) {
> - return s == null ? new Area() : new Area(t.createTransformedShape(s));
> - }
> -
> - @Override
> - public Object clone() {
> - return new Area(this);
> - }
> + // the internal class implements PathIterator
> + private class AreaPathIterator implements PathIterator {
>
> -}
> + AffineTransform t;
> + Area area;
> + int curRuleIndex = 0;
> + int curCoordIndex = 0;
> +
> + AreaPathIterator(Area area) {
> + this(area, null);
> + }
> +
> + AreaPathIterator(Area area, AffineTransform t) {
> + this.area = area;
> + this.t = t;
> + }
> +
> + public int getWindingRule() {
> + return WIND_EVEN_ODD;
> + }
> +
> + public boolean isDone() {
> + return curRuleIndex >= rulesSize;
> + }
> +
> + public void next() {
> + switch (rules[curRuleIndex]) {
> + case PathIterator.SEG_MOVETO:
> + case PathIterator.SEG_LINETO:
> + curCoordIndex += 2;
> + break;
> + case PathIterator.SEG_QUADTO:
> + curCoordIndex += 4;
> + break;
> + case PathIterator.SEG_CUBICTO:
> + curCoordIndex += 6;
> + break;
> + }
> + curRuleIndex++;
> + }
> +
> + public int currentSegment(double[] c) {
> + if (isDone()) {
> + throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
> + }
> + switch (rules[curRuleIndex]) {
> + case PathIterator.SEG_CUBICTO:
> + c[4] = coords[curCoordIndex + 4];
> + c[5] = coords[curCoordIndex + 5];
> + case PathIterator.SEG_QUADTO:
> + c[2] = coords[curCoordIndex + 2];
> + c[3] = coords[curCoordIndex + 3];
> + case PathIterator.SEG_MOVETO:
> + case PathIterator.SEG_LINETO:
> + c[0] = coords[curCoordIndex];
> + c[1] = coords[curCoordIndex + 1];
> + }
> + return rules[curRuleIndex];
> + }
> +
> + public int currentSegment(float[] c) {
> + double[] doubleCoords = new double[6];
> + int rule = currentSegment(doubleCoords);
> +
> + for (int i = 0; i < 6; i++) {
> + c[i] = (float) doubleCoords[i];
> + }
> + return rule;
> + }
> + }
> +}
> \ No newline at end of file
>
> Modified: harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java
> URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java?view=diff&rev=546906&r1=546905&r2=546906
> ==============================================================================
> --- harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java (original)
> +++ harmony/enhanced/classlib/trunk/modules/awt/src/test/api/java/common/java/awt/geom/AreaTest.java Wed Jun 13 08:05:17 2007
> @@ -45,54 +45,126 @@
> }
>
> public void testContainsPoint() {
> - // Regression test HARMONY-1404
> try {
> - Area a = new Area();
> - a.contains((Point2D)null);
> - fail("Expected NPE");
> - } catch (NullPointerException e) {
> - // expected
> - }
> - }
> + Area area = new Area(new Ellipse2D.Double(200, 300, 400, 200));
> + assertTrue(area.contains(250, 350));
> + assertFalse(area.contains(200, 300));
> + assertFalse(area.contains(50, 50));
> +
> + assertTrue(area.contains(new Point2D.Double(500, 400)));
> + assertFalse(area.contains(new Point2D.Double(700, 400)));
> +
> + // Regression test HARMONY-1404
> + Area emptyArea = new Area();
> + emptyArea.contains((Point2D)null);
> + fail("Expected NPE");
> + } catch (NullPointerException e) {
> + // expected
> + }
> + }
>
> - public void testContainsRect() {
> - // Regression test HARMONY-1404
> - try {
> - Area a = new Area();
> - a.contains((Rectangle2D)null);
> - fail("Expected NPE");
> - } catch (NullPointerException e) {
> - // expected
> - }
> - }
> + public void testContainsRect() {
> + // Regression test HARMONY-1476
> + GeneralPath path = new GeneralPath();
> + path.moveTo(100, 500);
> + path.lineTo(400, 100);
> + path.lineTo(700, 500);
> + path.closePath();
> +
> + Area area = new Area(path);
> + assertTrue(area.contains(new Rectangle2D.Double(300, 400, 100, 50)));
> + assertFalse(area.contains(new Rectangle2D.Double(50, 400, 700, 50)));
> +
> + GeneralPath path1 = new GeneralPath();
> + path1.moveTo(400, 500);
> + path1.quadTo(200, 200, 400, 100);
> + path1.quadTo(600, 200, 400, 500);
> + path1.closePath();
> +
> + Area area1 = new Area(path1);
> + assertTrue(area1.contains(350, 200, 50, 50));
> + assertFalse(area1.contains(100, 50, 600, 500));
> +
> + // Regression test HARMONY-1404
> + try {
> + Area emptyArea = new Area();
> + emptyArea.contains((Rectangle2D)null);
> + fail("Expected NPE");
> + } catch (NullPointerException e) {
> + // expected
> + }
> + }
>
> - public void testIntersectsRect() {
> - // Regression test HARMONY-1404
> - try {
> - Area a = new Area();
> - a.intersects((Rectangle2D)null);
> - fail("Expected NPE");
> - } catch (NullPointerException e) {
> - // expected
> - }
> - }
> -
> - public void testGetPathIterator() {
> - // Regression test HARMONY-1860
> - Area a = new Area();
> - PathIterator path = a.getPathIterator(null);
> - checkPathRule(path, PathIterator.WIND_NON_ZERO);
> - checkPathDone(path, true);
> - }
> -
> - public void testCreateTransformedArea() {
> - // Regression test HARMONY-1880
> - AffineTransform t = AffineTransform.getScaleInstance(2, 3);
> - Area a1 = new Area();
> - Area a2 = a1.createTransformedArea(t);
> - PathIterator path = a2.getPathIterator(null);
> - checkPathRule(path, PathIterator.WIND_NON_ZERO);
> - checkPathDone(path, true);
> - }
> + public void testIntersectsRect() {
> + // Regression test HARMONY-1476
> + GeneralPath path = new GeneralPath();
> + path.moveTo(100, 500);
> + path.lineTo(400, 100);
> + path.lineTo(700, 500);
> + path.closePath();
> +
> + Area area = new Area(path);
> + assertTrue(area.intersects(new Rectangle2D.Double(300, 400, 100, 50)));
> + assertFalse(area.intersects(new Rectangle2D.Double(50, 50, 50, 50)));
> +
> + GeneralPath path1 = new GeneralPath();
> + path1.moveTo(400, 500);
> + path1.quadTo(200, 200, 400, 100);
> + path1.quadTo(600, 200, 400, 500);
> + path1.closePath();
> +
> + Area area1 = new Area(path1);
> + assertTrue(area1.intersects(350, 200, 50, 50));
> + assertFalse(area1.intersects(500, 50, 100, 50));
> +
> + // Regression test HARMONY-1404
> + try {
> + Area emptyArea = new Area();
> + emptyArea.intersects((Rectangle2D)null);
> + fail("Expected NPE");
> + } catch (NullPointerException e) {
> + // expected
> + }
> + }
> +
> + public void testIsRectangle() {
> + // Regression test HARMONY-1476
> + Area area = new Area(new Rectangle2D.Double(200, 300, 400, 150));
> + assertTrue(area.isRectangular());
> +
> + GeneralPath path = new GeneralPath();
> + path.moveTo(200, 300);
> + path.lineTo(600, 300);
> + path.lineTo(600, 450);
> + path.lineTo(200, 450);
> + path.closePath();
> +
> + Area area1 = new Area(path);
> + assertTrue(area1.isRectangular());
> +
> + Area area2 = new Area(new Ellipse2D.Double(200, 300, 400, 150));
> + assertFalse(area2.isRectangular());
> + }
> +
> + public void testGetPathIterator() {
> + // Regression test HARMONY-1860
> + Area a = new Area();
> + PathIterator path = a.getPathIterator(null);
> + checkPathRule(path, PathIterator.WIND_EVEN_ODD);
> + checkPathDone(path, true);
> + }
> +
> + public void testCreateTransformedArea() {
> + // Regression test HARMONY-1880
> + AffineTransform t = AffineTransform.getScaleInstance(2, 3);
> + Area a1 = new Area();
> + Area a2 = a1.createTransformedArea(t);
> + PathIterator path = a2.getPathIterator(null);
> + checkPathRule(path, PathIterator.WIND_EVEN_ODD);
> + checkPathDone(path, true);
> + }
>
> + public static void main(String[] args) {
> + junit.textui.TestRunner.run(AreaTest.class);
> + }
> }
>
>
>