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/14 12:09:37 UTC
svn commit: r547195 [1/2] - in
/harmony/enhanced/classlib/trunk/modules/awt/src:
main/java/common/java/awt/geom/ main/java/common/org/apache/harmony/awt/geom/
test/api/java/common/java/awt/geom/
Author: ayza
Date: Thu Jun 14 03:09:36 2007
New Revision: 547195
URL: http://svn.apache.org/viewvc?view=rev&rev=547195
Log:
Another attempt to commit java.awt.geom.Area implementation from HARMONY-1476
Added:
harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/
harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CrossingHelper.java (with props)
harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CurveCrossingHelper.java (with props)
harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/GeometryUtil.java (with props)
harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/IntersectPoint.java (with props)
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=547195&r1=547194&r2=547195
==============================================================================
--- 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 Thu Jun 14 03:09:36 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.geom.CrossingHelper;
+import org.apache.harmony.awt.geom.CurveCrossingHelper;
+import org.apache.harmony.awt.geom.GeometryUtil;
+import org.apache.harmony.awt.geom.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
Added: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CrossingHelper.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CrossingHelper.java?view=auto&rev=547195
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CrossingHelper.java (added)
+++ harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CrossingHelper.java Thu Jun 14 03:09:36 2007
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.awt.geom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class CrossingHelper {
+
+ private double[][] coords;
+ private int[] sizes;
+ private List<IntersectPoint> isectPoints = new ArrayList<IntersectPoint>();
+
+ public CrossingHelper(double[][] coords, int[] sizes) {
+ this.coords = coords;
+ this.sizes = sizes;
+ }
+
+ public IntersectPoint[] findCrossing() {
+ int pointCount1 = sizes[0] / 2;
+ int pointCount2 = sizes[1] / 2;
+ int[] indices = new int[pointCount1 + pointCount2];
+
+ for(int i = 0; i < pointCount1 + pointCount2; i++) {
+ indices[i] = i;
+ }
+
+ sort(coords[0], pointCount1, coords[1], pointCount2, indices);
+ // the set for the shapes edges storing
+ List<Edge> edges = new ArrayList<Edge>();
+ Edge edge;
+ int begIndex, endIndex;
+ int areaNumber;
+
+ for (int i = 0; i < indices.length; i++) {
+ if (indices[i] < pointCount1) {
+ begIndex = indices[i];
+ endIndex = indices[i] - 1;
+
+ if (endIndex < 0) {
+ endIndex = pointCount1 - 1;
+ }
+
+ areaNumber = 0;
+ } else if (indices[i] < pointCount1 + pointCount2) {
+ begIndex = indices[i] - pointCount1;
+ endIndex = indices[i] - 1 - pointCount1;
+
+ if (endIndex < 0) {
+ endIndex = pointCount2 - 1;
+ }
+
+ areaNumber = 1;
+ } else {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (!removeEdge(edges, begIndex, endIndex)) {
+ edge = new Edge(begIndex, endIndex, areaNumber);
+ intersectShape(edges, coords[0], pointCount1,
+ coords[1], pointCount2, edge);
+ edges.add(edge);
+ }
+
+ begIndex = indices[i];
+ endIndex = indices[i] + 1;
+
+ if ((begIndex < pointCount1) && (endIndex == pointCount1)) {
+ endIndex = 0;
+ } else if ((begIndex >= pointCount1) &&
+ (endIndex == (pointCount2 + pointCount1))) {
+ endIndex = pointCount1;
+ }
+
+ if (endIndex < pointCount1) {
+ areaNumber = 0;
+ } else {
+ areaNumber = 1;
+ endIndex -= pointCount1;
+ begIndex -= pointCount1;
+ }
+
+ if (!removeEdge(edges, begIndex, endIndex)) {
+ edge = new Edge(begIndex, endIndex, areaNumber);
+ intersectShape(edges, coords[0], pointCount1,
+ coords[1], pointCount2, edge);
+ edges.add(edge);
+ }
+ }
+
+ return isectPoints.toArray(new IntersectPoint[isectPoints.size()]);
+ }
+
+ private boolean removeEdge(List<Edge> edges, int begIndex, int endIndex) {
+
+ for (Edge edge : edges) {
+ if (edge.reverseCompare(begIndex, endIndex)) {
+ edges.remove(edge);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // return the quantity of intersect points
+ private void intersectShape(List<Edge> edges,
+ double[] coords1, int length1,
+ double[] coords2, int length2,
+ Edge initEdge) {
+ int areaOfEdge1, areaOfEdge2;
+ int initBegin, initEnd;
+ int addBegin, addEnd;
+ double x1, y1, x2, y2, x3, y3, x4, y4;
+ double[] point = new double[2];
+ Edge edge;
+
+ if (initEdge.areaNumber == 0) {
+ x1 = coords1[2* initEdge.begIndex];
+ y1 = coords1[2* initEdge.begIndex + 1];
+ x2 = coords1[2* initEdge.endIndex];
+ y2 = coords1[2* initEdge.endIndex + 1];
+ areaOfEdge1 = 0;
+ } else {
+ x1 = coords2[2* initEdge.begIndex];
+ y1 = coords2[2* initEdge.begIndex + 1];
+ x2 = coords2[2* initEdge.endIndex];
+ y2 = coords2[2* initEdge.endIndex + 1];
+ areaOfEdge1 = 1;
+ }
+
+ for (Iterator iter = edges.iterator(); iter.hasNext(); ) {
+ edge = (Edge) iter.next();
+
+ if (edge.areaNumber == 0) {
+ x3 = coords1[2* edge.begIndex];
+ y3 = coords1[2* edge.begIndex + 1];
+ x4 = coords1[2* edge.endIndex];
+ y4 = coords1[2* edge.endIndex + 1];
+ areaOfEdge2 = 0;
+ } else {
+ x3 = coords2[2* edge.begIndex];
+ y3 = coords2[2* edge.begIndex + 1];
+ x4 = coords2[2* edge.endIndex];
+ y4 = coords2[2* edge.endIndex + 1];
+ areaOfEdge2 = 1;
+ }
+
+ if ((areaOfEdge1 != areaOfEdge2) &&
+ (GeometryUtil.intersectLines(
+ x1, y1, x2, y2, x3, y3, x4, y4, point) == 1) &&
+ (!containsPoint(point))) {
+
+ if (initEdge.areaNumber == 0) {
+ initBegin = initEdge.begIndex;
+ initEnd = initEdge.endIndex;
+ addBegin = edge.begIndex;
+ addEnd = edge.endIndex;
+ } else {
+ initBegin = edge.begIndex;
+ initEnd = edge.endIndex;
+ addBegin = initEdge.begIndex;
+ addEnd = initEdge.endIndex;
+ }
+
+ if (((initEnd == length1 - 1) &&
+ (initBegin == 0 && initEnd > initBegin)) ||
+ (((initEnd != length1 - 1) || (initBegin != 0)) &&
+ ((initBegin != length1 - 1) || (initEnd != 0)) &&
+ (initBegin > initEnd))) {
+
+ int temp = initBegin;
+ initBegin = initEnd;
+ initEnd = temp;
+ }
+
+ if (((addEnd == length2 - 1) && (addBegin == 0) && (addEnd > addBegin)) ||
+ (((addEnd != length2 - 1) || (addBegin != 0)) &&
+ ((addBegin != length2 - 1) || (addEnd != 0)) && (addBegin > addEnd))) {
+
+ int temp = addBegin;
+ addBegin = addEnd;
+ addEnd = temp;
+ }
+
+ IntersectPoint ip;
+ for (Iterator i = isectPoints.iterator(); i.hasNext(); ) {
+ ip = (IntersectPoint)i.next();
+
+ if ((initBegin == ip.getBegIndex(true)) &&
+ (initEnd == ip.getEndIndex(true))) {
+
+ if (compare(ip.getX(), ip.getY(), point[0], point[1]) > 0) {
+ initEnd = - (isectPoints.indexOf(ip) + 1);
+ ip.setBegIndex1(-(isectPoints.size() + 1));
+ } else {
+ initBegin = - (isectPoints.indexOf(ip) + 1);
+ ip.setEndIndex1(-(isectPoints.size() + 1));
+ }
+ }
+
+ if ((addBegin == ip.getBegIndex(false)) &&
+ (addEnd == ip.getEndIndex(false))) {
+
+ if (compare(ip.getX(), ip.getY(), point[0], point[1]) > 0) {
+ addEnd = - (isectPoints.indexOf(ip) + 1);
+ ip.setBegIndex2(-(isectPoints.size() + 1));
+ } else {
+ addBegin = - (isectPoints.indexOf(ip) + 1);
+ ip.setEndIndex2(-(isectPoints.size() + 1));
+ }
+ }
+ }
+
+ isectPoints.add(new IntersectPoint(initBegin, initEnd,
+ addBegin, addEnd,
+ point[0], point[1]));
+ }
+ }
+ }
+
+ // the array sorting
+ private static void sort(double[] coords1, int length1,
+ double[] coords2, int length2,
+ int[] array) {
+ int temp;
+ int length = length1 + length2;
+ double x1, y1, x2, y2;
+
+ for (int i = 1; i < length; i++) {
+ if (array[i-1] < length1) {
+ x1 = coords1[2*array[i-1]];
+ y1 = coords1[2*array[i-1] + 1];
+ } else {
+ x1 = coords2[2*(array[i-1] - length1)];
+ y1 = coords2[2*(array[i-1] - length1) + 1];
+ }
+ if (array[i] < length1) {
+ x2 = coords1[2*array[i]];
+ y2 = coords1[2*array[i] + 1];
+ } else {
+ x2 = coords2[2*(array[i] - length1)];
+ y2 = coords2[2*(array[i] - length1) + 1];
+ }
+ int j = i;
+ while (j > 0 && compare(x1, y1, x2, y2) <= 0) {
+ temp = array[j];
+ array[j] = array[j-1];
+ array[j-1] = temp;
+ j--;
+ if (j > 0) {
+ if (array[j-1] < length1) {
+ x1 = coords1[2*array[j-1]];
+ y1 = coords1[2*array[j-1] + 1];
+ } else {
+ x1 = coords2[2*(array[j-1] - length1)];
+ y1 = coords2[2*(array[j-1] - length1) + 1];
+ }
+ if (array[j] < length1) {
+ x2 = coords1[2*array[j]];
+ y2 = coords1[2*array[j] + 1];
+ } else {
+ x2 = coords2[2*(array[j] - length1)];
+ y2 = coords2[2*(array[j] - length1) + 1];
+ }
+ }
+ }
+ }
+ }
+
+ private boolean containsPoint(double[] point) {
+ IntersectPoint ipoint;
+
+ for (Iterator i = isectPoints.iterator(); i.hasNext(); ) {
+ ipoint = (IntersectPoint)i.next();
+
+ if (ipoint.getX() == point[0] && ipoint.getY() == point[1]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static int compare(double x1, double y1, double x2, double y2) {
+
+ if ((x1 < x2) || (x1 == x2 && y1 < y2)) {
+ return 1;
+ } else if (x1 == x2 && y1 == y2) {
+ return 0;
+ }
+
+ return -1;
+ }
+
+ private static class Edge {
+ int begIndex;
+ int endIndex;
+ int areaNumber;
+
+ public Edge(int begIndex, int endIndex, int areaNumber) {
+ this.begIndex = begIndex;
+ this.endIndex = endIndex;
+ this.areaNumber = areaNumber;
+ }
+
+ public boolean reverseCompare (int begIndex, int endIndex) {
+ return this.begIndex == endIndex && this.endIndex == begIndex;
+ }
+ }
+}
\ No newline at end of file
Propchange: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CrossingHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CurveCrossingHelper.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CurveCrossingHelper.java?view=auto&rev=547195
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CurveCrossingHelper.java (added)
+++ harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CurveCrossingHelper.java Thu Jun 14 03:09:36 2007
@@ -0,0 +1,317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.awt.geom;
+
+import java.awt.geom.PathIterator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+
+
+public class CurveCrossingHelper {
+ private double[][] coords;
+ private int[][] rules;
+ private int[] sizes;
+ private int[] rulesSizes;
+ private int[][] offsets;
+ private List<IntersectPoint> isectPoints = new ArrayList<IntersectPoint>();
+
+ public CurveCrossingHelper(double[][] coords, int[] sizes,
+ int[][] rules, int[] rulesSizes,
+ int[][] offsets) {
+ this.coords = coords;
+ this.rules = rules;
+ this.sizes = sizes;
+ this.rulesSizes = rulesSizes;
+ this.offsets = offsets;
+ }
+
+ public IntersectPoint[] findCrossing() {
+ double[] edge1 = new double[8];
+ double[] edge2 = new double[8];
+ double[] points = new double[6];
+ double[] params = new double[6];
+ double[] mp1 = new double[2];
+ double[] cp1 = new double[2];
+ double[] mp2 = new double[2];
+ double[] cp2 = new double[2];
+ int rule1, rule2, endIndex1, endIndex2;
+ int ipCount = 0;
+
+ for (int i = 0; i < rulesSizes[0]; i++) {
+ rule1 = rules[0][i];
+ endIndex1 = getCurrentEdge(0, i, edge1, mp1, cp1);
+ for (int j = 0; j < rulesSizes[1]; j++) {
+ ipCount = 0;
+ rule2 = rules[1][j];
+ endIndex2 = getCurrentEdge(1, j, edge2, mp2, cp2);
+ if (((rule1 == PathIterator.SEG_LINETO) ||
+ (rule1 == PathIterator.SEG_CLOSE)) &&
+ ((rule2 == PathIterator.SEG_LINETO) ||
+ (rule2 == PathIterator.SEG_CLOSE))) {
+
+ ipCount = GeometryUtil.intersectLinesWithParams(
+ edge1[0], edge1[1], edge1[2], edge1[3],
+ edge2[0], edge2[1], edge2[2], edge2[3],
+ params);
+
+ if (ipCount != 0) {
+ points[0] = GeometryUtil.line(
+ params[0], edge1[0], edge1[2]);
+ points[1] = GeometryUtil.line(
+ params[0], edge1[1], edge1[3]);
+ }
+ } else if (((rule1 == PathIterator.SEG_LINETO) ||
+ (rule1 == PathIterator.SEG_CLOSE)) &&
+ (rule2 == PathIterator.SEG_QUADTO)) {
+ ipCount = GeometryUtil.intersectLineAndQuad(
+ edge1[0], edge1[1], edge1[2],
+ edge1[3], edge2[0], edge2[1],
+ edge2[2], edge2[3], edge2[4],
+ edge2[5], params);
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.line(params[2*k], edge1[0], edge1[2]);
+ points[2*k + 1] = GeometryUtil.line(params[2*k], edge1[1], edge1[3]);
+ }
+ } else if (rule1 == PathIterator.SEG_QUADTO &&
+ (rule2 == PathIterator.SEG_LINETO || rule2 == PathIterator.SEG_CLOSE)) {
+ ipCount = GeometryUtil.intersectLineAndQuad(
+ edge2[0], edge2[1], edge2[2],
+ edge2[3], edge1[0], edge1[1],
+ edge1[2], edge1[3], edge1[4],
+ edge1[5], params);
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.line(
+ params[2*k + 1], edge2[0], edge2[2]);
+ points[2*k + 1] = GeometryUtil.line(
+ params[2*k + 1], edge2[1], edge2[3]);
+ }
+ } else if ((rule1 == PathIterator.SEG_CUBICTO) &&
+ ((rule2 == PathIterator.SEG_LINETO) ||
+ (rule2 == PathIterator.SEG_CLOSE))) {
+ ipCount = GeometryUtil.intersectLineAndCubic(
+ edge1[0], edge1[1], edge1[2],
+ edge1[3], edge1[4], edge1[5],
+ edge1[6], edge1[7], edge2[0],
+ edge2[1], edge2[2], edge2[3],
+ params);
+
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.line(
+ params[2*k + 1], edge2[0], edge2[2]);
+ points[2*k + 1] = GeometryUtil.line(
+ params[2*k + 1], edge2[1], edge2[3]);
+ }
+ } else if (((rule1 == PathIterator.SEG_LINETO) ||
+ (rule1 == PathIterator.SEG_CLOSE)) &&
+ (rule2 == PathIterator.SEG_CUBICTO)) {
+ ipCount = GeometryUtil.intersectLineAndCubic(
+ edge1[0], edge1[1], edge1[2],
+ edge1[3], edge2[0], edge2[1],
+ edge2[2], edge2[3], edge2[4],
+ edge2[5], edge2[6], edge2[7],
+ params);
+
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.line(
+ params[2*k], edge1[0], edge1[2]);
+ points[2*k + 1] = GeometryUtil.line(
+ params[2*k], edge1[1], edge1[3]);
+ }
+ } else if ((rule1 == PathIterator.SEG_QUADTO) &&
+ (rule2 == PathIterator.SEG_QUADTO)) {
+ ipCount = GeometryUtil.intersectQuads(
+ edge1[0], edge1[1], edge1[2], edge1[3],
+ edge1[4], edge1[5], edge2[0], edge2[1],
+ edge2[2], edge2[3], edge2[4], edge2[5],
+ params);
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.quad(
+ params[2*k], edge1[0], edge1[2], edge1[4]);
+ points[2*k + 1] = GeometryUtil.quad(
+ params[2*k], edge1[1], edge1[3], edge1[5]);
+ }
+ } else if ((rule1 == PathIterator.SEG_QUADTO) &&
+ (rule2 == PathIterator.SEG_CUBICTO)) {
+ ipCount = GeometryUtil.intersectQuadAndCubic(
+ edge1[0], edge1[1], edge1[2],
+ edge1[3], edge1[4], edge1[5],
+ edge2[0], edge2[1], edge2[2],
+ edge2[3], edge2[4], edge2[5],
+ edge2[6], edge2[7], params);
+
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.quad(
+ params[2*k], edge1[0], edge1[2], edge1[4]);
+ points[2*k + 1] = GeometryUtil.quad(
+ params[2*k], edge1[1], edge1[3], edge1[5]);
+ }
+ } else if ((rule1 == PathIterator.SEG_CUBICTO) &&
+ (rule2 == PathIterator.SEG_QUADTO)) {
+ ipCount = GeometryUtil.intersectQuadAndCubic(
+ edge2[0], edge2[1], edge2[2],
+ edge2[3], edge2[4], edge2[5],
+ edge1[0], edge1[1], edge1[2],
+ edge1[3], edge1[4], edge1[5],
+ edge2[6], edge2[7], params);
+
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.quad(
+ params[2*k + 1], edge2[0], edge2[2], edge2[4]);
+ points[2*k + 1] = GeometryUtil.quad(
+ params[2*k + 1], edge2[1], edge2[3], edge2[5]);
+ }
+ } else if ((rule1 == PathIterator.SEG_CUBICTO) &&
+ (rule2 == PathIterator.SEG_CUBICTO)) {
+ ipCount = GeometryUtil.intersectCubics(
+ edge1[0], edge1[1], edge1[2], edge1[3],
+ edge1[4], edge1[5], edge1[6], edge1[7],
+ edge2[0], edge2[1], edge2[2], edge2[3],
+ edge2[4], edge2[5], edge2[6], edge2[7],
+ params);
+
+ for (int k = 0; k < ipCount; k++) {
+ points[2*k] = GeometryUtil.cubic(
+ params[2*k], edge1[0], edge1[2], edge1[4], edge1[6]);
+ points[2*k + 1] = GeometryUtil.cubic(
+ params[2*k], edge1[1], edge1[3], edge1[5], edge1[7]);
+ }
+ }
+
+ endIndex1 = i;
+ endIndex2 = j;
+ int begIndex1 = i - 1;
+ int begIndex2 = j - 1;
+
+ for (int k = 0; k < ipCount; k++) {
+ IntersectPoint ip = null;
+ if (!containsPoint(points[2*k], points[2*k + 1])) {
+ for (Iterator iter = isectPoints.iterator();
+ iter.hasNext(); ) {
+ ip = (IntersectPoint)iter.next();
+ if ((begIndex1 == ip.getBegIndex(true)) &&
+ (endIndex1 == ip.getEndIndex(true))) {
+
+ if (ip.getParam(true) > params[2*k]) {
+ endIndex1 = - (isectPoints.indexOf(ip) + 1);
+ ip.setBegIndex1(-(isectPoints.size() + 1));
+ } else {
+ begIndex1 = - (isectPoints.indexOf(ip) + 1);
+ ip.setEndIndex1(-(isectPoints.size() + 1));
+ }
+ }
+
+ if ((begIndex2 == ip.getBegIndex(false)) &&
+ (endIndex2 == ip.getEndIndex(false))) {
+
+ if (ip.getParam(false) > params[2*k + 1]) {
+ endIndex2 = - (isectPoints.indexOf(ip) + 1);
+ ip.setBegIndex2(-(isectPoints.size() + 1));
+ } else {
+ begIndex2 = - (isectPoints.indexOf(ip) + 1);
+ ip.setEndIndex2(-(isectPoints.size() + 1));
+ }
+ }
+ }
+
+ if (rule1 == PathIterator.SEG_CLOSE) {
+ rule1 = PathIterator.SEG_LINETO;
+ }
+
+ if (rule2 == PathIterator.SEG_CLOSE) {
+ rule2 = PathIterator.SEG_LINETO;
+ }
+
+ isectPoints.add(new IntersectPoint(begIndex1, endIndex1,
+ rule1, i,
+ begIndex2, endIndex2,
+ rule2, j,
+ points[2*k], points[2*k + 1],
+ params[2*k], params[2*k + 1]));
+ }
+ }
+ }
+ }
+ return isectPoints.toArray(new IntersectPoint[isectPoints.size()]);
+ }
+
+ private int getCurrentEdge(int areaIndex, int index,
+ double[] c, double[] mp, double[] cp) {
+ int endIndex = 0;
+
+ switch (rules[areaIndex][index]) {
+ case PathIterator.SEG_MOVETO:
+ cp[0] = mp[0] = coords[areaIndex][offsets[areaIndex][index]];
+ cp[1] = mp[1] = coords[areaIndex][offsets[areaIndex][index] + 1];
+ break;
+ case PathIterator.SEG_LINETO:
+ c[0] = cp[0];
+ c[1] = cp[1];
+ cp[0] = c[2] = coords[areaIndex][offsets[areaIndex][index]];
+ cp[1] = c[3] = coords[areaIndex][offsets[areaIndex][index] + 1];
+ endIndex = 0;
+ break;
+ case PathIterator.SEG_QUADTO:
+ c[0] = cp[0];
+ c[1] = cp[1];
+ c[2] = coords[areaIndex][offsets[areaIndex][index]];
+ c[3] = coords[areaIndex][offsets[areaIndex][index] + 1];
+ cp[0] = c[4] = coords[areaIndex][offsets[areaIndex][index] + 2];
+ cp[1] = c[5] = coords[areaIndex][offsets[areaIndex][index] + 3];
+ endIndex = 2;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ c[0] = cp[0];
+ c[1] = cp[1];
+ c[2] = coords[areaIndex][offsets[areaIndex][index]];
+ c[3] = coords[areaIndex][offsets[areaIndex][index] + 1];
+ c[4] = coords[areaIndex][offsets[areaIndex][index] + 2];
+ c[5] = coords[areaIndex][offsets[areaIndex][index] + 3];
+ cp[0] = c[6] = coords[areaIndex][offsets[areaIndex][index] + 4];
+ cp[1] = c[7] = coords[areaIndex][offsets[areaIndex][index] + 5];
+ endIndex = 4;
+ break;
+ case PathIterator.SEG_CLOSE:
+ c[0] = cp[0];
+ c[1] = cp[1];
+ cp[0] = c[2] = mp[0];
+ cp[1] = c[3] = mp[1];
+ if (offsets[areaIndex][index] >= sizes[areaIndex]) {
+ endIndex = -sizes[areaIndex];
+ } else {
+ endIndex = 0;
+ }
+ break;
+ }
+ return offsets[areaIndex][index] + endIndex;
+ }
+
+ private boolean containsPoint(double x, double y) {
+ IntersectPoint ipoint;
+
+ for (Iterator i = isectPoints.iterator(); i.hasNext(); ) {
+ ipoint = (IntersectPoint)i.next();
+
+ if ((Math.abs(ipoint.getX() - x) < Math.pow(10, -6)) &&
+ (Math.abs(ipoint.getY() - y) < Math.pow(10, -6))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
Propchange: harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/geom/CurveCrossingHelper.java
------------------------------------------------------------------------------
svn:eol-style = native