Merge from the pain train
[official-gcc.git] / libjava / java / awt / geom / RoundRectangle2D.java
blobb9af7efc7ee5522733dadb1b2d4fb44127e3c7e5
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)
9 any later version.
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
19 02111-1307 USA.
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
24 combination.
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
58 * @param w The width
59 * @param h The height
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)
79 double mx = getX();
80 double mw = getWidth();
81 if (x < mx || x >= mx + mw)
82 return false;
83 double my = getY();
84 double mh = getHeight();
85 if (y < my || y >= my + mh)
86 return false;
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)
97 return true;
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:
103 dy = (ah - dy) / ah;
104 dx = (aw - dx) / aw;
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
112 * @param w The width
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()
158 return current > 9;
161 private void getPoint(int val)
163 switch (val)
165 case 0:
166 case 8:
167 temp[0] = maxx;
168 temp[1] = miny + archeight;
169 break;
170 case 7:
171 temp[0] = maxx;
172 temp[1] = maxy - archeight;
173 break;
174 case 6:
175 temp[0] = maxx - arcwidth;
176 temp[1] = maxy;
177 break;
178 case 5:
179 temp[0] = minx + arcwidth;
180 temp[1] = maxy;
181 break;
182 case 4:
183 temp[0] = minx;
184 temp[1] = maxy - archeight;
185 break;
186 case 3:
187 temp[0] = minx;
188 temp[1] = miny + archeight;
189 break;
190 case 2:
191 temp[0] = minx + arcwidth;
192 temp[1] = miny;
193 break;
194 case 1:
195 temp[0] = maxx - arcwidth;
196 temp[1] = miny;
197 break;
201 public void next()
203 if (current >= 8)
204 ++current;
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.
210 corner.next();
211 if (corner.isDone())
213 corner = null;
214 ++current;
217 else
219 // Make an arc between this point on the rectangle and
220 // the next one, and then iterate over this arc.
221 getPoint(current);
222 double x1 = temp[0];
223 double y1 = temp[1];
224 getPoint(current + 1);
225 Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1,
226 temp[0]),
227 Math.min(y1,
228 temp[1]),
229 Math.abs(x1
230 - temp[0]),
231 Math.abs(y1
232 - temp[1]));
233 arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN);
234 corner = arc.getPathIterator(at);
238 public int currentSegment(float[] coords)
240 if (corner != null)
242 int r = corner.currentSegment(coords);
243 if (r == SEG_MOVETO)
244 r = SEG_LINETO;
245 return r;
248 if (current < 9)
250 getPoint(current);
251 coords[0] = (float) temp[0];
252 coords[1] = (float) temp[1];
254 else if (current == 9)
255 return SEG_CLOSE;
256 else
257 throw new NoSuchElementException("rect iterator out of bounds");
259 if (at != null)
260 at.transform(coords, 0, coords, 0, 1);
261 return current == 0 ? SEG_MOVETO : SEG_LINETO;
264 public int currentSegment(double[] coords)
266 if (corner != null)
268 int r = corner.currentSegment(coords);
269 if (r == SEG_MOVETO)
270 r = SEG_LINETO;
271 return r;
274 if (current < 9)
276 getPoint(current);
277 coords[0] = temp[0];
278 coords[1] = temp[1];
280 else if (current == 9)
281 return SEG_CLOSE;
282 else
283 throw new NoSuchElementException("rect iterator out of bounds");
285 if (at != null)
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
295 * @param w The width
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
308 * @param w The width
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
318 * of the argument.
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
328 * doubles. */
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. */
338 public double x;
340 /** The y coordinate of this object. */
341 public double y;
343 /** The width of this object. */
344 public double width;
346 /** The height of this object. */
347 public double height;
349 /** Construct a new instance, with all parameters set to 0. */
350 public Double()
354 /** Construct a new instance with the given arguments.
355 * @param x The x coordinate
356 * @param y The y coordinate
357 * @param w The width
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,
363 double arcHeight)
365 this.x = x;
366 this.y = y;
367 this.width = w;
368 this.height = h;
369 this.arcwidth = arcWidth;
370 this.archeight = arcHeight;
373 public double getArcHeight()
375 return archeight;
378 public double getArcWidth()
380 return arcwidth;
383 public Rectangle2D getBounds2D()
385 return new Rectangle2D.Double(x, y, width, height);
388 public double getX()
390 return x;
393 public double getY()
395 return y;
398 public double getWidth()
400 return width;
403 public double getHeight()
405 return height;
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)
416 this.x = x;
417 this.y = y;
418 this.width = w;
419 this.height = h;
420 this.arcwidth = arcWidth;
421 this.archeight = arcHeight;
423 } // class Double
425 /** A subclass of RoundRectangle which keeps its parameters as
426 * floats. */
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. */
436 public float x;
438 /** The y coordinate of this object. */
439 public float y;
441 /** The width of this object. */
442 public float width;
444 /** The height of this object. */
445 public float height;
447 /** Construct a new instance, with all parameters set to 0. */
448 public Float()
452 /** Construct a new instance with the given arguments.
453 * @param x The x coordinate
454 * @param y The y coordinate
455 * @param w The width
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,
461 float arcHeight)
463 this.x = x;
464 this.y = y;
465 this.width = w;
466 this.height = h;
467 this.arcwidth = arcWidth;
468 this.archeight = arcHeight;
471 public double getArcHeight()
473 return archeight;
476 public double getArcWidth()
478 return arcwidth;
481 public Rectangle2D getBounds2D()
483 return new Rectangle2D.Float(x, y, width, height);
486 public double getX()
488 return x;
491 public double getY()
493 return y;
496 public double getWidth()
498 return width;
501 public double getHeight()
503 return height;
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)
514 this.x = x;
515 this.y = y;
516 this.width = w;
517 this.height = h;
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)
525 this.x = (float) x;
526 this.y = (float) y;
527 this.width = (float) w;
528 this.height = (float) h;
529 this.arcwidth = (float) arcWidth;
530 this.archeight = (float) arcHeight;
532 } // class Float
533 } // class RoundRectangle2D