2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / awt / geom / RoundRectangle2D.java
blob3a7899d3ed5bb786085de4e4d4c331588f1ada61
1 /* RoundRectangle2D.java -- represents a rectangle with rounded corners
2 Copyright (C) 2000, 2002, 2003 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;
42 /** This class implements a rectangle with rounded corners.
43 * @author Tom Tromey <tromey@cygnus.com>
44 * @date December 3, 2000
46 public abstract class RoundRectangle2D extends RectangularShape
48 /** Return the arc height of this round rectangle. */
49 public abstract double getArcHeight();
51 /** Return the arc width of this round rectangle. */
52 public abstract double getArcWidth();
54 /** Set the values of this round rectangle
55 * @param x The x coordinate
56 * @param y The y coordinate
57 * @param w The width
58 * @param h The height
59 * @param arcWidth The arc width
60 * @param arcHeight The arc height
62 public abstract void setRoundRect(double x, double y, double w, double h,
63 double arcWidth, double arcHeight);
65 /** Create a RoundRectangle2D. This is protected because this class
66 * is abstract and cannot be instantiated.
68 protected RoundRectangle2D()
72 /** Return true if this object contains the specified point.
73 * @param x The x coordinate
74 * @param y The y coordinate
76 public boolean contains(double x, double y)
78 double mx = getX();
79 double mw = getWidth();
80 if (x < mx || x >= mx + mw)
81 return false;
82 double my = getY();
83 double mh = getHeight();
84 if (y < my || y >= my + mh)
85 return false;
87 // Now check to see if the point is in range of an arc.
88 double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y));
89 double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x));
90 double aw = getArcWidth();
91 double ah = getArcHeight();
92 if (dx > aw || dy > ah)
93 return true;
95 // At this point DX represents the distance from the nearest edge
96 // of the rectangle. But we want to transform it to represent the
97 // scaled distance from the center of the ellipse that forms the
98 // arc. Hence this code:
99 dy = (ah - dy) / ah;
100 dx = (aw - dx) / aw;
102 return dx * dx + dy * dy <= 1.0;
105 /** Return true if this object contains the specified rectangle
106 * @param x The x coordinate
107 * @param y The y coordinate
108 * @param w The width
109 * @param h The height
111 public boolean contains(double x, double y, double w, double h)
113 // We have to check all four points here (for ordinary rectangles
114 // we can just check opposing corners).
115 return (contains(x, y) && contains(x + w, h)
116 && contains(x, y + h) && contains(x + w, y + h));
119 /** Return a new path iterator which iterates over this rectangle.
120 * @param at An affine transform to apply to the object
122 public PathIterator getPathIterator(final AffineTransform at)
124 final double minx = getX();
125 final double miny = getY();
126 final double maxx = minx + getWidth();
127 final double maxy = miny + getHeight();
128 final double arcwidth = getArcWidth();
129 final double archeight = getArcHeight();
130 return new PathIterator()
132 /** We iterate clockwise around the rectangle, starting in the
133 * upper left. This variable tracks our current point, which
134 * can be on either side of a given corner. */
135 private int current = 0;
137 /** Child path iterator, used for corners. */
138 private PathIterator corner;
140 /** This is used when rendering the corners. We re-use the arc
141 * for each corner. */
142 private Arc2D arc = new Arc2D.Double();
144 /** Temporary array used by getPoint. */
145 private double[] temp = new double[2];
147 public int getWindingRule()
149 return WIND_NON_ZERO;
152 public boolean isDone()
154 return current > 9;
157 private void getPoint(int val)
159 switch (val)
161 case 0:
162 case 8:
163 temp[0] = minx;
164 temp[1] = miny + archeight;
165 break;
166 case 1:
167 temp[0] = minx + arcwidth;
168 temp[1] = miny;
169 break;
170 case 2:
171 temp[0] = maxx - arcwidth;
172 temp[1] = maxy;
173 break;
174 case 3:
175 temp[0] = maxx;
176 temp[1] = miny + archeight;
177 break;
178 case 4:
179 temp[0] = maxx;
180 temp[1] = maxy - archeight;
181 break;
182 case 5:
183 temp[0] = maxx - arcwidth;
184 temp[1] = maxy;
185 break;
186 case 6:
187 temp[0] = minx + arcwidth;
188 temp[1] = maxy;
189 break;
190 case 7:
191 temp[0] = minx;
192 temp[1] = maxy - archeight;
193 break;
197 public void next()
199 if (current >= 8)
200 ++current;
201 else if (corner != null)
203 // We're iterating through the corner. Work on the child
204 // iterator; if it finishes, reset and move to the next
205 // point along the rectangle.
206 corner.next();
207 if (corner.isDone())
209 corner = null;
210 ++current;
213 else
215 // Make an arc between this point on the rectangle and
216 // the next one, and then iterate over this arc.
217 getPoint(current);
218 double x1 = temp[0];
219 double y1 = temp[1];
220 getPoint(current + 1);
221 arc.setFrameFromDiagonal(x1, y1, temp[0], temp[1]);
222 arc.setAngles(x1, y1, temp[0], temp[1]);
223 corner = arc.getPathIterator(at);
227 public int currentSegment(float[] coords)
229 if (corner != null)
231 int r = corner.currentSegment(coords);
232 if (r == SEG_MOVETO)
233 r = SEG_LINETO;
234 return r;
237 if (current < 9)
239 getPoint(current);
240 coords[0] = (float) temp[0];
241 coords[1] = (float) temp[1];
243 else if (current == 9)
244 return SEG_CLOSE;
245 else
246 throw new NoSuchElementException("rect iterator out of bounds");
248 if (at != null)
249 at.transform(coords, 0, coords, 0, 1);
250 return current == 0 ? SEG_MOVETO : SEG_LINETO;
253 public int currentSegment(double[] coords)
255 if (corner != null)
257 int r = corner.currentSegment(coords);
258 if (r == SEG_MOVETO)
259 r = SEG_LINETO;
260 return r;
263 if (current < 9)
265 getPoint(current);
266 coords[0] = temp[0];
267 coords[1] = temp[1];
269 else if (current == 9)
270 return SEG_CLOSE;
271 else
272 throw new NoSuchElementException("rect iterator out of bounds");
274 if (at != null)
275 at.transform(coords, 0, coords, 0, 1);
276 return current == 0 ? SEG_MOVETO : SEG_LINETO;
281 /** Return true if the given rectangle intersects this shape.
282 * @param x The x coordinate
283 * @param y The y coordinate
284 * @param w The width
285 * @param h The height
287 public boolean intersects(double x, double y, double w, double h)
289 // Here we can use the same code we use for an ordinary rectangle.
290 double mx = getX();
291 double mw = getWidth();
292 if (x < mx || x >= mx + mw || x + w < mx || x + w >= mx + mw)
293 return false;
294 double my = getY();
295 double mh = getHeight();
296 return y >= my && y < my + mh && y + h >= my && y + h < my + mh;
299 /** Set the boundary of this round rectangle.
300 * @param x The x coordinate
301 * @param y The y coordinate
302 * @param w The width
303 * @param h The height
305 public void setFrame(double x, double y, double w, double h)
307 // This is a bit lame.
308 setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
311 /** Set the values of this round rectangle to be the same as those
312 * of the argument.
313 * @param rr The round rectangle to copy
315 public void setRoundRect(RoundRectangle2D rr)
317 setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
318 rr.getArcWidth(), rr.getArcHeight());
321 /** A subclass of RoundRectangle which keeps its parameters as
322 * doubles. */
323 public static class Double extends RoundRectangle2D
325 /** The height of the corner arc. */
326 public double archeight;
328 /** The width of the corner arc. */
329 public double arcwidth;
331 /** The x coordinate of this object. */
332 public double x;
334 /** The y coordinate of this object. */
335 public double y;
337 /** The width of this object. */
338 public double width;
340 /** The height of this object. */
341 public double height;
343 /** Construct a new instance, with all parameters set to 0. */
344 public Double()
348 /** Construct a new instance with the given arguments.
349 * @param x The x coordinate
350 * @param y The y coordinate
351 * @param w The width
352 * @param h The height
353 * @param arcWidth The arc width
354 * @param arcHeight The arc height
356 public Double(double x, double y, double w, double h,
357 double arcWidth, double arcHeight)
359 this.x = x;
360 this.y = y;
361 this.width = w;
362 this.height = h;
363 this.arcwidth = arcWidth;
364 this.archeight = arcHeight;
367 public double getArcHeight()
369 return archeight;
372 public double getArcWidth()
374 return arcwidth;
377 public Rectangle2D getBounds2D()
379 return new Rectangle2D.Double(x, y, width, height);
382 public double getX()
384 return x;
387 public double getY()
389 return y;
392 public double getWidth()
394 return width;
397 public double getHeight()
399 return height;
402 public boolean isEmpty()
404 return width <= 0 || height <= 0;
407 public void setRoundRect(double x, double y, double w, double h,
408 double arcWidth, double arcHeight)
410 this.x = x;
411 this.y = y;
412 this.width = w;
413 this.height = h;
414 this.arcwidth = arcWidth;
415 this.archeight = arcHeight;
417 } // class Double
419 /** A subclass of RoundRectangle which keeps its parameters as
420 * floats. */
421 public static class Float extends RoundRectangle2D
423 /** The height of the corner arc. */
424 public float archeight;
426 /** The width of the corner arc. */
427 public float arcwidth;
429 /** The x coordinate of this object. */
430 public float x;
432 /** The y coordinate of this object. */
433 public float y;
435 /** The width of this object. */
436 public float width;
438 /** The height of this object. */
439 public float height;
441 /** Construct a new instance, with all parameters set to 0. */
442 public Float()
446 /** Construct a new instance with the given arguments.
447 * @param x The x coordinate
448 * @param y The y coordinate
449 * @param w The width
450 * @param h The height
451 * @param arcWidth The arc width
452 * @param arcHeight The arc height
454 public Float(float x, float y, float w, float h,
455 float arcWidth, float arcHeight)
457 this.x = x;
458 this.y = y;
459 this.width = w;
460 this.height = h;
461 this.arcwidth = arcWidth;
462 this.archeight = arcHeight;
465 public double getArcHeight()
467 return archeight;
470 public double getArcWidth()
472 return arcwidth;
475 public Rectangle2D getBounds2D()
477 return new Rectangle2D.Float(x, y, width, height);
480 public double getX()
482 return x;
485 public double getY()
487 return y;
490 public double getWidth()
492 return width;
495 public double getHeight()
497 return height;
500 public boolean isEmpty()
502 return width <= 0 || height <= 0;
505 public void setRoundRect(float x, float y, float w, float h,
506 float arcWidth, float arcHeight)
508 this.x = x;
509 this.y = y;
510 this.width = w;
511 this.height = h;
512 this.arcwidth = arcWidth;
513 this.archeight = arcHeight;
516 public void setRoundRect(double x, double y, double w, double h,
517 double arcWidth, double arcHeight)
519 this.x = (float) x;
520 this.y = (float) y;
521 this.width = (float) w;
522 this.height = (float) h;
523 this.arcwidth = (float) arcWidth;
524 this.archeight = (float) arcHeight;
526 } // class Float
527 } // class RoundRectangle2D