0001 /*
0002 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt;
0027
0028 import java.awt.geom.Rectangle2D;
0029
0030 /**
0031 * A <code>Rectangle</code> specifies an area in a coordinate space that is
0032 * enclosed by the <code>Rectangle</code> object's upper-left point
0033 * {@code (x,y)}
0034 * in the coordinate space, its width, and its height.
0035 * <p>
0036 * A <code>Rectangle</code> object's <code>width</code> and
0037 * <code>height</code> are <code>public</code> fields. The constructors
0038 * that create a <code>Rectangle</code>, and the methods that can modify
0039 * one, do not prevent setting a negative value for width or height.
0040 * <p>
0041 * <a name="Empty">
0042 * A {@code Rectangle} whose width or height is exactly zero has location
0043 * along those axes with zero dimension, but is otherwise considered empty.
0044 * The {@link #isEmpty} method will return true for such a {@code Rectangle}.
0045 * Methods which test if an empty {@code Rectangle} contains or intersects
0046 * a point or rectangle will always return false if either dimension is zero.
0047 * Methods which combine such a {@code Rectangle} with a point or rectangle
0048 * will include the location of the {@code Rectangle} on that axis in the
0049 * result as if the {@link #add(Point)} method were being called.
0050 * </a>
0051 * <p>
0052 * <a name="NonExistant">
0053 * A {@code Rectangle} whose width or height is negative has neither
0054 * location nor dimension along those axes with negative dimensions.
0055 * Such a {@code Rectangle} is treated as non-existant along those axes.
0056 * Such a {@code Rectangle} is also empty with respect to containment
0057 * calculations and methods which test if it contains or intersects a
0058 * point or rectangle will always return false.
0059 * Methods which combine such a {@code Rectangle} with a point or rectangle
0060 * will ignore the {@code Rectangle} entirely in generating the result.
0061 * If two {@code Rectangle} objects are combined and each has a negative
0062 * dimension, the result will have at least one negative dimension.
0063 * </a>
0064 * <p>
0065 * Methods which affect only the location of a {@code Rectangle} will
0066 * operate on its location regardless of whether or not it has a negative
0067 * or zero dimension along either axis.
0068 * <p>
0069 * Note that a {@code Rectangle} constructed with the default no-argument
0070 * constructor will have dimensions of {@code 0x0} and therefore be empty.
0071 * That {@code Rectangle} will still have a location of {@code (0,0)} and
0072 * will contribute that location to the union and add operations.
0073 * Code attempting to accumulate the bounds of a set of points should
0074 * therefore initially construct the {@code Rectangle} with a specifically
0075 * negative width and height or it should use the first point in the set
0076 * to construct the {@code Rectangle}.
0077 * For example:
0078 * <pre>
0079 * Rectangle bounds = new Rectangle(0, 0, -1, -1);
0080 * for (int i = 0; i < points.length; i++) {
0081 * bounds.add(points[i]);
0082 * }
0083 * </pre>
0084 * or if we know that the points array contains at least one point:
0085 * <pre>
0086 * Rectangle bounds = new Rectangle(points[0]);
0087 * for (int i = 1; i < points.length; i++) {
0088 * bounds.add(points[i]);
0089 * }
0090 * </pre>
0091 * <p>
0092 * This class uses 32-bit integers to store its location and dimensions.
0093 * Frequently operations may produce a result that exceeds the range of
0094 * a 32-bit integer.
0095 * The methods will calculate their results in a way that avoids any
0096 * 32-bit overflow for intermediate results and then choose the best
0097 * representation to store the final results back into the 32-bit fields
0098 * which hold the location and dimensions.
0099 * The location of the result will be stored into the {@link #x} and
0100 * {@link #y} fields by clipping the true result to the nearest 32-bit value.
0101 * The values stored into the {@link #width} and {@link #height} dimension
0102 * fields will be chosen as the 32-bit values that encompass the largest
0103 * part of the true result as possible.
0104 * Generally this means that the dimension will be clipped independently
0105 * to the range of 32-bit integers except that if the location had to be
0106 * moved to store it into its pair of 32-bit fields then the dimensions
0107 * will be adjusted relative to the "best representation" of the location.
0108 * If the true result had a negative dimension and was therefore
0109 * non-existant along one or both axes, the stored dimensions will be
0110 * negative numbers in those axes.
0111 * If the true result had a location that could be represented within
0112 * the range of 32-bit integers, but zero dimension along one or both
0113 * axes, then the stored dimensions will be zero in those axes.
0114 *
0115 * @version 1.79, 05/05/07
0116 * @author Sami Shaio
0117 * @since 1.0
0118 */
0119 public class Rectangle extends Rectangle2D implements Shape,
0120 java.io.Serializable {
0121
0122 /**
0123 * The X coordinate of the upper-left corner of the <code>Rectangle</code>.
0124 *
0125 * @serial
0126 * @see #setLocation(int, int)
0127 * @see #getLocation()
0128 * @since 1.0
0129 */
0130 public int x;
0131
0132 /**
0133 * The Y coordinate of the upper-left corner of the <code>Rectangle</code>.
0134 *
0135 * @serial
0136 * @see #setLocation(int, int)
0137 * @see #getLocation()
0138 * @since 1.0
0139 */
0140 public int y;
0141
0142 /**
0143 * The width of the <code>Rectangle</code>.
0144 * @serial
0145 * @see #setSize(int, int)
0146 * @see #getSize()
0147 * @since 1.0
0148 */
0149 public int width;
0150
0151 /**
0152 * The height of the <code>Rectangle</code>.
0153 *
0154 * @serial
0155 * @see #setSize(int, int)
0156 * @see #getSize()
0157 * @since 1.0
0158 */
0159 public int height;
0160
0161 /*
0162 * JDK 1.1 serialVersionUID
0163 */
0164 private static final long serialVersionUID = -4345857070255674764L;
0165
0166 /**
0167 * Initialize JNI field and method IDs
0168 */
0169 private static native void initIDs();
0170
0171 static {
0172 /* ensure that the necessary native libraries are loaded */
0173 Toolkit.loadLibraries();
0174 if (!GraphicsEnvironment.isHeadless()) {
0175 initIDs();
0176 }
0177 }
0178
0179 /**
0180 * Constructs a new <code>Rectangle</code> whose upper-left corner
0181 * is at (0, 0) in the coordinate space, and whose width and
0182 * height are both zero.
0183 */
0184 public Rectangle() {
0185 this (0, 0, 0, 0);
0186 }
0187
0188 /**
0189 * Constructs a new <code>Rectangle</code>, initialized to match
0190 * the values of the specified <code>Rectangle</code>.
0191 * @param r the <code>Rectangle</code> from which to copy initial values
0192 * to a newly constructed <code>Rectangle</code>
0193 * @since 1.1
0194 */
0195 public Rectangle(Rectangle r) {
0196 this (r.x, r.y, r.width, r.height);
0197 }
0198
0199 /**
0200 * Constructs a new <code>Rectangle</code> whose upper-left corner is
0201 * specified as
0202 * {@code (x,y)} and whose width and height
0203 * are specified by the arguments of the same name.
0204 * @param x the specified X coordinate
0205 * @param y the specified Y coordinate
0206 * @param width the width of the <code>Rectangle</code>
0207 * @param height the height of the <code>Rectangle</code>
0208 * @since 1.0
0209 */
0210 public Rectangle(int x, int y, int width, int height) {
0211 this .x = x;
0212 this .y = y;
0213 this .width = width;
0214 this .height = height;
0215 }
0216
0217 /**
0218 * Constructs a new <code>Rectangle</code> whose upper-left corner
0219 * is at (0, 0) in the coordinate space, and whose width and
0220 * height are specified by the arguments of the same name.
0221 * @param width the width of the <code>Rectangle</code>
0222 * @param height the height of the <code>Rectangle</code>
0223 */
0224 public Rectangle(int width, int height) {
0225 this (0, 0, width, height);
0226 }
0227
0228 /**
0229 * Constructs a new <code>Rectangle</code> whose upper-left corner is
0230 * specified by the {@link Point} argument, and
0231 * whose width and height are specified by the
0232 * {@link Dimension} argument.
0233 * @param p a <code>Point</code> that is the upper-left corner of
0234 * the <code>Rectangle</code>
0235 * @param d a <code>Dimension</code>, representing the
0236 * width and height of the <code>Rectangle</code>
0237 */
0238 public Rectangle(Point p, Dimension d) {
0239 this (p.x, p.y, d.width, d.height);
0240 }
0241
0242 /**
0243 * Constructs a new <code>Rectangle</code> whose upper-left corner is the
0244 * specified <code>Point</code>, and whose width and height are both zero.
0245 * @param p a <code>Point</code> that is the top left corner
0246 * of the <code>Rectangle</code>
0247 */
0248 public Rectangle(Point p) {
0249 this (p.x, p.y, 0, 0);
0250 }
0251
0252 /**
0253 * Constructs a new <code>Rectangle</code> whose top left corner is
0254 * (0, 0) and whose width and height are specified
0255 * by the <code>Dimension</code> argument.
0256 * @param d a <code>Dimension</code>, specifying width and height
0257 */
0258 public Rectangle(Dimension d) {
0259 this (0, 0, d.width, d.height);
0260 }
0261
0262 /**
0263 * Returns the X coordinate of the bounding <code>Rectangle</code> in
0264 * <code>double</code> precision.
0265 * @return the X coordinate of the bounding <code>Rectangle</code>.
0266 */
0267 public double getX() {
0268 return x;
0269 }
0270
0271 /**
0272 * Returns the Y coordinate of the bounding <code>Rectangle</code> in
0273 * <code>double</code> precision.
0274 * @return the Y coordinate of the bounding <code>Rectangle</code>.
0275 */
0276 public double getY() {
0277 return y;
0278 }
0279
0280 /**
0281 * Returns the width of the bounding <code>Rectangle</code> in
0282 * <code>double</code> precision.
0283 * @return the width of the bounding <code>Rectangle</code>.
0284 */
0285 public double getWidth() {
0286 return width;
0287 }
0288
0289 /**
0290 * Returns the height of the bounding <code>Rectangle</code> in
0291 * <code>double</code> precision.
0292 * @return the height of the bounding <code>Rectangle</code>.
0293 */
0294 public double getHeight() {
0295 return height;
0296 }
0297
0298 /**
0299 * Gets the bounding <code>Rectangle</code> of this <code>Rectangle</code>.
0300 * <p>
0301 * This method is included for completeness, to parallel the
0302 * <code>getBounds</code> method of
0303 * {@link Component}.
0304 * @return a new <code>Rectangle</code>, equal to the
0305 * bounding <code>Rectangle</code> for this <code>Rectangle</code>.
0306 * @see java.awt.Component#getBounds
0307 * @see #setBounds(Rectangle)
0308 * @see #setBounds(int, int, int, int)
0309 * @since 1.1
0310 */
0311 public Rectangle getBounds() {
0312 return new Rectangle(x, y, width, height);
0313 }
0314
0315 /**
0316 * {@inheritDoc}
0317 * @since 1.2
0318 */
0319 public Rectangle2D getBounds2D() {
0320 return new Rectangle(x, y, width, height);
0321 }
0322
0323 /**
0324 * Sets the bounding <code>Rectangle</code> of this <code>Rectangle</code>
0325 * to match the specified <code>Rectangle</code>.
0326 * <p>
0327 * This method is included for completeness, to parallel the
0328 * <code>setBounds</code> method of <code>Component</code>.
0329 * @param r the specified <code>Rectangle</code>
0330 * @see #getBounds
0331 * @see java.awt.Component#setBounds(java.awt.Rectangle)
0332 * @since 1.1
0333 */
0334 public void setBounds(Rectangle r) {
0335 setBounds(r.x, r.y, r.width, r.height);
0336 }
0337
0338 /**
0339 * Sets the bounding <code>Rectangle</code> of this
0340 * <code>Rectangle</code> to the specified
0341 * <code>x</code>, <code>y</code>, <code>width</code>,
0342 * and <code>height</code>.
0343 * <p>
0344 * This method is included for completeness, to parallel the
0345 * <code>setBounds</code> method of <code>Component</code>.
0346 * @param x the new X coordinate for the upper-left
0347 * corner of this <code>Rectangle</code>
0348 * @param y the new Y coordinate for the upper-left
0349 * corner of this <code>Rectangle</code>
0350 * @param width the new width for this <code>Rectangle</code>
0351 * @param height the new height for this <code>Rectangle</code>
0352 * @see #getBounds
0353 * @see java.awt.Component#setBounds(int, int, int, int)
0354 * @since 1.1
0355 */
0356 public void setBounds(int x, int y, int width, int height) {
0357 reshape(x, y, width, height);
0358 }
0359
0360 /**
0361 * Sets the bounds of this {@code Rectangle} to the integer bounds
0362 * which encompass the specified {@code x}, {@code y}, {@code width},
0363 * and {@code height}.
0364 * If the parameters specify a {@code Rectangle} that exceeds the
0365 * maximum range of integers, the result will be the best
0366 * representation of the specified {@code Rectangle} intersected
0367 * with the maximum integer bounds.
0368 * @param x the X coordinate of the upper-left corner of
0369 * the specified rectangle
0370 * @param y the Y coordinate of the upper-left corner of
0371 * the specified rectangle
0372 * @param width the width of the specified rectangle
0373 * @param height the new height of the specified rectangle
0374 */
0375 public void setRect(double x, double y, double width, double height) {
0376 int newx, newy, neww, newh;
0377
0378 if (x > 2.0 * Integer.MAX_VALUE) {
0379 // Too far in positive X direction to represent...
0380 // We cannot even reach the left side of the specified
0381 // rectangle even with both x & width set to MAX_VALUE.
0382 // The intersection with the "maximal integer rectangle"
0383 // is non-existant so we should use a width < 0.
0384 // REMIND: Should we try to determine a more "meaningful"
0385 // adjusted value for neww than just "-1"?
0386 newx = Integer.MAX_VALUE;
0387 neww = -1;
0388 } else {
0389 newx = clip(x, false);
0390 if (width >= 0)
0391 width += x - newx;
0392 neww = clip(width, width >= 0);
0393 }
0394
0395 if (y > 2.0 * Integer.MAX_VALUE) {
0396 // Too far in positive Y direction to represent...
0397 newy = Integer.MAX_VALUE;
0398 newh = -1;
0399 } else {
0400 newy = clip(y, false);
0401 if (height >= 0)
0402 height += y - newy;
0403 newh = clip(height, height >= 0);
0404 }
0405
0406 reshape(newx, newy, neww, newh);
0407 }
0408
0409 // Return best integer representation for v, clipped to integer
0410 // range and floor-ed or ceiling-ed, depending on the boolean.
0411 private static int clip(double v, boolean doceil) {
0412 if (v <= Integer.MIN_VALUE) {
0413 return Integer.MIN_VALUE;
0414 }
0415 if (v >= Integer.MAX_VALUE) {
0416 return Integer.MAX_VALUE;
0417 }
0418 return (int) (doceil ? Math.ceil(v) : Math.floor(v));
0419 }
0420
0421 /**
0422 * Sets the bounding <code>Rectangle</code> of this
0423 * <code>Rectangle</code> to the specified
0424 * <code>x</code>, <code>y</code>, <code>width</code>,
0425 * and <code>height</code>.
0426 * <p>
0427 * @param x the new X coordinate for the upper-left
0428 * corner of this <code>Rectangle</code>
0429 * @param y the new Y coordinate for the upper-left
0430 * corner of this <code>Rectangle</code>
0431 * @param width the new width for this <code>Rectangle</code>
0432 * @param height the new height for this <code>Rectangle</code>
0433 * @deprecated As of JDK version 1.1,
0434 * replaced by <code>setBounds(int, int, int, int)</code>.
0435 */
0436 @Deprecated
0437 public void reshape(int x, int y, int width, int height) {
0438 this .x = x;
0439 this .y = y;
0440 this .width = width;
0441 this .height = height;
0442 }
0443
0444 /**
0445 * Returns the location of this <code>Rectangle</code>.
0446 * <p>
0447 * This method is included for completeness, to parallel the
0448 * <code>getLocation</code> method of <code>Component</code>.
0449 * @return the <code>Point</code> that is the upper-left corner of
0450 * this <code>Rectangle</code>.
0451 * @see java.awt.Component#getLocation
0452 * @see #setLocation(Point)
0453 * @see #setLocation(int, int)
0454 * @since 1.1
0455 */
0456 public Point getLocation() {
0457 return new Point(x, y);
0458 }
0459
0460 /**
0461 * Moves this <code>Rectangle</code> to the specified location.
0462 * <p>
0463 * This method is included for completeness, to parallel the
0464 * <code>setLocation</code> method of <code>Component</code>.
0465 * @param p the <code>Point</code> specifying the new location
0466 * for this <code>Rectangle</code>
0467 * @see java.awt.Component#setLocation(java.awt.Point)
0468 * @see #getLocation
0469 * @since 1.1
0470 */
0471 public void setLocation(Point p) {
0472 setLocation(p.x, p.y);
0473 }
0474
0475 /**
0476 * Moves this <code>Rectangle</code> to the specified location.
0477 * <p>
0478 * This method is included for completeness, to parallel the
0479 * <code>setLocation</code> method of <code>Component</code>.
0480 * @param x the X coordinate of the new location
0481 * @param y the Y coordinate of the new location
0482 * @see #getLocation
0483 * @see java.awt.Component#setLocation(int, int)
0484 * @since 1.1
0485 */
0486 public void setLocation(int x, int y) {
0487 move(x, y);
0488 }
0489
0490 /**
0491 * Moves this <code>Rectangle</code> to the specified location.
0492 * <p>
0493 * @param x the X coordinate of the new location
0494 * @param y the Y coordinate of the new location
0495 * @deprecated As of JDK version 1.1,
0496 * replaced by <code>setLocation(int, int)</code>.
0497 */
0498 @Deprecated
0499 public void move(int x, int y) {
0500 this .x = x;
0501 this .y = y;
0502 }
0503
0504 /**
0505 * Translates this <code>Rectangle</code> the indicated distance,
0506 * to the right along the X coordinate axis, and
0507 * downward along the Y coordinate axis.
0508 * @param dx the distance to move this <code>Rectangle</code>
0509 * along the X axis
0510 * @param dy the distance to move this <code>Rectangle</code>
0511 * along the Y axis
0512 * @see java.awt.Rectangle#setLocation(int, int)
0513 * @see java.awt.Rectangle#setLocation(java.awt.Point)
0514 */
0515 public void translate(int dx, int dy) {
0516 int oldv = this .x;
0517 int newv = oldv + dx;
0518 if (dx < 0) {
0519 // moving leftward
0520 if (newv > oldv) {
0521 // negative overflow
0522 // Only adjust width if it was valid (>= 0).
0523 if (width >= 0) {
0524 // The right edge is now conceptually at
0525 // newv+width, but we may move newv to prevent
0526 // overflow. But we want the right edge to
0527 // remain at its new location in spite of the
0528 // clipping. Think of the following adjustment
0529 // conceptually the same as:
0530 // width += newv; newv = MIN_VALUE; width -= newv;
0531 width += newv - Integer.MIN_VALUE;
0532 // width may go negative if the right edge went past
0533 // MIN_VALUE, but it cannot overflow since it cannot
0534 // have moved more than MIN_VALUE and any non-negative
0535 // number + MIN_VALUE does not overflow.
0536 }
0537 newv = Integer.MIN_VALUE;
0538 }
0539 } else {
0540 // moving rightward (or staying still)
0541 if (newv < oldv) {
0542 // positive overflow
0543 if (width >= 0) {
0544 // Conceptually the same as:
0545 // width += newv; newv = MAX_VALUE; width -= newv;
0546 width += newv - Integer.MAX_VALUE;
0547 // With large widths and large displacements
0548 // we may overflow so we need to check it.
0549 if (width < 0)
0550 width = Integer.MAX_VALUE;
0551 }
0552 newv = Integer.MAX_VALUE;
0553 }
0554 }
0555 this .x = newv;
0556
0557 oldv = this .y;
0558 newv = oldv + dy;
0559 if (dy < 0) {
0560 // moving upward
0561 if (newv > oldv) {
0562 // negative overflow
0563 if (height >= 0) {
0564 height += newv - Integer.MIN_VALUE;
0565 // See above comment about no overflow in this case
0566 }
0567 newv = Integer.MIN_VALUE;
0568 }
0569 } else {
0570 // moving downward (or staying still)
0571 if (newv < oldv) {
0572 // positive overflow
0573 if (height >= 0) {
0574 height += newv - Integer.MAX_VALUE;
0575 if (height < 0)
0576 height = Integer.MAX_VALUE;
0577 }
0578 newv = Integer.MAX_VALUE;
0579 }
0580 }
0581 this .y = newv;
0582 }
0583
0584 /**
0585 * Gets the size of this <code>Rectangle</code>, represented by
0586 * the returned <code>Dimension</code>.
0587 * <p>
0588 * This method is included for completeness, to parallel the
0589 * <code>getSize</code> method of <code>Component</code>.
0590 * @return a <code>Dimension</code>, representing the size of
0591 * this <code>Rectangle</code>.
0592 * @see java.awt.Component#getSize
0593 * @see #setSize(Dimension)
0594 * @see #setSize(int, int)
0595 * @since 1.1
0596 */
0597 public Dimension getSize() {
0598 return new Dimension(width, height);
0599 }
0600
0601 /**
0602 * Sets the size of this <code>Rectangle</code> to match the
0603 * specified <code>Dimension</code>.
0604 * <p>
0605 * This method is included for completeness, to parallel the
0606 * <code>setSize</code> method of <code>Component</code>.
0607 * @param d the new size for the <code>Dimension</code> object
0608 * @see java.awt.Component#setSize(java.awt.Dimension)
0609 * @see #getSize
0610 * @since 1.1
0611 */
0612 public void setSize(Dimension d) {
0613 setSize(d.width, d.height);
0614 }
0615
0616 /**
0617 * Sets the size of this <code>Rectangle</code> to the specified
0618 * width and height.
0619 * <p>
0620 * This method is included for completeness, to parallel the
0621 * <code>setSize</code> method of <code>Component</code>.
0622 * @param width the new width for this <code>Rectangle</code>
0623 * @param height the new height for this <code>Rectangle</code>
0624 * @see java.awt.Component#setSize(int, int)
0625 * @see #getSize
0626 * @since 1.1
0627 */
0628 public void setSize(int width, int height) {
0629 resize(width, height);
0630 }
0631
0632 /**
0633 * Sets the size of this <code>Rectangle</code> to the specified
0634 * width and height.
0635 * <p>
0636 * @param width the new width for this <code>Rectangle</code>
0637 * @param height the new height for this <code>Rectangle</code>
0638 * @deprecated As of JDK version 1.1,
0639 * replaced by <code>setSize(int, int)</code>.
0640 */
0641 @Deprecated
0642 public void resize(int width, int height) {
0643 this .width = width;
0644 this .height = height;
0645 }
0646
0647 /**
0648 * Checks whether or not this <code>Rectangle</code> contains the
0649 * specified <code>Point</code>.
0650 * @param p the <code>Point</code> to test
0651 * @return <code>true</code> if the specified <code>Point</code>
0652 * is inside this <code>Rectangle</code>;
0653 * <code>false</code> otherwise.
0654 * @since 1.1
0655 */
0656 public boolean contains(Point p) {
0657 return contains(p.x, p.y);
0658 }
0659
0660 /**
0661 * Checks whether or not this <code>Rectangle</code> contains the
0662 * point at the specified location {@code (x,y)}.
0663 *
0664 * @param x the specified X coordinate
0665 * @param y the specified Y coordinate
0666 * @return <code>true</code> if the point
0667 * {@code (x,y)} is inside this
0668 * <code>Rectangle</code>;
0669 * <code>false</code> otherwise.
0670 * @since 1.1
0671 */
0672 public boolean contains(int x, int y) {
0673 return inside(x, y);
0674 }
0675
0676 /**
0677 * Checks whether or not this <code>Rectangle</code> entirely contains
0678 * the specified <code>Rectangle</code>.
0679 *
0680 * @param r the specified <code>Rectangle</code>
0681 * @return <code>true</code> if the <code>Rectangle</code>
0682 * is contained entirely inside this <code>Rectangle</code>;
0683 * <code>false</code> otherwise
0684 * @since 1.2
0685 */
0686 public boolean contains(Rectangle r) {
0687 return contains(r.x, r.y, r.width, r.height);
0688 }
0689
0690 /**
0691 * Checks whether this <code>Rectangle</code> entirely contains
0692 * the <code>Rectangle</code>
0693 * at the specified location {@code (X,Y)} with the
0694 * specified dimensions {@code (W,H)}.
0695 * @param X the specified X coordinate
0696 * @param Y the specified Y coordinate
0697 * @param W the width of the <code>Rectangle</code>
0698 * @param H the height of the <code>Rectangle</code>
0699 * @return <code>true</code> if the <code>Rectangle</code> specified by
0700 * {@code (X, Y, W, H)}
0701 * is entirely enclosed inside this <code>Rectangle</code>;
0702 * <code>false</code> otherwise.
0703 * @since 1.1
0704 */
0705 public boolean contains(int X, int Y, int W, int H) {
0706 int w = this .width;
0707 int h = this .height;
0708 if ((w | h | W | H) < 0) {
0709 // At least one of the dimensions is negative...
0710 return false;
0711 }
0712 // Note: if any dimension is zero, tests below must return false...
0713 int x = this .x;
0714 int y = this .y;
0715 if (X < x || Y < y) {
0716 return false;
0717 }
0718 w += x;
0719 W += X;
0720 if (W <= X) {
0721 // X+W overflowed or W was zero, return false if...
0722 // either original w or W was zero or
0723 // x+w did not overflow or
0724 // the overflowed x+w is smaller than the overflowed X+W
0725 if (w >= x || W > w)
0726 return false;
0727 } else {
0728 // X+W did not overflow and W was not zero, return false if...
0729 // original w was zero or
0730 // x+w did not overflow and x+w is smaller than X+W
0731 if (w >= x && W > w)
0732 return false;
0733 }
0734 h += y;
0735 H += Y;
0736 if (H <= Y) {
0737 if (h >= y || H > h)
0738 return false;
0739 } else {
0740 if (h >= y && H > h)
0741 return false;
0742 }
0743 return true;
0744 }
0745
0746 /**
0747 * Checks whether or not this <code>Rectangle</code> contains the
0748 * point at the specified location {@code (X,Y)}.
0749 *
0750 * @param X the specified X coordinate
0751 * @param Y the specified Y coordinate
0752 * @return <code>true</code> if the point
0753 * {@code (X,Y)} is inside this
0754 * <code>Rectangle</code>;
0755 * <code>false</code> otherwise.
0756 * @deprecated As of JDK version 1.1,
0757 * replaced by <code>contains(int, int)</code>.
0758 */
0759 @Deprecated
0760 public boolean inside(int X, int Y) {
0761 int w = this .width;
0762 int h = this .height;
0763 if ((w | h) < 0) {
0764 // At least one of the dimensions is negative...
0765 return false;
0766 }
0767 // Note: if either dimension is zero, tests below must return false...
0768 int x = this .x;
0769 int y = this .y;
0770 if (X < x || Y < y) {
0771 return false;
0772 }
0773 w += x;
0774 h += y;
0775 // overflow || intersect
0776 return ((w < x || w > X) && (h < y || h > Y));
0777 }
0778
0779 /**
0780 * Determines whether or not this <code>Rectangle</code> and the specified
0781 * <code>Rectangle</code> intersect. Two rectangles intersect if
0782 * their intersection is nonempty.
0783 *
0784 * @param r the specified <code>Rectangle</code>
0785 * @return <code>true</code> if the specified <code>Rectangle</code>
0786 * and this <code>Rectangle</code> intersect;
0787 * <code>false</code> otherwise.
0788 */
0789 public boolean intersects(Rectangle r) {
0790 int tw = this .width;
0791 int th = this .height;
0792 int rw = r.width;
0793 int rh = r.height;
0794 if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
0795 return false;
0796 }
0797 int tx = this .x;
0798 int ty = this .y;
0799 int rx = r.x;
0800 int ry = r.y;
0801 rw += rx;
0802 rh += ry;
0803 tw += tx;
0804 th += ty;
0805 // overflow || intersect
0806 return ((rw < rx || rw > tx) && (rh < ry || rh > ty)
0807 && (tw < tx || tw > rx) && (th < ty || th > ry));
0808 }
0809
0810 /**
0811 * Computes the intersection of this <code>Rectangle</code> with the
0812 * specified <code>Rectangle</code>. Returns a new <code>Rectangle</code>
0813 * that represents the intersection of the two rectangles.
0814 * If the two rectangles do not intersect, the result will be
0815 * an empty rectangle.
0816 *
0817 * @param r the specified <code>Rectangle</code>
0818 * @return the largest <code>Rectangle</code> contained in both the
0819 * specified <code>Rectangle</code> and in
0820 * this <code>Rectangle</code>; or if the rectangles
0821 * do not intersect, an empty rectangle.
0822 */
0823 public Rectangle intersection(Rectangle r) {
0824 int tx1 = this .x;
0825 int ty1 = this .y;
0826 int rx1 = r.x;
0827 int ry1 = r.y;
0828 long tx2 = tx1;
0829 tx2 += this .width;
0830 long ty2 = ty1;
0831 ty2 += this .height;
0832 long rx2 = rx1;
0833 rx2 += r.width;
0834 long ry2 = ry1;
0835 ry2 += r.height;
0836 if (tx1 < rx1)
0837 tx1 = rx1;
0838 if (ty1 < ry1)
0839 ty1 = ry1;
0840 if (tx2 > rx2)
0841 tx2 = rx2;
0842 if (ty2 > ry2)
0843 ty2 = ry2;
0844 tx2 -= tx1;
0845 ty2 -= ty1;
0846 // tx2,ty2 will never overflow (they will never be
0847 // larger than the smallest of the two source w,h)
0848 // they might underflow, though...
0849 if (tx2 < Integer.MIN_VALUE)
0850 tx2 = Integer.MIN_VALUE;
0851 if (ty2 < Integer.MIN_VALUE)
0852 ty2 = Integer.MIN_VALUE;
0853 return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
0854 }
0855
0856 /**
0857 * Computes the union of this <code>Rectangle</code> with the
0858 * specified <code>Rectangle</code>. Returns a new
0859 * <code>Rectangle</code> that
0860 * represents the union of the two rectangles.
0861 * <p>
0862 * If either {@code Rectangle} has any dimension less than zero
0863 * the rules for <a href=#NonExistant>non-existant</a> rectangles
0864 * apply.
0865 * If only one has a dimension less than zero, then the result
0866 * will be a copy of the other {@code Rectangle}.
0867 * If both have dimension less than zero, then the result will
0868 * have at least one dimension less than zero.
0869 * <p>
0870 * If the resulting {@code Rectangle} would have a dimension
0871 * too large to be expressed as an {@code int}, the result
0872 * will have a dimension of {@code Integer.MAX_VALUE} along
0873 * that dimension.
0874 * @param r the specified <code>Rectangle</code>
0875 * @return the smallest <code>Rectangle</code> containing both
0876 * the specified <code>Rectangle</code> and this
0877 * <code>Rectangle</code>.
0878 */
0879 public Rectangle union(Rectangle r) {
0880 long tx2 = this .width;
0881 long ty2 = this .height;
0882 if ((tx2 | ty2) < 0) {
0883 // This rectangle has negative dimensions...
0884 // If r has non-negative dimensions then it is the answer.
0885 // If r is non-existant (has a negative dimension), then both
0886 // are non-existant and we can return any non-existant rectangle
0887 // as an answer. Thus, returning r meets that criterion.
0888 // Either way, r is our answer.
0889 return new Rectangle(r);
0890 }
0891 long rx2 = r.width;
0892 long ry2 = r.height;
0893 if ((rx2 | ry2) < 0) {
0894 return new Rectangle(this );
0895 }
0896 int tx1 = this .x;
0897 int ty1 = this .y;
0898 tx2 += tx1;
0899 ty2 += ty1;
0900 int rx1 = r.x;
0901 int ry1 = r.y;
0902 rx2 += rx1;
0903 ry2 += ry1;
0904 if (tx1 > rx1)
0905 tx1 = rx1;
0906 if (ty1 > ry1)
0907 ty1 = ry1;
0908 if (tx2 < rx2)
0909 tx2 = rx2;
0910 if (ty2 < ry2)
0911 ty2 = ry2;
0912 tx2 -= tx1;
0913 ty2 -= ty1;
0914 // tx2,ty2 will never underflow since both original rectangles
0915 // were already proven to be non-empty
0916 // they might overflow, though...
0917 if (tx2 > Integer.MAX_VALUE)
0918 tx2 = Integer.MAX_VALUE;
0919 if (ty2 > Integer.MAX_VALUE)
0920 ty2 = Integer.MAX_VALUE;
0921 return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
0922 }
0923
0924 /**
0925 * Adds a point, specified by the integer arguments {@code newx,newy}
0926 * to the bounds of this {@code Rectangle}.
0927 * <p>
0928 * If this {@code Rectangle} has any dimension less than zero,
0929 * the rules for <a href=#NonExistant>non-existant</a>
0930 * rectangles apply.
0931 * In that case, the new bounds of this {@code Rectangle} will
0932 * have a location equal to the specified coordinates and
0933 * width and height equal to zero.
0934 * <p>
0935 * After adding a point, a call to <code>contains</code> with the
0936 * added point as an argument does not necessarily return
0937 * <code>true</code>. The <code>contains</code> method does not
0938 * return <code>true</code> for points on the right or bottom
0939 * edges of a <code>Rectangle</code>. Therefore, if the added point
0940 * falls on the right or bottom edge of the enlarged
0941 * <code>Rectangle</code>, <code>contains</code> returns
0942 * <code>false</code> for that point.
0943 * If the specified point must be contained within the new
0944 * {@code Rectangle}, a 1x1 rectangle should be added instead:
0945 * <pre>
0946 * r.add(newx, newy, 1, 1);
0947 * </pre>
0948 * @param newx the X coordinate of the new point
0949 * @param newy the Y coordinate of the new point
0950 */
0951 public void add(int newx, int newy) {
0952 if ((width | height) < 0) {
0953 this .x = newx;
0954 this .y = newy;
0955 this .width = this .height = 0;
0956 return;
0957 }
0958 int x1 = this .x;
0959 int y1 = this .y;
0960 long x2 = this .width;
0961 long y2 = this .height;
0962 x2 += x1;
0963 y2 += y1;
0964 if (x1 > newx)
0965 x1 = newx;
0966 if (y1 > newy)
0967 y1 = newy;
0968 if (x2 < newx)
0969 x2 = newx;
0970 if (y2 < newy)
0971 y2 = newy;
0972 x2 -= x1;
0973 y2 -= y1;
0974 if (x2 > Integer.MAX_VALUE)
0975 x2 = Integer.MAX_VALUE;
0976 if (y2 > Integer.MAX_VALUE)
0977 y2 = Integer.MAX_VALUE;
0978 reshape(x1, y1, (int) x2, (int) y2);
0979 }
0980
0981 /**
0982 * Adds the specified {@code Point} to the bounds of this
0983 * {@code Rectangle}.
0984 * <p>
0985 * If this {@code Rectangle} has any dimension less than zero,
0986 * the rules for <a href=#NonExistant>non-existant</a>
0987 * rectangles apply.
0988 * In that case, the new bounds of this {@code Rectangle} will
0989 * have a location equal to the coordinates of the specified
0990 * {@code Point} and width and height equal to zero.
0991 * <p>
0992 * After adding a <code>Point</code>, a call to <code>contains</code>
0993 * with the added <code>Point</code> as an argument does not
0994 * necessarily return <code>true</code>. The <code>contains</code>
0995 * method does not return <code>true</code> for points on the right
0996 * or bottom edges of a <code>Rectangle</code>. Therefore if the added
0997 * <code>Point</code> falls on the right or bottom edge of the
0998 * enlarged <code>Rectangle</code>, <code>contains</code> returns
0999 * <code>false</code> for that <code>Point</code>.
1000 * If the specified point must be contained within the new
1001 * {@code Rectangle}, a 1x1 rectangle should be added instead:
1002 * <pre>
1003 * r.add(pt.x, pt.y, 1, 1);
1004 * </pre>
1005 * @param pt the new <code>Point</code> to add to this
1006 * <code>Rectangle</code>
1007 */
1008 public void add(Point pt) {
1009 add(pt.x, pt.y);
1010 }
1011
1012 /**
1013 * Adds a <code>Rectangle</code> to this <code>Rectangle</code>.
1014 * The resulting <code>Rectangle</code> is the union of the two
1015 * rectangles.
1016 * <p>
1017 * If either {@code Rectangle} has any dimension less than 0, the
1018 * result will have the dimensions of the other {@code Rectangle}.
1019 * If both {@code Rectangle}s have at least one dimension less
1020 * than 0, the result will have at least one dimension less than 0.
1021 * <p>
1022 * If either {@code Rectangle} has one or both dimensions equal
1023 * to 0, the result along those axes with 0 dimensions will be
1024 * equivalent to the results obtained by adding the corresponding
1025 * origin coordinate to the result rectangle along that axis,
1026 * similar to the operation of the {@link #add(Point)} method,
1027 * but contribute no further dimension beyond that.
1028 * <p>
1029 * If the resulting {@code Rectangle} would have a dimension
1030 * too large to be expressed as an {@code int}, the result
1031 * will have a dimension of {@code Integer.MAX_VALUE} along
1032 * that dimension.
1033 * @param r the specified <code>Rectangle</code>
1034 */
1035 public void add(Rectangle r) {
1036 long tx2 = this .width;
1037 long ty2 = this .height;
1038 if ((tx2 | ty2) < 0) {
1039 reshape(r.x, r.y, r.width, r.height);
1040 }
1041 long rx2 = r.width;
1042 long ry2 = r.height;
1043 if ((rx2 | ry2) < 0) {
1044 return;
1045 }
1046 int tx1 = this .x;
1047 int ty1 = this .y;
1048 tx2 += tx1;
1049 ty2 += ty1;
1050 int rx1 = r.x;
1051 int ry1 = r.y;
1052 rx2 += rx1;
1053 ry2 += ry1;
1054 if (tx1 > rx1)
1055 tx1 = rx1;
1056 if (ty1 > ry1)
1057 ty1 = ry1;
1058 if (tx2 < rx2)
1059 tx2 = rx2;
1060 if (ty2 < ry2)
1061 ty2 = ry2;
1062 tx2 -= tx1;
1063 ty2 -= ty1;
1064 // tx2,ty2 will never underflow since both original
1065 // rectangles were non-empty
1066 // they might overflow, though...
1067 if (tx2 > Integer.MAX_VALUE)
1068 tx2 = Integer.MAX_VALUE;
1069 if (ty2 > Integer.MAX_VALUE)
1070 ty2 = Integer.MAX_VALUE;
1071 reshape(tx1, ty1, (int) tx2, (int) ty2);
1072 }
1073
1074 /**
1075 * Resizes the <code>Rectangle</code> both horizontally and vertically.
1076 * <p>
1077 * This method modifies the <code>Rectangle</code> so that it is
1078 * <code>h</code> units larger on both the left and right side,
1079 * and <code>v</code> units larger at both the top and bottom.
1080 * <p>
1081 * The new <code>Rectangle</code> has {@code (x - h, y - v)}
1082 * as its upper-left corner,
1083 * width of {@code (width + 2h)},
1084 * and a height of {@code (height + 2v)}.
1085 * <p>
1086 * If negative values are supplied for <code>h</code> and
1087 * <code>v</code>, the size of the <code>Rectangle</code>
1088 * decreases accordingly.
1089 * The {@code grow} method will check for integer overflow
1090 * and underflow, but does not check whether the resulting
1091 * values of {@code width} and {@code height} grow
1092 * from negative to non-negative or shrink from non-negative
1093 * to negative.
1094 * @param h the horizontal expansion
1095 * @param v the vertical expansion
1096 */
1097 public void grow(int h, int v) {
1098 long x0 = this .x;
1099 long y0 = this .y;
1100 long x1 = this .width;
1101 long y1 = this .height;
1102 x1 += x0;
1103 y1 += y0;
1104
1105 x0 -= h;
1106 y0 -= v;
1107 x1 += h;
1108 y1 += v;
1109
1110 if (x1 < x0) {
1111 // Non-existant in X direction
1112 // Final width must remain negative so subtract x0 before
1113 // it is clipped so that we avoid the risk that the clipping
1114 // of x0 will reverse the ordering of x0 and x1.
1115 x1 -= x0;
1116 if (x1 < Integer.MIN_VALUE)
1117 x1 = Integer.MIN_VALUE;
1118 if (x0 < Integer.MIN_VALUE)
1119 x0 = Integer.MIN_VALUE;
1120 else if (x0 > Integer.MAX_VALUE)
1121 x0 = Integer.MAX_VALUE;
1122 } else { // (x1 >= x0)
1123 // Clip x0 before we subtract it from x1 in case the clipping
1124 // affects the representable area of the rectangle.
1125 if (x0 < Integer.MIN_VALUE)
1126 x0 = Integer.MIN_VALUE;
1127 else if (x0 > Integer.MAX_VALUE)
1128 x0 = Integer.MAX_VALUE;
1129 x1 -= x0;
1130 // The only way x1 can be negative now is if we clipped
1131 // x0 against MIN and x1 is less than MIN - in which case
1132 // we want to leave the width negative since the result
1133 // did not intersect the representable area.
1134 if (x1 < Integer.MIN_VALUE)
1135 x1 = Integer.MIN_VALUE;
1136 else if (x1 > Integer.MAX_VALUE)
1137 x1 = Integer.MAX_VALUE;
1138 }
1139
1140 if (y1 < y0) {
1141 // Non-existant in Y direction
1142 y1 -= y0;
1143 if (y1 < Integer.MIN_VALUE)
1144 y1 = Integer.MIN_VALUE;
1145 if (y0 < Integer.MIN_VALUE)
1146 y0 = Integer.MIN_VALUE;
1147 else if (y0 > Integer.MAX_VALUE)
1148 y0 = Integer.MAX_VALUE;
1149 } else { // (y1 >= y0)
1150 if (y0 < Integer.MIN_VALUE)
1151 y0 = Integer.MIN_VALUE;
1152 else if (y0 > Integer.MAX_VALUE)
1153 y0 = Integer.MAX_VALUE;
1154 y1 -= y0;
1155 if (y1 < Integer.MIN_VALUE)
1156 y1 = Integer.MIN_VALUE;
1157 else if (y1 > Integer.MAX_VALUE)
1158 y1 = Integer.MAX_VALUE;
1159 }
1160
1161 reshape((int) x0, (int) y0, (int) x1, (int) y1);
1162 }
1163
1164 /**
1165 * {@inheritDoc}
1166 * @since 1.2
1167 */
1168 public boolean isEmpty() {
1169 return (width <= 0) || (height <= 0);
1170 }
1171
1172 /**
1173 * {@inheritDoc}
1174 * @since 1.2
1175 */
1176 public int outcode(double x, double y) {
1177 /*
1178 * Note on casts to double below. If the arithmetic of
1179 * x+w or y+h is done in int, then we may get integer
1180 * overflow. By converting to double before the addition
1181 * we force the addition to be carried out in double to
1182 * avoid overflow in the comparison.
1183 *
1184 * See bug 4320890 for problems that this can cause.
1185 */
1186 int out = 0;
1187 if (this .width <= 0) {
1188 out |= OUT_LEFT | OUT_RIGHT;
1189 } else if (x < this .x) {
1190 out |= OUT_LEFT;
1191 } else if (x > this .x + (double) this .width) {
1192 out |= OUT_RIGHT;
1193 }
1194 if (this .height <= 0) {
1195 out |= OUT_TOP | OUT_BOTTOM;
1196 } else if (y < this .y) {
1197 out |= OUT_TOP;
1198 } else if (y > this .y + (double) this .height) {
1199 out |= OUT_BOTTOM;
1200 }
1201 return out;
1202 }
1203
1204 /**
1205 * {@inheritDoc}
1206 * @since 1.2
1207 */
1208 public Rectangle2D createIntersection(Rectangle2D r) {
1209 if (r instanceof Rectangle) {
1210 return intersection((Rectangle) r);
1211 }
1212 Rectangle2D dest = new Rectangle2D.Double();
1213 Rectangle2D.intersect(this , r, dest);
1214 return dest;
1215 }
1216
1217 /**
1218 * {@inheritDoc}
1219 * @since 1.2
1220 */
1221 public Rectangle2D createUnion(Rectangle2D r) {
1222 if (r instanceof Rectangle) {
1223 return union((Rectangle) r);
1224 }
1225 Rectangle2D dest = new Rectangle2D.Double();
1226 Rectangle2D.union(this , r, dest);
1227 return dest;
1228 }
1229
1230 /**
1231 * Checks whether two rectangles are equal.
1232 * <p>
1233 * The result is <code>true</code> if and only if the argument is not
1234 * <code>null</code> and is a <code>Rectangle</code> object that has the
1235 * same upper-left corner, width, and height as
1236 * this <code>Rectangle</code>.
1237 * @param obj the <code>Object</code> to compare with
1238 * this <code>Rectangle</code>
1239 * @return <code>true</code> if the objects are equal;
1240 * <code>false</code> otherwise.
1241 */
1242 public boolean equals(Object obj) {
1243 if (obj instanceof Rectangle) {
1244 Rectangle r = (Rectangle) obj;
1245 return ((x == r.x) && (y == r.y) && (width == r.width) && (height == r.height));
1246 }
1247 return super .equals(obj);
1248 }
1249
1250 /**
1251 * Returns a <code>String</code> representing this
1252 * <code>Rectangle</code> and its values.
1253 * @return a <code>String</code> representing this
1254 * <code>Rectangle</code> object's coordinate and size values.
1255 */
1256 public String toString() {
1257 return getClass().getName() + "[x=" + x + ",y=" + y + ",width="
1258 + width + ",height=" + height + "]";
1259 }
1260 }
|