diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/graph/geom/plane/Path2F.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/graph/geom/plane/Path2F.java | 603 |
1 files changed, 0 insertions, 603 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/geom/plane/Path2F.java b/src/jogl/classes/com/jogamp/graph/geom/plane/Path2F.java deleted file mode 100644 index 588232d9a..000000000 --- a/src/jogl/classes/com/jogamp/graph/geom/plane/Path2F.java +++ /dev/null @@ -1,603 +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 - * @author Sven Gothel - */ -package com.jogamp.graph.geom.plane; - -import java.io.PrintStream; -import java.util.NoSuchElementException; - -import com.jogamp.opengl.math.geom.AABBox; - -/** - * Path2F represents and provides construction method for a 2D shape using float[2] points. - */ -public final class Path2F implements Cloneable { - static final String invalidWindingRuleValue = "Invalid winding rule value"; - static final String iteratorOutOfBounds = "Iterator out of bounds"; - - /** A Path2D segment type */ - public static enum SegmentType { - MOVETO(1), - LINETO(1), - QUADTO(2), - CUBICTO(3), - CLOSE(0); - - /** Number of points associated with this segment type */ - public final int point_count; - - /** Return the integer segment type value as a byte */ - public byte integer() { - return (byte) this.ordinal(); - } - - /** Return the SegmentType associated with the integer segment type */ - public static SegmentType valueOf(final int type) { - switch( type ) { - case 0: return MOVETO; - case 1: return LINETO; - case 2: return QUADTO; - case 3: return CUBICTO; - case 4: return CLOSE; - default: - throw new IllegalArgumentException("Unhandled Segment Type: "+type); - } - } - - /** Return the number of points associated with the integer segment type */ - public static int getPointCount(final int type) { - switch( type ) { - case 0: return MOVETO.point_count; - case 1: return LINETO.point_count; - case 2: return QUADTO.point_count; - case 3: return CUBICTO.point_count; - case 4: return CLOSE.point_count; - default: - throw new IllegalArgumentException("Unhandled Segment Type: "+type); - } - } - - SegmentType(final int v) { - this.point_count = v; - } - } - - /** - * 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 - */ - private byte[] m_types; - - /** - * The points buffer - */ - private float[] m_points; - - /** - * The point's type buffer size - */ - private int m_typeSize; - - /** - * The points buffer size - */ - private int m_pointSize; - - /** - * The winding path rule - */ - private WindingRule m_rule; - - /* - * GeneralPath path iterator - */ - public static final class Iterator { - - /** - * The source GeneralPath object - */ - private final Path2F p; - - /** - * The path iterator transformation - */ - private final AffineTransform t; - - /** - * The current cursor position in types buffer - */ - private int typeIndex; - - /** - * The current cursor position in points buffer - */ - private int pointIndex; - - /** - * Constructs a new GeneralPath.Iterator for given general path - * @param path - the source GeneralPath object - */ - Iterator(final Path2F 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 - */ - public Iterator(final Path2F path, final AffineTransform at) { - this.p = path; - this.t = at; - reset(); - } - - private void reset() { - typeIndex = 0; - pointIndex = 0; - } - - /** Return the {@link WindingRule} set */ - public WindingRule getWindingRule() { - return p.getWindingRule(); - } - - /** - * Compute the general winding of the vertices - * @return CCW or CW {@link Winding} - */ - public Winding getWinding() { - return area() >= 0 ? Winding.CCW : Winding.CW ; - } - - /** Returns reference of the point array covering the whole iteration of Path2D, use {@link #index()} to access the current point. */ - public float[] points() { return p.m_points; } - - /** Return the {@link #points()} index for the current segment. */ - public int index() { return pointIndex; } - - /** Return current segment type */ - public SegmentType getType() { return SegmentType.valueOf( p.m_types[typeIndex] ); } - - /** - * Return the current segment type and copies the current segment's points to given storage - * @param coords storage for current segment's points - * @return current segment type - * @see #points() - * @see #type_index() - * @see #getType() - * @deprecated try to use {@link #index()}, {@link #points()} and {@link #next()} to avoid copying - */ - @Deprecated - public SegmentType currentSegment(final float[] coords) { - if (!hasNext()) { - throw new NoSuchElementException(iteratorOutOfBounds); - } - final SegmentType type = getType(); - final int count = type.point_count; - System.arraycopy(p.m_points, pointIndex, coords, 0, count*2); - if (t != null) { - t.transform(coords, 0, coords, 0, count); - } - return type; - } - - /** Returns true if the iteration has more elements. */ - public boolean hasNext() { - return typeIndex < p.m_typeSize; - } - - /** Returns the current segment type in the iteration, then moving to the next path segment. */ - public SegmentType next() { - final SegmentType t = getType(); - pointIndex += 2 * t.point_count; - ++typeIndex; - return t; - } - - /** - * Computes the area of the path to check if ccw - * @return positive area if ccw else negative area value - */ - private float area() { - float area = 0.0f; - final float[] points = points(); - final float[] pCoord = new float[2]; - while ( hasNext() ) { - final int idx = index(); - final SegmentType type = next(); - switch ( type ) { - case MOVETO: - pCoord[0] = points[idx+0]; - pCoord[1] = points[idx+1]; - break; - case LINETO: - area += pCoord[0] * points[idx+1] - points[idx+0] * pCoord[1]; - pCoord[0] = points[idx+0]; - pCoord[1] = points[idx+1]; - break; - case QUADTO: - area += pCoord[0] * points[idx+1] - points[idx+0] * pCoord[1]; - area += points[idx+0] * points[idx+3] - points[idx+2] * points[idx+1]; - pCoord[0] = points[idx+2]; - pCoord[1] = points[idx+3]; - break; - case CUBICTO: - area += pCoord[0] * points[idx+1] - points[idx+0] * pCoord[1]; - area += points[idx+0] * points[idx+3] - points[idx+2] * points[idx+1]; - area += points[idx+2] * points[idx+5] - points[idx+4] * points[idx+3]; - pCoord[0] = points[idx+4]; - pCoord[1] = points[idx+5]; - break; - case CLOSE: - break; - } - } - reset(); - return area; - } - } - - public Path2F() { - this(WindingRule.NON_ZERO, BUFFER_SIZE, BUFFER_SIZE); - } - - public Path2F(final WindingRule rule) { - this(rule, BUFFER_SIZE, BUFFER_SIZE); - } - - public Path2F(final WindingRule rule, final int initialCapacity) { - this(rule, initialCapacity, initialCapacity); - } - - public Path2F(final WindingRule rule, final int initialTypeCapacity, final int initialPointCapacity) { - setWindingRule(rule); - m_types = new byte[initialTypeCapacity]; - m_points = new float[initialPointCapacity * 2]; - } - - public Path2F(final Path2F path) { - this(WindingRule.NON_ZERO, BUFFER_SIZE); - final Iterator p = path.iterator(null); - setWindingRule(p.getWindingRule()); - append(p, false); - } - - /** Set the {@link WindingRule} set */ - public void setWindingRule(final WindingRule rule) { - this.m_rule = rule; - } - - /** Return the {@link WindingRule} set */ - public WindingRule getWindingRule() { - return m_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 - */ - private void checkBuf(final int pointCount, final boolean checkMove) { - if (checkMove && m_typeSize == 0) { - throw new IllegalPathStateException("First segment should be SEG_MOVETO type"); - } - if (m_typeSize == m_types.length) { - final byte tmp[] = new byte[m_typeSize + BUFFER_CAPACITY]; - System.arraycopy(m_types, 0, tmp, 0, m_typeSize); - m_types = tmp; - } - if (m_pointSize + pointCount > m_points.length) { - final float tmp[] = new float[m_pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; - System.arraycopy(m_points, 0, tmp, 0, m_pointSize); - m_points = tmp; - } - } - - /** - * Start a new position for the next line segment at given point x/y (P1). - * @param x point (P1) - * @param y point (P1) - */ - public void moveTo(final float x, final float y) { - if ( m_typeSize > 0 && m_types[m_typeSize - 1] == SegmentType.MOVETO.integer() ) { - m_points[m_pointSize - 2] = x; - m_points[m_pointSize - 1] = y; - } else { - checkBuf(2, false); - m_types[m_typeSize++] = SegmentType.MOVETO.integer(); - m_points[m_pointSize++] = x; - m_points[m_pointSize++] = y; - } - } - - /** - * Add a line segment, intersecting the last point and the given point x/y (P1). - * @param x final point (P1) - * @param y final point (P1) - */ - public void lineTo(final float x, final float y) { - checkBuf(2, true); - m_types[m_typeSize++] = SegmentType.LINETO.integer(); - m_points[m_pointSize++] = x; - m_points[m_pointSize++] = y; - } - - /** - * Add a quadratic curve segment, intersecting the last point and the second given point x2/y2 (P2). - * @param x1 quadratic parametric control point (P1) - * @param y1 quadratic parametric control point (P1) - * @param x2 final interpolated control point (P2) - * @param y2 final interpolated control point (P2) - */ - public void quadTo(final float x1, final float y1, final float x2, final float y2) { - checkBuf(4, true); - m_types[m_typeSize++] = SegmentType.QUADTO.integer(); - m_points[m_pointSize++] = x1; - m_points[m_pointSize++] = y1; - m_points[m_pointSize++] = x2; - m_points[m_pointSize++] = y2; - } - - /** - * Add a cubic Bézier curve segment, intersecting the last point and the second given point x3/y3 (P3). - * @param x1 Bézier control point (P1) - * @param y1 Bézier control point (P1) - * @param x2 Bézier control point (P2) - * @param y2 Bézier control point (P2) - * @param x3 final interpolated control point (P3) - * @param y3 final interpolated control point (P3) - */ - public void cubicTo(final float x1, final float y1, final float x2, final float y2, final float x3, final float y3) { - checkBuf(6, true); - m_types[m_typeSize++] = SegmentType.CUBICTO.integer(); - m_points[m_pointSize++] = x1; - m_points[m_pointSize++] = y1; - m_points[m_pointSize++] = x2; - m_points[m_pointSize++] = y2; - m_points[m_pointSize++] = x3; - m_points[m_pointSize++] = y3; - } - - /** - * Closes the current sub-path segment by drawing a straight line back to the coordinates of the last moveTo. If the path is already closed then this method has no effect. - */ - public void closePath() { - if (!isClosed()) { - checkBuf(0, true); - m_types[m_typeSize++] = SegmentType.CLOSE.integer(); - } - } - - final public int size() { - return m_typeSize; - } - - /** - * Returns true if the last sub-path is closed, otherwise false. - */ - final public boolean isClosed() { - return m_typeSize > 0 && m_types[m_typeSize - 1] == SegmentType.CLOSE.integer() ; - } - - /** - * Compute the general winding of the vertices - * @param vertices array of Vertices - * @return CCW or CW {@link Winding} - */ - public Winding getWinding() { - return iterator(null).getWinding(); - } - - @Override - public String toString() { - return "[size "+size()+", closed "+isClosed()+", winding[rule "+getWindingRule()+", "+getWinding()+"]]"; - } - - /** - * Append the given path geometry to this instance - * @param path the {@link Path2F} to append to this instance - * @param connect pass true to turn an initial moveTo segment into a lineTo segment to connect the new geometry to the existing path, otherwise pass false. - */ - public void append(final Path2F path, final boolean connect) { - append(path.iterator(null), connect); - } - - /** - * Append the given path geometry to this instance - * @param path the {@link Path2F.Iterator} to append to this instance - * @param connect pass true to turn an initial moveTo segment into a lineTo segment to connect the new geometry to the existing path, otherwise pass false. - */ - public void append(final Iterator path, boolean connect) { - final float[] points = path.points(); - while ( path.hasNext() ) { - final int idx = path.index(); - final SegmentType type = path.next(); - switch ( type ) { - case MOVETO: - if ( !connect || 0 == m_typeSize ) { - moveTo(points[idx+0], points[idx+1]); - break; - } - if ( m_types[m_typeSize - 1] != SegmentType.CLOSE.integer() && - m_points[m_pointSize - 2] == points[idx+0] && - m_points[m_pointSize - 1] == points[idx+1] - ) - { - break; - } - // fallthrough: MOVETO -> LINETO - case LINETO: - lineTo(points[idx+0], points[idx+1]); - break; - case QUADTO: - quadTo(points[idx+0], points[idx+1], points[idx+2], points[idx+3]); - break; - case CUBICTO: - cubicTo(points[idx+0], points[idx+1], points[idx+2], points[idx+3], points[idx+4], points[idx+5]); - break; - case CLOSE: - closePath(); - break; - } - connect = false; - } - } - - public void printSegments(final PrintStream out) { - final Iterator path = iterator(); - final float[] points = path.points(); - int i = 0; - while ( path.hasNext() ) { - final int idx = path.index(); - final SegmentType type = path.next(); - switch ( type ) { - case MOVETO: - out.printf("%2d: moveTo(%.4f/%.4f)%n", i, points[idx+0], points[idx+1]); - break; - case LINETO: - out.printf("%2d: lineTo(%.4f/%.4f)%n", i, points[idx+0], points[idx+1]); - break; - case QUADTO: - out.printf("%2d: quadTo(%.4f/%.4f, %.4f/%.4f)%n", i, points[idx+0], points[idx+1], points[idx+2], points[idx+3]); - break; - case CUBICTO: - out.printf("%2d: cubicTo(%.4f/%.4f, %.4f/%.4f, %.4f/%.4f)%n", i, points[idx+0], points[idx+1], points[idx+2], points[idx+3], points[idx+4], points[idx+5]); - break; - case CLOSE: - out.printf("%2d: closePath()%n", i); - break; - } - ++i; - } - } - - public void reset() { - m_typeSize = 0; - m_pointSize = 0; - } - - public void transform(final AffineTransform t) { - t.transform(m_points, 0, m_points, 0, m_pointSize / 2); - } - - public Path2F createTransformedShape(final AffineTransform t) { - final Path2F p = (Path2F)clone(); - if (t != null) { - p.transform(t); - } - return p; - } - - public final synchronized AABBox getBounds2D() { - float rx1, ry1, rx2, ry2; - if (m_pointSize == 0) { - rx1 = ry1 = rx2 = ry2 = 0.0f; - } else { - int i = m_pointSize - 1; - ry1 = ry2 = m_points[i--]; - rx1 = rx2 = m_points[i--]; - while (i > 0) { - final float y = m_points[i--]; - final float x = m_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 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(final int cross) { - if (m_rule == WindingRule.NON_ZERO) { - return Crossing2F.isInsideNonZero(cross); - } - return Crossing2F.isInsideEvenOdd(cross); - } - - public boolean contains(final float px, final float py) { - return isInside(Crossing2F.crossShape(this, px, py)); - } - - public boolean contains(final float rx, final float ry, final float rw, final float rh) { - final int cross = Crossing2F.intersectShape(this, rx, ry, rw, rh); - return cross != Crossing2F.CROSSING && isInside(cross); - } - - public boolean intersects(final float rx, final float ry, final float rw, final float rh) { - final int cross = Crossing2F.intersectShape(this, rx, ry, rw, rh); - return cross == Crossing2F.CROSSING || isInside(cross); - } - - public boolean contains(final AABBox r) { - return contains(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight()); - } - - public boolean intersects(final AABBox r) { - return intersects(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight()); - } - - public Iterator iterator() { - return new Iterator(this); - } - - public Iterator iterator(final AffineTransform t) { - return new Iterator(this, t); - } - - /* public Path2F.Iterator getPathIterator(AffineTransform t, float flatness) { - return new FlatteningPathIterator(getPathIterator(t), flatness); - } */ - - @Override - public Object clone() { - try { - final Path2F p = (Path2F) super.clone(); - p.m_types = m_types.clone(); - p.m_points = m_points.clone(); - return p; - } catch (final CloneNotSupportedException e) { - throw new InternalError(); - } - } -} - |