1 /* RoundRectangle2D.java -- represents a rectangle with rounded corners
2 Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package java.awt.geom;
40 import java.util.NoSuchElementException;
43 /** This class implements a rectangle with rounded corners.
44 * @author Tom Tromey <tromey@cygnus.com>
45 * @date December 3, 2000
47 public abstract class RoundRectangle2D extends RectangularShape
49 /** Return the arc height of this round rectangle. */
50 public abstract double getArcHeight();
52 /** Return the arc width of this round rectangle. */
53 public abstract double getArcWidth();
55 /** Set the values of this round rectangle
56 * @param x The x coordinate
57 * @param y The y coordinate
60 * @param arcWidth The arc width
61 * @param arcHeight The arc height
63 public abstract void setRoundRect(double x, double y, double w, double h,
64 double arcWidth, double arcHeight);
66 /** Create a RoundRectangle2D. This is protected because this class
67 * is abstract and cannot be instantiated.
69 protected RoundRectangle2D()
73 /** Return true if this object contains the specified point.
74 * @param x The x coordinate
75 * @param y The y coordinate
77 public boolean contains(double x, double y)
80 double mw = getWidth();
81 if (x < mx || x >= mx + mw)
84 double mh = getHeight();
85 if (y < my || y >= my + mh)
88 // Now check to see if the point is in range of an arc.
89 double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y));
90 double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x));
92 // The arc dimensions are that of the corresponding ellipse
93 // thus a 90 degree segment is half of that.
94 double aw = getArcWidth() / 2.0;
95 double ah = getArcHeight() / 2.0;
96 if (dx > aw || dy > ah)
99 // At this point DX represents the distance from the nearest edge
100 // of the rectangle. But we want to transform it to represent the
101 // scaled distance from the center of the ellipse that forms the
102 // arc. Hence this code:
106 return dx * dx + dy * dy <= 1.0;
109 /** Return true if this object contains the specified rectangle
110 * @param x The x coordinate
111 * @param y The y coordinate
113 * @param h The height
115 public boolean contains(double x, double y, double w, double h)
117 // We have to check all four points here (for ordinary rectangles
118 // we can just check opposing corners).
119 return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h)
120 && contains(x + w, y));
123 /** Return a new path iterator which iterates over this rectangle.
124 * @param at An affine transform to apply to the object
126 public PathIterator getPathIterator(final AffineTransform at)
128 final double minx = getX();
129 final double miny = getY();
130 final double maxx = minx + getWidth();
131 final double maxy = miny + getHeight();
132 final double arcwidth = getArcWidth();
133 final double archeight = getArcHeight();
134 return new PathIterator()
136 /** We iterate counterclockwise around the rectangle, starting in the
137 * upper right. This variable tracks our current point, which
138 * can be on either side of a given corner. */
139 private int current = 0;
141 /** Child path iterator, used for corners. */
142 private PathIterator corner;
144 /** This is used when rendering the corners. We re-use the arc
145 * for each corner. */
146 private Arc2D arc = new Arc2D.Double();
148 /** Temporary array used by getPoint. */
149 private double[] temp = new double[2];
151 public int getWindingRule()
153 return WIND_NON_ZERO;
156 public boolean isDone()
161 private void getPoint(int val)
168 temp[1] = miny + archeight;
172 temp[1] = maxy - archeight;
175 temp[0] = maxx - arcwidth;
179 temp[0] = minx + arcwidth;
184 temp[1] = maxy - archeight;
188 temp[1] = miny + archeight;
191 temp[0] = minx + arcwidth;
195 temp[0] = maxx - arcwidth;
205 else if (corner != null)
207 // We're iterating through the corner. Work on the child
208 // iterator; if it finishes, reset and move to the next
209 // point along the rectangle.
219 // Make an arc between this point on the rectangle and
220 // the next one, and then iterate over this arc.
224 getPoint(current + 1);
225 Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1,
233 arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN);
234 corner = arc.getPathIterator(at);
238 public int currentSegment(float[] coords)
242 int r = corner.currentSegment(coords);
251 coords[0] = (float) temp[0];
252 coords[1] = (float) temp[1];
254 else if (current == 9)
257 throw new NoSuchElementException("rect iterator out of bounds");
260 at.transform(coords, 0, coords, 0, 1);
261 return current == 0 ? SEG_MOVETO : SEG_LINETO;
264 public int currentSegment(double[] coords)
268 int r = corner.currentSegment(coords);
280 else if (current == 9)
283 throw new NoSuchElementException("rect iterator out of bounds");
286 at.transform(coords, 0, coords, 0, 1);
287 return current == 0 ? SEG_MOVETO : SEG_LINETO;
292 /** Return true if the given rectangle intersects this shape.
293 * @param x The x coordinate
294 * @param y The y coordinate
296 * @param h The height
298 public boolean intersects(double x, double y, double w, double h)
300 // Check if any corner is within the rectangle
301 return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h)
302 || contains(x + w, y));
305 /** Set the boundary of this round rectangle.
306 * @param x The x coordinate
307 * @param y The y coordinate
309 * @param h The height
311 public void setFrame(double x, double y, double w, double h)
313 // This is a bit lame.
314 setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
317 /** Set the values of this round rectangle to be the same as those
319 * @param rr The round rectangle to copy
321 public void setRoundRect(RoundRectangle2D rr)
323 setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
324 rr.getArcWidth(), rr.getArcHeight());
327 /** A subclass of RoundRectangle which keeps its parameters as
329 public static class Double extends RoundRectangle2D
331 /** The height of the corner arc. */
332 public double archeight;
334 /** The width of the corner arc. */
335 public double arcwidth;
337 /** The x coordinate of this object. */
340 /** The y coordinate of this object. */
343 /** The width of this object. */
346 /** The height of this object. */
347 public double height;
349 /** Construct a new instance, with all parameters set to 0. */
354 /** Construct a new instance with the given arguments.
355 * @param x The x coordinate
356 * @param y The y coordinate
358 * @param h The height
359 * @param arcWidth The arc width
360 * @param arcHeight The arc height
362 public Double(double x, double y, double w, double h, double arcWidth,
369 this.arcwidth = arcWidth;
370 this.archeight = arcHeight;
373 public double getArcHeight()
378 public double getArcWidth()
383 public Rectangle2D getBounds2D()
385 return new Rectangle2D.Double(x, y, width, height);
398 public double getWidth()
403 public double getHeight()
408 public boolean isEmpty()
410 return width <= 0 || height <= 0;
413 public void setRoundRect(double x, double y, double w, double h,
414 double arcWidth, double arcHeight)
420 this.arcwidth = arcWidth;
421 this.archeight = arcHeight;
425 /** A subclass of RoundRectangle which keeps its parameters as
427 public static class Float extends RoundRectangle2D
429 /** The height of the corner arc. */
430 public float archeight;
432 /** The width of the corner arc. */
433 public float arcwidth;
435 /** The x coordinate of this object. */
438 /** The y coordinate of this object. */
441 /** The width of this object. */
444 /** The height of this object. */
447 /** Construct a new instance, with all parameters set to 0. */
452 /** Construct a new instance with the given arguments.
453 * @param x The x coordinate
454 * @param y The y coordinate
456 * @param h The height
457 * @param arcWidth The arc width
458 * @param arcHeight The arc height
460 public Float(float x, float y, float w, float h, float arcWidth,
467 this.arcwidth = arcWidth;
468 this.archeight = arcHeight;
471 public double getArcHeight()
476 public double getArcWidth()
481 public Rectangle2D getBounds2D()
483 return new Rectangle2D.Float(x, y, width, height);
496 public double getWidth()
501 public double getHeight()
506 public boolean isEmpty()
508 return width <= 0 || height <= 0;
511 public void setRoundRect(float x, float y, float w, float h,
512 float arcWidth, float arcHeight)
518 this.arcwidth = arcWidth;
519 this.archeight = arcHeight;
522 public void setRoundRect(double x, double y, double w, double h,
523 double arcWidth, double arcHeight)
527 this.width = (float) w;
528 this.height = (float) h;
529 this.arcwidth = (float) arcWidth;
530 this.archeight = (float) arcHeight;
533 } // class RoundRectangle2D