feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
3941
jdkSrc/jdk8/java/awt/geom/AffineTransform.java
Normal file
3941
jdkSrc/jdk8/java/awt/geom/AffineTransform.java
Normal file
File diff suppressed because it is too large
Load Diff
1474
jdkSrc/jdk8/java/awt/geom/Arc2D.java
Normal file
1474
jdkSrc/jdk8/java/awt/geom/Arc2D.java
Normal file
File diff suppressed because it is too large
Load Diff
312
jdkSrc/jdk8/java/awt/geom/ArcIterator.java
Normal file
312
jdkSrc/jdk8/java/awt/geom/ArcIterator.java
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of an arc
|
||||
* through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class ArcIterator implements PathIterator {
|
||||
double x, y, w, h, angStRad, increment, cv;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
int arcSegs;
|
||||
int lineSegs;
|
||||
|
||||
ArcIterator(Arc2D a, AffineTransform at) {
|
||||
this.w = a.getWidth() / 2;
|
||||
this.h = a.getHeight() / 2;
|
||||
this.x = a.getX() + w;
|
||||
this.y = a.getY() + h;
|
||||
this.angStRad = -Math.toRadians(a.getAngleStart());
|
||||
this.affine = at;
|
||||
double ext = -a.getAngleExtent();
|
||||
if (ext >= 360.0 || ext <= -360) {
|
||||
arcSegs = 4;
|
||||
this.increment = Math.PI / 2;
|
||||
// btan(Math.PI / 2);
|
||||
this.cv = 0.5522847498307933;
|
||||
if (ext < 0) {
|
||||
increment = -increment;
|
||||
cv = -cv;
|
||||
}
|
||||
} else {
|
||||
arcSegs = (int) Math.ceil(Math.abs(ext) / 90.0);
|
||||
this.increment = Math.toRadians(ext / arcSegs);
|
||||
this.cv = btan(increment);
|
||||
if (cv == 0) {
|
||||
arcSegs = 0;
|
||||
}
|
||||
}
|
||||
switch (a.getArcType()) {
|
||||
case Arc2D.OPEN:
|
||||
lineSegs = 0;
|
||||
break;
|
||||
case Arc2D.CHORD:
|
||||
lineSegs = 1;
|
||||
break;
|
||||
case Arc2D.PIE:
|
||||
lineSegs = 2;
|
||||
break;
|
||||
}
|
||||
if (w < 0 || h < 0) {
|
||||
arcSegs = lineSegs = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return index > arcSegs + lineSegs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
/*
|
||||
* btan computes the length (k) of the control segments at
|
||||
* the beginning and end of a cubic bezier that approximates
|
||||
* a segment of an arc with extent less than or equal to
|
||||
* 90 degrees. This length (k) will be used to generate the
|
||||
* 2 bezier control points for such a segment.
|
||||
*
|
||||
* Assumptions:
|
||||
* a) arc is centered on 0,0 with radius of 1.0
|
||||
* b) arc extent is less than 90 degrees
|
||||
* c) control points should preserve tangent
|
||||
* d) control segments should have equal length
|
||||
*
|
||||
* Initial data:
|
||||
* start angle: ang1
|
||||
* end angle: ang2 = ang1 + extent
|
||||
* start point: P1 = (x1, y1) = (cos(ang1), sin(ang1))
|
||||
* end point: P4 = (x4, y4) = (cos(ang2), sin(ang2))
|
||||
*
|
||||
* Control points:
|
||||
* P2 = (x2, y2)
|
||||
* | x2 = x1 - k * sin(ang1) = cos(ang1) - k * sin(ang1)
|
||||
* | y2 = y1 + k * cos(ang1) = sin(ang1) + k * cos(ang1)
|
||||
*
|
||||
* P3 = (x3, y3)
|
||||
* | x3 = x4 + k * sin(ang2) = cos(ang2) + k * sin(ang2)
|
||||
* | y3 = y4 - k * cos(ang2) = sin(ang2) - k * cos(ang2)
|
||||
*
|
||||
* The formula for this length (k) can be found using the
|
||||
* following derivations:
|
||||
*
|
||||
* Midpoints:
|
||||
* a) bezier (t = 1/2)
|
||||
* bPm = P1 * (1-t)^3 +
|
||||
* 3 * P2 * t * (1-t)^2 +
|
||||
* 3 * P3 * t^2 * (1-t) +
|
||||
* P4 * t^3 =
|
||||
* = (P1 + 3P2 + 3P3 + P4)/8
|
||||
*
|
||||
* b) arc
|
||||
* aPm = (cos((ang1 + ang2)/2), sin((ang1 + ang2)/2))
|
||||
*
|
||||
* Let angb = (ang2 - ang1)/2; angb is half of the angle
|
||||
* between ang1 and ang2.
|
||||
*
|
||||
* Solve the equation bPm == aPm
|
||||
*
|
||||
* a) For xm coord:
|
||||
* x1 + 3*x2 + 3*x3 + x4 = 8*cos((ang1 + ang2)/2)
|
||||
*
|
||||
* cos(ang1) + 3*cos(ang1) - 3*k*sin(ang1) +
|
||||
* 3*cos(ang2) + 3*k*sin(ang2) + cos(ang2) =
|
||||
* = 8*cos((ang1 + ang2)/2)
|
||||
*
|
||||
* 4*cos(ang1) + 4*cos(ang2) + 3*k*(sin(ang2) - sin(ang1)) =
|
||||
* = 8*cos((ang1 + ang2)/2)
|
||||
*
|
||||
* 8*cos((ang1 + ang2)/2)*cos((ang2 - ang1)/2) +
|
||||
* 6*k*sin((ang2 - ang1)/2)*cos((ang1 + ang2)/2) =
|
||||
* = 8*cos((ang1 + ang2)/2)
|
||||
*
|
||||
* 4*cos(angb) + 3*k*sin(angb) = 4
|
||||
*
|
||||
* k = 4 / 3 * (1 - cos(angb)) / sin(angb)
|
||||
*
|
||||
* b) For ym coord we derive the same formula.
|
||||
*
|
||||
* Since this formula can generate "NaN" values for small
|
||||
* angles, we will derive a safer form that does not involve
|
||||
* dividing by very small values:
|
||||
* (1 - cos(angb)) / sin(angb) =
|
||||
* = (1 - cos(angb))*(1 + cos(angb)) / sin(angb)*(1 + cos(angb)) =
|
||||
* = (1 - cos(angb)^2) / sin(angb)*(1 + cos(angb)) =
|
||||
* = sin(angb)^2 / sin(angb)*(1 + cos(angb)) =
|
||||
* = sin(angb) / (1 + cos(angb))
|
||||
*
|
||||
*/
|
||||
private static double btan(double increment) {
|
||||
increment /= 2.0;
|
||||
return 4.0 / 3.0 * Math.sin(increment) / (1.0 + Math.cos(increment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("arc iterator out of bounds");
|
||||
}
|
||||
double angle = angStRad;
|
||||
if (index == 0) {
|
||||
coords[0] = (float) (x + Math.cos(angle) * w);
|
||||
coords[1] = (float) (y + Math.sin(angle) * h);
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return SEG_MOVETO;
|
||||
}
|
||||
if (index > arcSegs) {
|
||||
if (index == arcSegs + lineSegs) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
coords[0] = (float) x;
|
||||
coords[1] = (float) y;
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return SEG_LINETO;
|
||||
}
|
||||
angle += increment * (index - 1);
|
||||
double relx = Math.cos(angle);
|
||||
double rely = Math.sin(angle);
|
||||
coords[0] = (float) (x + (relx - cv * rely) * w);
|
||||
coords[1] = (float) (y + (rely + cv * relx) * h);
|
||||
angle += increment;
|
||||
relx = Math.cos(angle);
|
||||
rely = Math.sin(angle);
|
||||
coords[2] = (float) (x + (relx + cv * rely) * w);
|
||||
coords[3] = (float) (y + (rely - cv * relx) * h);
|
||||
coords[4] = (float) (x + relx * w);
|
||||
coords[5] = (float) (y + rely * h);
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 3);
|
||||
}
|
||||
return SEG_CUBICTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("arc iterator out of bounds");
|
||||
}
|
||||
double angle = angStRad;
|
||||
if (index == 0) {
|
||||
coords[0] = x + Math.cos(angle) * w;
|
||||
coords[1] = y + Math.sin(angle) * h;
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return SEG_MOVETO;
|
||||
}
|
||||
if (index > arcSegs) {
|
||||
if (index == arcSegs + lineSegs) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
coords[0] = x;
|
||||
coords[1] = y;
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return SEG_LINETO;
|
||||
}
|
||||
angle += increment * (index - 1);
|
||||
double relx = Math.cos(angle);
|
||||
double rely = Math.sin(angle);
|
||||
coords[0] = x + (relx - cv * rely) * w;
|
||||
coords[1] = y + (rely + cv * relx) * h;
|
||||
angle += increment;
|
||||
relx = Math.cos(angle);
|
||||
rely = Math.sin(angle);
|
||||
coords[2] = x + (relx + cv * rely) * w;
|
||||
coords[3] = y + (rely - cv * relx) * h;
|
||||
coords[4] = x + relx * w;
|
||||
coords[5] = y + rely * h;
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 3);
|
||||
}
|
||||
return SEG_CUBICTO;
|
||||
}
|
||||
}
|
744
jdkSrc/jdk8/java/awt/geom/Area.java
Normal file
744
jdkSrc/jdk8/java/awt/geom/Area.java
Normal file
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
import sun.awt.geom.Curve;
|
||||
import sun.awt.geom.Crossings;
|
||||
import sun.awt.geom.AreaOp;
|
||||
|
||||
/**
|
||||
* An <code>Area</code> object stores and manipulates a
|
||||
* resolution-independent description of an enclosed area of
|
||||
* 2-dimensional space.
|
||||
* <code>Area</code> objects can be transformed and can perform
|
||||
* various Constructive Area Geometry (CAG) operations when combined
|
||||
* with other <code>Area</code> objects.
|
||||
* The CAG operations include area
|
||||
* {@link #add addition}, {@link #subtract subtraction},
|
||||
* {@link #intersect intersection}, and {@link #exclusiveOr exclusive or}.
|
||||
* See the linked method documentation for examples of the various
|
||||
* operations.
|
||||
* <p>
|
||||
* The <code>Area</code> class implements the <code>Shape</code>
|
||||
* interface and provides full support for all of its hit-testing
|
||||
* and path iteration facilities, but an <code>Area</code> is more
|
||||
* specific than a generalized path in a number of ways:
|
||||
* <ul>
|
||||
* <li>Only closed paths and sub-paths are stored.
|
||||
* <code>Area</code> objects constructed from unclosed paths
|
||||
* are implicitly closed during construction as if those paths
|
||||
* had been filled by the <code>Graphics2D.fill</code> method.
|
||||
* <li>The interiors of the individual stored sub-paths are all
|
||||
* non-empty and non-overlapping. Paths are decomposed during
|
||||
* construction into separate component non-overlapping parts,
|
||||
* empty pieces of the path are discarded, and then these
|
||||
* non-empty and non-overlapping properties are maintained
|
||||
* through all subsequent CAG operations. Outlines of different
|
||||
* component sub-paths may touch each other, as long as they
|
||||
* do not cross so that their enclosed areas overlap.
|
||||
* <li>The geometry of the path describing the outline of the
|
||||
* <code>Area</code> resembles the path from which it was
|
||||
* constructed only in that it describes the same enclosed
|
||||
* 2-dimensional area, but may use entirely different types
|
||||
* and ordering of the path segments to do so.
|
||||
* </ul>
|
||||
* Interesting issues which are not always obvious when using
|
||||
* the <code>Area</code> include:
|
||||
* <ul>
|
||||
* <li>Creating an <code>Area</code> from an unclosed (open)
|
||||
* <code>Shape</code> results in a closed outline in the
|
||||
* <code>Area</code> object.
|
||||
* <li>Creating an <code>Area</code> from a <code>Shape</code>
|
||||
* which encloses no area (even when "closed") produces an
|
||||
* empty <code>Area</code>. A common example of this issue
|
||||
* is that producing an <code>Area</code> from a line will
|
||||
* be empty since the line encloses no area. An empty
|
||||
* <code>Area</code> will iterate no geometry in its
|
||||
* <code>PathIterator</code> objects.
|
||||
* <li>A self-intersecting <code>Shape</code> may be split into
|
||||
* two (or more) sub-paths each enclosing one of the
|
||||
* non-intersecting portions of the original path.
|
||||
* <li>An <code>Area</code> may take more path segments to
|
||||
* describe the same geometry even when the original
|
||||
* outline is simple and obvious. The analysis that the
|
||||
* <code>Area</code> class must perform on the path may
|
||||
* not reflect the same concepts of "simple and obvious"
|
||||
* as a human being perceives.
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public class Area implements Shape, Cloneable {
|
||||
private static Vector EmptyCurves = new Vector();
|
||||
|
||||
private Vector curves;
|
||||
|
||||
/**
|
||||
* Default constructor which creates an empty area.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Area() {
|
||||
curves = EmptyCurves;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>Area</code> class creates an area geometry from the
|
||||
* specified {@link Shape} object. The geometry is explicitly
|
||||
* closed, if the <code>Shape</code> is not already closed. The
|
||||
* fill rule (even-odd or winding) specified by the geometry of the
|
||||
* <code>Shape</code> is used to determine the resulting enclosed area.
|
||||
* @param s the <code>Shape</code> from which the area is constructed
|
||||
* @throws NullPointerException if <code>s</code> is null
|
||||
* @since 1.2
|
||||
*/
|
||||
public Area(Shape s) {
|
||||
if (s instanceof Area) {
|
||||
curves = ((Area) s).curves;
|
||||
} else {
|
||||
curves = pathToCurves(s.getPathIterator(null));
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector pathToCurves(PathIterator pi) {
|
||||
Vector curves = new Vector();
|
||||
int windingRule = pi.getWindingRule();
|
||||
// coords array is big enough for holding:
|
||||
// coordinates returned from currentSegment (6)
|
||||
// OR
|
||||
// two subdivided quadratic curves (2+4+4=10)
|
||||
// AND
|
||||
// 0-1 horizontal splitting parameters
|
||||
// OR
|
||||
// 2 parametric equation derivative coefficients
|
||||
// OR
|
||||
// three subdivided cubic curves (2+6+6+6=20)
|
||||
// AND
|
||||
// 0-2 horizontal splitting parameters
|
||||
// OR
|
||||
// 3 parametric equation derivative coefficients
|
||||
double coords[] = new double[23];
|
||||
double movx = 0, movy = 0;
|
||||
double curx = 0, cury = 0;
|
||||
double newx, newy;
|
||||
while (!pi.isDone()) {
|
||||
switch (pi.currentSegment(coords)) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
Curve.insertLine(curves, curx, cury, movx, movy);
|
||||
curx = movx = coords[0];
|
||||
cury = movy = coords[1];
|
||||
Curve.insertMove(curves, movx, movy);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
newx = coords[0];
|
||||
newy = coords[1];
|
||||
Curve.insertLine(curves, curx, cury, newx, newy);
|
||||
curx = newx;
|
||||
cury = newy;
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
newx = coords[2];
|
||||
newy = coords[3];
|
||||
Curve.insertQuad(curves, curx, cury, coords);
|
||||
curx = newx;
|
||||
cury = newy;
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
newx = coords[4];
|
||||
newy = coords[5];
|
||||
Curve.insertCubic(curves, curx, cury, coords);
|
||||
curx = newx;
|
||||
cury = newy;
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
Curve.insertLine(curves, curx, cury, movx, movy);
|
||||
curx = movx;
|
||||
cury = movy;
|
||||
break;
|
||||
}
|
||||
pi.next();
|
||||
}
|
||||
Curve.insertLine(curves, curx, cury, movx, movy);
|
||||
AreaOp operator;
|
||||
if (windingRule == PathIterator.WIND_EVEN_ODD) {
|
||||
operator = new AreaOp.EOWindOp();
|
||||
} else {
|
||||
operator = new AreaOp.NZWindOp();
|
||||
}
|
||||
return operator.calculate(curves, EmptyCurves);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the shape of the specified <code>Area</code> to the
|
||||
* shape of this <code>Area</code>.
|
||||
* The resulting shape of this <code>Area</code> will include
|
||||
* the union of both shapes, or all areas that were contained
|
||||
* in either this or the specified <code>Area</code>.
|
||||
* <pre>
|
||||
* // Example:
|
||||
* Area a1 = new Area([triangle 0,0 => 8,0 => 0,8]);
|
||||
* Area a2 = new Area([triangle 0,0 => 8,0 => 8,8]);
|
||||
* a1.add(a2);
|
||||
*
|
||||
* a1(before) + a2 = a1(after)
|
||||
*
|
||||
* ################ ################ ################
|
||||
* ############## ############## ################
|
||||
* ############ ############ ################
|
||||
* ########## ########## ################
|
||||
* ######## ######## ################
|
||||
* ###### ###### ###### ######
|
||||
* #### #### #### ####
|
||||
* ## ## ## ##
|
||||
* </pre>
|
||||
* @param rhs the <code>Area</code> to be added to the
|
||||
* current shape
|
||||
* @throws NullPointerException if <code>rhs</code> is null
|
||||
* @since 1.2
|
||||
*/
|
||||
public void add(Area rhs) {
|
||||
curves = new AreaOp.AddOp().calculate(this.curves, rhs.curves);
|
||||
invalidateBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the shape of the specified <code>Area</code> from the
|
||||
* shape of this <code>Area</code>.
|
||||
* The resulting shape of this <code>Area</code> will include
|
||||
* areas that were contained only in this <code>Area</code>
|
||||
* and not in the specified <code>Area</code>.
|
||||
* <pre>
|
||||
* // Example:
|
||||
* Area a1 = new Area([triangle 0,0 => 8,0 => 0,8]);
|
||||
* Area a2 = new Area([triangle 0,0 => 8,0 => 8,8]);
|
||||
* a1.subtract(a2);
|
||||
*
|
||||
* a1(before) - a2 = a1(after)
|
||||
*
|
||||
* ################ ################
|
||||
* ############## ############## ##
|
||||
* ############ ############ ####
|
||||
* ########## ########## ######
|
||||
* ######## ######## ########
|
||||
* ###### ###### ######
|
||||
* #### #### ####
|
||||
* ## ## ##
|
||||
* </pre>
|
||||
* @param rhs the <code>Area</code> to be subtracted from the
|
||||
* current shape
|
||||
* @throws NullPointerException if <code>rhs</code> is null
|
||||
* @since 1.2
|
||||
*/
|
||||
public void subtract(Area rhs) {
|
||||
curves = new AreaOp.SubOp().calculate(this.curves, rhs.curves);
|
||||
invalidateBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the shape of this <code>Area</code> to the intersection of
|
||||
* its current shape and the shape of the specified <code>Area</code>.
|
||||
* The resulting shape of this <code>Area</code> will include
|
||||
* only areas that were contained in both this <code>Area</code>
|
||||
* and also in the specified <code>Area</code>.
|
||||
* <pre>
|
||||
* // Example:
|
||||
* Area a1 = new Area([triangle 0,0 => 8,0 => 0,8]);
|
||||
* Area a2 = new Area([triangle 0,0 => 8,0 => 8,8]);
|
||||
* a1.intersect(a2);
|
||||
*
|
||||
* a1(before) intersect a2 = a1(after)
|
||||
*
|
||||
* ################ ################ ################
|
||||
* ############## ############## ############
|
||||
* ############ ############ ########
|
||||
* ########## ########## ####
|
||||
* ######## ########
|
||||
* ###### ######
|
||||
* #### ####
|
||||
* ## ##
|
||||
* </pre>
|
||||
* @param rhs the <code>Area</code> to be intersected with this
|
||||
* <code>Area</code>
|
||||
* @throws NullPointerException if <code>rhs</code> is null
|
||||
* @since 1.2
|
||||
*/
|
||||
public void intersect(Area rhs) {
|
||||
curves = new AreaOp.IntOp().calculate(this.curves, rhs.curves);
|
||||
invalidateBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the shape of this <code>Area</code> to be the combined area
|
||||
* of its current shape and the shape of the specified <code>Area</code>,
|
||||
* minus their intersection.
|
||||
* The resulting shape of this <code>Area</code> will include
|
||||
* only areas that were contained in either this <code>Area</code>
|
||||
* or in the specified <code>Area</code>, but not in both.
|
||||
* <pre>
|
||||
* // Example:
|
||||
* Area a1 = new Area([triangle 0,0 => 8,0 => 0,8]);
|
||||
* Area a2 = new Area([triangle 0,0 => 8,0 => 8,8]);
|
||||
* a1.exclusiveOr(a2);
|
||||
*
|
||||
* a1(before) xor a2 = a1(after)
|
||||
*
|
||||
* ################ ################
|
||||
* ############## ############## ## ##
|
||||
* ############ ############ #### ####
|
||||
* ########## ########## ###### ######
|
||||
* ######## ######## ################
|
||||
* ###### ###### ###### ######
|
||||
* #### #### #### ####
|
||||
* ## ## ## ##
|
||||
* </pre>
|
||||
* @param rhs the <code>Area</code> to be exclusive ORed with this
|
||||
* <code>Area</code>.
|
||||
* @throws NullPointerException if <code>rhs</code> is null
|
||||
* @since 1.2
|
||||
*/
|
||||
public void exclusiveOr(Area rhs) {
|
||||
curves = new AreaOp.XorOp().calculate(this.curves, rhs.curves);
|
||||
invalidateBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the geometry from this <code>Area</code> and
|
||||
* restores it to an empty area.
|
||||
* @since 1.2
|
||||
*/
|
||||
public void reset() {
|
||||
curves = new Vector();
|
||||
invalidateBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this <code>Area</code> object encloses any area.
|
||||
* @return <code>true</code> if this <code>Area</code> object
|
||||
* represents an empty area; <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (curves.size() == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this <code>Area</code> consists entirely of
|
||||
* straight edged polygonal geometry.
|
||||
* @return <code>true</code> if the geometry of this
|
||||
* <code>Area</code> consists entirely of line segments;
|
||||
* <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isPolygonal() {
|
||||
Enumeration enum_ = curves.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
if (((Curve) enum_.nextElement()).getOrder() > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this <code>Area</code> is rectangular in shape.
|
||||
* @return <code>true</code> if the geometry of this
|
||||
* <code>Area</code> is rectangular in shape; <code>false</code>
|
||||
* otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isRectangular() {
|
||||
int size = curves.size();
|
||||
if (size == 0) {
|
||||
return true;
|
||||
}
|
||||
if (size > 3) {
|
||||
return false;
|
||||
}
|
||||
Curve c1 = (Curve) curves.get(1);
|
||||
Curve c2 = (Curve) curves.get(2);
|
||||
if (c1.getOrder() != 1 || c2.getOrder() != 1) {
|
||||
return false;
|
||||
}
|
||||
if (c1.getXTop() != c1.getXBot() || c2.getXTop() != c2.getXBot()) {
|
||||
return false;
|
||||
}
|
||||
if (c1.getYTop() != c2.getYTop() || c1.getYBot() != c2.getYBot()) {
|
||||
// One might be able to prove that this is impossible...
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this <code>Area</code> is comprised of a single
|
||||
* closed subpath. This method returns <code>true</code> if the
|
||||
* path contains 0 or 1 subpaths, or <code>false</code> if the path
|
||||
* contains more than 1 subpath. The subpaths are counted by the
|
||||
* number of {@link PathIterator#SEG_MOVETO SEG_MOVETO} segments
|
||||
* that appear in the path.
|
||||
* @return <code>true</code> if the <code>Area</code> is comprised
|
||||
* of a single basic geometry; <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isSingular() {
|
||||
if (curves.size() < 3) {
|
||||
return true;
|
||||
}
|
||||
Enumeration enum_ = curves.elements();
|
||||
enum_.nextElement(); // First Order0 "moveto"
|
||||
while (enum_.hasMoreElements()) {
|
||||
if (((Curve) enum_.nextElement()).getOrder() == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Rectangle2D cachedBounds;
|
||||
private void invalidateBounds() {
|
||||
cachedBounds = null;
|
||||
}
|
||||
private Rectangle2D getCachedBounds() {
|
||||
if (cachedBounds != null) {
|
||||
return cachedBounds;
|
||||
}
|
||||
Rectangle2D r = new Rectangle2D.Double();
|
||||
if (curves.size() > 0) {
|
||||
Curve c = (Curve) curves.get(0);
|
||||
// First point is always an order 0 curve (moveto)
|
||||
r.setRect(c.getX0(), c.getY0(), 0, 0);
|
||||
for (int i = 1; i < curves.size(); i++) {
|
||||
((Curve) curves.get(i)).enlarge(r);
|
||||
}
|
||||
}
|
||||
return (cachedBounds = r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a high precision bounding {@link Rectangle2D} that
|
||||
* completely encloses this <code>Area</code>.
|
||||
* <p>
|
||||
* The Area class will attempt to return the tightest bounding
|
||||
* box possible for the Shape. The bounding box will not be
|
||||
* padded to include the control points of curves in the outline
|
||||
* of the Shape, but should tightly fit the actual geometry of
|
||||
* the outline itself.
|
||||
* @return the bounding <code>Rectangle2D</code> for the
|
||||
* <code>Area</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return getCachedBounds().getBounds2D();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bounding {@link Rectangle} that completely encloses
|
||||
* this <code>Area</code>.
|
||||
* <p>
|
||||
* The Area class will attempt to return the tightest bounding
|
||||
* box possible for the Shape. The bounding box will not be
|
||||
* padded to include the control points of curves in the outline
|
||||
* of the Shape, but should tightly fit the actual geometry of
|
||||
* the outline itself. Since the returned object represents
|
||||
* the bounding box with integers, the bounding box can only be
|
||||
* as tight as the nearest integer coordinates that encompass
|
||||
* the geometry of the Shape.
|
||||
* @return the bounding <code>Rectangle</code> for the
|
||||
* <code>Area</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle getBounds() {
|
||||
return getCachedBounds().getBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an exact copy of this <code>Area</code> object.
|
||||
* @return Created clone object
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object clone() {
|
||||
return new Area(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the geometries of the two <code>Area</code> objects
|
||||
* are equal.
|
||||
* This method will return false if the argument is null.
|
||||
* @param other the <code>Area</code> to be compared to this
|
||||
* <code>Area</code>
|
||||
* @return <code>true</code> if the two geometries are equal;
|
||||
* <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean equals(Area other) {
|
||||
// REMIND: A *much* simpler operation should be possible...
|
||||
// Should be able to do a curve-wise comparison since all Areas
|
||||
// should evaluate their curves in the same top-down order.
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
Vector c = new AreaOp.XorOp().calculate(this.curves, other.curves);
|
||||
return c.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the geometry of this <code>Area</code> using the specified
|
||||
* {@link AffineTransform}. The geometry is transformed in place, which
|
||||
* permanently changes the enclosed area defined by this object.
|
||||
* @param t the transformation used to transform the area
|
||||
* @throws NullPointerException if <code>t</code> is null
|
||||
* @since 1.2
|
||||
*/
|
||||
public void transform(AffineTransform t) {
|
||||
if (t == null) {
|
||||
throw new NullPointerException("transform must not be null");
|
||||
}
|
||||
// REMIND: A simpler operation can be performed for some types
|
||||
// of transform.
|
||||
curves = pathToCurves(getPathIterator(t));
|
||||
invalidateBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Area</code> object that contains the same
|
||||
* geometry as this <code>Area</code> transformed by the specified
|
||||
* <code>AffineTransform</code>. This <code>Area</code> object
|
||||
* is unchanged.
|
||||
* @param t the specified <code>AffineTransform</code> used to transform
|
||||
* the new <code>Area</code>
|
||||
* @throws NullPointerException if <code>t</code> is null
|
||||
* @return a new <code>Area</code> object representing the transformed
|
||||
* geometry.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Area createTransformedArea(AffineTransform t) {
|
||||
Area a = new Area(this);
|
||||
a.transform(t);
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y) {
|
||||
if (!getCachedBounds().contains(x, y)) {
|
||||
return false;
|
||||
}
|
||||
Enumeration enum_ = curves.elements();
|
||||
int crossings = 0;
|
||||
while (enum_.hasMoreElements()) {
|
||||
Curve c = (Curve) enum_.nextElement();
|
||||
crossings += c.crossingsFor(x, y);
|
||||
}
|
||||
return ((crossings & 1) == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(Point2D p) {
|
||||
return contains(p.getX(), p.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y, double w, double h) {
|
||||
if (w < 0 || h < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!getCachedBounds().contains(x, y, w, h)) {
|
||||
return false;
|
||||
}
|
||||
Crossings c = Crossings.findCrossings(curves, x, y, x+w, y+h);
|
||||
return (c != null && c.covers(y, y+h));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(Rectangle2D r) {
|
||||
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersects(double x, double y, double w, double h) {
|
||||
if (w < 0 || h < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!getCachedBounds().intersects(x, y, w, h)) {
|
||||
return false;
|
||||
}
|
||||
Crossings c = Crossings.findCrossings(curves, x, y, x+w, y+h);
|
||||
return (c == null || !c.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersects(Rectangle2D r) {
|
||||
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PathIterator} for the outline of this
|
||||
* <code>Area</code> object. This <code>Area</code> object is unchanged.
|
||||
* @param at an optional <code>AffineTransform</code> to be applied to
|
||||
* the coordinates as they are returned in the iteration, or
|
||||
* <code>null</code> if untransformed coordinates are desired
|
||||
* @return the <code>PathIterator</code> object that returns the
|
||||
* geometry of the outline of this <code>Area</code>, one
|
||||
* segment at a time.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at) {
|
||||
return new AreaIterator(curves, at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>PathIterator</code> for the flattened outline of
|
||||
* this <code>Area</code> object. Only uncurved path segments
|
||||
* represented by the SEG_MOVETO, SEG_LINETO, and SEG_CLOSE point
|
||||
* types are returned by the iterator. This <code>Area</code>
|
||||
* object is unchanged.
|
||||
* @param at an optional <code>AffineTransform</code> to be
|
||||
* applied to the coordinates as they are returned in the
|
||||
* iteration, or <code>null</code> if untransformed coordinates
|
||||
* are desired
|
||||
* @param flatness the maximum amount that the control points
|
||||
* for a given curve can vary from colinear before a subdivided
|
||||
* curve is replaced by a straight line connecting the end points
|
||||
* @return the <code>PathIterator</code> object that returns the
|
||||
* geometry of the outline of this <code>Area</code>, one segment
|
||||
* at a time.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(at), flatness);
|
||||
}
|
||||
}
|
||||
|
||||
class AreaIterator implements PathIterator {
|
||||
private AffineTransform transform;
|
||||
private Vector curves;
|
||||
private int index;
|
||||
private Curve prevcurve;
|
||||
private Curve thiscurve;
|
||||
|
||||
public AreaIterator(Vector curves, AffineTransform at) {
|
||||
this.curves = curves;
|
||||
this.transform = at;
|
||||
if (curves.size() >= 1) {
|
||||
thiscurve = (Curve) curves.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public int getWindingRule() {
|
||||
// REMIND: Which is better, EVEN_ODD or NON_ZERO?
|
||||
// The paths calculated could be classified either way.
|
||||
//return WIND_EVEN_ODD;
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return (prevcurve == null && thiscurve == null);
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (prevcurve != null) {
|
||||
prevcurve = null;
|
||||
} else {
|
||||
prevcurve = thiscurve;
|
||||
index++;
|
||||
if (index < curves.size()) {
|
||||
thiscurve = (Curve) curves.get(index);
|
||||
if (thiscurve.getOrder() != 0 &&
|
||||
prevcurve.getX1() == thiscurve.getX0() &&
|
||||
prevcurve.getY1() == thiscurve.getY0())
|
||||
{
|
||||
prevcurve = null;
|
||||
}
|
||||
} else {
|
||||
thiscurve = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int currentSegment(float coords[]) {
|
||||
double dcoords[] = new double[6];
|
||||
int segtype = currentSegment(dcoords);
|
||||
int numpoints = (segtype == SEG_CLOSE ? 0
|
||||
: (segtype == SEG_QUADTO ? 2
|
||||
: (segtype == SEG_CUBICTO ? 3
|
||||
: 1)));
|
||||
for (int i = 0; i < numpoints * 2; i++) {
|
||||
coords[i] = (float) dcoords[i];
|
||||
}
|
||||
return segtype;
|
||||
}
|
||||
|
||||
public int currentSegment(double coords[]) {
|
||||
int segtype;
|
||||
int numpoints;
|
||||
if (prevcurve != null) {
|
||||
// Need to finish off junction between curves
|
||||
if (thiscurve == null || thiscurve.getOrder() == 0) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
coords[0] = thiscurve.getX0();
|
||||
coords[1] = thiscurve.getY0();
|
||||
segtype = SEG_LINETO;
|
||||
numpoints = 1;
|
||||
} else if (thiscurve == null) {
|
||||
throw new NoSuchElementException("area iterator out of bounds");
|
||||
} else {
|
||||
segtype = thiscurve.getSegment(coords);
|
||||
numpoints = thiscurve.getOrder();
|
||||
if (numpoints == 0) {
|
||||
numpoints = 1;
|
||||
}
|
||||
}
|
||||
if (transform != null) {
|
||||
transform.transform(coords, 0, coords, 0, numpoints);
|
||||
}
|
||||
return segtype;
|
||||
}
|
||||
}
|
1575
jdkSrc/jdk8/java/awt/geom/CubicCurve2D.java
Normal file
1575
jdkSrc/jdk8/java/awt/geom/CubicCurve2D.java
Normal file
File diff suppressed because it is too large
Load Diff
156
jdkSrc/jdk8/java/awt/geom/CubicIterator.java
Normal file
156
jdkSrc/jdk8/java/awt/geom/CubicIterator.java
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of a cubic curve
|
||||
* segment through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class CubicIterator implements PathIterator {
|
||||
CubicCurve2D cubic;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
|
||||
CubicIterator(CubicCurve2D q, AffineTransform at) {
|
||||
this.cubic = q;
|
||||
this.affine = at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return (index > 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("cubic iterator iterator out of bounds");
|
||||
}
|
||||
int type;
|
||||
if (index == 0) {
|
||||
coords[0] = (float) cubic.getX1();
|
||||
coords[1] = (float) cubic.getY1();
|
||||
type = SEG_MOVETO;
|
||||
} else {
|
||||
coords[0] = (float) cubic.getCtrlX1();
|
||||
coords[1] = (float) cubic.getCtrlY1();
|
||||
coords[2] = (float) cubic.getCtrlX2();
|
||||
coords[3] = (float) cubic.getCtrlY2();
|
||||
coords[4] = (float) cubic.getX2();
|
||||
coords[5] = (float) cubic.getY2();
|
||||
type = SEG_CUBICTO;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, index == 0 ? 1 : 3);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("cubic iterator iterator out of bounds");
|
||||
}
|
||||
int type;
|
||||
if (index == 0) {
|
||||
coords[0] = cubic.getX1();
|
||||
coords[1] = cubic.getY1();
|
||||
type = SEG_MOVETO;
|
||||
} else {
|
||||
coords[0] = cubic.getCtrlX1();
|
||||
coords[1] = cubic.getCtrlY1();
|
||||
coords[2] = cubic.getCtrlX2();
|
||||
coords[3] = cubic.getCtrlY2();
|
||||
coords[4] = cubic.getX2();
|
||||
coords[5] = cubic.getY2();
|
||||
type = SEG_CUBICTO;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, index == 0 ? 1 : 3);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
114
jdkSrc/jdk8/java/awt/geom/Dimension2D.java
Normal file
114
jdkSrc/jdk8/java/awt/geom/Dimension2D.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
/**
|
||||
* The <code>Dimension2D</code> class is to encapsulate a width
|
||||
* and a height dimension.
|
||||
* <p>
|
||||
* This class is only the abstract superclass for all objects that
|
||||
* store a 2D dimension.
|
||||
* The actual storage representation of the sizes is left to
|
||||
* the subclass.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract class Dimension2D implements Cloneable {
|
||||
|
||||
/**
|
||||
* This is an abstract class that cannot be instantiated directly.
|
||||
* Type-specific implementation subclasses are available for
|
||||
* instantiation and provide a number of formats for storing
|
||||
* the information necessary to satisfy the various accessor
|
||||
* methods below.
|
||||
*
|
||||
* @see java.awt.Dimension
|
||||
* @since 1.2
|
||||
*/
|
||||
protected Dimension2D() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of this <code>Dimension</code> in double
|
||||
* precision.
|
||||
* @return the width of this <code>Dimension</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getWidth();
|
||||
|
||||
/**
|
||||
* Returns the height of this <code>Dimension</code> in double
|
||||
* precision.
|
||||
* @return the height of this <code>Dimension</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getHeight();
|
||||
|
||||
/**
|
||||
* Sets the size of this <code>Dimension</code> object to the
|
||||
* specified width and height.
|
||||
* This method is included for completeness, to parallel the
|
||||
* {@link java.awt.Component#getSize getSize} method of
|
||||
* {@link java.awt.Component}.
|
||||
* @param width the new width for the <code>Dimension</code>
|
||||
* object
|
||||
* @param height the new height for the <code>Dimension</code>
|
||||
* object
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract void setSize(double width, double height);
|
||||
|
||||
/**
|
||||
* Sets the size of this <code>Dimension2D</code> object to
|
||||
* match the specified size.
|
||||
* This method is included for completeness, to parallel the
|
||||
* <code>getSize</code> method of <code>Component</code>.
|
||||
* @param d the new size for the <code>Dimension2D</code>
|
||||
* object
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setSize(Dimension2D d) {
|
||||
setSize(d.getWidth(), d.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object of the same class as this object.
|
||||
*
|
||||
* @return a clone of this instance.
|
||||
* @exception OutOfMemoryError if there is not enough memory.
|
||||
* @see java.lang.Cloneable
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// this shouldn't happen, since we are Cloneable
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
}
|
464
jdkSrc/jdk8/java/awt/geom/Ellipse2D.java
Normal file
464
jdkSrc/jdk8/java/awt/geom/Ellipse2D.java
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The <code>Ellipse2D</code> class describes an ellipse that is defined
|
||||
* by a framing rectangle.
|
||||
* <p>
|
||||
* This class is only the abstract superclass for all objects which
|
||||
* store a 2D ellipse.
|
||||
* The actual storage representation of the coordinates is left to
|
||||
* the subclass.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract class Ellipse2D extends RectangularShape {
|
||||
|
||||
/**
|
||||
* The <code>Float</code> class defines an ellipse specified
|
||||
* in <code>float</code> precision.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Float extends Ellipse2D implements Serializable {
|
||||
/**
|
||||
* The X coordinate of the upper-left corner of the
|
||||
* framing rectangle of this {@code Ellipse2D}.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of the upper-left corner of the
|
||||
* framing rectangle of this {@code Ellipse2D}.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float y;
|
||||
|
||||
/**
|
||||
* The overall width of this <code>Ellipse2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float width;
|
||||
|
||||
/**
|
||||
* The overall height of this <code>Ellipse2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float height;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Ellipse2D</code>, initialized to
|
||||
* location (0, 0) and size (0, 0).
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes an <code>Ellipse2D</code> from the
|
||||
* specified coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of the framing rectangle
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of the framing rectangle
|
||||
* @param w the width of the framing rectangle
|
||||
* @param h the height of the framing rectangle
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float(float x, float y, float w, float h) {
|
||||
setFrame(x, y, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return (double) x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return (double) y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getWidth() {
|
||||
return (double) width;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getHeight() {
|
||||
return (double) height;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (width <= 0.0 || height <= 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location and size of the framing rectangle of this
|
||||
* <code>Shape</code> to the specified rectangular values.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner of the
|
||||
* specified rectangular shape
|
||||
* @param y the Y coordinate of the upper-left corner of the
|
||||
* specified rectangular shape
|
||||
* @param w the width of the specified rectangular shape
|
||||
* @param h the height of the specified rectangular shape
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(float x, float y, float w, float h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(double x, double y, double w, double h) {
|
||||
this.x = (float) x;
|
||||
this.y = (float) y;
|
||||
this.width = (float) w;
|
||||
this.height = (float) h;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return new Rectangle2D.Float(x, y, width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -6633761252372475977L;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>Double</code> class defines an ellipse specified
|
||||
* in <code>double</code> precision.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Double extends Ellipse2D implements Serializable {
|
||||
/**
|
||||
* The X coordinate of the upper-left corner of the
|
||||
* framing rectangle of this {@code Ellipse2D}.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of the upper-left corner of the
|
||||
* framing rectangle of this {@code Ellipse2D}.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double y;
|
||||
|
||||
/**
|
||||
* The overall width of this <code>Ellipse2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double width;
|
||||
|
||||
/**
|
||||
* The overall height of the <code>Ellipse2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double height;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Ellipse2D</code>, initialized to
|
||||
* location (0, 0) and size (0, 0).
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes an <code>Ellipse2D</code> from the
|
||||
* specified coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of the framing rectangle
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of the framing rectangle
|
||||
* @param w the width of the framing rectangle
|
||||
* @param h the height of the framing rectangle
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double(double x, double y, double w, double h) {
|
||||
setFrame(x, y, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (width <= 0.0 || height <= 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(double x, double y, double w, double h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return new Rectangle2D.Double(x, y, width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 5555464816372320683L;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an abstract class that cannot be instantiated directly.
|
||||
* Type-specific implementation subclasses are available for
|
||||
* instantiation and provide a number of formats for storing
|
||||
* the information necessary to satisfy the various accessor
|
||||
* methods below.
|
||||
*
|
||||
* @see java.awt.geom.Ellipse2D.Float
|
||||
* @see java.awt.geom.Ellipse2D.Double
|
||||
* @since 1.2
|
||||
*/
|
||||
protected Ellipse2D() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y) {
|
||||
// Normalize the coordinates compared to the ellipse
|
||||
// having a center at 0,0 and a radius of 0.5.
|
||||
double ellw = getWidth();
|
||||
if (ellw <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
double normx = (x - getX()) / ellw - 0.5;
|
||||
double ellh = getHeight();
|
||||
if (ellh <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
double normy = (y - getY()) / ellh - 0.5;
|
||||
return (normx * normx + normy * normy) < 0.25;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersects(double x, double y, double w, double h) {
|
||||
if (w <= 0.0 || h <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
// Normalize the rectangular coordinates compared to the ellipse
|
||||
// having a center at 0,0 and a radius of 0.5.
|
||||
double ellw = getWidth();
|
||||
if (ellw <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
double normx0 = (x - getX()) / ellw - 0.5;
|
||||
double normx1 = normx0 + w / ellw;
|
||||
double ellh = getHeight();
|
||||
if (ellh <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
double normy0 = (y - getY()) / ellh - 0.5;
|
||||
double normy1 = normy0 + h / ellh;
|
||||
// find nearest x (left edge, right edge, 0.0)
|
||||
// find nearest y (top edge, bottom edge, 0.0)
|
||||
// if nearest x,y is inside circle of radius 0.5, then intersects
|
||||
double nearx, neary;
|
||||
if (normx0 > 0.0) {
|
||||
// center to left of X extents
|
||||
nearx = normx0;
|
||||
} else if (normx1 < 0.0) {
|
||||
// center to right of X extents
|
||||
nearx = normx1;
|
||||
} else {
|
||||
nearx = 0.0;
|
||||
}
|
||||
if (normy0 > 0.0) {
|
||||
// center above Y extents
|
||||
neary = normy0;
|
||||
} else if (normy1 < 0.0) {
|
||||
// center below Y extents
|
||||
neary = normy1;
|
||||
} else {
|
||||
neary = 0.0;
|
||||
}
|
||||
return (nearx * nearx + neary * neary) < 0.25;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y, double w, double h) {
|
||||
return (contains(x, y) &&
|
||||
contains(x + w, y) &&
|
||||
contains(x, y + h) &&
|
||||
contains(x + w, y + h));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iteration object that defines the boundary of this
|
||||
* <code>Ellipse2D</code>.
|
||||
* The iterator for this class is multi-threaded safe, which means
|
||||
* that this <code>Ellipse2D</code> class guarantees that
|
||||
* modifications to the geometry of this <code>Ellipse2D</code>
|
||||
* object do not affect any iterations of that geometry that
|
||||
* are already in process.
|
||||
* @param at an optional <code>AffineTransform</code> to be applied to
|
||||
* the coordinates as they are returned in the iteration, or
|
||||
* <code>null</code> if untransformed coordinates are desired
|
||||
* @return the <code>PathIterator</code> object that returns the
|
||||
* geometry of the outline of this <code>Ellipse2D</code>,
|
||||
* one segment at a time.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at) {
|
||||
return new EllipseIterator(this, at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashcode for this <code>Ellipse2D</code>.
|
||||
* @return the hashcode for this <code>Ellipse2D</code>.
|
||||
* @since 1.6
|
||||
*/
|
||||
public int hashCode() {
|
||||
long bits = java.lang.Double.doubleToLongBits(getX());
|
||||
bits += java.lang.Double.doubleToLongBits(getY()) * 37;
|
||||
bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
|
||||
bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
|
||||
return (((int) bits) ^ ((int) (bits >> 32)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the specified <code>Object</code> is
|
||||
* equal to this <code>Ellipse2D</code>. The specified
|
||||
* <code>Object</code> is equal to this <code>Ellipse2D</code>
|
||||
* if it is an instance of <code>Ellipse2D</code> and if its
|
||||
* location and size are the same as this <code>Ellipse2D</code>.
|
||||
* @param obj an <code>Object</code> to be compared with this
|
||||
* <code>Ellipse2D</code>.
|
||||
* @return <code>true</code> if <code>obj</code> is an instance
|
||||
* of <code>Ellipse2D</code> and has the same values;
|
||||
* <code>false</code> otherwise.
|
||||
* @since 1.6
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Ellipse2D) {
|
||||
Ellipse2D e2d = (Ellipse2D) obj;
|
||||
return ((getX() == e2d.getX()) &&
|
||||
(getY() == e2d.getY()) &&
|
||||
(getWidth() == e2d.getWidth()) &&
|
||||
(getHeight() == e2d.getHeight()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
189
jdkSrc/jdk8/java/awt/geom/EllipseIterator.java
Normal file
189
jdkSrc/jdk8/java/awt/geom/EllipseIterator.java
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of an ellipse
|
||||
* through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class EllipseIterator implements PathIterator {
|
||||
double x, y, w, h;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
|
||||
EllipseIterator(Ellipse2D e, AffineTransform at) {
|
||||
this.x = e.getX();
|
||||
this.y = e.getY();
|
||||
this.w = e.getWidth();
|
||||
this.h = e.getHeight();
|
||||
this.affine = at;
|
||||
if (w < 0 || h < 0) {
|
||||
index = 6;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return index > 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
// ArcIterator.btan(Math.PI/2)
|
||||
public static final double CtrlVal = 0.5522847498307933;
|
||||
|
||||
/*
|
||||
* ctrlpts contains the control points for a set of 4 cubic
|
||||
* bezier curves that approximate a circle of radius 0.5
|
||||
* centered at 0.5, 0.5
|
||||
*/
|
||||
private static final double pcv = 0.5 + CtrlVal * 0.5;
|
||||
private static final double ncv = 0.5 - CtrlVal * 0.5;
|
||||
private static double ctrlpts[][] = {
|
||||
{ 1.0, pcv, pcv, 1.0, 0.5, 1.0 },
|
||||
{ ncv, 1.0, 0.0, pcv, 0.0, 0.5 },
|
||||
{ 0.0, ncv, ncv, 0.0, 0.5, 0.0 },
|
||||
{ pcv, 0.0, 1.0, ncv, 1.0, 0.5 }
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("ellipse iterator out of bounds");
|
||||
}
|
||||
if (index == 5) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
if (index == 0) {
|
||||
double ctrls[] = ctrlpts[3];
|
||||
coords[0] = (float) (x + ctrls[4] * w);
|
||||
coords[1] = (float) (y + ctrls[5] * h);
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return SEG_MOVETO;
|
||||
}
|
||||
double ctrls[] = ctrlpts[index - 1];
|
||||
coords[0] = (float) (x + ctrls[0] * w);
|
||||
coords[1] = (float) (y + ctrls[1] * h);
|
||||
coords[2] = (float) (x + ctrls[2] * w);
|
||||
coords[3] = (float) (y + ctrls[3] * h);
|
||||
coords[4] = (float) (x + ctrls[4] * w);
|
||||
coords[5] = (float) (y + ctrls[5] * h);
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 3);
|
||||
}
|
||||
return SEG_CUBICTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("ellipse iterator out of bounds");
|
||||
}
|
||||
if (index == 5) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
if (index == 0) {
|
||||
double ctrls[] = ctrlpts[3];
|
||||
coords[0] = x + ctrls[4] * w;
|
||||
coords[1] = y + ctrls[5] * h;
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return SEG_MOVETO;
|
||||
}
|
||||
double ctrls[] = ctrlpts[index - 1];
|
||||
coords[0] = x + ctrls[0] * w;
|
||||
coords[1] = y + ctrls[1] * h;
|
||||
coords[2] = x + ctrls[2] * w;
|
||||
coords[3] = y + ctrls[3] * h;
|
||||
coords[4] = x + ctrls[4] * w;
|
||||
coords[5] = y + ctrls[5] * h;
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 3);
|
||||
}
|
||||
return SEG_CUBICTO;
|
||||
}
|
||||
}
|
395
jdkSrc/jdk8/java/awt/geom/FlatteningPathIterator.java
Normal file
395
jdkSrc/jdk8/java/awt/geom/FlatteningPathIterator.java
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The <code>FlatteningPathIterator</code> class returns a flattened view of
|
||||
* another {@link PathIterator} object. Other {@link java.awt.Shape Shape}
|
||||
* classes can use this class to provide flattening behavior for their paths
|
||||
* without having to perform the interpolation calculations themselves.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
public class FlatteningPathIterator implements PathIterator {
|
||||
static final int GROW_SIZE = 24; // Multiple of cubic & quad curve size
|
||||
|
||||
PathIterator src; // The source iterator
|
||||
|
||||
double squareflat; // Square of the flatness parameter
|
||||
// for testing against squared lengths
|
||||
|
||||
int limit; // Maximum number of recursion levels
|
||||
|
||||
double hold[] = new double[14]; // The cache of interpolated coords
|
||||
// Note that this must be long enough
|
||||
// to store a full cubic segment and
|
||||
// a relative cubic segment to avoid
|
||||
// aliasing when copying the coords
|
||||
// of a curve to the end of the array.
|
||||
// This is also serendipitously equal
|
||||
// to the size of a full quad segment
|
||||
// and 2 relative quad segments.
|
||||
|
||||
double curx, cury; // The ending x,y of the last segment
|
||||
|
||||
double movx, movy; // The x,y of the last move segment
|
||||
|
||||
int holdType; // The type of the curve being held
|
||||
// for interpolation
|
||||
|
||||
int holdEnd; // The index of the last curve segment
|
||||
// being held for interpolation
|
||||
|
||||
int holdIndex; // The index of the curve segment
|
||||
// that was last interpolated. This
|
||||
// is the curve segment ready to be
|
||||
// returned in the next call to
|
||||
// currentSegment().
|
||||
|
||||
int levels[]; // The recursion level at which
|
||||
// each curve being held in storage
|
||||
// was generated.
|
||||
|
||||
int levelIndex; // The index of the entry in the
|
||||
// levels array of the curve segment
|
||||
// at the holdIndex
|
||||
|
||||
boolean done; // True when iteration is done
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FlatteningPathIterator</code> object that
|
||||
* flattens a path as it iterates over it. The iterator does not
|
||||
* subdivide any curve read from the source iterator to more than
|
||||
* 10 levels of subdivision which yields a maximum of 1024 line
|
||||
* segments per curve.
|
||||
* @param src the original unflattened path being iterated over
|
||||
* @param flatness the maximum allowable distance between the
|
||||
* control points and the flattened curve
|
||||
*/
|
||||
public FlatteningPathIterator(PathIterator src, double flatness) {
|
||||
this(src, flatness, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FlatteningPathIterator</code> object
|
||||
* that flattens a path as it iterates over it.
|
||||
* The <code>limit</code> parameter allows you to control the
|
||||
* maximum number of recursive subdivisions that the iterator
|
||||
* can make before it assumes that the curve is flat enough
|
||||
* without measuring against the <code>flatness</code> parameter.
|
||||
* The flattened iteration therefore never generates more than
|
||||
* a maximum of <code>(2^limit)</code> line segments per curve.
|
||||
* @param src the original unflattened path being iterated over
|
||||
* @param flatness the maximum allowable distance between the
|
||||
* control points and the flattened curve
|
||||
* @param limit the maximum number of recursive subdivisions
|
||||
* allowed for any curved segment
|
||||
* @exception IllegalArgumentException if
|
||||
* <code>flatness</code> or <code>limit</code>
|
||||
* is less than zero
|
||||
*/
|
||||
public FlatteningPathIterator(PathIterator src, double flatness,
|
||||
int limit) {
|
||||
if (flatness < 0.0) {
|
||||
throw new IllegalArgumentException("flatness must be >= 0");
|
||||
}
|
||||
if (limit < 0) {
|
||||
throw new IllegalArgumentException("limit must be >= 0");
|
||||
}
|
||||
this.src = src;
|
||||
this.squareflat = flatness * flatness;
|
||||
this.limit = limit;
|
||||
this.levels = new int[limit + 1];
|
||||
// prime the first path segment
|
||||
next(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flatness of this iterator.
|
||||
* @return the flatness of this <code>FlatteningPathIterator</code>.
|
||||
*/
|
||||
public double getFlatness() {
|
||||
return Math.sqrt(squareflat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the recursion limit of this iterator.
|
||||
* @return the recursion limit of this
|
||||
* <code>FlatteningPathIterator</code>.
|
||||
*/
|
||||
public int getRecursionLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the winding rule for determining the interior of the
|
||||
* path.
|
||||
* @return the winding rule of the original unflattened path being
|
||||
* iterated over.
|
||||
* @see PathIterator#WIND_EVEN_ODD
|
||||
* @see PathIterator#WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return src.getWindingRule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the iteration is complete.
|
||||
* @return <code>true</code> if all the segments have
|
||||
* been read; <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures that the hold array can hold up to (want) more values.
|
||||
* It is currently holding (hold.length - holdIndex) values.
|
||||
*/
|
||||
void ensureHoldCapacity(int want) {
|
||||
if (holdIndex - want < 0) {
|
||||
int have = hold.length - holdIndex;
|
||||
int newsize = hold.length + GROW_SIZE;
|
||||
double newhold[] = new double[newsize];
|
||||
System.arraycopy(hold, holdIndex,
|
||||
newhold, holdIndex + GROW_SIZE,
|
||||
have);
|
||||
hold = newhold;
|
||||
holdIndex += GROW_SIZE;
|
||||
holdEnd += GROW_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
next(true);
|
||||
}
|
||||
|
||||
private void next(boolean doNext) {
|
||||
int level;
|
||||
|
||||
if (holdIndex >= holdEnd) {
|
||||
if (doNext) {
|
||||
src.next();
|
||||
}
|
||||
if (src.isDone()) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
holdType = src.currentSegment(hold);
|
||||
levelIndex = 0;
|
||||
levels[0] = 0;
|
||||
}
|
||||
|
||||
switch (holdType) {
|
||||
case SEG_MOVETO:
|
||||
case SEG_LINETO:
|
||||
curx = hold[0];
|
||||
cury = hold[1];
|
||||
if (holdType == SEG_MOVETO) {
|
||||
movx = curx;
|
||||
movy = cury;
|
||||
}
|
||||
holdIndex = 0;
|
||||
holdEnd = 0;
|
||||
break;
|
||||
case SEG_CLOSE:
|
||||
curx = movx;
|
||||
cury = movy;
|
||||
holdIndex = 0;
|
||||
holdEnd = 0;
|
||||
break;
|
||||
case SEG_QUADTO:
|
||||
if (holdIndex >= holdEnd) {
|
||||
// Move the coordinates to the end of the array.
|
||||
holdIndex = hold.length - 6;
|
||||
holdEnd = hold.length - 2;
|
||||
hold[holdIndex + 0] = curx;
|
||||
hold[holdIndex + 1] = cury;
|
||||
hold[holdIndex + 2] = hold[0];
|
||||
hold[holdIndex + 3] = hold[1];
|
||||
hold[holdIndex + 4] = curx = hold[2];
|
||||
hold[holdIndex + 5] = cury = hold[3];
|
||||
}
|
||||
|
||||
level = levels[levelIndex];
|
||||
while (level < limit) {
|
||||
if (QuadCurve2D.getFlatnessSq(hold, holdIndex) < squareflat) {
|
||||
break;
|
||||
}
|
||||
|
||||
ensureHoldCapacity(4);
|
||||
QuadCurve2D.subdivide(hold, holdIndex,
|
||||
hold, holdIndex - 4,
|
||||
hold, holdIndex);
|
||||
holdIndex -= 4;
|
||||
|
||||
// Now that we have subdivided, we have constructed
|
||||
// two curves of one depth lower than the original
|
||||
// curve. One of those curves is in the place of
|
||||
// the former curve and one of them is in the next
|
||||
// set of held coordinate slots. We now set both
|
||||
// curves level values to the next higher level.
|
||||
level++;
|
||||
levels[levelIndex] = level;
|
||||
levelIndex++;
|
||||
levels[levelIndex] = level;
|
||||
}
|
||||
|
||||
// This curve segment is flat enough, or it is too deep
|
||||
// in recursion levels to try to flatten any more. The
|
||||
// two coordinates at holdIndex+4 and holdIndex+5 now
|
||||
// contain the endpoint of the curve which can be the
|
||||
// endpoint of an approximating line segment.
|
||||
holdIndex += 4;
|
||||
levelIndex--;
|
||||
break;
|
||||
case SEG_CUBICTO:
|
||||
if (holdIndex >= holdEnd) {
|
||||
// Move the coordinates to the end of the array.
|
||||
holdIndex = hold.length - 8;
|
||||
holdEnd = hold.length - 2;
|
||||
hold[holdIndex + 0] = curx;
|
||||
hold[holdIndex + 1] = cury;
|
||||
hold[holdIndex + 2] = hold[0];
|
||||
hold[holdIndex + 3] = hold[1];
|
||||
hold[holdIndex + 4] = hold[2];
|
||||
hold[holdIndex + 5] = hold[3];
|
||||
hold[holdIndex + 6] = curx = hold[4];
|
||||
hold[holdIndex + 7] = cury = hold[5];
|
||||
}
|
||||
|
||||
level = levels[levelIndex];
|
||||
while (level < limit) {
|
||||
if (CubicCurve2D.getFlatnessSq(hold, holdIndex) < squareflat) {
|
||||
break;
|
||||
}
|
||||
|
||||
ensureHoldCapacity(6);
|
||||
CubicCurve2D.subdivide(hold, holdIndex,
|
||||
hold, holdIndex - 6,
|
||||
hold, holdIndex);
|
||||
holdIndex -= 6;
|
||||
|
||||
// Now that we have subdivided, we have constructed
|
||||
// two curves of one depth lower than the original
|
||||
// curve. One of those curves is in the place of
|
||||
// the former curve and one of them is in the next
|
||||
// set of held coordinate slots. We now set both
|
||||
// curves level values to the next higher level.
|
||||
level++;
|
||||
levels[levelIndex] = level;
|
||||
levelIndex++;
|
||||
levels[levelIndex] = level;
|
||||
}
|
||||
|
||||
// This curve segment is flat enough, or it is too deep
|
||||
// in recursion levels to try to flatten any more. The
|
||||
// two coordinates at holdIndex+6 and holdIndex+7 now
|
||||
// contain the endpoint of the curve which can be the
|
||||
// endpoint of an approximating line segment.
|
||||
holdIndex += 6;
|
||||
levelIndex--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and can be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types return one point,
|
||||
* and SEG_CLOSE does not return any points.
|
||||
* @param coords an array that holds the data returned from
|
||||
* this method
|
||||
* @return the path segment type of the current path segment.
|
||||
* @exception NoSuchElementException if there
|
||||
* are no more elements in the flattening path to be
|
||||
* returned.
|
||||
* @see PathIterator#SEG_MOVETO
|
||||
* @see PathIterator#SEG_LINETO
|
||||
* @see PathIterator#SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("flattening iterator out of bounds");
|
||||
}
|
||||
int type = holdType;
|
||||
if (type != SEG_CLOSE) {
|
||||
coords[0] = (float) hold[holdIndex + 0];
|
||||
coords[1] = (float) hold[holdIndex + 1];
|
||||
if (type != SEG_MOVETO) {
|
||||
type = SEG_LINETO;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and can be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types return one point,
|
||||
* and SEG_CLOSE does not return any points.
|
||||
* @param coords an array that holds the data returned from
|
||||
* this method
|
||||
* @return the path segment type of the current path segment.
|
||||
* @exception NoSuchElementException if there
|
||||
* are no more elements in the flattening path to be
|
||||
* returned.
|
||||
* @see PathIterator#SEG_MOVETO
|
||||
* @see PathIterator#SEG_LINETO
|
||||
* @see PathIterator#SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("flattening iterator out of bounds");
|
||||
}
|
||||
int type = holdType;
|
||||
if (type != SEG_CLOSE) {
|
||||
coords[0] = hold[holdIndex + 0];
|
||||
coords[1] = hold[holdIndex + 1];
|
||||
if (type != SEG_MOVETO) {
|
||||
type = SEG_LINETO;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
127
jdkSrc/jdk8/java/awt/geom/GeneralPath.java
Normal file
127
jdkSrc/jdk8/java/awt/geom/GeneralPath.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.awt.Shape;
|
||||
|
||||
/**
|
||||
* The {@code GeneralPath} class represents a geometric path
|
||||
* constructed from straight lines, and quadratic and cubic
|
||||
* (Bézier) curves. It can contain multiple subpaths.
|
||||
* <p>
|
||||
* {@code GeneralPath} is a legacy final class which exactly
|
||||
* implements the behavior of its superclass {@link Path2D.Float}.
|
||||
* Together with {@link Path2D.Double}, the {@link Path2D} classes
|
||||
* provide full implementations of a general geometric path that
|
||||
* support all of the functionality of the {@link Shape} and
|
||||
* {@link PathIterator} interfaces with the ability to explicitly
|
||||
* select different levels of internal coordinate precision.
|
||||
* <p>
|
||||
* Use {@code Path2D.Float} (or this legacy {@code GeneralPath}
|
||||
* subclass) when dealing with data that can be represented
|
||||
* and used with floating point precision. Use {@code Path2D.Double}
|
||||
* for data that requires the accuracy or range of double precision.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public final class GeneralPath extends Path2D.Float {
|
||||
/**
|
||||
* Constructs a new empty single precision {@code GeneralPath} object
|
||||
* with a default winding rule of {@link #WIND_NON_ZERO}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public GeneralPath() {
|
||||
super(WIND_NON_ZERO, INIT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>GeneralPath</code> object with the specified
|
||||
* winding rule to control operations that require the interior of the
|
||||
* path to be defined.
|
||||
*
|
||||
* @param rule the winding rule
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
* @since 1.2
|
||||
*/
|
||||
public GeneralPath(int rule) {
|
||||
super(rule, INIT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>GeneralPath</code> object with the specified
|
||||
* winding rule and the specified initial capacity to store path
|
||||
* coordinates.
|
||||
* This number is an initial guess as to how many path segments
|
||||
* will be added to the path, but the storage is expanded as
|
||||
* needed to store whatever path segments are added.
|
||||
*
|
||||
* @param rule the winding rule
|
||||
* @param initialCapacity the estimate for the number of path segments
|
||||
* in the path
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
* @since 1.2
|
||||
*/
|
||||
public GeneralPath(int rule, int initialCapacity) {
|
||||
super(rule, initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>GeneralPath</code> object from an arbitrary
|
||||
* {@link Shape} object.
|
||||
* All of the initial geometry and the winding rule for this path are
|
||||
* taken from the specified <code>Shape</code> object.
|
||||
*
|
||||
* @param s the specified <code>Shape</code> object
|
||||
* @since 1.2
|
||||
*/
|
||||
public GeneralPath(Shape s) {
|
||||
super(s, null);
|
||||
}
|
||||
|
||||
GeneralPath(int windingRule,
|
||||
byte[] pointTypes,
|
||||
int numTypes,
|
||||
float[] pointCoords,
|
||||
int numCoords)
|
||||
{
|
||||
// used to construct from native
|
||||
|
||||
this.windingRule = windingRule;
|
||||
this.pointTypes = pointTypes;
|
||||
this.numTypes = numTypes;
|
||||
this.floatCoords = pointCoords;
|
||||
this.numCoords = numCoords;
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -8327096662768731142L;
|
||||
}
|
56
jdkSrc/jdk8/java/awt/geom/IllegalPathStateException.java
Normal file
56
jdkSrc/jdk8/java/awt/geom/IllegalPathStateException.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
/**
|
||||
* The <code>IllegalPathStateException</code> represents an
|
||||
* exception that is thrown if an operation is performed on a path
|
||||
* that is in an illegal state with respect to the particular
|
||||
* operation being performed, such as appending a path segment
|
||||
* to a {@link GeneralPath} without an initial moveto.
|
||||
*
|
||||
*/
|
||||
|
||||
public class IllegalPathStateException extends RuntimeException {
|
||||
/**
|
||||
* Constructs an <code>IllegalPathStateException</code> with no
|
||||
* detail message.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public IllegalPathStateException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <code>IllegalPathStateException</code> with the
|
||||
* specified detail message.
|
||||
* @param s the detail message
|
||||
* @since 1.2
|
||||
*/
|
||||
public IllegalPathStateException(String s) {
|
||||
super (s);
|
||||
}
|
||||
}
|
1128
jdkSrc/jdk8/java/awt/geom/Line2D.java
Normal file
1128
jdkSrc/jdk8/java/awt/geom/Line2D.java
Normal file
File diff suppressed because it is too large
Load Diff
148
jdkSrc/jdk8/java/awt/geom/LineIterator.java
Normal file
148
jdkSrc/jdk8/java/awt/geom/LineIterator.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of a line segment
|
||||
* through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class LineIterator implements PathIterator {
|
||||
Line2D line;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
|
||||
LineIterator(Line2D l, AffineTransform at) {
|
||||
this.line = l;
|
||||
this.affine = at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return (index > 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("line iterator out of bounds");
|
||||
}
|
||||
int type;
|
||||
if (index == 0) {
|
||||
coords[0] = (float) line.getX1();
|
||||
coords[1] = (float) line.getY1();
|
||||
type = SEG_MOVETO;
|
||||
} else {
|
||||
coords[0] = (float) line.getX2();
|
||||
coords[1] = (float) line.getY2();
|
||||
type = SEG_LINETO;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("line iterator out of bounds");
|
||||
}
|
||||
int type;
|
||||
if (index == 0) {
|
||||
coords[0] = line.getX1();
|
||||
coords[1] = line.getY1();
|
||||
type = SEG_MOVETO;
|
||||
} else {
|
||||
coords[0] = line.getX2();
|
||||
coords[1] = line.getY2();
|
||||
type = SEG_LINETO;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
/**
|
||||
* The <code>NoninvertibleTransformException</code> class represents
|
||||
* an exception that is thrown if an operation is performed requiring
|
||||
* the inverse of an {@link AffineTransform} object but the
|
||||
* <code>AffineTransform</code> is in a non-invertible state.
|
||||
*/
|
||||
|
||||
public class NoninvertibleTransformException extends java.lang.Exception {
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>NoninvertibleTransformException</code>
|
||||
* with the specified detail message.
|
||||
* @param s the detail message
|
||||
* @since 1.2
|
||||
*/
|
||||
public NoninvertibleTransformException(String s) {
|
||||
super (s);
|
||||
}
|
||||
}
|
2706
jdkSrc/jdk8/java/awt/geom/Path2D.java
Normal file
2706
jdkSrc/jdk8/java/awt/geom/Path2D.java
Normal file
File diff suppressed because it is too large
Load Diff
217
jdkSrc/jdk8/java/awt/geom/PathIterator.java
Normal file
217
jdkSrc/jdk8/java/awt/geom/PathIterator.java
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
/**
|
||||
* The <code>PathIterator</code> interface provides the mechanism
|
||||
* for objects that implement the {@link java.awt.Shape Shape}
|
||||
* interface to return the geometry of their boundary by allowing
|
||||
* a caller to retrieve the path of that boundary a segment at a
|
||||
* time. This interface allows these objects to retrieve the path of
|
||||
* their boundary a segment at a time by using 1st through 3rd order
|
||||
* Bézier curves, which are lines and quadratic or cubic
|
||||
* Bézier splines.
|
||||
* <p>
|
||||
* Multiple subpaths can be expressed by using a "MOVETO" segment to
|
||||
* create a discontinuity in the geometry to move from the end of
|
||||
* one subpath to the beginning of the next.
|
||||
* <p>
|
||||
* Each subpath can be closed manually by ending the last segment in
|
||||
* the subpath on the same coordinate as the beginning "MOVETO" segment
|
||||
* for that subpath or by using a "CLOSE" segment to append a line
|
||||
* segment from the last point back to the first.
|
||||
* Be aware that manually closing an outline as opposed to using a
|
||||
* "CLOSE" segment to close the path might result in different line
|
||||
* style decorations being used at the end points of the subpath.
|
||||
* For example, the {@link java.awt.BasicStroke BasicStroke} object
|
||||
* uses a line "JOIN" decoration to connect the first and last points
|
||||
* if a "CLOSE" segment is encountered, whereas simply ending the path
|
||||
* on the same coordinate as the beginning coordinate results in line
|
||||
* "CAP" decorations being used at the ends.
|
||||
*
|
||||
* @see java.awt.Shape
|
||||
* @see java.awt.BasicStroke
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
public interface PathIterator {
|
||||
/**
|
||||
* The winding rule constant for specifying an even-odd rule
|
||||
* for determining the interior of a path.
|
||||
* The even-odd rule specifies that a point lies inside the
|
||||
* path if a ray drawn in any direction from that point to
|
||||
* infinity is crossed by path segments an odd number of times.
|
||||
*/
|
||||
@Native public static final int WIND_EVEN_ODD = 0;
|
||||
|
||||
/**
|
||||
* The winding rule constant for specifying a non-zero rule
|
||||
* for determining the interior of a path.
|
||||
* The non-zero rule specifies that a point lies inside the
|
||||
* path if a ray drawn in any direction from that point to
|
||||
* infinity is crossed by path segments a different number
|
||||
* of times in the counter-clockwise direction than the
|
||||
* clockwise direction.
|
||||
*/
|
||||
@Native public static final int WIND_NON_ZERO = 1;
|
||||
|
||||
/**
|
||||
* The segment type constant for a point that specifies the
|
||||
* starting location for a new subpath.
|
||||
*/
|
||||
@Native public static final int SEG_MOVETO = 0;
|
||||
|
||||
/**
|
||||
* The segment type constant for a point that specifies the
|
||||
* end point of a line to be drawn from the most recently
|
||||
* specified point.
|
||||
*/
|
||||
@Native public static final int SEG_LINETO = 1;
|
||||
|
||||
/**
|
||||
* The segment type constant for the pair of points that specify
|
||||
* a quadratic parametric curve to be drawn from the most recently
|
||||
* specified point.
|
||||
* The curve is interpolated by solving the parametric control
|
||||
* equation in the range <code>(t=[0..1])</code> using
|
||||
* the most recently specified (current) point (CP),
|
||||
* the first control point (P1),
|
||||
* and the final interpolated control point (P2).
|
||||
* The parametric control equation for this curve is:
|
||||
* <pre>
|
||||
* P(t) = B(2,0)*CP + B(2,1)*P1 + B(2,2)*P2
|
||||
* 0 <= t <= 1
|
||||
*
|
||||
* B(n,m) = mth coefficient of nth degree Bernstein polynomial
|
||||
* = C(n,m) * t^(m) * (1 - t)^(n-m)
|
||||
* C(n,m) = Combinations of n things, taken m at a time
|
||||
* = n! / (m! * (n-m)!)
|
||||
* </pre>
|
||||
*/
|
||||
@Native public static final int SEG_QUADTO = 2;
|
||||
|
||||
/**
|
||||
* The segment type constant for the set of 3 points that specify
|
||||
* a cubic parametric curve to be drawn from the most recently
|
||||
* specified point.
|
||||
* The curve is interpolated by solving the parametric control
|
||||
* equation in the range <code>(t=[0..1])</code> using
|
||||
* the most recently specified (current) point (CP),
|
||||
* the first control point (P1),
|
||||
* the second control point (P2),
|
||||
* and the final interpolated control point (P3).
|
||||
* The parametric control equation for this curve is:
|
||||
* <pre>
|
||||
* P(t) = B(3,0)*CP + B(3,1)*P1 + B(3,2)*P2 + B(3,3)*P3
|
||||
* 0 <= t <= 1
|
||||
*
|
||||
* B(n,m) = mth coefficient of nth degree Bernstein polynomial
|
||||
* = C(n,m) * t^(m) * (1 - t)^(n-m)
|
||||
* C(n,m) = Combinations of n things, taken m at a time
|
||||
* = n! / (m! * (n-m)!)
|
||||
* </pre>
|
||||
* This form of curve is commonly known as a Bézier curve.
|
||||
*/
|
||||
@Native public static final int SEG_CUBICTO = 3;
|
||||
|
||||
/**
|
||||
* The segment type constant that specifies that
|
||||
* the preceding subpath should be closed by appending a line segment
|
||||
* back to the point corresponding to the most recent SEG_MOVETO.
|
||||
*/
|
||||
@Native public static final int SEG_CLOSE = 4;
|
||||
|
||||
/**
|
||||
* Returns the winding rule for determining the interior of the
|
||||
* path.
|
||||
* @return the winding rule.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule();
|
||||
|
||||
/**
|
||||
* Tests if the iteration is complete.
|
||||
* @return <code>true</code> if all the segments have
|
||||
* been read; <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isDone();
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next();
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path-segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and can be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types returns one point,
|
||||
* SEG_QUADTO returns two points,
|
||||
* SEG_CUBICTO returns 3 points
|
||||
* and SEG_CLOSE does not return any points.
|
||||
* @param coords an array that holds the data returned from
|
||||
* this method
|
||||
* @return the path-segment type of the current path segment.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords);
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path-segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and can be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types returns one point,
|
||||
* SEG_QUADTO returns two points,
|
||||
* SEG_CUBICTO returns 3 points
|
||||
* and SEG_CLOSE does not return any points.
|
||||
* @param coords an array that holds the data returned from
|
||||
* this method
|
||||
* @return the path-segment type of the current path segment.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords);
|
||||
}
|
428
jdkSrc/jdk8/java/awt/geom/Point2D.java
Normal file
428
jdkSrc/jdk8/java/awt/geom/Point2D.java
Normal file
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The <code>Point2D</code> class defines a point representing a location
|
||||
* in {@code (x,y)} coordinate space.
|
||||
* <p>
|
||||
* This class is only the abstract superclass for all objects that
|
||||
* store a 2D coordinate.
|
||||
* The actual storage representation of the coordinates is left to
|
||||
* the subclass.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract class Point2D implements Cloneable {
|
||||
|
||||
/**
|
||||
* The <code>Float</code> class defines a point specified in float
|
||||
* precision.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Float extends Point2D implements Serializable {
|
||||
/**
|
||||
* The X coordinate of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float y;
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>Point2D</code> with
|
||||
* coordinates (0, 0).
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>Point2D</code> with
|
||||
* the specified coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the newly
|
||||
* constructed <code>Point2D</code>
|
||||
* @param y the Y coordinate of the newly
|
||||
* constructed <code>Point2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return (double) x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return (double) y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setLocation(double x, double y) {
|
||||
this.x = (float) x;
|
||||
this.y = (float) y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location of this <code>Point2D</code> to the
|
||||
* specified <code>float</code> coordinates.
|
||||
*
|
||||
* @param x the new X coordinate of this {@code Point2D}
|
||||
* @param y the new Y coordinate of this {@code Point2D}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setLocation(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> that represents the value
|
||||
* of this <code>Point2D</code>.
|
||||
* @return a string representation of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public String toString() {
|
||||
return "Point2D.Float["+x+", "+y+"]";
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -2870572449815403710L;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>Double</code> class defines a point specified in
|
||||
* <code>double</code> precision.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Double extends Point2D implements Serializable {
|
||||
/**
|
||||
* The X coordinate of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double y;
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>Point2D</code> with
|
||||
* coordinates (0, 0).
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>Point2D</code> with the
|
||||
* specified coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the newly
|
||||
* constructed <code>Point2D</code>
|
||||
* @param y the Y coordinate of the newly
|
||||
* constructed <code>Point2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setLocation(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> that represents the value
|
||||
* of this <code>Point2D</code>.
|
||||
* @return a string representation of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public String toString() {
|
||||
return "Point2D.Double["+x+", "+y+"]";
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 6150783262733311327L;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an abstract class that cannot be instantiated directly.
|
||||
* Type-specific implementation subclasses are available for
|
||||
* instantiation and provide a number of formats for storing
|
||||
* the information necessary to satisfy the various accessor
|
||||
* methods below.
|
||||
*
|
||||
* @see java.awt.geom.Point2D.Float
|
||||
* @see java.awt.geom.Point2D.Double
|
||||
* @see java.awt.Point
|
||||
* @since 1.2
|
||||
*/
|
||||
protected Point2D() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X coordinate of this <code>Point2D</code> in
|
||||
* <code>double</code> precision.
|
||||
* @return the X coordinate of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getX();
|
||||
|
||||
/**
|
||||
* Returns the Y coordinate of this <code>Point2D</code> in
|
||||
* <code>double</code> precision.
|
||||
* @return the Y coordinate of this <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getY();
|
||||
|
||||
/**
|
||||
* Sets the location of this <code>Point2D</code> to the
|
||||
* specified <code>double</code> coordinates.
|
||||
*
|
||||
* @param x the new X coordinate of this {@code Point2D}
|
||||
* @param y the new Y coordinate of this {@code Point2D}
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract void setLocation(double x, double y);
|
||||
|
||||
/**
|
||||
* Sets the location of this <code>Point2D</code> to the same
|
||||
* coordinates as the specified <code>Point2D</code> object.
|
||||
* @param p the specified <code>Point2D</code> to which to set
|
||||
* this <code>Point2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setLocation(Point2D p) {
|
||||
setLocation(p.getX(), p.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the distance between two points.
|
||||
*
|
||||
* @param x1 the X coordinate of the first specified point
|
||||
* @param y1 the Y coordinate of the first specified point
|
||||
* @param x2 the X coordinate of the second specified point
|
||||
* @param y2 the Y coordinate of the second specified point
|
||||
* @return the square of the distance between the two
|
||||
* sets of specified coordinates.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static double distanceSq(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
x1 -= x2;
|
||||
y1 -= y2;
|
||||
return (x1 * x1 + y1 * y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance between two points.
|
||||
*
|
||||
* @param x1 the X coordinate of the first specified point
|
||||
* @param y1 the Y coordinate of the first specified point
|
||||
* @param x2 the X coordinate of the second specified point
|
||||
* @param y2 the Y coordinate of the second specified point
|
||||
* @return the distance between the two sets of specified
|
||||
* coordinates.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static double distance(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
x1 -= x2;
|
||||
y1 -= y2;
|
||||
return Math.sqrt(x1 * x1 + y1 * y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the distance from this
|
||||
* <code>Point2D</code> to a specified point.
|
||||
*
|
||||
* @param px the X coordinate of the specified point to be measured
|
||||
* against this <code>Point2D</code>
|
||||
* @param py the Y coordinate of the specified point to be measured
|
||||
* against this <code>Point2D</code>
|
||||
* @return the square of the distance between this
|
||||
* <code>Point2D</code> and the specified point.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double distanceSq(double px, double py) {
|
||||
px -= getX();
|
||||
py -= getY();
|
||||
return (px * px + py * py);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the distance from this
|
||||
* <code>Point2D</code> to a specified <code>Point2D</code>.
|
||||
*
|
||||
* @param pt the specified point to be measured
|
||||
* against this <code>Point2D</code>
|
||||
* @return the square of the distance between this
|
||||
* <code>Point2D</code> to a specified <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double distanceSq(Point2D pt) {
|
||||
double px = pt.getX() - this.getX();
|
||||
double py = pt.getY() - this.getY();
|
||||
return (px * px + py * py);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance from this <code>Point2D</code> to
|
||||
* a specified point.
|
||||
*
|
||||
* @param px the X coordinate of the specified point to be measured
|
||||
* against this <code>Point2D</code>
|
||||
* @param py the Y coordinate of the specified point to be measured
|
||||
* against this <code>Point2D</code>
|
||||
* @return the distance between this <code>Point2D</code>
|
||||
* and a specified point.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double distance(double px, double py) {
|
||||
px -= getX();
|
||||
py -= getY();
|
||||
return Math.sqrt(px * px + py * py);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance from this <code>Point2D</code> to a
|
||||
* specified <code>Point2D</code>.
|
||||
*
|
||||
* @param pt the specified point to be measured
|
||||
* against this <code>Point2D</code>
|
||||
* @return the distance between this <code>Point2D</code> and
|
||||
* the specified <code>Point2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double distance(Point2D pt) {
|
||||
double px = pt.getX() - this.getX();
|
||||
double py = pt.getY() - this.getY();
|
||||
return Math.sqrt(px * px + py * py);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object of the same class and with the
|
||||
* same contents as this object.
|
||||
* @return a clone of this instance.
|
||||
* @exception OutOfMemoryError if there is not enough memory.
|
||||
* @see java.lang.Cloneable
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// this shouldn't happen, since we are Cloneable
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashcode for this <code>Point2D</code>.
|
||||
* @return a hash code for this <code>Point2D</code>.
|
||||
*/
|
||||
public int hashCode() {
|
||||
long bits = java.lang.Double.doubleToLongBits(getX());
|
||||
bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
|
||||
return (((int) bits) ^ ((int) (bits >> 32)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not two points are equal. Two instances of
|
||||
* <code>Point2D</code> are equal if the values of their
|
||||
* <code>x</code> and <code>y</code> member fields, representing
|
||||
* their position in the coordinate space, are the same.
|
||||
* @param obj an object to be compared with this <code>Point2D</code>
|
||||
* @return <code>true</code> if the object to be compared is
|
||||
* an instance of <code>Point2D</code> and has
|
||||
* the same values; <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Point2D) {
|
||||
Point2D p2d = (Point2D) obj;
|
||||
return (getX() == p2d.getX()) && (getY() == p2d.getY());
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
}
|
1401
jdkSrc/jdk8/java/awt/geom/QuadCurve2D.java
Normal file
1401
jdkSrc/jdk8/java/awt/geom/QuadCurve2D.java
Normal file
File diff suppressed because it is too large
Load Diff
152
jdkSrc/jdk8/java/awt/geom/QuadIterator.java
Normal file
152
jdkSrc/jdk8/java/awt/geom/QuadIterator.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of a quadratic curve
|
||||
* segment through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class QuadIterator implements PathIterator {
|
||||
QuadCurve2D quad;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
|
||||
QuadIterator(QuadCurve2D q, AffineTransform at) {
|
||||
this.quad = q;
|
||||
this.affine = at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return (index > 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("quad iterator iterator out of bounds");
|
||||
}
|
||||
int type;
|
||||
if (index == 0) {
|
||||
coords[0] = (float) quad.getX1();
|
||||
coords[1] = (float) quad.getY1();
|
||||
type = SEG_MOVETO;
|
||||
} else {
|
||||
coords[0] = (float) quad.getCtrlX();
|
||||
coords[1] = (float) quad.getCtrlY();
|
||||
coords[2] = (float) quad.getX2();
|
||||
coords[3] = (float) quad.getY2();
|
||||
type = SEG_QUADTO;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, index == 0 ? 1 : 2);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("quad iterator iterator out of bounds");
|
||||
}
|
||||
int type;
|
||||
if (index == 0) {
|
||||
coords[0] = quad.getX1();
|
||||
coords[1] = quad.getY1();
|
||||
type = SEG_MOVETO;
|
||||
} else {
|
||||
coords[0] = quad.getCtrlX();
|
||||
coords[1] = quad.getCtrlY();
|
||||
coords[2] = quad.getX2();
|
||||
coords[3] = quad.getY2();
|
||||
type = SEG_QUADTO;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, index == 0 ? 1 : 2);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
156
jdkSrc/jdk8/java/awt/geom/RectIterator.java
Normal file
156
jdkSrc/jdk8/java/awt/geom/RectIterator.java
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of a rectangle
|
||||
* through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class RectIterator implements PathIterator {
|
||||
double x, y, w, h;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
|
||||
RectIterator(Rectangle2D r, AffineTransform at) {
|
||||
this.x = r.getX();
|
||||
this.y = r.getY();
|
||||
this.w = r.getWidth();
|
||||
this.h = r.getHeight();
|
||||
this.affine = at;
|
||||
if (w < 0 || h < 0) {
|
||||
index = 6;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return index > 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("rect iterator out of bounds");
|
||||
}
|
||||
if (index == 5) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
coords[0] = (float) x;
|
||||
coords[1] = (float) y;
|
||||
if (index == 1 || index == 2) {
|
||||
coords[0] += (float) w;
|
||||
}
|
||||
if (index == 2 || index == 3) {
|
||||
coords[1] += (float) h;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return (index == 0 ? SEG_MOVETO : SEG_LINETO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("rect iterator out of bounds");
|
||||
}
|
||||
if (index == 5) {
|
||||
return SEG_CLOSE;
|
||||
}
|
||||
coords[0] = x;
|
||||
coords[1] = y;
|
||||
if (index == 1 || index == 2) {
|
||||
coords[0] += w;
|
||||
}
|
||||
if (index == 2 || index == 3) {
|
||||
coords[1] += h;
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, 1);
|
||||
}
|
||||
return (index == 0 ? SEG_MOVETO : SEG_LINETO);
|
||||
}
|
||||
}
|
930
jdkSrc/jdk8/java/awt/geom/Rectangle2D.java
Normal file
930
jdkSrc/jdk8/java/awt/geom/Rectangle2D.java
Normal file
@@ -0,0 +1,930 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The <code>Rectangle2D</code> class describes a rectangle
|
||||
* defined by a location {@code (x,y)} and dimension
|
||||
* {@code (w x h)}.
|
||||
* <p>
|
||||
* This class is only the abstract superclass for all objects that
|
||||
* store a 2D rectangle.
|
||||
* The actual storage representation of the coordinates is left to
|
||||
* the subclass.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract class Rectangle2D extends RectangularShape {
|
||||
/**
|
||||
* The bitmask that indicates that a point lies to the left of
|
||||
* this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static final int OUT_LEFT = 1;
|
||||
|
||||
/**
|
||||
* The bitmask that indicates that a point lies above
|
||||
* this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static final int OUT_TOP = 2;
|
||||
|
||||
/**
|
||||
* The bitmask that indicates that a point lies to the right of
|
||||
* this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static final int OUT_RIGHT = 4;
|
||||
|
||||
/**
|
||||
* The bitmask that indicates that a point lies below
|
||||
* this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static final int OUT_BOTTOM = 8;
|
||||
|
||||
/**
|
||||
* The <code>Float</code> class defines a rectangle specified in float
|
||||
* coordinates.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Float extends Rectangle2D implements Serializable {
|
||||
/**
|
||||
* The X coordinate of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float y;
|
||||
|
||||
/**
|
||||
* The width of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float width;
|
||||
|
||||
/**
|
||||
* The height of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float height;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Rectangle2D</code>, initialized to
|
||||
* location (0.0, 0.0) and size (0.0, 0.0).
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>Rectangle2D</code>
|
||||
* from the specified <code>float</code> coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of the newly constructed <code>Rectangle2D</code>
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of the newly constructed <code>Rectangle2D</code>
|
||||
* @param w the width of the newly constructed
|
||||
* <code>Rectangle2D</code>
|
||||
* @param h the height of the newly constructed
|
||||
* <code>Rectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float(float x, float y, float w, float h) {
|
||||
setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return (double) x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return (double) y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getWidth() {
|
||||
return (double) width;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getHeight() {
|
||||
return (double) height;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (width <= 0.0f) || (height <= 0.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location and size of this <code>Rectangle2D</code>
|
||||
* to the specified <code>float</code> values.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of this <code>Rectangle2D</code>
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of this <code>Rectangle2D</code>
|
||||
* @param w the width of this <code>Rectangle2D</code>
|
||||
* @param h the height of this <code>Rectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRect(float x, float y, float w, float h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRect(double x, double y, double w, double h) {
|
||||
this.x = (float) x;
|
||||
this.y = (float) y;
|
||||
this.width = (float) w;
|
||||
this.height = (float) h;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRect(Rectangle2D r) {
|
||||
this.x = (float) r.getX();
|
||||
this.y = (float) r.getY();
|
||||
this.width = (float) r.getWidth();
|
||||
this.height = (float) r.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public int outcode(double x, double y) {
|
||||
/*
|
||||
* Note on casts to double below. If the arithmetic of
|
||||
* x+w or y+h is done in float, then some bits may be
|
||||
* lost if the binary exponents of x/y and w/h are not
|
||||
* similar. By converting to double before the addition
|
||||
* we force the addition to be carried out in double to
|
||||
* avoid rounding error in the comparison.
|
||||
*
|
||||
* See bug 4320890 for problems that this inaccuracy causes.
|
||||
*/
|
||||
int out = 0;
|
||||
if (this.width <= 0) {
|
||||
out |= OUT_LEFT | OUT_RIGHT;
|
||||
} else if (x < this.x) {
|
||||
out |= OUT_LEFT;
|
||||
} else if (x > this.x + (double) this.width) {
|
||||
out |= OUT_RIGHT;
|
||||
}
|
||||
if (this.height <= 0) {
|
||||
out |= OUT_TOP | OUT_BOTTOM;
|
||||
} else if (y < this.y) {
|
||||
out |= OUT_TOP;
|
||||
} else if (y > this.y + (double) this.height) {
|
||||
out |= OUT_BOTTOM;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return new Float(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D createIntersection(Rectangle2D r) {
|
||||
Rectangle2D dest;
|
||||
if (r instanceof Float) {
|
||||
dest = new Rectangle2D.Float();
|
||||
} else {
|
||||
dest = new Rectangle2D.Double();
|
||||
}
|
||||
Rectangle2D.intersect(this, r, dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D createUnion(Rectangle2D r) {
|
||||
Rectangle2D dest;
|
||||
if (r instanceof Float) {
|
||||
dest = new Rectangle2D.Float();
|
||||
} else {
|
||||
dest = new Rectangle2D.Double();
|
||||
}
|
||||
Rectangle2D.union(this, r, dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>String</code> representation of this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @return a <code>String</code> representing this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public String toString() {
|
||||
return getClass().getName()
|
||||
+ "[x=" + x +
|
||||
",y=" + y +
|
||||
",w=" + width +
|
||||
",h=" + height + "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 3798716824173675777L;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>Double</code> class defines a rectangle specified in
|
||||
* double coordinates.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Double extends Rectangle2D implements Serializable {
|
||||
/**
|
||||
* The X coordinate of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double y;
|
||||
|
||||
/**
|
||||
* The width of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double width;
|
||||
|
||||
/**
|
||||
* The height of this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double height;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Rectangle2D</code>, initialized to
|
||||
* location (0, 0) and size (0, 0).
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>Rectangle2D</code>
|
||||
* from the specified <code>double</code> coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of the newly constructed <code>Rectangle2D</code>
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of the newly constructed <code>Rectangle2D</code>
|
||||
* @param w the width of the newly constructed
|
||||
* <code>Rectangle2D</code>
|
||||
* @param h the height of the newly constructed
|
||||
* <code>Rectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double(double x, double y, double w, double h) {
|
||||
setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (width <= 0.0) || (height <= 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRect(double x, double y, double w, double h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRect(Rectangle2D r) {
|
||||
this.x = r.getX();
|
||||
this.y = r.getY();
|
||||
this.width = r.getWidth();
|
||||
this.height = r.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public int outcode(double x, double y) {
|
||||
int out = 0;
|
||||
if (this.width <= 0) {
|
||||
out |= OUT_LEFT | OUT_RIGHT;
|
||||
} else if (x < this.x) {
|
||||
out |= OUT_LEFT;
|
||||
} else if (x > this.x + this.width) {
|
||||
out |= OUT_RIGHT;
|
||||
}
|
||||
if (this.height <= 0) {
|
||||
out |= OUT_TOP | OUT_BOTTOM;
|
||||
} else if (y < this.y) {
|
||||
out |= OUT_TOP;
|
||||
} else if (y > this.y + this.height) {
|
||||
out |= OUT_BOTTOM;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return new Double(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D createIntersection(Rectangle2D r) {
|
||||
Rectangle2D dest = new Rectangle2D.Double();
|
||||
Rectangle2D.intersect(this, r, dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D createUnion(Rectangle2D r) {
|
||||
Rectangle2D dest = new Rectangle2D.Double();
|
||||
Rectangle2D.union(this, r, dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>String</code> representation of this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @return a <code>String</code> representing this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public String toString() {
|
||||
return getClass().getName()
|
||||
+ "[x=" + x +
|
||||
",y=" + y +
|
||||
",w=" + width +
|
||||
",h=" + height + "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 7771313791441850493L;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an abstract class that cannot be instantiated directly.
|
||||
* Type-specific implementation subclasses are available for
|
||||
* instantiation and provide a number of formats for storing
|
||||
* the information necessary to satisfy the various accessor
|
||||
* methods below.
|
||||
*
|
||||
* @see java.awt.geom.Rectangle2D.Float
|
||||
* @see java.awt.geom.Rectangle2D.Double
|
||||
* @see java.awt.Rectangle
|
||||
* @since 1.2
|
||||
*/
|
||||
protected Rectangle2D() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location and size of this <code>Rectangle2D</code>
|
||||
* to the specified <code>double</code> values.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of this <code>Rectangle2D</code>
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of this <code>Rectangle2D</code>
|
||||
* @param w the width of this <code>Rectangle2D</code>
|
||||
* @param h the height of this <code>Rectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract void setRect(double x, double y, double w, double h);
|
||||
|
||||
/**
|
||||
* Sets this <code>Rectangle2D</code> to be the same as the specified
|
||||
* <code>Rectangle2D</code>.
|
||||
* @param r the specified <code>Rectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRect(Rectangle2D r) {
|
||||
setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the specified line segment intersects the interior of this
|
||||
* <code>Rectangle2D</code>.
|
||||
*
|
||||
* @param x1 the X coordinate of the start point of the specified
|
||||
* line segment
|
||||
* @param y1 the Y coordinate of the start point of the specified
|
||||
* line segment
|
||||
* @param x2 the X coordinate of the end point of the specified
|
||||
* line segment
|
||||
* @param y2 the Y coordinate of the end point of the specified
|
||||
* line segment
|
||||
* @return <code>true</code> if the specified line segment intersects
|
||||
* the interior of this <code>Rectangle2D</code>; <code>false</code>
|
||||
* otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersectsLine(double x1, double y1, double x2, double y2) {
|
||||
int out1, out2;
|
||||
if ((out2 = outcode(x2, y2)) == 0) {
|
||||
return true;
|
||||
}
|
||||
while ((out1 = outcode(x1, y1)) != 0) {
|
||||
if ((out1 & out2) != 0) {
|
||||
return false;
|
||||
}
|
||||
if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) {
|
||||
double x = getX();
|
||||
if ((out1 & OUT_RIGHT) != 0) {
|
||||
x += getWidth();
|
||||
}
|
||||
y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
|
||||
x1 = x;
|
||||
} else {
|
||||
double y = getY();
|
||||
if ((out1 & OUT_BOTTOM) != 0) {
|
||||
y += getHeight();
|
||||
}
|
||||
x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
|
||||
y1 = y;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the specified line segment intersects the interior of this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @param l the specified {@link Line2D} to test for intersection
|
||||
* with the interior of this <code>Rectangle2D</code>
|
||||
* @return <code>true</code> if the specified <code>Line2D</code>
|
||||
* intersects the interior of this <code>Rectangle2D</code>;
|
||||
* <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersectsLine(Line2D l) {
|
||||
return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines where the specified coordinates lie with respect
|
||||
* to this <code>Rectangle2D</code>.
|
||||
* This method computes a binary OR of the appropriate mask values
|
||||
* indicating, for each side of this <code>Rectangle2D</code>,
|
||||
* whether or not the specified coordinates are on the same side
|
||||
* of the edge as the rest of this <code>Rectangle2D</code>.
|
||||
* @param x the specified X coordinate
|
||||
* @param y the specified Y coordinate
|
||||
* @return the logical OR of all appropriate out codes.
|
||||
* @see #OUT_LEFT
|
||||
* @see #OUT_TOP
|
||||
* @see #OUT_RIGHT
|
||||
* @see #OUT_BOTTOM
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract int outcode(double x, double y);
|
||||
|
||||
/**
|
||||
* Determines where the specified {@link Point2D} lies with
|
||||
* respect to this <code>Rectangle2D</code>.
|
||||
* This method computes a binary OR of the appropriate mask values
|
||||
* indicating, for each side of this <code>Rectangle2D</code>,
|
||||
* whether or not the specified <code>Point2D</code> is on the same
|
||||
* side of the edge as the rest of this <code>Rectangle2D</code>.
|
||||
* @param p the specified <code>Point2D</code>
|
||||
* @return the logical OR of all appropriate out codes.
|
||||
* @see #OUT_LEFT
|
||||
* @see #OUT_TOP
|
||||
* @see #OUT_RIGHT
|
||||
* @see #OUT_BOTTOM
|
||||
* @since 1.2
|
||||
*/
|
||||
public int outcode(Point2D p) {
|
||||
return outcode(p.getX(), p.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location and size of the outer bounds of this
|
||||
* <code>Rectangle2D</code> to the specified rectangular values.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner
|
||||
* of this <code>Rectangle2D</code>
|
||||
* @param y the Y coordinate of the upper-left corner
|
||||
* of this <code>Rectangle2D</code>
|
||||
* @param w the width of this <code>Rectangle2D</code>
|
||||
* @param h the height of this <code>Rectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(double x, double y, double w, double h) {
|
||||
setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return (Rectangle2D) clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y) {
|
||||
double x0 = getX();
|
||||
double y0 = getY();
|
||||
return (x >= x0 &&
|
||||
y >= y0 &&
|
||||
x < x0 + getWidth() &&
|
||||
y < y0 + getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersects(double x, double y, double w, double h) {
|
||||
if (isEmpty() || w <= 0 || h <= 0) {
|
||||
return false;
|
||||
}
|
||||
double x0 = getX();
|
||||
double y0 = getY();
|
||||
return (x + w > x0 &&
|
||||
y + h > y0 &&
|
||||
x < x0 + getWidth() &&
|
||||
y < y0 + getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y, double w, double h) {
|
||||
if (isEmpty() || w <= 0 || h <= 0) {
|
||||
return false;
|
||||
}
|
||||
double x0 = getX();
|
||||
double y0 = getY();
|
||||
return (x >= x0 &&
|
||||
y >= y0 &&
|
||||
(x + w) <= x0 + getWidth() &&
|
||||
(y + h) <= y0 + getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>Rectangle2D</code> object representing the
|
||||
* intersection of this <code>Rectangle2D</code> with the specified
|
||||
* <code>Rectangle2D</code>.
|
||||
* @param r the <code>Rectangle2D</code> to be intersected with
|
||||
* this <code>Rectangle2D</code>
|
||||
* @return the largest <code>Rectangle2D</code> contained in both
|
||||
* the specified <code>Rectangle2D</code> and in this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract Rectangle2D createIntersection(Rectangle2D r);
|
||||
|
||||
/**
|
||||
* Intersects the pair of specified source <code>Rectangle2D</code>
|
||||
* objects and puts the result into the specified destination
|
||||
* <code>Rectangle2D</code> object. One of the source rectangles
|
||||
* can also be the destination to avoid creating a third Rectangle2D
|
||||
* object, but in this case the original points of this source
|
||||
* rectangle will be overwritten by this method.
|
||||
* @param src1 the first of a pair of <code>Rectangle2D</code>
|
||||
* objects to be intersected with each other
|
||||
* @param src2 the second of a pair of <code>Rectangle2D</code>
|
||||
* objects to be intersected with each other
|
||||
* @param dest the <code>Rectangle2D</code> that holds the
|
||||
* results of the intersection of <code>src1</code> and
|
||||
* <code>src2</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public static void intersect(Rectangle2D src1,
|
||||
Rectangle2D src2,
|
||||
Rectangle2D dest) {
|
||||
double x1 = Math.max(src1.getMinX(), src2.getMinX());
|
||||
double y1 = Math.max(src1.getMinY(), src2.getMinY());
|
||||
double x2 = Math.min(src1.getMaxX(), src2.getMaxX());
|
||||
double y2 = Math.min(src1.getMaxY(), src2.getMaxY());
|
||||
dest.setFrame(x1, y1, x2-x1, y2-y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>Rectangle2D</code> object representing the
|
||||
* union of this <code>Rectangle2D</code> with the specified
|
||||
* <code>Rectangle2D</code>.
|
||||
* @param r the <code>Rectangle2D</code> to be combined with
|
||||
* this <code>Rectangle2D</code>
|
||||
* @return the smallest <code>Rectangle2D</code> containing both
|
||||
* the specified <code>Rectangle2D</code> and this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract Rectangle2D createUnion(Rectangle2D r);
|
||||
|
||||
/**
|
||||
* Unions the pair of source <code>Rectangle2D</code> objects
|
||||
* and puts the result into the specified destination
|
||||
* <code>Rectangle2D</code> object. One of the source rectangles
|
||||
* can also be the destination to avoid creating a third Rectangle2D
|
||||
* object, but in this case the original points of this source
|
||||
* rectangle will be overwritten by this method.
|
||||
* @param src1 the first of a pair of <code>Rectangle2D</code>
|
||||
* objects to be combined with each other
|
||||
* @param src2 the second of a pair of <code>Rectangle2D</code>
|
||||
* objects to be combined with each other
|
||||
* @param dest the <code>Rectangle2D</code> that holds the
|
||||
* results of the union of <code>src1</code> and
|
||||
* <code>src2</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public static void union(Rectangle2D src1,
|
||||
Rectangle2D src2,
|
||||
Rectangle2D dest) {
|
||||
double x1 = Math.min(src1.getMinX(), src2.getMinX());
|
||||
double y1 = Math.min(src1.getMinY(), src2.getMinY());
|
||||
double x2 = Math.max(src1.getMaxX(), src2.getMaxX());
|
||||
double y2 = Math.max(src1.getMaxY(), src2.getMaxY());
|
||||
dest.setFrameFromDiagonal(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a point, specified by the double precision arguments
|
||||
* <code>newx</code> and <code>newy</code>, to this
|
||||
* <code>Rectangle2D</code>. The resulting <code>Rectangle2D</code>
|
||||
* is the smallest <code>Rectangle2D</code> that
|
||||
* contains both the original <code>Rectangle2D</code> and the
|
||||
* specified point.
|
||||
* <p>
|
||||
* After adding a point, a call to <code>contains</code> with the
|
||||
* added point as an argument does not necessarily return
|
||||
* <code>true</code>. The <code>contains</code> method does not
|
||||
* return <code>true</code> for points on the right or bottom
|
||||
* edges of a rectangle. Therefore, if the added point falls on
|
||||
* the left or bottom edge of the enlarged rectangle,
|
||||
* <code>contains</code> returns <code>false</code> for that point.
|
||||
* @param newx the X coordinate of the new point
|
||||
* @param newy the Y coordinate of the new point
|
||||
* @since 1.2
|
||||
*/
|
||||
public void add(double newx, double newy) {
|
||||
double x1 = Math.min(getMinX(), newx);
|
||||
double x2 = Math.max(getMaxX(), newx);
|
||||
double y1 = Math.min(getMinY(), newy);
|
||||
double y2 = Math.max(getMaxY(), newy);
|
||||
setRect(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the <code>Point2D</code> object <code>pt</code> to this
|
||||
* <code>Rectangle2D</code>.
|
||||
* The resulting <code>Rectangle2D</code> is the smallest
|
||||
* <code>Rectangle2D</code> that contains both the original
|
||||
* <code>Rectangle2D</code> and the specified <code>Point2D</code>.
|
||||
* <p>
|
||||
* After adding a point, a call to <code>contains</code> with the
|
||||
* added point as an argument does not necessarily return
|
||||
* <code>true</code>. The <code>contains</code>
|
||||
* method does not return <code>true</code> for points on the right
|
||||
* or bottom edges of a rectangle. Therefore, if the added point falls
|
||||
* on the left or bottom edge of the enlarged rectangle,
|
||||
* <code>contains</code> returns <code>false</code> for that point.
|
||||
* @param pt the new <code>Point2D</code> to add to this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public void add(Point2D pt) {
|
||||
add(pt.getX(), pt.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a <code>Rectangle2D</code> object to this
|
||||
* <code>Rectangle2D</code>. The resulting <code>Rectangle2D</code>
|
||||
* is the union of the two <code>Rectangle2D</code> objects.
|
||||
* @param r the <code>Rectangle2D</code> to add to this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public void add(Rectangle2D r) {
|
||||
double x1 = Math.min(getMinX(), r.getMinX());
|
||||
double x2 = Math.max(getMaxX(), r.getMaxX());
|
||||
double y1 = Math.min(getMinY(), r.getMinY());
|
||||
double y2 = Math.max(getMaxY(), r.getMaxY());
|
||||
setRect(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iteration object that defines the boundary of this
|
||||
* <code>Rectangle2D</code>.
|
||||
* The iterator for this class is multi-threaded safe, which means
|
||||
* that this <code>Rectangle2D</code> class guarantees that
|
||||
* modifications to the geometry of this <code>Rectangle2D</code>
|
||||
* object do not affect any iterations of that geometry that
|
||||
* are already in process.
|
||||
* @param at an optional <code>AffineTransform</code> to be applied to
|
||||
* the coordinates as they are returned in the iteration, or
|
||||
* <code>null</code> if untransformed coordinates are desired
|
||||
* @return the <code>PathIterator</code> object that returns the
|
||||
* geometry of the outline of this
|
||||
* <code>Rectangle2D</code>, one segment at a time.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at) {
|
||||
return new RectIterator(this, at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iteration object that defines the boundary of the
|
||||
* flattened <code>Rectangle2D</code>. Since rectangles are already
|
||||
* flat, the <code>flatness</code> parameter is ignored.
|
||||
* The iterator for this class is multi-threaded safe, which means
|
||||
* that this <code>Rectangle2D</code> class guarantees that
|
||||
* modifications to the geometry of this <code>Rectangle2D</code>
|
||||
* object do not affect any iterations of that geometry that
|
||||
* are already in process.
|
||||
* @param at an optional <code>AffineTransform</code> to be applied to
|
||||
* the coordinates as they are returned in the iteration, or
|
||||
* <code>null</code> if untransformed coordinates are desired
|
||||
* @param flatness the maximum distance that the line segments used to
|
||||
* approximate the curved segments are allowed to deviate from any
|
||||
* point on the original curve. Since rectangles are already flat,
|
||||
* the <code>flatness</code> parameter is ignored.
|
||||
* @return the <code>PathIterator</code> object that returns the
|
||||
* geometry of the outline of this
|
||||
* <code>Rectangle2D</code>, one segment at a time.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at, double flatness) {
|
||||
return new RectIterator(this, at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashcode for this <code>Rectangle2D</code>.
|
||||
* @return the hashcode for this <code>Rectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public int hashCode() {
|
||||
long bits = java.lang.Double.doubleToLongBits(getX());
|
||||
bits += java.lang.Double.doubleToLongBits(getY()) * 37;
|
||||
bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
|
||||
bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
|
||||
return (((int) bits) ^ ((int) (bits >> 32)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the specified <code>Object</code> is
|
||||
* equal to this <code>Rectangle2D</code>. The specified
|
||||
* <code>Object</code> is equal to this <code>Rectangle2D</code>
|
||||
* if it is an instance of <code>Rectangle2D</code> and if its
|
||||
* location and size are the same as this <code>Rectangle2D</code>.
|
||||
* @param obj an <code>Object</code> to be compared with this
|
||||
* <code>Rectangle2D</code>.
|
||||
* @return <code>true</code> if <code>obj</code> is an instance
|
||||
* of <code>Rectangle2D</code> and has
|
||||
* the same values; <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Rectangle2D) {
|
||||
Rectangle2D r2d = (Rectangle2D) obj;
|
||||
return ((getX() == r2d.getX()) &&
|
||||
(getY() == r2d.getY()) &&
|
||||
(getWidth() == r2d.getWidth()) &&
|
||||
(getHeight() == r2d.getHeight()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
397
jdkSrc/jdk8/java/awt/geom/RectangularShape.java
Normal file
397
jdkSrc/jdk8/java/awt/geom/RectangularShape.java
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.Transient;
|
||||
|
||||
/**
|
||||
* <code>RectangularShape</code> is the base class for a number of
|
||||
* {@link Shape} objects whose geometry is defined by a rectangular frame.
|
||||
* This class does not directly specify any specific geometry by
|
||||
* itself, but merely provides manipulation methods inherited by
|
||||
* a whole category of <code>Shape</code> objects.
|
||||
* The manipulation methods provided by this class can be used to
|
||||
* query and modify the rectangular frame, which provides a reference
|
||||
* for the subclasses to define their geometry.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract class RectangularShape implements Shape, Cloneable {
|
||||
|
||||
/**
|
||||
* This is an abstract class that cannot be instantiated directly.
|
||||
*
|
||||
* @see Arc2D
|
||||
* @see Ellipse2D
|
||||
* @see Rectangle2D
|
||||
* @see RoundRectangle2D
|
||||
* @since 1.2
|
||||
*/
|
||||
protected RectangularShape() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X coordinate of the upper-left corner of
|
||||
* the framing rectangle in <code>double</code> precision.
|
||||
* @return the X coordinate of the upper-left corner of
|
||||
* the framing rectangle.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getX();
|
||||
|
||||
/**
|
||||
* Returns the Y coordinate of the upper-left corner of
|
||||
* the framing rectangle in <code>double</code> precision.
|
||||
* @return the Y coordinate of the upper-left corner of
|
||||
* the framing rectangle.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getY();
|
||||
|
||||
/**
|
||||
* Returns the width of the framing rectangle in
|
||||
* <code>double</code> precision.
|
||||
* @return the width of the framing rectangle.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getWidth();
|
||||
|
||||
/**
|
||||
* Returns the height of the framing rectangle
|
||||
* in <code>double</code> precision.
|
||||
* @return the height of the framing rectangle.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getHeight();
|
||||
|
||||
/**
|
||||
* Returns the smallest X coordinate of the framing
|
||||
* rectangle of the <code>Shape</code> in <code>double</code>
|
||||
* precision.
|
||||
* @return the smallest X coordinate of the framing
|
||||
* rectangle of the <code>Shape</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getMinX() {
|
||||
return getX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smallest Y coordinate of the framing
|
||||
* rectangle of the <code>Shape</code> in <code>double</code>
|
||||
* precision.
|
||||
* @return the smallest Y coordinate of the framing
|
||||
* rectangle of the <code>Shape</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getMinY() {
|
||||
return getY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest X coordinate of the framing
|
||||
* rectangle of the <code>Shape</code> in <code>double</code>
|
||||
* precision.
|
||||
* @return the largest X coordinate of the framing
|
||||
* rectangle of the <code>Shape</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getMaxX() {
|
||||
return getX() + getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest Y coordinate of the framing
|
||||
* rectangle of the <code>Shape</code> in <code>double</code>
|
||||
* precision.
|
||||
* @return the largest Y coordinate of the framing
|
||||
* rectangle of the <code>Shape</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getMaxY() {
|
||||
return getY() + getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X coordinate of the center of the framing
|
||||
* rectangle of the <code>Shape</code> in <code>double</code>
|
||||
* precision.
|
||||
* @return the X coordinate of the center of the framing rectangle
|
||||
* of the <code>Shape</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getCenterX() {
|
||||
return getX() + getWidth() / 2.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Y coordinate of the center of the framing
|
||||
* rectangle of the <code>Shape</code> in <code>double</code>
|
||||
* precision.
|
||||
* @return the Y coordinate of the center of the framing rectangle
|
||||
* of the <code>Shape</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getCenterY() {
|
||||
return getY() + getHeight() / 2.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the framing {@link Rectangle2D}
|
||||
* that defines the overall shape of this object.
|
||||
* @return a <code>Rectangle2D</code>, specified in
|
||||
* <code>double</code> coordinates.
|
||||
* @see #setFrame(double, double, double, double)
|
||||
* @see #setFrame(Point2D, Dimension2D)
|
||||
* @see #setFrame(Rectangle2D)
|
||||
* @since 1.2
|
||||
*/
|
||||
@Transient
|
||||
public Rectangle2D getFrame() {
|
||||
return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the <code>RectangularShape</code> is empty.
|
||||
* When the <code>RectangularShape</code> is empty, it encloses no
|
||||
* area.
|
||||
* @return <code>true</code> if the <code>RectangularShape</code> is empty;
|
||||
* <code>false</code> otherwise.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Sets the location and size of the framing rectangle of this
|
||||
* <code>Shape</code> to the specified rectangular values.
|
||||
*
|
||||
* @param x the X coordinate of the upper-left corner of the
|
||||
* specified rectangular shape
|
||||
* @param y the Y coordinate of the upper-left corner of the
|
||||
* specified rectangular shape
|
||||
* @param w the width of the specified rectangular shape
|
||||
* @param h the height of the specified rectangular shape
|
||||
* @see #getFrame
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract void setFrame(double x, double y, double w, double h);
|
||||
|
||||
/**
|
||||
* Sets the location and size of the framing rectangle of this
|
||||
* <code>Shape</code> to the specified {@link Point2D} and
|
||||
* {@link Dimension2D}, respectively. The framing rectangle is used
|
||||
* by the subclasses of <code>RectangularShape</code> to define
|
||||
* their geometry.
|
||||
* @param loc the specified <code>Point2D</code>
|
||||
* @param size the specified <code>Dimension2D</code>
|
||||
* @see #getFrame
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(Point2D loc, Dimension2D size) {
|
||||
setFrame(loc.getX(), loc.getY(), size.getWidth(), size.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the framing rectangle of this <code>Shape</code> to
|
||||
* be the specified <code>Rectangle2D</code>. The framing rectangle is
|
||||
* used by the subclasses of <code>RectangularShape</code> to define
|
||||
* their geometry.
|
||||
* @param r the specified <code>Rectangle2D</code>
|
||||
* @see #getFrame
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(Rectangle2D r) {
|
||||
setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the diagonal of the framing rectangle of this <code>Shape</code>
|
||||
* based on the two specified coordinates. The framing rectangle is
|
||||
* used by the subclasses of <code>RectangularShape</code> to define
|
||||
* their geometry.
|
||||
*
|
||||
* @param x1 the X coordinate of the start point of the specified diagonal
|
||||
* @param y1 the Y coordinate of the start point of the specified diagonal
|
||||
* @param x2 the X coordinate of the end point of the specified diagonal
|
||||
* @param y2 the Y coordinate of the end point of the specified diagonal
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrameFromDiagonal(double x1, double y1,
|
||||
double x2, double y2) {
|
||||
if (x2 < x1) {
|
||||
double t = x1;
|
||||
x1 = x2;
|
||||
x2 = t;
|
||||
}
|
||||
if (y2 < y1) {
|
||||
double t = y1;
|
||||
y1 = y2;
|
||||
y2 = t;
|
||||
}
|
||||
setFrame(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the diagonal of the framing rectangle of this <code>Shape</code>
|
||||
* based on two specified <code>Point2D</code> objects. The framing
|
||||
* rectangle is used by the subclasses of <code>RectangularShape</code>
|
||||
* to define their geometry.
|
||||
*
|
||||
* @param p1 the start <code>Point2D</code> of the specified diagonal
|
||||
* @param p2 the end <code>Point2D</code> of the specified diagonal
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrameFromDiagonal(Point2D p1, Point2D p2) {
|
||||
setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the framing rectangle of this <code>Shape</code>
|
||||
* based on the specified center point coordinates and corner point
|
||||
* coordinates. The framing rectangle is used by the subclasses of
|
||||
* <code>RectangularShape</code> to define their geometry.
|
||||
*
|
||||
* @param centerX the X coordinate of the specified center point
|
||||
* @param centerY the Y coordinate of the specified center point
|
||||
* @param cornerX the X coordinate of the specified corner point
|
||||
* @param cornerY the Y coordinate of the specified corner point
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrameFromCenter(double centerX, double centerY,
|
||||
double cornerX, double cornerY) {
|
||||
double halfW = Math.abs(cornerX - centerX);
|
||||
double halfH = Math.abs(cornerY - centerY);
|
||||
setFrame(centerX - halfW, centerY - halfH, halfW * 2.0, halfH * 2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the framing rectangle of this <code>Shape</code> based on a
|
||||
* specified center <code>Point2D</code> and corner
|
||||
* <code>Point2D</code>. The framing rectangle is used by the subclasses
|
||||
* of <code>RectangularShape</code> to define their geometry.
|
||||
* @param center the specified center <code>Point2D</code>
|
||||
* @param corner the specified corner <code>Point2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrameFromCenter(Point2D center, Point2D corner) {
|
||||
setFrameFromCenter(center.getX(), center.getY(),
|
||||
corner.getX(), corner.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(Point2D p) {
|
||||
return contains(p.getX(), p.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersects(Rectangle2D r) {
|
||||
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(Rectangle2D r) {
|
||||
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle getBounds() {
|
||||
double width = getWidth();
|
||||
double height = getHeight();
|
||||
if (width < 0 || height < 0) {
|
||||
return new Rectangle();
|
||||
}
|
||||
double x = getX();
|
||||
double y = getY();
|
||||
double x1 = Math.floor(x);
|
||||
double y1 = Math.floor(y);
|
||||
double x2 = Math.ceil(x + width);
|
||||
double y2 = Math.ceil(y + height);
|
||||
return new Rectangle((int) x1, (int) y1,
|
||||
(int) (x2 - x1), (int) (y2 - y1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator object that iterates along the
|
||||
* <code>Shape</code> object's boundary and provides access to a
|
||||
* flattened view of the outline of the <code>Shape</code>
|
||||
* object's geometry.
|
||||
* <p>
|
||||
* Only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE point types will
|
||||
* be returned by the iterator.
|
||||
* <p>
|
||||
* The amount of subdivision of the curved segments is controlled
|
||||
* by the <code>flatness</code> parameter, which specifies the
|
||||
* maximum distance that any point on the unflattened transformed
|
||||
* curve can deviate from the returned flattened path segments.
|
||||
* An optional {@link AffineTransform} can
|
||||
* be specified so that the coordinates returned in the iteration are
|
||||
* transformed accordingly.
|
||||
* @param at an optional <code>AffineTransform</code> to be applied to the
|
||||
* coordinates as they are returned in the iteration,
|
||||
* or <code>null</code> if untransformed coordinates are desired.
|
||||
* @param flatness the maximum distance that the line segments used to
|
||||
* approximate the curved segments are allowed to deviate
|
||||
* from any point on the original curve
|
||||
* @return a <code>PathIterator</code> object that provides access to
|
||||
* the <code>Shape</code> object's flattened geometry.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(at), flatness);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object of the same class and with the same
|
||||
* contents as this object.
|
||||
* @return a clone of this instance.
|
||||
* @exception OutOfMemoryError if there is not enough memory.
|
||||
* @see java.lang.Cloneable
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// this shouldn't happen, since we are Cloneable
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
}
|
189
jdkSrc/jdk8/java/awt/geom/RoundRectIterator.java
Normal file
189
jdkSrc/jdk8/java/awt/geom/RoundRectIterator.java
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A utility class to iterate over the path segments of an rounded rectangle
|
||||
* through the PathIterator interface.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
class RoundRectIterator implements PathIterator {
|
||||
double x, y, w, h, aw, ah;
|
||||
AffineTransform affine;
|
||||
int index;
|
||||
|
||||
RoundRectIterator(RoundRectangle2D rr, AffineTransform at) {
|
||||
this.x = rr.getX();
|
||||
this.y = rr.getY();
|
||||
this.w = rr.getWidth();
|
||||
this.h = rr.getHeight();
|
||||
this.aw = Math.min(w, Math.abs(rr.getArcWidth()));
|
||||
this.ah = Math.min(h, Math.abs(rr.getArcHeight()));
|
||||
this.affine = at;
|
||||
if (aw < 0 || ah < 0) {
|
||||
// Don't draw anything...
|
||||
index = ctrlpts.length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the winding rule for determining the insideness of the
|
||||
* path.
|
||||
* @see #WIND_EVEN_ODD
|
||||
* @see #WIND_NON_ZERO
|
||||
*/
|
||||
public int getWindingRule() {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if there are more points to read.
|
||||
* @return true if there are more points to read
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return index >= ctrlpts.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next segment of the path forwards
|
||||
* along the primary direction of traversal as long as there are
|
||||
* more points in that direction.
|
||||
*/
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
|
||||
private static final double angle = Math.PI / 4.0;
|
||||
private static final double a = 1.0 - Math.cos(angle);
|
||||
private static final double b = Math.tan(angle);
|
||||
private static final double c = Math.sqrt(1.0 + b * b) - 1 + a;
|
||||
private static final double cv = 4.0 / 3.0 * a * b / c;
|
||||
private static final double acv = (1.0 - cv) / 2.0;
|
||||
|
||||
// For each array:
|
||||
// 4 values for each point {v0, v1, v2, v3}:
|
||||
// point = (x + v0 * w + v1 * arcWidth,
|
||||
// y + v2 * h + v3 * arcHeight);
|
||||
private static double ctrlpts[][] = {
|
||||
{ 0.0, 0.0, 0.0, 0.5 },
|
||||
{ 0.0, 0.0, 1.0, -0.5 },
|
||||
{ 0.0, 0.0, 1.0, -acv,
|
||||
0.0, acv, 1.0, 0.0,
|
||||
0.0, 0.5, 1.0, 0.0 },
|
||||
{ 1.0, -0.5, 1.0, 0.0 },
|
||||
{ 1.0, -acv, 1.0, 0.0,
|
||||
1.0, 0.0, 1.0, -acv,
|
||||
1.0, 0.0, 1.0, -0.5 },
|
||||
{ 1.0, 0.0, 0.0, 0.5 },
|
||||
{ 1.0, 0.0, 0.0, acv,
|
||||
1.0, -acv, 0.0, 0.0,
|
||||
1.0, -0.5, 0.0, 0.0 },
|
||||
{ 0.0, 0.5, 0.0, 0.0 },
|
||||
{ 0.0, acv, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, acv,
|
||||
0.0, 0.0, 0.0, 0.5 },
|
||||
{},
|
||||
};
|
||||
private static int types[] = {
|
||||
SEG_MOVETO,
|
||||
SEG_LINETO, SEG_CUBICTO,
|
||||
SEG_LINETO, SEG_CUBICTO,
|
||||
SEG_LINETO, SEG_CUBICTO,
|
||||
SEG_LINETO, SEG_CUBICTO,
|
||||
SEG_CLOSE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A float array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of float x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(float[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("roundrect iterator out of bounds");
|
||||
}
|
||||
double ctrls[] = ctrlpts[index];
|
||||
int nc = 0;
|
||||
for (int i = 0; i < ctrls.length; i += 4) {
|
||||
coords[nc++] = (float) (x + ctrls[i + 0] * w + ctrls[i + 1] * aw);
|
||||
coords[nc++] = (float) (y + ctrls[i + 2] * h + ctrls[i + 3] * ah);
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, nc / 2);
|
||||
}
|
||||
return types[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates and type of the current path segment in
|
||||
* the iteration.
|
||||
* The return value is the path segment type:
|
||||
* SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
|
||||
* A double array of length 6 must be passed in and may be used to
|
||||
* store the coordinates of the point(s).
|
||||
* Each point is stored as a pair of double x,y coordinates.
|
||||
* SEG_MOVETO and SEG_LINETO types will return one point,
|
||||
* SEG_QUADTO will return two points,
|
||||
* SEG_CUBICTO will return 3 points
|
||||
* and SEG_CLOSE will not return any points.
|
||||
* @see #SEG_MOVETO
|
||||
* @see #SEG_LINETO
|
||||
* @see #SEG_QUADTO
|
||||
* @see #SEG_CUBICTO
|
||||
* @see #SEG_CLOSE
|
||||
*/
|
||||
public int currentSegment(double[] coords) {
|
||||
if (isDone()) {
|
||||
throw new NoSuchElementException("roundrect iterator out of bounds");
|
||||
}
|
||||
double ctrls[] = ctrlpts[index];
|
||||
int nc = 0;
|
||||
for (int i = 0; i < ctrls.length; i += 4) {
|
||||
coords[nc++] = (x + ctrls[i + 0] * w + ctrls[i + 1] * aw);
|
||||
coords[nc++] = (y + ctrls[i + 2] * h + ctrls[i + 3] * ah);
|
||||
}
|
||||
if (affine != null) {
|
||||
affine.transform(coords, 0, coords, 0, nc / 2);
|
||||
}
|
||||
return types[index];
|
||||
}
|
||||
}
|
681
jdkSrc/jdk8/java/awt/geom/RoundRectangle2D.java
Normal file
681
jdkSrc/jdk8/java/awt/geom/RoundRectangle2D.java
Normal file
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt.geom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The <code>RoundRectangle2D</code> class defines a rectangle with
|
||||
* rounded corners defined by a location {@code (x,y)}, a
|
||||
* dimension {@code (w x h)}, and the width and height of an arc
|
||||
* with which to round the corners.
|
||||
* <p>
|
||||
* This class is the abstract superclass for all objects that
|
||||
* store a 2D rounded rectangle.
|
||||
* The actual storage representation of the coordinates is left to
|
||||
* the subclass.
|
||||
*
|
||||
* @author Jim Graham
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract class RoundRectangle2D extends RectangularShape {
|
||||
|
||||
/**
|
||||
* The <code>Float</code> class defines a rectangle with rounded
|
||||
* corners all specified in <code>float</code> coordinates.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Float extends RoundRectangle2D
|
||||
implements Serializable
|
||||
{
|
||||
/**
|
||||
* The X coordinate of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float y;
|
||||
|
||||
/**
|
||||
* The width of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float width;
|
||||
|
||||
/**
|
||||
* The height of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float height;
|
||||
|
||||
/**
|
||||
* The width of the arc that rounds off the corners.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float arcwidth;
|
||||
|
||||
/**
|
||||
* The height of the arc that rounds off the corners.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public float archeight;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>RoundRectangle2D</code>, initialized to
|
||||
* location (0.0, 0.0), size (0.0, 0.0), and corner arcs
|
||||
* of radius 0.0.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>RoundRectangle2D</code>
|
||||
* from the specified <code>float</code> coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param y the Y coordinate of the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param w the width to which to set the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param h the height to which to set the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param arcw the width of the arc to use to round off the
|
||||
* corners of the newly constructed
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param arch the height of the arc to use to round off the
|
||||
* corners of the newly constructed
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public Float(float x, float y, float w, float h,
|
||||
float arcw, float arch)
|
||||
{
|
||||
setRoundRect(x, y, w, h, arcw, arch);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return (double) x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return (double) y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getWidth() {
|
||||
return (double) width;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getHeight() {
|
||||
return (double) height;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getArcWidth() {
|
||||
return (double) arcwidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getArcHeight() {
|
||||
return (double) archeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (width <= 0.0f) || (height <= 0.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location, size, and corner radii of this
|
||||
* <code>RoundRectangle2D</code> to the specified
|
||||
* <code>float</code> values.
|
||||
*
|
||||
* @param x the X coordinate to which to set the
|
||||
* location of this <code>RoundRectangle2D</code>
|
||||
* @param y the Y coordinate to which to set the
|
||||
* location of this <code>RoundRectangle2D</code>
|
||||
* @param w the width to which to set this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param h the height to which to set this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param arcw the width to which to set the arc of this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param arch the height to which to set the arc of this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRoundRect(float x, float y, float w, float h,
|
||||
float arcw, float arch)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.arcwidth = arcw;
|
||||
this.archeight = arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRoundRect(double x, double y, double w, double h,
|
||||
double arcw, double arch)
|
||||
{
|
||||
this.x = (float) x;
|
||||
this.y = (float) y;
|
||||
this.width = (float) w;
|
||||
this.height = (float) h;
|
||||
this.arcwidth = (float) arcw;
|
||||
this.archeight = (float) arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRoundRect(RoundRectangle2D rr) {
|
||||
this.x = (float) rr.getX();
|
||||
this.y = (float) rr.getY();
|
||||
this.width = (float) rr.getWidth();
|
||||
this.height = (float) rr.getHeight();
|
||||
this.arcwidth = (float) rr.getArcWidth();
|
||||
this.archeight = (float) rr.getArcHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return new Rectangle2D.Float(x, y, width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -3423150618393866922L;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>Double</code> class defines a rectangle with rounded
|
||||
* corners all specified in <code>double</code> coordinates.
|
||||
* @since 1.2
|
||||
*/
|
||||
public static class Double extends RoundRectangle2D
|
||||
implements Serializable
|
||||
{
|
||||
/**
|
||||
* The X coordinate of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double x;
|
||||
|
||||
/**
|
||||
* The Y coordinate of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double y;
|
||||
|
||||
/**
|
||||
* The width of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double width;
|
||||
|
||||
/**
|
||||
* The height of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double height;
|
||||
|
||||
/**
|
||||
* The width of the arc that rounds off the corners.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double arcwidth;
|
||||
|
||||
/**
|
||||
* The height of the arc that rounds off the corners.
|
||||
* @since 1.2
|
||||
* @serial
|
||||
*/
|
||||
public double archeight;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>RoundRectangle2D</code>, initialized to
|
||||
* location (0.0, 0.0), size (0.0, 0.0), and corner arcs
|
||||
* of radius 0.0.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes a <code>RoundRectangle2D</code>
|
||||
* from the specified <code>double</code> coordinates.
|
||||
*
|
||||
* @param x the X coordinate of the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param y the Y coordinate of the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param w the width to which to set the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param h the height to which to set the newly
|
||||
* constructed <code>RoundRectangle2D</code>
|
||||
* @param arcw the width of the arc to use to round off the
|
||||
* corners of the newly constructed
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param arch the height of the arc to use to round off the
|
||||
* corners of the newly constructed
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public Double(double x, double y, double w, double h,
|
||||
double arcw, double arch)
|
||||
{
|
||||
setRoundRect(x, y, w, h, arcw, arch);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getArcWidth() {
|
||||
return arcwidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public double getArcHeight() {
|
||||
return archeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (width <= 0.0f) || (height <= 0.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRoundRect(double x, double y, double w, double h,
|
||||
double arcw, double arch)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.arcwidth = arcw;
|
||||
this.archeight = arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRoundRect(RoundRectangle2D rr) {
|
||||
this.x = rr.getX();
|
||||
this.y = rr.getY();
|
||||
this.width = rr.getWidth();
|
||||
this.height = rr.getHeight();
|
||||
this.arcwidth = rr.getArcWidth();
|
||||
this.archeight = rr.getArcHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public Rectangle2D getBounds2D() {
|
||||
return new Rectangle2D.Double(x, y, width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
* JDK 1.6 serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 1048939333485206117L;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an abstract class that cannot be instantiated directly.
|
||||
* Type-specific implementation subclasses are available for
|
||||
* instantiation and provide a number of formats for storing
|
||||
* the information necessary to satisfy the various accessor
|
||||
* methods below.
|
||||
*
|
||||
* @see java.awt.geom.RoundRectangle2D.Float
|
||||
* @see java.awt.geom.RoundRectangle2D.Double
|
||||
* @since 1.2
|
||||
*/
|
||||
protected RoundRectangle2D() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the arc that rounds off the corners.
|
||||
* @return the width of the arc that rounds off the corners
|
||||
* of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getArcWidth();
|
||||
|
||||
/**
|
||||
* Gets the height of the arc that rounds off the corners.
|
||||
* @return the height of the arc that rounds off the corners
|
||||
* of this <code>RoundRectangle2D</code>.
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract double getArcHeight();
|
||||
|
||||
/**
|
||||
* Sets the location, size, and corner radii of this
|
||||
* <code>RoundRectangle2D</code> to the specified
|
||||
* <code>double</code> values.
|
||||
*
|
||||
* @param x the X coordinate to which to set the
|
||||
* location of this <code>RoundRectangle2D</code>
|
||||
* @param y the Y coordinate to which to set the
|
||||
* location of this <code>RoundRectangle2D</code>
|
||||
* @param w the width to which to set this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param h the height to which to set this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param arcWidth the width to which to set the arc of this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @param arcHeight the height to which to set the arc of this
|
||||
* <code>RoundRectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public abstract void setRoundRect(double x, double y, double w, double h,
|
||||
double arcWidth, double arcHeight);
|
||||
|
||||
/**
|
||||
* Sets this <code>RoundRectangle2D</code> to be the same as the
|
||||
* specified <code>RoundRectangle2D</code>.
|
||||
* @param rr the specified <code>RoundRectangle2D</code>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setRoundRect(RoundRectangle2D rr) {
|
||||
setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
|
||||
rr.getArcWidth(), rr.getArcHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setFrame(double x, double y, double w, double h) {
|
||||
setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y) {
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
double rrx0 = getX();
|
||||
double rry0 = getY();
|
||||
double rrx1 = rrx0 + getWidth();
|
||||
double rry1 = rry0 + getHeight();
|
||||
// Check for trivial rejection - point is outside bounding rectangle
|
||||
if (x < rrx0 || y < rry0 || x >= rrx1 || y >= rry1) {
|
||||
return false;
|
||||
}
|
||||
double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
|
||||
double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
|
||||
// Check which corner point is in and do circular containment
|
||||
// test - otherwise simple acceptance
|
||||
if (x >= (rrx0 += aw) && x < (rrx0 = rrx1 - aw)) {
|
||||
return true;
|
||||
}
|
||||
if (y >= (rry0 += ah) && y < (rry0 = rry1 - ah)) {
|
||||
return true;
|
||||
}
|
||||
x = (x - rrx0) / aw;
|
||||
y = (y - rry0) / ah;
|
||||
return (x * x + y * y <= 1.0);
|
||||
}
|
||||
|
||||
private int classify(double coord, double left, double right,
|
||||
double arcsize)
|
||||
{
|
||||
if (coord < left) {
|
||||
return 0;
|
||||
} else if (coord < left + arcsize) {
|
||||
return 1;
|
||||
} else if (coord < right - arcsize) {
|
||||
return 2;
|
||||
} else if (coord < right) {
|
||||
return 3;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean intersects(double x, double y, double w, double h) {
|
||||
if (isEmpty() || w <= 0 || h <= 0) {
|
||||
return false;
|
||||
}
|
||||
double rrx0 = getX();
|
||||
double rry0 = getY();
|
||||
double rrx1 = rrx0 + getWidth();
|
||||
double rry1 = rry0 + getHeight();
|
||||
// Check for trivial rejection - bounding rectangles do not intersect
|
||||
if (x + w <= rrx0 || x >= rrx1 || y + h <= rry0 || y >= rry1) {
|
||||
return false;
|
||||
}
|
||||
double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
|
||||
double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
|
||||
int x0class = classify(x, rrx0, rrx1, aw);
|
||||
int x1class = classify(x + w, rrx0, rrx1, aw);
|
||||
int y0class = classify(y, rry0, rry1, ah);
|
||||
int y1class = classify(y + h, rry0, rry1, ah);
|
||||
// Trivially accept if any point is inside inner rectangle
|
||||
if (x0class == 2 || x1class == 2 || y0class == 2 || y1class == 2) {
|
||||
return true;
|
||||
}
|
||||
// Trivially accept if either edge spans inner rectangle
|
||||
if ((x0class < 2 && x1class > 2) || (y0class < 2 && y1class > 2)) {
|
||||
return true;
|
||||
}
|
||||
// Since neither edge spans the center, then one of the corners
|
||||
// must be in one of the rounded edges. We detect this case if
|
||||
// a [xy]0class is 3 or a [xy]1class is 1. One of those two cases
|
||||
// must be true for each direction.
|
||||
// We now find a "nearest point" to test for being inside a rounded
|
||||
// corner.
|
||||
x = (x1class == 1) ? (x = x + w - (rrx0 + aw)) : (x = x - (rrx1 - aw));
|
||||
y = (y1class == 1) ? (y = y + h - (rry0 + ah)) : (y = y - (rry1 - ah));
|
||||
x = x / aw;
|
||||
y = y / ah;
|
||||
return (x * x + y * y <= 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean contains(double x, double y, double w, double h) {
|
||||
if (isEmpty() || w <= 0 || h <= 0) {
|
||||
return false;
|
||||
}
|
||||
return (contains(x, y) &&
|
||||
contains(x + w, y) &&
|
||||
contains(x, y + h) &&
|
||||
contains(x + w, y + h));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iteration object that defines the boundary of this
|
||||
* <code>RoundRectangle2D</code>.
|
||||
* The iterator for this class is multi-threaded safe, which means
|
||||
* that this <code>RoundRectangle2D</code> class guarantees that
|
||||
* modifications to the geometry of this <code>RoundRectangle2D</code>
|
||||
* object do not affect any iterations of that geometry that
|
||||
* are already in process.
|
||||
* @param at an optional <code>AffineTransform</code> to be applied to
|
||||
* the coordinates as they are returned in the iteration, or
|
||||
* <code>null</code> if untransformed coordinates are desired
|
||||
* @return the <code>PathIterator</code> object that returns the
|
||||
* geometry of the outline of this
|
||||
* <code>RoundRectangle2D</code>, one segment at a time.
|
||||
* @since 1.2
|
||||
*/
|
||||
public PathIterator getPathIterator(AffineTransform at) {
|
||||
return new RoundRectIterator(this, at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashcode for this <code>RoundRectangle2D</code>.
|
||||
* @return the hashcode for this <code>RoundRectangle2D</code>.
|
||||
* @since 1.6
|
||||
*/
|
||||
public int hashCode() {
|
||||
long bits = java.lang.Double.doubleToLongBits(getX());
|
||||
bits += java.lang.Double.doubleToLongBits(getY()) * 37;
|
||||
bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
|
||||
bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
|
||||
bits += java.lang.Double.doubleToLongBits(getArcWidth()) * 53;
|
||||
bits += java.lang.Double.doubleToLongBits(getArcHeight()) * 59;
|
||||
return (((int) bits) ^ ((int) (bits >> 32)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the specified <code>Object</code> is
|
||||
* equal to this <code>RoundRectangle2D</code>. The specified
|
||||
* <code>Object</code> is equal to this <code>RoundRectangle2D</code>
|
||||
* if it is an instance of <code>RoundRectangle2D</code> and if its
|
||||
* location, size, and corner arc dimensions are the same as this
|
||||
* <code>RoundRectangle2D</code>.
|
||||
* @param obj an <code>Object</code> to be compared with this
|
||||
* <code>RoundRectangle2D</code>.
|
||||
* @return <code>true</code> if <code>obj</code> is an instance
|
||||
* of <code>RoundRectangle2D</code> and has the same values;
|
||||
* <code>false</code> otherwise.
|
||||
* @since 1.6
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof RoundRectangle2D) {
|
||||
RoundRectangle2D rr2d = (RoundRectangle2D) obj;
|
||||
return ((getX() == rr2d.getX()) &&
|
||||
(getY() == rr2d.getY()) &&
|
||||
(getWidth() == rr2d.getWidth()) &&
|
||||
(getHeight() == rr2d.getHeight()) &&
|
||||
(getArcWidth() == rr2d.getArcWidth()) &&
|
||||
(getArcHeight() == rr2d.getArcHeight()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user