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)
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
;
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
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
)
79 double mw
= getWidth();
80 if (x
< mx
|| x
>= mx
+ mw
)
83 double mh
= getHeight();
84 if (y
< my
|| y
>= my
+ mh
)
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
)
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:
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
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()
157 private void getPoint(int val
)
164 temp
[1] = miny
+ archeight
;
167 temp
[0] = minx
+ arcwidth
;
171 temp
[0] = maxx
- arcwidth
;
176 temp
[1] = miny
+ archeight
;
180 temp
[1] = maxy
- archeight
;
183 temp
[0] = maxx
- arcwidth
;
187 temp
[0] = minx
+ arcwidth
;
192 temp
[1] = maxy
- archeight
;
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.
215 // Make an arc between this point on the rectangle and
216 // the next one, and then iterate over this arc.
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
)
231 int r
= corner
.currentSegment(coords
);
240 coords
[0] = (float) temp
[0];
241 coords
[1] = (float) temp
[1];
243 else if (current
== 9)
246 throw new NoSuchElementException("rect iterator out of bounds");
249 at
.transform(coords
, 0, coords
, 0, 1);
250 return current
== 0 ? SEG_MOVETO
: SEG_LINETO
;
253 public int currentSegment(double[] coords
)
257 int r
= corner
.currentSegment(coords
);
269 else if (current
== 9)
272 throw new NoSuchElementException("rect iterator out of bounds");
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
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.
291 double mw
= getWidth();
292 if (x
< mx
|| x
>= mx
+ mw
|| x
+ w
< mx
|| x
+ w
>= mx
+ mw
)
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
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
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
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. */
334 /** The y coordinate of this object. */
337 /** The width of this object. */
340 /** The height of this object. */
341 public double height
;
343 /** Construct a new instance, with all parameters set to 0. */
348 /** Construct a new instance with the given arguments.
349 * @param x The x coordinate
350 * @param y The y coordinate
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
)
363 this.arcwidth
= arcWidth
;
364 this.archeight
= arcHeight
;
367 public double getArcHeight()
372 public double getArcWidth()
377 public Rectangle2D
getBounds2D()
379 return new Rectangle2D
.Double(x
, y
, width
, height
);
392 public double getWidth()
397 public double getHeight()
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
)
414 this.arcwidth
= arcWidth
;
415 this.archeight
= arcHeight
;
419 /** A subclass of RoundRectangle which keeps its parameters as
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. */
432 /** The y coordinate of this object. */
435 /** The width of this object. */
438 /** The height of this object. */
441 /** Construct a new instance, with all parameters set to 0. */
446 /** Construct a new instance with the given arguments.
447 * @param x The x coordinate
448 * @param y The y coordinate
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
)
461 this.arcwidth
= arcWidth
;
462 this.archeight
= arcHeight
;
465 public double getArcHeight()
470 public double getArcWidth()
475 public Rectangle2D
getBounds2D()
477 return new Rectangle2D
.Float(x
, y
, width
, height
);
490 public double getWidth()
495 public double getHeight()
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
)
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
)
521 this.width
= (float) w
;
522 this.height
= (float) h
;
523 this.arcwidth
= (float) arcWidth
;
524 this.archeight
= (float) arcHeight
;
527 } // class RoundRectangle2D