/*
* @(#)Rectangle.java 1.70 04/05/18
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.awt;
import java.awt.geom.Rectangle2D;
/**
* A Rectangle
specifies an area in a coordinate space that is
* enclosed by the Rectangle
object's top-left point
* (x, y)
* in the coordinate space, its width, and its height.
*
* A Rectangle
object's width
and
* height
are public
fields. The constructors
* that create a Rectangle
, and the methods that can modify
* one, do not prevent setting a negative value for width or height.
*
* A Rectangle
whose width or height is negative is considered
* empty. If the Rectangle
is empty, then the
* isEmpty
method returns true
. No point can be
* contained by or inside an empty Rectangle
. The
* values of width
and height
, however, are still
* valid. An empty Rectangle
still has a location in the
* coordinate space, and methods that change its size or location remain
* valid. The behavior of methods that operate on more than one
* Rectangle
is undefined if any of the participating
* Rectangle
objects has a negative
* width
or height
. These methods include
* intersects
, intersection
, and
* union
.
*
* @version 1.70, 05/18/04
* @author Sami Shaio
* @since JDK1.0
*/
public class Rectangle extends Rectangle2D
implements Shape, java.io.Serializable
{
/**
* The x coordinate of the Rectangle
.
*
* @serial
* @see #setLocation(int, int)
* @see #getLocation()
*/
public int x;
/**
* The y coordinate of the Rectangle
.
*
* @serial
* @see #setLocation(int, int)
* @see #getLocation()
*/
public int y;
/**
* The width of the Rectangle
.
* @serial
* @see #setSize(int, int)
* @see #getSize()
* @since JDK1.0.
*/
public int width;
/**
* The height of the Rectangle
.
*
* @serial
* @see #setSize(int, int)
* @see #getSize()
*/
public int height;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -4345857070255674764L;
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Constructs a new Rectangle
whose top-left corner
* is at (0, 0) in the coordinate space, and whose width and
* height are both zero.
*/
public Rectangle() {
this(0, 0, 0, 0);
}
/**
* Constructs a new Rectangle
, initialized to match
* the values of the specified Rectangle
.
* @param r the Rectangle
from which to copy initial values
* to a newly constructed Rectangle
* @since JDK1.1
*/
public Rectangle(Rectangle r) {
this(r.x, r.y, r.width, r.height);
}
/**
* Constructs a new Rectangle
whose top-left corner is
* specified as
* (x
, y
) and whose width and height
* are specified by the arguments of the same name.
* @param x the specified x coordinate
* @param y the specified y coordinate
* @param width the width of the Rectangle
* @param height the height of the Rectangle
*/
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
/**
* Constructs a new Rectangle
whose top-left corner
* is at (0, 0) in the coordinate space, and whose width and
* height are specified by the arguments of the same name.
* @param width the width of the Rectangle
* @param height the height of the Rectangle
*/
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
/**
* Constructs a new Rectangle
whose top-left corner is
* specified by the {@link Point} argument, and
* whose width and height are specified by the
* {@link Dimension} argument.
* @param p a Point
that is the top-left corner of
* the Rectangle
* @param d a Dimension
, representing the
* width and height of the Rectangle
*/
public Rectangle(Point p, Dimension d) {
this(p.x, p.y, d.width, d.height);
}
/**
* Constructs a new Rectangle
whose top-left corner is the
* specified Point
, and whose width and height are both zero.
* @param p a Point
that is the top left corner
* of the Rectangle
*/
public Rectangle(Point p) {
this(p.x, p.y, 0, 0);
}
/**
* Constructs a new Rectangle
whose top left corner is
* (0, 0) and whose width and height are specified
* by the Dimension
argument.
* @param d a Dimension
, specifying width and height
*/
public Rectangle(Dimension d) {
this(0, 0, d.width, d.height);
}
/**
* Returns the X coordinate of the bounding Rectangle
in
* double
precision.
* @return the x coordinate of the bounding Rectangle
.
*/
public double getX() {
return x;
}
/**
* Returns the Y coordinate of the bounding Rectangle
in
* double
precision.
* @return the y coordinate of the bounding Rectangle
.
*/
public double getY() {
return y;
}
/**
* Returns the width of the bounding Rectangle
in
* double
precision.
* @return the width of the bounding Rectangle
.
*/
public double getWidth() {
return width;
}
/**
* Returns the height of the bounding Rectangle
in
* double
precision.
* @return the height of the bounding Rectangle
.
*/
public double getHeight() {
return height;
}
/**
* Gets the bounding Rectangle
of this Rectangle
.
*
* This method is included for completeness, to parallel the
* getBounds
method of
* {@link Component}.
* @return a new Rectangle
, equal to the
* bounding Rectangle
for this Rectangle
.
* @see java.awt.Component#getBounds
* @see #setBounds(Rectangle)
* @see #setBounds(int, int, int, int)
* @since JDK1.1
*/
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
/**
* Return the high precision bounding box of this rectangle.
* @since 1.2
*/
public Rectangle2D getBounds2D() {
return new Rectangle(x, y, width, height);
}
/**
* Sets the bounding Rectangle
of this Rectangle
* to match the specified Rectangle
.
*
* This method is included for completeness, to parallel the
* setBounds
method of Component
.
* @param r the specified Rectangle
* @see #getBounds
* @see java.awt.Component#setBounds(java.awt.Rectangle)
* @since JDK1.1
*/
public void setBounds(Rectangle r) {
setBounds(r.x, r.y, r.width, r.height);
}
/**
* Sets the bounding Rectangle
of this
* Rectangle
to the specified
* x
, y
, width
,
* and height
.
*
* This method is included for completeness, to parallel the
* setBounds
method of Component
.
* @param x the new x coordinate for the top-left
* corner of this Rectangle
* @param y the new y coordinate for the top-left
* corner of this Rectangle
* @param width the new width for this Rectangle
* @param height the new height for this Rectangle
* @see #getBounds
* @see java.awt.Component#setBounds(int, int, int, int)
* @since JDK1.1
*/
public void setBounds(int x, int y, int width, int height) {
reshape(x, y, width, height);
}
/**
* Sets the bounds of this Rectangle
to the specified
* x
, y
, width
,
* and height
.
* This method is included for completeness, to parallel the
* setBounds
method of Component
.
* @param x the x coordinate of the upper-left corner of
* the specified rectangle
* @param y the y coordinate of the upper-left corner of
* the specified rectangle
* @param width the new width for the Dimension
object
* @param height the new height for the Dimension
object
*/
public void setRect(double x, double y, double width, double height) {
int x0 = (int) Math.floor(x);
int y0 = (int) Math.floor(y);
int x1 = (int) Math.ceil(x+width);
int y1 = (int) Math.ceil(y+height);
setBounds(x0, y0, x1-x0, y1-y0);
}
/**
* Sets the bounding Rectangle
of this
* Rectangle
to the specified
* x
, y
, width
,
* and height
.
*
* @param x the new x coordinate for the top-left
* corner of this Rectangle
* @param y the new y coordinate for the top-left
* corner of this Rectangle
* @param width the new width for this Rectangle
* @param height the new height for this Rectangle
* @deprecated As of JDK version 1.1,
* replaced by setBounds(int, int, int, int)
.
*/
@Deprecated
public void reshape(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
/**
* Returns the location of this Rectangle
.
*
* This method is included for completeness, to parallel the
* getLocation
method of Component
.
* @return the Point
that is the top-left corner of
* this Rectangle
.
* @see java.awt.Component#getLocation
* @see #setLocation(Point)
* @see #setLocation(int, int)
* @since JDK1.1
*/
public Point getLocation() {
return new Point(x, y);
}
/**
* Moves this Rectangle
to the specified location.
*
* This method is included for completeness, to parallel the
* setLocation
method of Component
.
* @param p the Point
specifying the new location
* for this Rectangle
* @see java.awt.Component#setLocation(java.awt.Point)
* @see #getLocation
* @since JDK1.1
*/
public void setLocation(Point p) {
setLocation(p.x, p.y);
}
/**
* Moves this Rectangle
to the specified location.
*
* This method is included for completeness, to parallel the
* setLocation
method of Component
.
* @param x the x coordinate of the new location
* @param y the y coordinate of the new location
* @see #getLocation
* @see java.awt.Component#setLocation(int, int)
* @since JDK1.1
*/
public void setLocation(int x, int y) {
move(x, y);
}
/**
* Moves this Rectangle
to the specified location.
*
* @param x the x coordinate of the new location
* @param y the y coordinate of the new location
* @deprecated As of JDK version 1.1,
* replaced by setLocation(int, int)
.
*/
@Deprecated
public void move(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Translates this Rectangle
the indicated distance,
* to the right along the x coordinate axis, and
* downward along the y coordinate axis.
* @param x the distance to move this Rectangle
* along the x axis
* @param y the distance to move this Rectangle
* along the y axis
* @see java.awt.Rectangle#setLocation(int, int)
* @see java.awt.Rectangle#setLocation(java.awt.Point)
*/
public void translate(int x, int y) {
this.x += x;
this.y += y;
}
/**
* Gets the size of this Rectangle
, represented by
* the returned Dimension
.
*
* This method is included for completeness, to parallel the
* getSize
method of Component
.
* @return a Dimension
, representing the size of
* this Rectangle
.
* @see java.awt.Component#getSize
* @see #setSize(Dimension)
* @see #setSize(int, int)
* @since JDK1.1
*/
public Dimension getSize() {
return new Dimension(width, height);
}
/**
* Sets the size of this Rectangle
to match the
* specified Dimension
.
*
* This method is included for completeness, to parallel the
* setSize
method of Component
.
* @param d the new size for the Dimension
object
* @see java.awt.Component#setSize(java.awt.Dimension)
* @see #getSize
* @since JDK1.1
*/
public void setSize(Dimension d) {
setSize(d.width, d.height);
}
/**
* Sets the size of this Rectangle
to the specified
* width and height.
*
* This method is included for completeness, to parallel the
* setSize
method of Component
.
* @param width the new width for this Rectangle
* @param height the new height for this Rectangle
* @see java.awt.Component#setSize(int, int)
* @see #getSize
* @since JDK1.1
*/
public void setSize(int width, int height) {
resize(width, height);
}
/**
* Sets the size of this Rectangle
to the specified
* width and height.
*
* @param width the new width for this Rectangle
* @param height the new height for this Rectangle
* @deprecated As of JDK version 1.1,
* replaced by setSize(int, int)
.
*/
@Deprecated
public void resize(int width, int height) {
this.width = width;
this.height = height;
}
/**
* Checks whether or not this Rectangle
contains the
* specified Point
.
* @param p the Point
to test
* @return true
if the Point
* (x, y) is inside this
* Rectangle
;
* false
otherwise.
* @since JDK1.1
*/
public boolean contains(Point p) {
return contains(p.x, p.y);
}
/**
* Checks whether or not this Rectangle
contains the
* point at the specified location
* (x, y).
* @param x the specified x coordinate
* @param y the specified y coordinate
* @return true
if the point
* (x, y) is inside this
* Rectangle
;
* false
otherwise.
* @since JDK1.1
*/
public boolean contains(int x, int y) {
return inside(x, y);
}
/**
* Checks whether or not this Rectangle
entirely contains
* the specified Rectangle
.
*
* @param r the specified Rectangle
* @return true
if the Rectangle
* is contained entirely inside this Rectangle
;
* false
otherwise
* @since JDK1.2
*/
public boolean contains(Rectangle r) {
return contains(r.x, r.y, r.width, r.height);
}
/**
* Checks whether this Rectangle
entirely contains
* the Rectangle
* at the specified location (X, Y) with the
* specified dimensions (W, H).
* @param X the specified x coordinate
* @param Y the specified y coordinate
* @param W the width of the Rectangle
* @param H the height of the Rectangle
* @return true
if the Rectangle
specified by
* (X, Y, W, H)
* is entirely enclosed inside this Rectangle
;
* false
otherwise.
* @since JDK1.1
*/
public boolean contains(int X, int Y, int W, int H) {
int w = this.width;
int h = this.height;
if ((w | h | W | H) < 0) {
// At least one of the dimensions is negative...
return false;
}
// Note: if any dimension is zero, tests below must return false...
int x = this.x;
int y = this.y;
if (X < x || Y < y) {
return false;
}
w += x;
W += X;
if (W <= X) {
// X+W overflowed or W was zero, return false if...
// either original w or W was zero or
// x+w did not overflow or
// the overflowed x+w is smaller than the overflowed X+W
if (w >= x || W > w) return false;
} else {
// X+W did not overflow and W was not zero, return false if...
// original w was zero or
// x+w did not overflow and x+w is smaller than X+W
if (w >= x && W > w) return false;
}
h += y;
H += Y;
if (H <= Y) {
if (h >= y || H > h) return false;
} else {
if (h >= y && H > h) return false;
}
return true;
}
/**
* Checks whether or not this Rectangle
contains the
* point at the specified location
* (X, Y).
* @param X the specified x coordinate
* @param Y the specified y coordinate
* @return true
if the point
* (X, Y) is inside this
* Rectangle
;
* false
otherwise.
* @deprecated As of JDK version 1.1,
* replaced by contains(int, int)
.
*/
@Deprecated
public boolean inside(int X, int Y) {
int w = this.width;
int h = this.height;
if ((w | h) < 0) {
// At least one of the dimensions is negative...
return false;
}
// Note: if either dimension is zero, tests below must return false...
int x = this.x;
int y = this.y;
if (X < x || Y < y) {
return false;
}
w += x;
h += y;
// overflow || intersect
return ((w < x || w > X) &&
(h < y || h > Y));
}
/**
* Determines whether or not this Rectangle
and the specified
* Rectangle
intersect. Two rectangles intersect if
* their intersection is nonempty.
*
* @param r the specified Rectangle
* @return true
if the specified Rectangle
* and this Rectangle
intersect;
* false
otherwise.
*/
public boolean intersects(Rectangle r) {
int tw = this.width;
int th = this.height;
int rw = r.width;
int rh = r.height;
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
return false;
}
int tx = this.x;
int ty = this.y;
int rx = r.x;
int ry = r.y;
rw += rx;
rh += ry;
tw += tx;
th += ty;
// overflow || intersect
return ((rw < rx || rw > tx) &&
(rh < ry || rh > ty) &&
(tw < tx || tw > rx) &&
(th < ty || th > ry));
}
/**
* Computes the intersection of this Rectangle
with the
* specified Rectangle
. Returns a new Rectangle
* that represents the intersection of the two rectangles.
* If the two rectangles do not intersect, the result will be
* an empty rectangle.
*
* @param r the specified Rectangle
* @return the largest Rectangle
contained in both the
* specified Rectangle
and in
* this Rectangle
; or if the rectangles
* do not intersect, an empty rectangle.
*/
public Rectangle intersection(Rectangle r) {
int tx1 = this.x;
int ty1 = this.y;
int rx1 = r.x;
int ry1 = r.y;
long tx2 = tx1; tx2 += this.width;
long ty2 = ty1; ty2 += this.height;
long rx2 = rx1; rx2 += r.width;
long ry2 = ry1; ry2 += r.height;
if (tx1 < rx1) tx1 = rx1;
if (ty1 < ry1) ty1 = ry1;
if (tx2 > rx2) tx2 = rx2;
if (ty2 > ry2) ty2 = ry2;
tx2 -= tx1;
ty2 -= ty1;
// tx2,ty2 will never overflow (they will never be
// larger than the smallest of the two source w,h)
// they might underflow, though...
if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
}
/**
* Computes the union of this Rectangle
with the
* specified Rectangle
. Returns a new
* Rectangle
that
* represents the union of the two rectangles
* @param r the specified Rectangle
* @return the smallest Rectangle
containing both
* the specified Rectangle
and this
* Rectangle
.
*/
public Rectangle union(Rectangle r) {
int x1 = Math.min(x, r.x);
int x2 = Math.max(x + width, r.x + r.width);
int y1 = Math.min(y, r.y);
int y2 = Math.max(y + height, r.y + r.height);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
/**
* Adds a point, specified by the integer arguments newx
* and newy
, to this Rectangle
. The
* resulting Rectangle
is
* the smallest Rectangle
that contains both the
* original Rectangle
and the specified point.
*
* After adding a point, a call to contains
with the
* added point as an argument does not necessarily return
* true
. The contains
method does not
* return true
for points on the right or bottom
* edges of a Rectangle
. Therefore, if the added point
* falls on the right or bottom edge of the enlarged
* Rectangle
, contains
returns
* false
for that point.
* @param newx the x coordinate of the new point
* @param newy the y coordinate of the new point
*/
public void add(int newx, int newy) {
int x1 = Math.min(x, newx);
int x2 = Math.max(x + width, newx);
int y1 = Math.min(y, newy);
int y2 = Math.max(y + height, newy);
x = x1;
y = y1;
width = x2 - x1;
height = y2 - y1;
}
/**
* Adds the specified Point
to this
* Rectangle
. The resulting Rectangle
* is the smallest Rectangle
that contains both the
* original Rectangle
and the specified
* Point
.
*
* After adding a Point
, a call to contains
* with the added Point
as an argument does not
* necessarily return true
. The contains
* method does not return true
for points on the right
* or bottom edges of a Rectangle
. Therefore if the added
* Point
falls on the right or bottom edge of the
* enlarged Rectangle
, contains
returns
* false
for that Point
.
* @param pt the new Point
to add to this
* Rectangle
*/
public void add(Point pt) {
add(pt.x, pt.y);
}
/**
* Adds a Rectangle
to this Rectangle
.
* The resulting Rectangle
is the union of the two
* rectangles.
* @param r the specified Rectangle
*/
public void add(Rectangle r) {
int x1 = Math.min(x, r.x);
int x2 = Math.max(x + width, r.x + r.width);
int y1 = Math.min(y, r.y);
int y2 = Math.max(y + height, r.y + r.height);
x = x1;
y = y1;
width = x2 - x1;
height = y2 - y1;
}
/**
* Resizes the Rectangle
both horizontally and vertically.
*
* This method modifies the Rectangle
so that it is
* h
units larger on both the left and right side,
* and v
units larger at both the top and bottom.
*
* The new Rectangle
has (x - h
,
* y - v
) as its top-left corner, a
* width of
* width
+
2h
,
* and a height of
* height
+
2v
.
*
* If negative values are supplied for h
and
* v
, the size of the Rectangle
* decreases accordingly.
* The grow
method does not check whether the resulting
* values of width
and height
are
* non-negative.
* @param h the horizontal expansion
* @param v the vertical expansion
*/
public void grow(int h, int v) {
x -= h;
y -= v;
width += h * 2;
height += v * 2;
}
/**
* Determines whether or not this Rectangle
is empty. A
* Rectangle
is empty if its width or its height is less
* than or equal to zero.
* @return true
if this Rectangle
is empty;
* false
otherwise.
*/
public boolean isEmpty() {
return (width <= 0) || (height <= 0);
}
/**
* Determines where the specified coordinates lie with respect
* to this Rectangle
.
* This method computes a binary OR of the appropriate mask values
* indicating, for each side of this Rectangle
,
* whether or not the specified coordinates are on the same side of the
* edge as the rest of this Rectangle
.
* @param x the specified x coordinate
* @param y the specified y coordinate
* @return the logical OR of all appropriate out codes.
* @see #OUT_LEFT
* @see #OUT_TOP
* @see #OUT_RIGHT
* @see #OUT_BOTTOM
* @since 1.2
*/
public int outcode(double x, double y) {
/*
* Note on casts to double below. If the arithmetic of
* x+w or y+h is done in int, then we may get integer
* overflow. By converting to double before the addition
* we force the addition to be carried out in double to
* avoid overflow in the comparison.
*
* See bug 4320890 for problems that this can cause.
*/
int out = 0;
if (this.width <= 0) {
out |= OUT_LEFT | OUT_RIGHT;
} else if (x < this.x) {
out |= OUT_LEFT;
} else if (x > this.x + (double) this.width) {
out |= OUT_RIGHT;
}
if (this.height <= 0) {
out |= OUT_TOP | OUT_BOTTOM;
} else if (y < this.y) {
out |= OUT_TOP;
} else if (y > this.y + (double) this.height) {
out |= OUT_BOTTOM;
}
return out;
}
/**
* Returns a new {@link Rectangle2D} object
* representing the intersection of this Rectangle
with the
* specified Rectangle2D
.
* @param r the Rectangle2D
to be intersected
* with this Rectangle
* @return the largest Rectangle2D
contained in both the
* specified Rectangle2D
and in
* this Rectangle
.
* @since 1.2
*/
public Rectangle2D createIntersection(Rectangle2D r) {
if (r instanceof Rectangle) {
return intersection((Rectangle) r);
}
Rectangle2D dest = new Rectangle2D.Double();
Rectangle2D.intersect(this, r, dest);
return dest;
}
/**
* Returns a new Rectangle2D
object representing the
* union of this Rectangle
with the specified
* Rectangle2D
.
* @param r the Rectangle2D
to be combined with
* this Rectangle
* @return the smallest Rectangle2D
containing
* both the specified Rectangle2D
and this
* Rectangle
.
* @since 1.2
*/
public Rectangle2D createUnion(Rectangle2D r) {
if (r instanceof Rectangle) {
return union((Rectangle) r);
}
Rectangle2D dest = new Rectangle2D.Double();
Rectangle2D.union(this, r, dest);
return dest;
}
/**
* Checks whether two rectangles are equal.
*
* The result is true
if and only if the argument is not
* null
and is a Rectangle
object that has the
* same top-left corner, width, and height as this Rectangle
.
* @param obj the Object
to compare with
* this Rectangle
* @return true
if the objects are equal;
* false
otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Rectangle) {
Rectangle r = (Rectangle)obj;
return ((x == r.x) &&
(y == r.y) &&
(width == r.width) &&
(height == r.height));
}
return super.equals(obj);
}
/**
* Returns a String
representing this
* Rectangle
and its values.
* @return a String
representing this
* Rectangle
object's coordinate and size values.
*/
public String toString() {
return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]";
}
}