1 /* Rectangle.java -- represents a graphics rectangle
2 Copyright (C) 1999, 2000, 2001, 2002 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. */
41 import java.awt.geom.Rectangle2D;
42 import java.io.Serializable;
45 * This class represents a rectangle and all the interesting things you
46 * might want to do with it. Note that the coordinate system uses
47 * the origin (0,0) as the top left of the screen, with the x and y
48 * values increasing as they move to the right and down respectively.
50 * <p>It is valid for a rectangle to have negative width or height; but it
51 * is considered to have no area or internal points. Therefore, the behavior
52 * in methods like <code>contains</code> or <code>intersects</code> is
53 * undefined unless the rectangle has positive width and height.
55 * <p>There are some public fields; if you mess with them in an inconsistent
56 * manner, it is your own fault when you get NullPointerException,
57 * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
60 * @author Warren Levy <warrenl@cygnus.com>
61 * @author Aaron M. Renn <arenn@urbanophile.com>
62 * @author Eric Blake <ebb9@email.byu.edu>
64 * @status updated to 1.4
66 public class Rectangle extends Rectangle2D implements Shape, Serializable
69 * Compatible with JDK 1.0+.
71 private static final long serialVersionUID = -4345857070255674764L;
74 * The X coordinate of the top-left corner of the rectangle.
76 * @see #setLocation(int, int)
78 * @serial the x coordinate
83 * The Y coordinate of the top-left corner of the rectangle.
85 * @see #setLocation(int, int)
87 * @serial the y coordinate
92 * The width of the rectangle.
94 * @see #setSize(int, int)
101 * The height of the rectangle.
103 * @see #setSize(int, int)
110 * Initializes a new instance of <code>Rectangle</code> with a top
111 * left corner at (0,0) and a width and height of 0.
118 * Initializes a new instance of <code>Rectangle</code> from the
119 * coordinates of the specified rectangle.
121 * @param r the rectangle to copy from
122 * @throws NullPointerException if r is null
125 public Rectangle(Rectangle r)
134 * Initializes a new instance of <code>Rectangle</code> from the specified
137 * @param x the X coordinate of the top left corner
138 * @param y the Y coordinate of the top left corner
139 * @param width the width of the rectangle
140 * @param height the height of the rectangle
142 public Rectangle(int x, int y, int width, int height)
147 this.height = height;
151 * Initializes a new instance of <code>Rectangle</code> with the specified
152 * width and height. The upper left corner of the rectangle will be at
155 * @param width the width of the rectangle
156 * @param height the height of the rectange
158 public Rectangle(int width, int height)
161 this.height = height;
165 * Initializes a new instance of <code>Rectangle</code> with a top-left
166 * corner represented by the specified point and the width and height
167 * represented by the specified dimension.
169 * @param p the upper left corner of the rectangle
170 * @param d the width and height of the rectangle
171 * @throws NullPointerException if p or d is null
173 public Rectangle(Point p, Dimension d)
182 * Initializes a new instance of <code>Rectangle</code> with a top left
183 * corner at the specified point and a width and height of zero.
185 * @param p the upper left corner of the rectangle
187 public Rectangle(Point p)
194 * Initializes a new instance of <code>Rectangle</code> with an
195 * upper left corner at the origin (0,0) and a width and height represented
196 * by the specified dimension.
198 * @param d the width and height of the rectangle
200 public Rectangle(Dimension d)
207 * Get the X coordinate of the upper-left corner.
209 * @return the value of x, as a double
217 * Get the Y coordinate of the upper-left corner.
219 * @return the value of y, as a double
227 * Get the width of the rectangle.
229 * @return the value of width, as a double
231 public double getWidth()
237 * Get the height of the rectangle.
239 * @return the value of height, as a double
241 public double getHeight()
247 * Returns the bounds of this rectangle. A pretty useless method, as this
248 * is already a rectangle; it is included to mimic the
249 * <code>getBounds</code> method in Component.
251 * @return a copy of this rectangle
252 * @see #setBounds(Rectangle)
255 public Rectangle getBounds()
257 return new Rectangle(this);
261 * Returns the high-precision bounds of this rectangle. A pretty useless
262 * method, as this is already a rectangle.
264 * @return a copy of this rectangle
265 * @see #setBounds(Rectangle)
268 public Rectangle2D getBounds2D()
270 return new Rectangle(x, y, width, height);
274 * Updates this rectangle to match the dimensions of the specified
277 * @param r the rectangle to update from
278 * @throws NullPointerException if r is null
279 * @see #setBounds(int, int, int, int)
282 public void setBounds(Rectangle r)
291 * Updates this rectangle to have the specified dimensions.
293 * @param x the new X coordinate of the upper left hand corner
294 * @param y the new Y coordinate of the upper left hand corner
295 * @param width the new width of this rectangle
296 * @param height the new height of this rectangle
299 public void setBounds(int x, int y, int width, int height)
304 this.height = height;
308 * Updates this rectangle to have the specified dimensions, as rounded to
311 * @param x the new X coordinate of the upper left hand corner
312 * @param y the new Y coordinate of the upper left hand corner
313 * @param width the new width of this rectangle
314 * @param height the new height of this rectangle
317 public void setRect(double x, double y, double width, double height)
321 this.width = (int) width;
322 this.height = (int) height;
326 * Updates this rectangle to have the specified dimensions.
328 * @param x the new X coordinate of the upper left hand corner
329 * @param y the new Y coordinate of the upper left hand corner
330 * @param width the new width of this rectangle
331 * @param height the new height of this rectangle
332 * @deprecated use {@link #setBounds(int, int, int, int)} instead
334 public void reshape(int x, int y, int width, int height)
336 setBounds(x, y, width, height);
340 * Returns the location of this rectangle, which is the coordinates of
341 * its upper left corner.
343 * @return the point where this rectangle is located
344 * @see setLocation(Point)
347 public Point getLocation()
349 return new Point(x,y);
353 * Moves the location of this rectangle by setting its upper left
354 * corner to the specified point.
356 * @param p the point to move the rectangle to
357 * @throws NullPointerException if p is null
358 * @see #getLocation()
361 public void setLocation(Point p)
368 * Moves the location of this rectangle by setting its upper left
369 * corner to the specified coordinates.
371 * @param x the new X coordinate for this rectangle
372 * @param y the new Y coordinate for this rectangle
375 public void setLocation(int x, int y)
382 * Moves the location of this rectangle by setting its upper left
383 * corner to the specified coordinates.
385 * @param x the new X coordinate for this rectangle
386 * @param y the new Y coordinate for this rectangle
387 * @deprecated use {@link #setLocation(int, int)} instead
389 public void move(int x, int y)
395 * Translate the location of this rectangle by the given amounts.
397 * @param dx the x distance to move by
398 * @param dy the y distance to move by
399 * @see #setLocation(int, int)
401 public void translate(int dx, int dy)
408 * Returns the size of this rectangle.
410 * @return the size of this rectangle
411 * @see #setSize(Dimension)
414 public Dimension getSize()
416 return new Dimension(width, height);
420 * Sets the size of this rectangle based on the specified dimensions.
422 * @param d the new dimensions of the rectangle
423 * @throws NullPointerException if d is null
427 public void setSize(Dimension d)
434 * Sets the size of this rectangle based on the specified dimensions.
436 * @param width the new width of the rectangle
437 * @param height the new height of the rectangle
440 public void setSize(int width, int height)
443 this.height = height;
447 * Sets the size of this rectangle based on the specified dimensions.
449 * @param width the new width of the rectangle
450 * @param height the new height of the rectangle
451 * @deprecated use {@link #setSize(int, int)} instead
453 public void resize(int width, int height)
455 setSize(width, height);
459 * Tests whether or not the specified point is inside this rectangle.
460 * According to the contract of Shape, a point on the border is in only if
461 * it has an adjacent point inside the rectangle in either the increasing
464 * @param p the point to test
465 * @return true if the point is inside the rectangle
466 * @throws NullPointerException if p is null
467 * @see #contains(int, int)
470 public boolean contains(Point p)
472 return width > 0 && height > 0
473 && p.x >= x && p.x < x + width
474 && p.y >= y && p.y < y + height;
478 * Tests whether or not the specified point is inside this rectangle.
479 * According to the contract of Shape, a point on the border is in only if
480 * it has an adjacent point inside the rectangle in either the increasing
483 * @param x the X coordinate of the point to test
484 * @param y the Y coordinate of the point to test
485 * @return true if the point is inside the rectangle
488 public boolean contains(int x, int y)
490 return width > 0 && height > 0
491 && x >= this.x && x < this.x + width
492 && y >= this.y && y < this.y + height;
496 * Checks whether all points in the given rectangle are contained in this
499 * @param r the rectangle to check
500 * @return true if r is contained in this rectangle
501 * @throws NullPointerException if r is null
502 * @see #contains(int, int, int, int)
505 public boolean contains(Rectangle r)
507 return width > 0 && height > 0 && r.width > 0 && r.height > 0
508 && r.x >= x && r.x + r.width <= x + width
509 && r.y >= y && r.y + r.height <= y + height;
513 * Checks whether all points in the given rectangle are contained in this
516 * @param x the x coordinate of the rectangle to check
517 * @param y the y coordinate of the rectangle to check
518 * @param w the width of the rectangle to check
519 * @param h the height of the rectangle to check
520 * @return true if the parameters are contained in this rectangle
523 public boolean contains(int x, int y, int w, int h)
525 return width > 0 && height > 0 && w > 0 && h > 0
526 && x >= this.x && x + w <= this.x + this.width
527 && y >= this.y && y + h <= this.y + this.height;
531 * Tests whether or not the specified point is inside this rectangle.
533 * @param x the X coordinate of the point to test
534 * @param y the Y coordinate of the point to test
535 * @return true if the point is inside the rectangle
536 * @deprecated use {@link #contains(int, int)} instead
538 public boolean inside(int x, int y)
540 return contains(x, y);
544 * Tests whether or not the specified rectangle intersects this rectangle.
545 * This means the two rectangles share at least one internal point.
547 * @param r the rectangle to test against
548 * @return true if the specified rectangle intersects this one
549 * @throws NullPointerException if r is null
552 public boolean intersects(Rectangle r)
554 return width > 0 && height > 0 && r.width > 0 && r.height > 0
555 && r.x < x + width && r.x + r.width > x
556 && r.y < y + height && r.y + r.height > y;
560 * Determines the rectangle which is formed by the intersection of this
561 * rectangle with the specified rectangle. If the two do not intersect,
562 * an empty rectangle will be returned (meaning the width and/or height
563 * will be non-positive).
565 * @param r the rectange to calculate the intersection with
566 * @return a new rectangle bounding the intersection
567 * @throws NullPointerException if r is null
569 public Rectangle intersection(Rectangle r)
571 Rectangle res = new Rectangle();
572 intersect(this, r, res);
577 * Returns the smallest rectangle that contains both this rectangle
578 * and the specified rectangle.
580 * @param r the rectangle to compute the union with
581 * @return the smallest rectangle containing both rectangles
582 * @throws NullPointerException if r is null
584 public Rectangle union(Rectangle r)
586 Rectangle res = new Rectangle();
592 * Modifies this rectangle so that it represents the smallest rectangle
593 * that contains both the existing rectangle and the specified point.
594 * However, if the point falls on one of the two borders which are not
595 * inside the rectangle, a subsequent call to <code>contains</code> may
598 * @param x the X coordinate of the point to add to this rectangle
599 * @param y the Y coordinate of the point to add to this rectangle
601 public void add(int x, int y)
603 add((double) x, (double) y);
607 * Modifies this rectangle so that it represents the smallest rectangle
608 * that contains both the existing rectangle and the specified point.
609 * However, if the point falls on one of the two borders which are not
610 * inside the rectangle, a subsequent call to <code>contains</code> may
613 * @param p the point to add to this rectangle
614 * @throws NullPointerException if p is null
616 public void add(Point p)
618 add((double) p.x, (double) p.y);
622 * Modifies this rectangle so that it represents the smallest rectangle
623 * that contains both the existing rectangle and the specified rectangle.
625 * @param r the rectangle to add to this rectangle
626 * @throws NullPointerException if r is null
627 * @see #union(Rectangle)
629 public void add(Rectangle r)
631 union(this, r, this);
635 * Expands the rectangle by the specified amount. The horizontal
636 * and vertical expansion values are applied both to the X,Y coordinate
637 * of this rectangle, and its width and height. Thus the width and
638 * height will increase by 2h and 2v accordingly.
640 * @param h the horizontal expansion value
641 * @param v the vertical expansion value
643 public void grow(int h, int v)
652 * Tests whether or not this rectangle is empty. An empty rectangle
653 * has a non-positive width or height.
655 * @return true if the rectangle is empty
657 public boolean isEmpty()
659 return width <= 0 || height <= 0;
663 * Determine where the point lies with respect to this rectangle. The
664 * result will be the binary OR of the appropriate bit masks.
666 * @param x the x coordinate to check
667 * @param y the y coordinate to check
668 * @return the binary OR of the result
675 public int outcode(double x, double y)
679 result |= OUT_LEFT | OUT_RIGHT;
682 else if (x > this.x + width)
685 result |= OUT_BOTTOM | OUT_TOP;
686 else if (y < this.y) // Remember that +y heads top-to-bottom.
688 else if (y > this.y + height)
689 result |= OUT_BOTTOM;
694 * Determines the rectangle which is formed by the intersection of this
695 * rectangle with the specified rectangle. If the two do not intersect,
696 * an empty rectangle will be returned (meaning the width and/or height
697 * will be non-positive).
699 * @param r the rectange to calculate the intersection with
700 * @return a new rectangle bounding the intersection
701 * @throws NullPointerException if r is null
704 public Rectangle2D createIntersection(Rectangle2D r)
706 // Favor runtime type of other rectangle.
707 Rectangle2D res = r.getBounds2D();
708 intersect(this, r, res);
713 * Returns the smallest rectangle that contains both this rectangle
714 * and the specified rectangle.
716 * @param r the rectangle to compute the union with
717 * @return the smallest rectangle containing both rectangles
718 * @throws NullPointerException if r is null
721 public Rectangle2D createUnion(Rectangle2D r)
723 // Favor runtime type of other rectangle.
724 Rectangle2D res = r.getBounds2D();
730 * Tests this rectangle for equality against the specified object. This
731 * will be true if an only if the specified object is an instance of
732 * Rectangle2D with the same coordinates and dimensions.
734 * @param obj the object to test against for equality
735 * @return true if the specified object is equal to this one
737 public boolean equals(Object obj)
739 if (! (obj instanceof Rectangle2D))
741 Rectangle2D r = (Rectangle2D) obj;
742 return r.getX() == x && r.getY() == y
743 && r.getWidth() == width && r.getHeight() == height;
747 * Returns a string representation of this rectangle. This is in the form
748 * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
749 * + ",height=" + height + ']'</code>.
751 * @return a string representation of this rectangle
753 public String toString()
755 return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
756 + ",height=" + height + ']';