From 524a7d61a4fc4a4d38aeb543b9887e787555bb71 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 03:45:53 +0100 Subject: Fitting of jogamp.graph.geom.plane: double -> float, package location, use PointFactory, GeneralPath -> Path2D, .. --- .../jogamp/graph/geom/plane/AffineTransform.java | 330 +++++++--------- src/com/jogamp/graph/geom/plane/GeneralPath.java | 433 --------------------- .../geom/plane/IllegalPathStateException.java | 2 +- .../plane/NoninvertibleTransformException.java | 2 +- src/com/jogamp/graph/geom/plane/Path2D.java | 430 ++++++++++++++++++++ src/com/jogamp/graph/geom/plane/PathIterator.java | 4 +- 6 files changed, 566 insertions(+), 635 deletions(-) delete mode 100644 src/com/jogamp/graph/geom/plane/GeneralPath.java create mode 100644 src/com/jogamp/graph/geom/plane/Path2D.java (limited to 'src/com/jogamp/graph/geom/plane') diff --git a/src/com/jogamp/graph/geom/plane/AffineTransform.java b/src/com/jogamp/graph/geom/plane/AffineTransform.java index 065ad94b2..321551edc 100644 --- a/src/com/jogamp/graph/geom/plane/AffineTransform.java +++ b/src/com/jogamp/graph/geom/plane/AffineTransform.java @@ -17,19 +17,23 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; -import java.awt.Shape; import java.io.IOException; import java.io.Serializable; -import org.apache.harmony.awt.internal.nls.Messages; +import jogamp.graph.math.MathFloat; import org.apache.harmony.misc.HashCode; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.Point.Factory; + public class AffineTransform implements Cloneable, Serializable { private static final long serialVersionUID = 1330973210523860834L; + static final String determinantIsZero = "Determinant is zero"; + public static final int TYPE_IDENTITY = 0; public static final int TYPE_TRANSLATION = 1; public static final int TYPE_UNIFORM_SCALE = 2; @@ -49,30 +53,34 @@ public class AffineTransform implements Cloneable, Serializable { /** * The min value equivalent to zero. If absolute value less then ZERO it considered as zero. */ - static final double ZERO = 1E-10; + static final float ZERO = (float) 1E-10; + private final Point.Factory pointFactory; + /** * The values of transformation matrix */ - double m00; - double m10; - double m01; - double m11; - double m02; - double m12; + float m00; + float m10; + float m01; + float m11; + float m02; + float m12; /** * The transformation type */ transient int type; - public AffineTransform() { + public AffineTransform(Factory factory) { + pointFactory = factory; type = TYPE_IDENTITY; - m00 = m11 = 1.0; - m10 = m01 = m02 = m12 = 0.0; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; } public AffineTransform(AffineTransform t) { + this.pointFactory = t.pointFactory; this.type = t.type; this.m00 = t.m00; this.m10 = t.m10; @@ -82,7 +90,8 @@ public class AffineTransform implements Cloneable, Serializable { this.m12 = t.m12; } - public AffineTransform(float m00, float m10, float m01, float m11, float m02, float m12) { + public AffineTransform(Point.Factory factory, float m00, float m10, float m01, float m11, float m02, float m12) { + pointFactory = factory; this.type = TYPE_UNKNOWN; this.m00 = m00; this.m10 = m10; @@ -92,29 +101,8 @@ public class AffineTransform implements Cloneable, Serializable { this.m12 = m12; } - public AffineTransform(double m00, double m10, double m01, double m11, double m02, double m12) { - this.type = TYPE_UNKNOWN; - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - } - - public AffineTransform(float[] matrix) { - this.type = TYPE_UNKNOWN; - m00 = matrix[0]; - m10 = matrix[1]; - m01 = matrix[2]; - m11 = matrix[3]; - if (matrix.length > 4) { - m02 = matrix[4]; - m12 = matrix[5]; - } - } - - public AffineTransform(double[] matrix) { + public AffineTransform(Point.Factory factory, float[] matrix) { + pointFactory = factory; this.type = TYPE_UNKNOWN; m00 = matrix[0]; m10 = matrix[1]; @@ -169,8 +157,8 @@ public class AffineTransform implements Cloneable, Serializable { type |= TYPE_FLIP; } - double dx = m00 * m00 + m10 * m10; - double dy = m01 * m01 + m11 * m11; + float dx = m00 * m00 + m10 * m10; + float dy = m01 * m01 + m11 * m11; if (dx != dy) { type |= TYPE_GENERAL_SCALE; } else @@ -190,27 +178,27 @@ public class AffineTransform implements Cloneable, Serializable { return type; } - public double getScaleX() { + public float getScaleX() { return m00; } - public double getScaleY() { + public float getScaleY() { return m11; } - public double getShearX() { + public float getShearX() { return m01; } - public double getShearY() { + public float getShearY() { return m10; } - public double getTranslateX() { + public float getTranslateX() { return m02; } - public double getTranslateY() { + public float getTranslateY() { return m12; } @@ -218,7 +206,7 @@ public class AffineTransform implements Cloneable, Serializable { return getType() == TYPE_IDENTITY; } - public void getMatrix(double[] matrix) { + public void getMatrix(float[] matrix) { matrix[0] = m00; matrix[1] = m10; matrix[2] = m01; @@ -229,11 +217,11 @@ public class AffineTransform implements Cloneable, Serializable { } } - public double getDeterminant() { + public float getDeterminant() { return m00 * m11 - m01 * m10; } - public void setTransform(double m00, double m10, double m01, double m11, double m02, double m12) { + public void setTransform(float m00, float m10, float m01, float m11, float m02, float m12) { this.type = TYPE_UNKNOWN; this.m00 = m00; this.m10 = m10; @@ -250,128 +238,130 @@ public class AffineTransform implements Cloneable, Serializable { public void setToIdentity() { type = TYPE_IDENTITY; - m00 = m11 = 1.0; - m10 = m01 = m02 = m12 = 0.0; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; } - public void setToTranslation(double mx, double my) { - m00 = m11 = 1.0; - m01 = m10 = 0.0; + public void setToTranslation(float mx, float my) { + m00 = m11 = 1.0f; + m01 = m10 = 0.0f; m02 = mx; m12 = my; - if (mx == 0.0 && my == 0.0) { + if (mx == 0.0f && my == 0.0f) { type = TYPE_IDENTITY; } else { type = TYPE_TRANSLATION; } } - public void setToScale(double scx, double scy) { + public void setToScale(float scx, float scy) { m00 = scx; m11 = scy; - m10 = m01 = m02 = m12 = 0.0; - if (scx != 1.0 || scy != 1.0) { + m10 = m01 = m02 = m12 = 0.0f; + if (scx != 1.0f || scy != 1.0f) { type = TYPE_UNKNOWN; } else { type = TYPE_IDENTITY; } } - public void setToShear(double shx, double shy) { - m00 = m11 = 1.0; - m02 = m12 = 0.0; + public void setToShear(float shx, float shy) { + m00 = m11 = 1.0f; + m02 = m12 = 0.0f; m01 = shx; m10 = shy; - if (shx != 0.0 || shy != 0.0) { + if (shx != 0.0f || shy != 0.0f) { type = TYPE_UNKNOWN; } else { type = TYPE_IDENTITY; } } - public void setToRotation(double angle) { - double sin = Math.sin(angle); - double cos = Math.cos(angle); - if (Math.abs(cos) < ZERO) { - cos = 0.0; - sin = sin > 0.0 ? 1.0 : -1.0; + public void setToRotation(float angle) { + float sin = MathFloat.sin(angle); + float cos = MathFloat.cos(angle); + if (MathFloat.abs(cos) < ZERO) { + cos = 0.0f; + sin = sin > 0.0f ? 1.0f : -1.0f; } else - if (Math.abs(sin) < ZERO) { - sin = 0.0; - cos = cos > 0.0 ? 1.0 : -1.0; + if (MathFloat.abs(sin) < ZERO) { + sin = 0.0f; + cos = cos > 0.0f ? 1.0f : -1.0f; } m00 = m11 = cos; m01 = -sin; m10 = sin; - m02 = m12 = 0.0; + m02 = m12 = 0.0f; type = TYPE_UNKNOWN; } - public void setToRotation(double angle, double px, double py) { + public void setToRotation(float angle, float px, float py) { setToRotation(angle); - m02 = px * (1.0 - m00) + py * m10; - m12 = py * (1.0 - m00) - px * m10; + m02 = px * (1.0f - m00) + py * m10; + m12 = py * (1.0f - m00) - px * m10; type = TYPE_UNKNOWN; } - public static AffineTransform getTranslateInstance(double mx, double my) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getTranslateInstance(Point.Factory factory, float mx, float my) { + AffineTransform t = new AffineTransform(factory); t.setToTranslation(mx, my); return t; } - public static AffineTransform getScaleInstance(double scx, double scY) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getScaleInstance(Point.Factory factory, float scx, float scY) { + AffineTransform t = new AffineTransform(factory); t.setToScale(scx, scY); return t; } - public static AffineTransform getShearInstance(double shx, double shy) { - AffineTransform m = new AffineTransform(); - m.setToShear(shx, shy); - return m; + public static AffineTransform getShearInstance(Point.Factory factory, float shx, float shy) { + AffineTransform t = new AffineTransform(factory); + t.setToShear(shx, shy); + return t; } - public static AffineTransform getRotateInstance(double angle) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getRotateInstance(Point.Factory factory, float angle) { + AffineTransform t = new AffineTransform(factory); t.setToRotation(angle); return t; } - public static AffineTransform getRotateInstance(double angle, double x, double y) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getRotateInstance(Point.Factory factory, float angle, float x, float y) { + AffineTransform t = new AffineTransform(factory); t.setToRotation(angle, x, y); return t; } - public void translate(double mx, double my) { - concatenate(AffineTransform.getTranslateInstance(mx, my)); + public void translate(float mx, float my) { + concatenate(AffineTransform.getTranslateInstance(pointFactory, mx, my)); } - public void scale(double scx, double scy) { - concatenate(AffineTransform.getScaleInstance(scx, scy)); + public void scale(float scx, float scy) { + concatenate(AffineTransform.getScaleInstance(pointFactory, scx, scy)); } - public void shear(double shx, double shy) { - concatenate(AffineTransform.getShearInstance(shx, shy)); + public void shear(float shx, float shy) { + concatenate(AffineTransform.getShearInstance(pointFactory, shx, shy)); } - public void rotate(double angle) { - concatenate(AffineTransform.getRotateInstance(angle)); + public void rotate(float angle) { + concatenate(AffineTransform.getRotateInstance(pointFactory, angle)); } - public void rotate(double angle, double px, double py) { - concatenate(AffineTransform.getRotateInstance(angle, px, py)); + public void rotate(float angle, float px, float py) { + concatenate(AffineTransform.getRotateInstance(pointFactory, angle, px, py)); } /** - * Multiply matrix of two AffineTransform objects + * Multiply matrix of two AffineTransform objects. + * The first argument's {@link Point.Factory} is being used. + * * @param t1 - the AffineTransform object is a multiplicand * @param t2 - the AffineTransform object is a multiplier * @return an AffineTransform object that is a result of t1 multiplied by matrix t2. */ AffineTransform multiply(AffineTransform t1, AffineTransform t2) { - return new AffineTransform( + return new AffineTransform(t1.pointFactory, t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00 t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01 t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10 @@ -389,12 +379,12 @@ public class AffineTransform implements Cloneable, Serializable { } public AffineTransform createInverse() throws NoninvertibleTransformException { - double det = getDeterminant(); - if (Math.abs(det) < ZERO) { - // awt.204=Determinant is zero - throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); } return new AffineTransform( + this.pointFactory, m11 / det, // m00 -m10 / det, // m10 -m01 / det, // m01 @@ -404,57 +394,32 @@ public class AffineTransform implements Cloneable, Serializable { ); } - public Point2D transform(Point2D src, Point2D dst) { + public Point transform(Point src, Point dst) { if (dst == null) { - if (src instanceof Point2D.Double) { - dst = new Point2D.Double(); - } else { - dst = new Point2D.Float(); - } + dst = pointFactory.create(); } - double x = src.getX(); - double y = src.getY(); + float x = src.getX(); + float y = src.getY(); - dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); return dst; } - public void transform(Point2D[] src, int srcOff, Point2D[] dst, int dstOff, int length) { + public void transform(Point[] src, int srcOff, Point[] dst, int dstOff, int length) { while (--length >= 0) { - Point2D srcPoint = src[srcOff++]; - double x = srcPoint.getX(); - double y = srcPoint.getY(); - Point2D dstPoint = dst[dstOff]; + Point srcPoint = src[srcOff++]; + float x = srcPoint.getX(); + float y = srcPoint.getY(); + Point dstPoint = dst[dstOff]; if (dstPoint == null) { - if (srcPoint instanceof Point2D.Double) { - dstPoint = new Point2D.Double(); - } else { - dstPoint = new Point2D.Float(); - } + throw new IllegalArgumentException("dst["+dstOff+"] is null"); } - dstPoint.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); dst[dstOff++] = dstPoint; } } - public void transform(double[] src, int srcOff, double[] dst, int dstOff, int length) { - int step = 2; - if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { - srcOff = srcOff + length * 2 - 2; - dstOff = dstOff + length * 2 - 2; - step = -2; - } - while (--length >= 0) { - double x = src[srcOff + 0]; - double y = src[srcOff + 1]; - dst[dstOff + 0] = x * m00 + y * m01 + m02; - dst[dstOff + 1] = x * m10 + y * m11 + m12; - srcOff += step; - dstOff += step; - } - } - public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) { int step = 2; if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { @@ -465,104 +430,75 @@ public class AffineTransform implements Cloneable, Serializable { while (--length >= 0) { float x = src[srcOff + 0]; float y = src[srcOff + 1]; - dst[dstOff + 0] = (float)(x * m00 + y * m01 + m02); - dst[dstOff + 1] = (float)(x * m10 + y * m11 + m12); + dst[dstOff + 0] = x * m00 + y * m01 + m02; + dst[dstOff + 1] = x * m10 + y * m11 + m12; srcOff += step; dstOff += step; } } - public void transform(float[] src, int srcOff, double[] dst, int dstOff, int length) { - while (--length >= 0) { - float x = src[srcOff++]; - float y = src[srcOff++]; - dst[dstOff++] = x * m00 + y * m01 + m02; - dst[dstOff++] = x * m10 + y * m11 + m12; - } - } - - public void transform(double[] src, int srcOff, float[] dst, int dstOff, int length) { - while (--length >= 0) { - double x = src[srcOff++]; - double y = src[srcOff++]; - dst[dstOff++] = (float)(x * m00 + y * m01 + m02); - dst[dstOff++] = (float)(x * m10 + y * m11 + m12); - } - } - - public Point2D deltaTransform(Point2D src, Point2D dst) { + public Point deltaTransform(Point src, Point dst) { if (dst == null) { - if (src instanceof Point2D.Double) { - dst = new Point2D.Double(); - } else { - dst = new Point2D.Float(); - } + dst = pointFactory.create(); } - double x = src.getX(); - double y = src.getY(); + float x = src.getX(); + float y = src.getY(); - dst.setLocation(x * m00 + y * m01, x * m10 + y * m11); + dst.setCoord(x * m00 + y * m01, x * m10 + y * m11); return dst; } - public void deltaTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) { + public void deltaTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) { while (--length >= 0) { - double x = src[srcOff++]; - double y = src[srcOff++]; + float x = src[srcOff++]; + float y = src[srcOff++]; dst[dstOff++] = x * m00 + y * m01; dst[dstOff++] = x * m10 + y * m11; } } - public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException { - double det = getDeterminant(); - if (Math.abs(det) < ZERO) { - // awt.204=Determinant is zero - throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + public Point inverseTransform(Point src, Point dst) throws NoninvertibleTransformException { + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); } - if (dst == null) { - if (src instanceof Point2D.Double) { - dst = new Point2D.Double(); - } else { - dst = new Point2D.Float(); - } + dst = pointFactory.create(); } - double x = src.getX() - m02; - double y = src.getY() - m12; + float x = src.getX() - m02; + float y = src.getY() - m12; - dst.setLocation((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); + dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); return dst; } - public void inverseTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) + public void inverseTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) throws NoninvertibleTransformException { - double det = getDeterminant(); - if (Math.abs(det) < ZERO) { - // awt.204=Determinant is zero - throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); } while (--length >= 0) { - double x = src[srcOff++] - m02; - double y = src[srcOff++] - m12; + float x = src[srcOff++] - m02; + float y = src[srcOff++] - m12; dst[dstOff++] = (x * m11 - y * m01) / det; dst[dstOff++] = (y * m00 - x * m10) / det; } } - public Shape createTransformedShape(Shape src) { + public Path2D createTransformedShape(Path2D src) { if (src == null) { return null; } - if (src instanceof GeneralPath) { - return ((GeneralPath)src).createTransformedShape(this); + if (src instanceof Path2D) { + return ((Path2D)src).createTransformedShape(this); } - PathIterator path = src.getPathIterator(this); - GeneralPath dst = new GeneralPath(path.getWindingRule()); + PathIterator path = src.iterator(this); + Path2D dst = new Path2D(path.getWindingRule()); dst.append(path, false); return dst; } diff --git a/src/com/jogamp/graph/geom/plane/GeneralPath.java b/src/com/jogamp/graph/geom/plane/GeneralPath.java deleted file mode 100644 index 6d6282ef1..000000000 --- a/src/com/jogamp/graph/geom/plane/GeneralPath.java +++ /dev/null @@ -1,433 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.util.NoSuchElementException; - -import org.apache.harmony.awt.gl.Crossing; -import org.apache.harmony.awt.internal.nls.Messages; - -public final class GeneralPath implements Shape, Cloneable { - - public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; - public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; - - /** - * The buffers size - */ - private static final int BUFFER_SIZE = 10; - - /** - * The buffers capacity - */ - private static final int BUFFER_CAPACITY = 10; - - /** - * The point's types buffer - */ - byte[] types; - - /** - * The points buffer - */ - float[] points; - - /** - * The point's type buffer size - */ - int typeSize; - - /** - * The points buffer size - */ - int pointSize; - - /** - * The path rule - */ - int rule; - - /** - * The space amount in points buffer for different segmenet's types - */ - static int pointShift[] = { - 2, // MOVETO - 2, // LINETO - 4, // QUADTO - 6, // CUBICTO - 0}; // CLOSE - - /* - * GeneralPath path iterator - */ - class Iterator implements PathIterator { - - /** - * The current cursor position in types buffer - */ - int typeIndex; - - /** - * The current cursor position in points buffer - */ - int pointIndex; - - /** - * The source GeneralPath object - */ - GeneralPath p; - - /** - * The path iterator transformation - */ - AffineTransform t; - - /** - * Constructs a new GeneralPath.Iterator for given general path - * @param path - the source GeneralPath object - */ - Iterator(GeneralPath path) { - this(path, null); - } - - /** - * Constructs a new GeneralPath.Iterator for given general path and transformation - * @param path - the source GeneralPath object - * @param at - the AffineTransform object to apply rectangle path - */ - Iterator(GeneralPath path, AffineTransform at) { - this.p = path; - this.t = at; - } - - public int getWindingRule() { - return p.getWindingRule(); - } - - public boolean isDone() { - return typeIndex >= p.typeSize; - } - - public void next() { - typeIndex++; - } - - public int currentSegment(double[] coords) { - if (isDone()) { - // awt.4B=Iterator out of bounds - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$ - } - int type = p.types[typeIndex]; - int count = GeneralPath.pointShift[type]; - for (int i = 0; i < count; i++) { - coords[i] = p.points[pointIndex + i]; - } - if (t != null) { - t.transform(coords, 0, coords, 0, count / 2); - } - pointIndex += count; - return type; - } - - public int currentSegment(float[] coords) { - if (isDone()) { - // awt.4B=Iterator out of bounds - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$ - } - int type = p.types[typeIndex]; - int count = GeneralPath.pointShift[type]; - System.arraycopy(p.points, pointIndex, coords, 0, count); - if (t != null) { - t.transform(coords, 0, coords, 0, count / 2); - } - pointIndex += count; - return type; - } - - } - - public GeneralPath() { - this(WIND_NON_ZERO, BUFFER_SIZE); - } - - public GeneralPath(int rule) { - this(rule, BUFFER_SIZE); - } - - public GeneralPath(int rule, int initialCapacity) { - setWindingRule(rule); - types = new byte[initialCapacity]; - points = new float[initialCapacity * 2]; - } - - public GeneralPath(Shape shape) { - this(WIND_NON_ZERO, BUFFER_SIZE); - PathIterator p = shape.getPathIterator(null); - setWindingRule(p.getWindingRule()); - append(p, false); - } - - public void setWindingRule(int rule) { - if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { - // awt.209=Invalid winding rule value - throw new java.lang.IllegalArgumentException(Messages.getString("awt.209")); //$NON-NLS-1$ - } - this.rule = rule; - } - - public int getWindingRule() { - return rule; - } - - /** - * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. - * @param pointCount - the point count to be added in buffer - */ - void checkBuf(int pointCount, boolean checkMove) { - if (checkMove && typeSize == 0) { - // awt.20A=First segment should be SEG_MOVETO type - throw new IllegalPathStateException(Messages.getString("awt.20A")); //$NON-NLS-1$ - } - if (typeSize == types.length) { - byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; - System.arraycopy(types, 0, tmp, 0, typeSize); - types = tmp; - } - if (pointSize + pointCount > points.length) { - float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; - System.arraycopy(points, 0, tmp, 0, pointSize); - points = tmp; - } - } - - public void moveTo(float x, float y) { - if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { - points[pointSize - 2] = x; - points[pointSize - 1] = y; - } else { - checkBuf(2, false); - types[typeSize++] = PathIterator.SEG_MOVETO; - points[pointSize++] = x; - points[pointSize++] = y; - } - } - - public void lineTo(float x, float y) { - checkBuf(2, true); - types[typeSize++] = PathIterator.SEG_LINETO; - points[pointSize++] = x; - points[pointSize++] = y; - } - - public void quadTo(float x1, float y1, float x2, float y2) { - checkBuf(4, true); - types[typeSize++] = PathIterator.SEG_QUADTO; - points[pointSize++] = x1; - points[pointSize++] = y1; - points[pointSize++] = x2; - points[pointSize++] = y2; - } - - public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { - checkBuf(6, true); - types[typeSize++] = PathIterator.SEG_CUBICTO; - points[pointSize++] = x1; - points[pointSize++] = y1; - points[pointSize++] = x2; - points[pointSize++] = y2; - points[pointSize++] = x3; - points[pointSize++] = y3; - } - - public void closePath() { - if (typeSize == 0 || types[typeSize - 1] != PathIterator.SEG_CLOSE) { - checkBuf(0, true); - types[typeSize++] = PathIterator.SEG_CLOSE; - } - } - - public void append(Shape shape, boolean connect) { - PathIterator p = shape.getPathIterator(null); - append(p, connect); - } - - public void append(PathIterator path, boolean connect) { - while (!path.isDone()) { - float coords[] = new float[6]; - switch (path.currentSegment(coords)) { - case PathIterator.SEG_MOVETO: - if (!connect || typeSize == 0) { - moveTo(coords[0], coords[1]); - break; - } - if (types[typeSize - 1] != PathIterator.SEG_CLOSE && - points[pointSize - 2] == coords[0] && - points[pointSize - 1] == coords[1]) - { - break; - } - // NO BREAK; - case PathIterator.SEG_LINETO: - lineTo(coords[0], coords[1]); - break; - case PathIterator.SEG_QUADTO: - quadTo(coords[0], coords[1], coords[2], coords[3]); - break; - case PathIterator.SEG_CUBICTO: - curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); - break; - case PathIterator.SEG_CLOSE: - closePath(); - break; - } - path.next(); - connect = false; - } - } - - public Point2D getCurrentPoint() { - if (typeSize == 0) { - return null; - } - int j = pointSize - 2; - if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { - - for (int i = typeSize - 2; i > 0; i--) { - int type = types[i]; - if (type == PathIterator.SEG_MOVETO) { - break; - } - j -= pointShift[type]; - } - } - return new Point2D.Float(points[j], points[j + 1]); - } - - public void reset() { - typeSize = 0; - pointSize = 0; - } - - public void transform(AffineTransform t) { - t.transform(points, 0, points, 0, pointSize / 2); - } - - public Shape createTransformedShape(AffineTransform t) { - GeneralPath p = (GeneralPath)clone(); - if (t != null) { - p.transform(t); - } - return p; - } - - public Rectangle2D getBounds2D() { - float rx1, ry1, rx2, ry2; - if (pointSize == 0) { - rx1 = ry1 = rx2 = ry2 = 0.0f; - } else { - int i = pointSize - 1; - ry1 = ry2 = points[i--]; - rx1 = rx2 = points[i--]; - while (i > 0) { - float y = points[i--]; - float x = points[i--]; - if (x < rx1) { - rx1 = x; - } else - if (x > rx2) { - rx2 = x; - } - if (y < ry1) { - ry1 = y; - } else - if (y > ry2) { - ry2 = y; - } - } - } - return new Rectangle2D.Float(rx1, ry1, rx2 - rx1, ry2 - ry1); - } - - public Rectangle getBounds() { - return getBounds2D().getBounds(); - } - - /** - * Checks cross count according to path rule to define is it point inside shape or not. - * @param cross - the point cross count - * @return true if point is inside path, or false otherwise - */ - boolean isInside(int cross) { - if (rule == WIND_NON_ZERO) { - return Crossing.isInsideNonZero(cross); - } - return Crossing.isInsideEvenOdd(cross); - } - - public boolean contains(double px, double py) { - return isInside(Crossing.crossShape(this, px, py)); - } - - public boolean contains(double rx, double ry, double rw, double rh) { - int cross = Crossing.intersectShape(this, rx, ry, rw, rh); - return cross != Crossing.CROSSING && isInside(cross); - } - - public boolean intersects(double rx, double ry, double rw, double rh) { - int cross = Crossing.intersectShape(this, rx, ry, rw, rh); - return cross == Crossing.CROSSING || isInside(cross); - } - - 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 intersects(Rectangle2D r) { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - public PathIterator getPathIterator(AffineTransform t) { - return new Iterator(this, t); - } - - public PathIterator getPathIterator(AffineTransform t, double flatness) { - return new FlatteningPathIterator(getPathIterator(t), flatness); - } - - @Override - public Object clone() { - try { - GeneralPath p = (GeneralPath) super.clone(); - p.types = types.clone(); - p.points = points.clone(); - return p; - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } - -} - diff --git a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java index 9d667e510..15f629b88 100644 --- a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java +++ b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java @@ -17,7 +17,7 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; public class IllegalPathStateException extends RuntimeException { diff --git a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java index eee170ec1..cd1ec8d16 100644 --- a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java +++ b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java @@ -17,7 +17,7 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; public class NoninvertibleTransformException extends java.lang.Exception { diff --git a/src/com/jogamp/graph/geom/plane/Path2D.java b/src/com/jogamp/graph/geom/plane/Path2D.java new file mode 100644 index 000000000..031450c8e --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/Path2D.java @@ -0,0 +1,430 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package com.jogamp.graph.geom.plane; + +import java.util.NoSuchElementException; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.opengl.Vertex; + +import jogamp.graph.math.plane.Crossing; + +public final class Path2D implements Cloneable { + + public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; + public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; + + static final String invalidWindingRuleValue = "Invalid winding rule value"; + static final String iteratorOutOfBounds = "Iterator out of bounds"; + + /** + * The buffers size + */ + private static final int BUFFER_SIZE = 10; + + /** + * The buffers capacity + */ + private static final int BUFFER_CAPACITY = 10; + + /** + * The point's types buffer + */ + byte[] types; + + /** + * The points buffer + */ + float[] points; + + /** + * The point's type buffer size + */ + int typeSize; + + /** + * The points buffer size + */ + int pointSize; + + /** + * The path rule + */ + int rule; + + /** + * The space amount in points buffer for different segmenet's types + */ + static int pointShift[] = { + 2, // MOVETO + 2, // LINETO + 4, // QUADTO + 6, // CUBICTO + 0}; // CLOSE + + /* + * GeneralPath path iterator + */ + class Iterator implements PathIterator { + + /** + * The current cursor position in types buffer + */ + int typeIndex; + + /** + * The current cursor position in points buffer + */ + int pointIndex; + + /** + * The source GeneralPath object + */ + Path2D p; + + /** + * The path iterator transformation + */ + AffineTransform t; + + /** + * Constructs a new GeneralPath.Iterator for given general path + * @param path - the source GeneralPath object + */ + Iterator(Path2D path) { + this(path, null); + } + + /** + * Constructs a new GeneralPath.Iterator for given general path and transformation + * @param path - the source GeneralPath object + * @param at - the AffineTransform object to apply rectangle path + */ + Iterator(Path2D path, AffineTransform at) { + this.p = path; + this.t = at; + } + + public int getWindingRule() { + return p.getWindingRule(); + } + + public boolean isDone() { + return typeIndex >= p.typeSize; + } + + public void next() { + typeIndex++; + } + + public int currentSegment(float[] coords) { + if (isDone()) { + throw new NoSuchElementException(iteratorOutOfBounds); + } + int type = p.types[typeIndex]; + int count = Path2D.pointShift[type]; + System.arraycopy(p.points, pointIndex, coords, 0, count); + if (t != null) { + t.transform(coords, 0, coords, 0, count / 2); + } + pointIndex += count; + return type; + } + + } + + public Path2D() { + this(WIND_NON_ZERO, BUFFER_SIZE); + } + + public Path2D(int rule) { + this(rule, BUFFER_SIZE); + } + + public Path2D(int rule, int initialCapacity) { + setWindingRule(rule); + types = new byte[initialCapacity]; + points = new float[initialCapacity * 2]; + } + + public Path2D(Path2D path) { + this(WIND_NON_ZERO, BUFFER_SIZE); + PathIterator p = path.iterator(null); + setWindingRule(p.getWindingRule()); + append(p, false); + } + + public void setWindingRule(int rule) { + if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { + throw new NoSuchElementException(invalidWindingRuleValue); + } + this.rule = rule; + } + + public int getWindingRule() { + return rule; + } + + /** + * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. + * @param pointCount - the point count to be added in buffer + */ + void checkBuf(int pointCount, boolean checkMove) { + if (checkMove && typeSize == 0) { + throw new IllegalPathStateException("First segment should be SEG_MOVETO type"); + } + if (typeSize == types.length) { + byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; + System.arraycopy(types, 0, tmp, 0, typeSize); + types = tmp; + } + if (pointSize + pointCount > points.length) { + float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; + System.arraycopy(points, 0, tmp, 0, pointSize); + points = tmp; + } + } + + public void moveTo(float x, float y) { + if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { + points[pointSize - 2] = x; + points[pointSize - 1] = y; + } else { + checkBuf(2, false); + types[typeSize++] = PathIterator.SEG_MOVETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + } + + public void lineTo(float x, float y) { + checkBuf(2, true); + types[typeSize++] = PathIterator.SEG_LINETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + + public void quadTo(float x1, float y1, float x2, float y2) { + checkBuf(4, true); + types[typeSize++] = PathIterator.SEG_QUADTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + } + + public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { + checkBuf(6, true); + types[typeSize++] = PathIterator.SEG_CUBICTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + points[pointSize++] = x3; + points[pointSize++] = y3; + } + + final public int size() { + return typeSize; + } + + final public boolean isClosed() { + return typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_CLOSE ; + } + + public void closePath() { + if (!isClosed()) { + checkBuf(0, true); + types[typeSize++] = PathIterator.SEG_CLOSE; + } + } + + public String toString() { + return "[size "+size()+", closed "+isClosed()+"]"; + } + + public void append(Path2D path, boolean connect) { + PathIterator p = path.iterator(null); + append(p, connect); + } + + public void append(PathIterator path, boolean connect) { + while (!path.isDone()) { + float coords[] = new float[6]; + switch (path.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + if (!connect || typeSize == 0) { + moveTo(coords[0], coords[1]); + break; + } + if (types[typeSize - 1] != PathIterator.SEG_CLOSE && + points[pointSize - 2] == coords[0] && + points[pointSize - 1] == coords[1]) + { + break; + } + // NO BREAK; + case PathIterator.SEG_LINETO: + lineTo(coords[0], coords[1]); + break; + case PathIterator.SEG_QUADTO: + quadTo(coords[0], coords[1], coords[2], coords[3]); + break; + case PathIterator.SEG_CUBICTO: + curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); + break; + case PathIterator.SEG_CLOSE: + closePath(); + break; + } + path.next(); + connect = false; + } + } + + public Vertex getCurrentPoint() { + if (typeSize == 0) { + return null; + } + int j = pointSize - 2; + if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { + + for (int i = typeSize - 2; i > 0; i--) { + int type = types[i]; + if (type == PathIterator.SEG_MOVETO) { + break; + } + j -= pointShift[type]; + } + } + return new Vertex(points[j], points[j + 1]); + } + + public void reset() { + typeSize = 0; + pointSize = 0; + } + + public void transform(AffineTransform t) { + t.transform(points, 0, points, 0, pointSize / 2); + } + + public Path2D createTransformedShape(AffineTransform t) { + Path2D p = (Path2D)clone(); + if (t != null) { + p.transform(t); + } + return p; + } + + public final synchronized AABBox getBounds2D() { + float rx1, ry1, rx2, ry2; + if (pointSize == 0) { + rx1 = ry1 = rx2 = ry2 = 0.0f; + } else { + int i = pointSize - 1; + ry1 = ry2 = points[i--]; + rx1 = rx2 = points[i--]; + while (i > 0) { + float y = points[i--]; + float x = points[i--]; + if (x < rx1) { + rx1 = x; + } else + if (x > rx2) { + rx2 = x; + } + if (y < ry1) { + ry1 = y; + } else + if (y > ry2) { + ry2 = y; + } + } + } + // FIXME: Rami's code had this in, but AABBox uses upper left - lower right - right ? + // return new AABBox(rx1, ry1, 0f, rx2 - rx1, ry2 - ry1, 0f); + return new AABBox(rx1, ry1, 0f, rx2, ry2, 0f); + } + + /** + * Checks cross count according to path rule to define is it point inside shape or not. + * @param cross - the point cross count + * @return true if point is inside path, or false otherwise + */ + boolean isInside(int cross) { + if (rule == WIND_NON_ZERO) { + return Crossing.isInsideNonZero(cross); + } + return Crossing.isInsideEvenOdd(cross); + } + + public boolean contains(float px, float py) { + return isInside(Crossing.crossShape(this, px, py)); + } + + public boolean contains(float rx, float ry, float rw, float rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross != Crossing.CROSSING && isInside(cross); + } + + public boolean intersects(float rx, float ry, float rw, float rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross == Crossing.CROSSING || isInside(cross); + } + + public boolean contains(Point p) { + return contains(p.getX(), p.getY()); + } + + public boolean contains(AABBox r) { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public boolean intersects(AABBox r) { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public PathIterator iterator() { + return new Iterator(this); + } + + public PathIterator iterator(AffineTransform t) { + return new Iterator(this, t); + } + + /* public PathIterator getPathIterator(AffineTransform t, float flatness) { + return new FlatteningPathIterator(getPathIterator(t), flatness); + } */ + + @Override + public Object clone() { + try { + Path2D p = (Path2D) super.clone(); + p.types = types.clone(); + p.points = points.clone(); + return p; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } +} + diff --git a/src/com/jogamp/graph/geom/plane/PathIterator.java b/src/com/jogamp/graph/geom/plane/PathIterator.java index 22b897841..b4681df0a 100644 --- a/src/com/jogamp/graph/geom/plane/PathIterator.java +++ b/src/com/jogamp/graph/geom/plane/PathIterator.java @@ -17,7 +17,7 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; public interface PathIterator { @@ -38,7 +38,5 @@ public interface PathIterator { public int currentSegment(float[] coords); - public int currentSegment(double[] coords); - } -- cgit v1.2.3