diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/java/awt/geom/RoundRectangle2D.java | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2 |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/java/awt/geom/RoundRectangle2D.java')
-rw-r--r-- | libjava/classpath/java/awt/geom/RoundRectangle2D.java | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/libjava/classpath/java/awt/geom/RoundRectangle2D.java b/libjava/classpath/java/awt/geom/RoundRectangle2D.java new file mode 100644 index 0000000..ac0e6f8 --- /dev/null +++ b/libjava/classpath/java/awt/geom/RoundRectangle2D.java @@ -0,0 +1,533 @@ +/* RoundRectangle2D.java -- represents a rectangle with rounded corners + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.util.NoSuchElementException; + + +/** This class implements a rectangle with rounded corners. + * @author Tom Tromey (tromey@cygnus.com) + * @date December 3, 2000 + */ +public abstract class RoundRectangle2D extends RectangularShape +{ + /** Return the arc height of this round rectangle. */ + public abstract double getArcHeight(); + + /** Return the arc width of this round rectangle. */ + public abstract double getArcWidth(); + + /** Set the values of this round rectangle + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @param arcWidth The arc width + * @param arcHeight The arc height + */ + public abstract void setRoundRect(double x, double y, double w, double h, + double arcWidth, double arcHeight); + + /** Create a RoundRectangle2D. This is protected because this class + * is abstract and cannot be instantiated. + */ + protected RoundRectangle2D() + { + } + + /** Return true if this object contains the specified point. + * @param x The x coordinate + * @param y The y coordinate + */ + public boolean contains(double x, double y) + { + double mx = getX(); + double mw = getWidth(); + if (x < mx || x >= mx + mw) + return false; + double my = getY(); + double mh = getHeight(); + if (y < my || y >= my + mh) + return false; + + // Now check to see if the point is in range of an arc. + double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y)); + double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x)); + + // The arc dimensions are that of the corresponding ellipse + // thus a 90 degree segment is half of that. + double aw = getArcWidth() / 2.0; + double ah = getArcHeight() / 2.0; + if (dx > aw || dy > ah) + return true; + + // At this point DX represents the distance from the nearest edge + // of the rectangle. But we want to transform it to represent the + // scaled distance from the center of the ellipse that forms the + // arc. Hence this code: + dy = (ah - dy) / ah; + dx = (aw - dx) / aw; + + return dx * dx + dy * dy <= 1.0; + } + + /** Return true if this object contains the specified rectangle + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public boolean contains(double x, double y, double w, double h) + { + // We have to check all four points here (for ordinary rectangles + // we can just check opposing corners). + return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h) + && contains(x + w, y)); + } + + /** Return a new path iterator which iterates over this rectangle. + * @param at An affine transform to apply to the object + */ + public PathIterator getPathIterator(final AffineTransform at) + { + final double minx = getX(); + final double miny = getY(); + final double maxx = minx + getWidth(); + final double maxy = miny + getHeight(); + final double arcwidth = getArcWidth(); + final double archeight = getArcHeight(); + return new PathIterator() + { + /** We iterate counterclockwise around the rectangle, starting in the + * upper right. This variable tracks our current point, which + * can be on either side of a given corner. */ + private int current = 0; + + /** Child path iterator, used for corners. */ + private PathIterator corner; + + /** This is used when rendering the corners. We re-use the arc + * for each corner. */ + private Arc2D arc = new Arc2D.Double(); + + /** Temporary array used by getPoint. */ + private double[] temp = new double[2]; + + public int getWindingRule() + { + return WIND_NON_ZERO; + } + + public boolean isDone() + { + return current > 9; + } + + private void getPoint(int val) + { + switch (val) + { + case 0: + case 8: + temp[0] = maxx; + temp[1] = miny + archeight; + break; + case 7: + temp[0] = maxx; + temp[1] = maxy - archeight; + break; + case 6: + temp[0] = maxx - arcwidth; + temp[1] = maxy; + break; + case 5: + temp[0] = minx + arcwidth; + temp[1] = maxy; + break; + case 4: + temp[0] = minx; + temp[1] = maxy - archeight; + break; + case 3: + temp[0] = minx; + temp[1] = miny + archeight; + break; + case 2: + temp[0] = minx + arcwidth; + temp[1] = miny; + break; + case 1: + temp[0] = maxx - arcwidth; + temp[1] = miny; + break; + } + } + + public void next() + { + if (current >= 8) + ++current; + else if (corner != null) + { + // We're iterating through the corner. Work on the child + // iterator; if it finishes, reset and move to the next + // point along the rectangle. + corner.next(); + if (corner.isDone()) + { + corner = null; + ++current; + } + } + else + { + // Make an arc between this point on the rectangle and + // the next one, and then iterate over this arc. + getPoint(current); + double x1 = temp[0]; + double y1 = temp[1]; + getPoint(current + 1); + Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1, + temp[0]), + Math.min(y1, + temp[1]), + Math.abs(x1 + - temp[0]), + Math.abs(y1 + - temp[1])); + arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN); + corner = arc.getPathIterator(at); + } + } + + public int currentSegment(float[] coords) + { + if (corner != null) + { + int r = corner.currentSegment(coords); + if (r == SEG_MOVETO) + r = SEG_LINETO; + return r; + } + + if (current < 9) + { + getPoint(current); + coords[0] = (float) temp[0]; + coords[1] = (float) temp[1]; + } + else if (current == 9) + return SEG_CLOSE; + else + throw new NoSuchElementException("rect iterator out of bounds"); + + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return current == 0 ? SEG_MOVETO : SEG_LINETO; + } + + public int currentSegment(double[] coords) + { + if (corner != null) + { + int r = corner.currentSegment(coords); + if (r == SEG_MOVETO) + r = SEG_LINETO; + return r; + } + + if (current < 9) + { + getPoint(current); + coords[0] = temp[0]; + coords[1] = temp[1]; + } + else if (current == 9) + return SEG_CLOSE; + else + throw new NoSuchElementException("rect iterator out of bounds"); + + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return current == 0 ? SEG_MOVETO : SEG_LINETO; + } + }; + } + + /** Return true if the given rectangle intersects this shape. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public boolean intersects(double x, double y, double w, double h) + { + // Check if any corner is within the rectangle + return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h) + || contains(x + w, y)); + } + + /** Set the boundary of this round rectangle. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public void setFrame(double x, double y, double w, double h) + { + // This is a bit lame. + setRoundRect(x, y, w, h, getArcWidth(), getArcHeight()); + } + + /** Set the values of this round rectangle to be the same as those + * of the argument. + * @param rr The round rectangle to copy + */ + public void setRoundRect(RoundRectangle2D rr) + { + setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(), + rr.getArcWidth(), rr.getArcHeight()); + } + + /** A subclass of RoundRectangle which keeps its parameters as + * doubles. */ + public static class Double extends RoundRectangle2D + { + /** The height of the corner arc. */ + public double archeight; + + /** The width of the corner arc. */ + public double arcwidth; + + /** The x coordinate of this object. */ + public double x; + + /** The y coordinate of this object. */ + public double y; + + /** The width of this object. */ + public double width; + + /** The height of this object. */ + public double height; + + /** Construct a new instance, with all parameters set to 0. */ + public Double() + { + } + + /** Construct a new instance with the given arguments. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @param arcWidth The arc width + * @param arcHeight The arc height + */ + public Double(double x, double y, double w, double h, double arcWidth, + double arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + + public double getArcHeight() + { + return archeight; + } + + public double getArcWidth() + { + return arcwidth; + } + + public Rectangle2D getBounds2D() + { + return new Rectangle2D.Double(x, y, width, height); + } + + public double getX() + { + return x; + } + + public double getY() + { + return y; + } + + public double getWidth() + { + return width; + } + + public double getHeight() + { + return height; + } + + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + public void setRoundRect(double x, double y, double w, double h, + double arcWidth, double arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + } // class Double + + /** A subclass of RoundRectangle which keeps its parameters as + * floats. */ + public static class Float extends RoundRectangle2D + { + /** The height of the corner arc. */ + public float archeight; + + /** The width of the corner arc. */ + public float arcwidth; + + /** The x coordinate of this object. */ + public float x; + + /** The y coordinate of this object. */ + public float y; + + /** The width of this object. */ + public float width; + + /** The height of this object. */ + public float height; + + /** Construct a new instance, with all parameters set to 0. */ + public Float() + { + } + + /** Construct a new instance with the given arguments. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @param arcWidth The arc width + * @param arcHeight The arc height + */ + public Float(float x, float y, float w, float h, float arcWidth, + float arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + + public double getArcHeight() + { + return archeight; + } + + public double getArcWidth() + { + return arcwidth; + } + + public Rectangle2D getBounds2D() + { + return new Rectangle2D.Float(x, y, width, height); + } + + public double getX() + { + return x; + } + + public double getY() + { + return y; + } + + public double getWidth() + { + return width; + } + + public double getHeight() + { + return height; + } + + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + public void setRoundRect(float x, float y, float w, float h, + float arcWidth, float arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + + public void setRoundRect(double x, double y, double w, double h, + double arcWidth, double arcHeight) + { + this.x = (float) x; + this.y = (float) y; + this.width = (float) w; + this.height = (float) h; + this.arcwidth = (float) arcWidth; + this.archeight = (float) arcHeight; + } + } // class Float +} // class RoundRectangle2D |