1 /*
   2  * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt;
  27 
  28 import java.awt.geom.Rectangle2D;
  29 import java.beans.Transient;
  30 
  31 /**
  32  * A {@code Rectangle} specifies an area in a coordinate space that is
  33  * enclosed by the {@code Rectangle} object's upper-left point
  34  * {@code (x,y)}
  35  * in the coordinate space, its width, and its height.
  36  * <p>
  37  * A {@code Rectangle} object's {@code width} and
  38  * {@code height} are {@code public} fields. The constructors
  39  * that create a {@code Rectangle}, and the methods that can modify
  40  * one, do not prevent setting a negative value for width or height.
  41  * <p>
  42  * <a id="Empty">
  43  * A {@code Rectangle} whose width or height is exactly zero has location
  44  * along those axes with zero dimension, but is otherwise considered empty.</a>
  45  * The {@link #isEmpty} method will return true for such a {@code Rectangle}.
  46  * Methods which test if an empty {@code Rectangle} contains or intersects
  47  * a point or rectangle will always return false if either dimension is zero.
  48  * Methods which combine such a {@code Rectangle} with a point or rectangle
  49  * will include the location of the {@code Rectangle} on that axis in the
  50  * result as if the {@link #add(Point)} method were being called.
  51  * <p>
  52  * <a id="NonExistent">
  53  * A {@code Rectangle} whose width or height is negative has neither
  54  * location nor dimension along those axes with negative dimensions.
  55  * Such a {@code Rectangle} is treated as non-existent along those axes.
  56  * Such a {@code Rectangle} is also empty with respect to containment
  57  * calculations and methods which test if it contains or intersects a
  58  * point or rectangle will always return false.
  59  * Methods which combine such a {@code Rectangle} with a point or rectangle
  60  * will ignore the {@code Rectangle} entirely in generating the result.
  61  * If two {@code Rectangle} objects are combined and each has a negative
  62  * dimension, the result will have at least one negative dimension.
  63  * </a>
  64  * <p>
  65  * Methods which affect only the location of a {@code Rectangle} will
  66  * operate on its location regardless of whether or not it has a negative
  67  * or zero dimension along either axis.
  68  * <p>
  69  * Note that a {@code Rectangle} constructed with the default no-argument
  70  * constructor will have dimensions of {@code 0x0} and therefore be empty.
  71  * That {@code Rectangle} will still have a location of {@code (0,0)} and
  72  * will contribute that location to the union and add operations.
  73  * Code attempting to accumulate the bounds of a set of points should
  74  * therefore initially construct the {@code Rectangle} with a specifically
  75  * negative width and height or it should use the first point in the set
  76  * to construct the {@code Rectangle}.
  77  * For example:
  78  * <pre>{@code
  79  *     Rectangle bounds = new Rectangle(0, 0, -1, -1);
  80  *     for (int i = 0; i < points.length; i++) {
  81  *         bounds.add(points[i]);
  82  *     }
  83  * }</pre>
  84  * or if we know that the points array contains at least one point:
  85  * <pre>{@code
  86  *     Rectangle bounds = new Rectangle(points[0]);
  87  *     for (int i = 1; i < points.length; i++) {
  88  *         bounds.add(points[i]);
  89  *     }
  90  * }</pre>
  91  * <p>
  92  * This class uses 32-bit integers to store its location and dimensions.
  93  * Frequently operations may produce a result that exceeds the range of
  94  * a 32-bit integer.
  95  * The methods will calculate their results in a way that avoids any
  96  * 32-bit overflow for intermediate results and then choose the best
  97  * representation to store the final results back into the 32-bit fields
  98  * which hold the location and dimensions.
  99  * The location of the result will be stored into the {@link #x} and
 100  * {@link #y} fields by clipping the true result to the nearest 32-bit value.
 101  * The values stored into the {@link #width} and {@link #height} dimension
 102  * fields will be chosen as the 32-bit values that encompass the largest
 103  * part of the true result as possible.
 104  * Generally this means that the dimension will be clipped independently
 105  * to the range of 32-bit integers except that if the location had to be
 106  * moved to store it into its pair of 32-bit fields then the dimensions
 107  * will be adjusted relative to the "best representation" of the location.
 108  * If the true result had a negative dimension and was therefore
 109  * non-existent along one or both axes, the stored dimensions will be
 110  * negative numbers in those axes.
 111  * If the true result had a location that could be represented within
 112  * the range of 32-bit integers, but zero dimension along one or both
 113  * axes, then the stored dimensions will be zero in those axes.
 114  *
 115  * @author      Sami Shaio
 116  * @since 1.0
 117  */
 118 public class Rectangle extends Rectangle2D
 119     implements Shape, java.io.Serializable
 120 {
 121 
 122     /**
 123      * The X coordinate of the upper-left corner of the {@code Rectangle}.
 124      *
 125      * @serial
 126      * @see #setLocation(int, int)
 127      * @see #getLocation()
 128      * @since 1.0
 129      */
 130     public int x;
 131 
 132     /**
 133      * The Y coordinate of the upper-left corner of the {@code Rectangle}.
 134      *
 135      * @serial
 136      * @see #setLocation(int, int)
 137      * @see #getLocation()
 138      * @since 1.0
 139      */
 140     public int y;
 141 
 142     /**
 143      * The width of the {@code Rectangle}.
 144      * @serial
 145      * @see #setSize(int, int)
 146      * @see #getSize()
 147      * @since 1.0
 148      */
 149     public int width;
 150 
 151     /**
 152      * The height of the {@code Rectangle}.
 153      *
 154      * @serial
 155      * @see #setSize(int, int)
 156      * @see #getSize()
 157      * @since 1.0
 158      */
 159     public int height;
 160 
 161     /*
 162      * JDK 1.1 serialVersionUID
 163      */
 164      private static final long serialVersionUID = -4345857070255674764L;
 165 
 166     /**
 167      * Initialize JNI field and method IDs
 168      */
 169     private static native void initIDs();
 170 
 171     static {
 172         /* ensure that the necessary native libraries are loaded */
 173         Toolkit.loadLibraries();
 174         if (!GraphicsEnvironment.isHeadless()) {
 175             initIDs();
 176         }
 177     }
 178 
 179     /**
 180      * Constructs a new {@code Rectangle} whose upper-left corner
 181      * is at (0,&nbsp;0) in the coordinate space, and whose width and
 182      * height are both zero.
 183      */
 184     public Rectangle() {
 185         this(0, 0, 0, 0);
 186     }
 187 
 188     /**
 189      * Constructs a new {@code Rectangle}, initialized to match
 190      * the values of the specified {@code Rectangle}.
 191      * @param r  the {@code Rectangle} from which to copy initial values
 192      *           to a newly constructed {@code Rectangle}
 193      * @since 1.1
 194      */
 195     public Rectangle(Rectangle r) {
 196         this(r.x, r.y, r.width, r.height);
 197     }
 198 
 199     /**
 200      * Constructs a new {@code Rectangle} whose upper-left corner is
 201      * specified as
 202      * {@code (x,y)} and whose width and height
 203      * are specified by the arguments of the same name.
 204      * @param     x the specified X coordinate
 205      * @param     y the specified Y coordinate
 206      * @param     width    the width of the {@code Rectangle}
 207      * @param     height   the height of the {@code Rectangle}
 208      * @since 1.0
 209      */
 210     public Rectangle(int x, int y, int width, int height) {
 211         this.x = x;
 212         this.y = y;
 213         this.width = width;
 214         this.height = height;
 215     }
 216 
 217     /**
 218      * Constructs a new {@code Rectangle} whose upper-left corner
 219      * is at (0,&nbsp;0) in the coordinate space, and whose width and
 220      * height are specified by the arguments of the same name.
 221      * @param width the width of the {@code Rectangle}
 222      * @param height the height of the {@code Rectangle}
 223      */
 224     public Rectangle(int width, int height) {
 225         this(0, 0, width, height);
 226     }
 227 
 228     /**
 229      * Constructs a new {@code Rectangle} whose upper-left corner is
 230      * specified by the {@link Point} argument, and
 231      * whose width and height are specified by the
 232      * {@link Dimension} argument.
 233      * @param p a {@code Point} that is the upper-left corner of
 234      * the {@code Rectangle}
 235      * @param d a {@code Dimension}, representing the
 236      * width and height of the {@code Rectangle}
 237      */
 238     public Rectangle(Point p, Dimension d) {
 239         this(p.x, p.y, d.width, d.height);
 240     }
 241 
 242     /**
 243      * Constructs a new {@code Rectangle} whose upper-left corner is the
 244      * specified {@code Point}, and whose width and height are both zero.
 245      * @param p a {@code Point} that is the top left corner
 246      * of the {@code Rectangle}
 247      */
 248     public Rectangle(Point p) {
 249         this(p.x, p.y, 0, 0);
 250     }
 251 
 252     /**
 253      * Constructs a new {@code Rectangle} whose top left corner is
 254      * (0,&nbsp;0) and whose width and height are specified
 255      * by the {@code Dimension} argument.
 256      * @param d a {@code Dimension}, specifying width and height
 257      */
 258     public Rectangle(Dimension d) {
 259         this(0, 0, d.width, d.height);
 260     }
 261 
 262     /**
 263      * Returns the X coordinate of the bounding {@code Rectangle} in
 264      * {@code double} precision.
 265      * @return the X coordinate of the bounding {@code Rectangle}.
 266      */
 267     public double getX() {
 268         return x;
 269     }
 270 
 271     /**
 272      * Returns the Y coordinate of the bounding {@code Rectangle} in
 273      * {@code double} precision.
 274      * @return the Y coordinate of the bounding {@code Rectangle}.
 275      */
 276     public double getY() {
 277         return y;
 278     }
 279 
 280     /**
 281      * Returns the width of the bounding {@code Rectangle} in
 282      * {@code double} precision.
 283      * @return the width of the bounding {@code Rectangle}.
 284      */
 285     public double getWidth() {
 286         return width;
 287     }
 288 
 289     /**
 290      * Returns the height of the bounding {@code Rectangle} in
 291      * {@code double} precision.
 292      * @return the height of the bounding {@code Rectangle}.
 293      */
 294     public double getHeight() {
 295         return height;
 296     }
 297 
 298     /**
 299      * Gets the bounding {@code Rectangle} of this {@code Rectangle}.
 300      * <p>
 301      * This method is included for completeness, to parallel the
 302      * {@code getBounds} method of
 303      * {@link Component}.
 304      * @return    a new {@code Rectangle}, equal to the
 305      * bounding {@code Rectangle} for this {@code Rectangle}.
 306      * @see       java.awt.Component#getBounds
 307      * @see       #setBounds(Rectangle)
 308      * @see       #setBounds(int, int, int, int)
 309      * @since     1.1
 310      */
 311     @Transient
 312     public Rectangle getBounds() {
 313         return new Rectangle(x, y, width, height);
 314     }
 315 
 316     /**
 317      * {@inheritDoc}
 318      * @since 1.2
 319      */
 320     public Rectangle2D getBounds2D() {
 321         return new Rectangle(x, y, width, height);
 322     }
 323 
 324     /**
 325      * Sets the bounding {@code Rectangle} of this {@code Rectangle}
 326      * to match the specified {@code Rectangle}.
 327      * <p>
 328      * This method is included for completeness, to parallel the
 329      * {@code setBounds} method of {@code Component}.
 330      * @param r the specified {@code Rectangle}
 331      * @see       #getBounds
 332      * @see       java.awt.Component#setBounds(java.awt.Rectangle)
 333      * @since     1.1
 334      */
 335     public void setBounds(Rectangle r) {
 336         setBounds(r.x, r.y, r.width, r.height);
 337     }
 338 
 339     /**
 340      * Sets the bounding {@code Rectangle} of this
 341      * {@code Rectangle} to the specified
 342      * {@code x}, {@code y}, {@code width},
 343      * and {@code height}.
 344      * <p>
 345      * This method is included for completeness, to parallel the
 346      * {@code setBounds} method of {@code Component}.
 347      * @param x the new X coordinate for the upper-left
 348      *                    corner of this {@code Rectangle}
 349      * @param y the new Y coordinate for the upper-left
 350      *                    corner of this {@code Rectangle}
 351      * @param width the new width for this {@code Rectangle}
 352      * @param height the new height for this {@code Rectangle}
 353      * @see       #getBounds
 354      * @see       java.awt.Component#setBounds(int, int, int, int)
 355      * @since     1.1
 356      */
 357     public void setBounds(int x, int y, int width, int height) {
 358         reshape(x, y, width, height);
 359     }
 360 
 361     /**
 362      * Sets the bounds of this {@code Rectangle} to the integer bounds
 363      * which encompass the specified {@code x}, {@code y}, {@code width},
 364      * and {@code height}.
 365      * If the parameters specify a {@code Rectangle} that exceeds the
 366      * maximum range of integers, the result will be the best
 367      * representation of the specified {@code Rectangle} intersected
 368      * with the maximum integer bounds.
 369      * @param x the X coordinate of the upper-left corner of
 370      *                  the specified rectangle
 371      * @param y the Y coordinate of the upper-left corner of
 372      *                  the specified rectangle
 373      * @param width the width of the specified rectangle
 374      * @param height the new height of the specified rectangle
 375      */
 376     public void setRect(double x, double y, double width, double height) {
 377         int newx, newy, neww, newh;
 378 
 379         if (x > 2.0 * Integer.MAX_VALUE) {
 380             // Too far in positive X direction to represent...
 381             // We cannot even reach the left side of the specified
 382             // rectangle even with both x & width set to MAX_VALUE.
 383             // The intersection with the "maximal integer rectangle"
 384             // is non-existent so we should use a width < 0.
 385             // REMIND: Should we try to determine a more "meaningful"
 386             // adjusted value for neww than just "-1"?
 387             newx = Integer.MAX_VALUE;
 388             neww = -1;
 389         } else {
 390             newx = clip(x, false);
 391             if (width >= 0) width += x-newx;
 392             neww = clip(width, width >= 0);
 393         }
 394 
 395         if (y > 2.0 * Integer.MAX_VALUE) {
 396             // Too far in positive Y direction to represent...
 397             newy = Integer.MAX_VALUE;
 398             newh = -1;
 399         } else {
 400             newy = clip(y, false);
 401             if (height >= 0) height += y-newy;
 402             newh = clip(height, height >= 0);
 403         }
 404 
 405         reshape(newx, newy, neww, newh);
 406     }
 407     // Return best integer representation for v, clipped to integer
 408     // range and floor-ed or ceiling-ed, depending on the boolean.
 409     private static int clip(double v, boolean doceil) {
 410         if (v <= Integer.MIN_VALUE) {
 411             return Integer.MIN_VALUE;
 412         }
 413         if (v >= Integer.MAX_VALUE) {
 414             return Integer.MAX_VALUE;
 415         }
 416         return (int) (doceil ? Math.ceil(v) : Math.floor(v));
 417     }
 418 
 419     /**
 420      * Sets the bounding {@code Rectangle} of this
 421      * {@code Rectangle} to the specified
 422      * {@code x}, {@code y}, {@code width},
 423      * and {@code height}.
 424      *
 425      * @param x the new X coordinate for the upper-left
 426      *                    corner of this {@code Rectangle}
 427      * @param y the new Y coordinate for the upper-left
 428      *                    corner of this {@code Rectangle}
 429      * @param width the new width for this {@code Rectangle}
 430      * @param height the new height for this {@code Rectangle}
 431      * @deprecated As of JDK version 1.1,
 432      * replaced by {@code setBounds(int, int, int, int)}.
 433      */
 434     @Deprecated
 435     public void reshape(int x, int y, int width, int height) {
 436         this.x = x;
 437         this.y = y;
 438         this.width = width;
 439         this.height = height;
 440     }
 441 
 442     /**
 443      * Returns the location of this {@code Rectangle}.
 444      * <p>
 445      * This method is included for completeness, to parallel the
 446      * {@code getLocation} method of {@code Component}.
 447      * @return the {@code Point} that is the upper-left corner of
 448      *                  this {@code Rectangle}.
 449      * @see       java.awt.Component#getLocation
 450      * @see       #setLocation(Point)
 451      * @see       #setLocation(int, int)
 452      * @since     1.1
 453      */
 454     public Point getLocation() {
 455         return new Point(x, y);
 456     }
 457 
 458     /**
 459      * Moves this {@code Rectangle} to the specified location.
 460      * <p>
 461      * This method is included for completeness, to parallel the
 462      * {@code setLocation} method of {@code Component}.
 463      * @param p the {@code Point} specifying the new location
 464      *                for this {@code Rectangle}
 465      * @see       java.awt.Component#setLocation(java.awt.Point)
 466      * @see       #getLocation
 467      * @since     1.1
 468      */
 469     public void setLocation(Point p) {
 470         setLocation(p.x, p.y);
 471     }
 472 
 473     /**
 474      * Moves this {@code Rectangle} to the specified location.
 475      * <p>
 476      * This method is included for completeness, to parallel the
 477      * {@code setLocation} method of {@code Component}.
 478      * @param x the X coordinate of the new location
 479      * @param y the Y coordinate of the new location
 480      * @see       #getLocation
 481      * @see       java.awt.Component#setLocation(int, int)
 482      * @since     1.1
 483      */
 484     public void setLocation(int x, int y) {
 485         move(x, y);
 486     }
 487 
 488     /**
 489      * Moves this {@code Rectangle} to the specified location.
 490      *
 491      * @param x the X coordinate of the new location
 492      * @param y the Y coordinate of the new location
 493      * @deprecated As of JDK version 1.1,
 494      * replaced by {@code setLocation(int, int)}.
 495      */
 496     @Deprecated
 497     public void move(int x, int y) {
 498         this.x = x;
 499         this.y = y;
 500     }
 501 
 502     /**
 503      * Translates this {@code Rectangle} the indicated distance,
 504      * to the right along the X coordinate axis, and
 505      * downward along the Y coordinate axis.
 506      * @param dx the distance to move this {@code Rectangle}
 507      *                 along the X axis
 508      * @param dy the distance to move this {@code Rectangle}
 509      *                 along the Y axis
 510      * @see       java.awt.Rectangle#setLocation(int, int)
 511      * @see       java.awt.Rectangle#setLocation(java.awt.Point)
 512      */
 513     public void translate(int dx, int dy) {
 514         int oldv = this.x;
 515         int newv = oldv + dx;
 516         if (dx < 0) {
 517             // moving leftward
 518             if (newv > oldv) {
 519                 // negative overflow
 520                 // Only adjust width if it was valid (>= 0).
 521                 if (width >= 0) {
 522                     // The right edge is now conceptually at
 523                     // newv+width, but we may move newv to prevent
 524                     // overflow.  But we want the right edge to
 525                     // remain at its new location in spite of the
 526                     // clipping.  Think of the following adjustment
 527                     // conceptually the same as:
 528                     // width += newv; newv = MIN_VALUE; width -= newv;
 529                     width += newv - Integer.MIN_VALUE;
 530                     // width may go negative if the right edge went past
 531                     // MIN_VALUE, but it cannot overflow since it cannot
 532                     // have moved more than MIN_VALUE and any non-negative
 533                     // number + MIN_VALUE does not overflow.
 534                 }
 535                 newv = Integer.MIN_VALUE;
 536             }
 537         } else {
 538             // moving rightward (or staying still)
 539             if (newv < oldv) {
 540                 // positive overflow
 541                 if (width >= 0) {
 542                     // Conceptually the same as:
 543                     // width += newv; newv = MAX_VALUE; width -= newv;
 544                     width += newv - Integer.MAX_VALUE;
 545                     // With large widths and large displacements
 546                     // we may overflow so we need to check it.
 547                     if (width < 0) width = Integer.MAX_VALUE;
 548                 }
 549                 newv = Integer.MAX_VALUE;
 550             }
 551         }
 552         this.x = newv;
 553 
 554         oldv = this.y;
 555         newv = oldv + dy;
 556         if (dy < 0) {
 557             // moving upward
 558             if (newv > oldv) {
 559                 // negative overflow
 560                 if (height >= 0) {
 561                     height += newv - Integer.MIN_VALUE;
 562                     // See above comment about no overflow in this case
 563                 }
 564                 newv = Integer.MIN_VALUE;
 565             }
 566         } else {
 567             // moving downward (or staying still)
 568             if (newv < oldv) {
 569                 // positive overflow
 570                 if (height >= 0) {
 571                     height += newv - Integer.MAX_VALUE;
 572                     if (height < 0) height = Integer.MAX_VALUE;
 573                 }
 574                 newv = Integer.MAX_VALUE;
 575             }
 576         }
 577         this.y = newv;
 578     }
 579 
 580     /**
 581      * Gets the size of this {@code Rectangle}, represented by
 582      * the returned {@code Dimension}.
 583      * <p>
 584      * This method is included for completeness, to parallel the
 585      * {@code getSize} method of {@code Component}.
 586      * @return a {@code Dimension}, representing the size of
 587      *            this {@code Rectangle}.
 588      * @see       java.awt.Component#getSize
 589      * @see       #setSize(Dimension)
 590      * @see       #setSize(int, int)
 591      * @since     1.1
 592      */
 593     public Dimension getSize() {
 594         return new Dimension(width, height);
 595     }
 596 
 597     /**
 598      * Sets the size of this {@code Rectangle} to match the
 599      * specified {@code Dimension}.
 600      * <p>
 601      * This method is included for completeness, to parallel the
 602      * {@code setSize} method of {@code Component}.
 603      * @param d the new size for the {@code Dimension} object
 604      * @see       java.awt.Component#setSize(java.awt.Dimension)
 605      * @see       #getSize
 606      * @since     1.1
 607      */
 608     public void setSize(Dimension d) {
 609         setSize(d.width, d.height);
 610     }
 611 
 612     /**
 613      * Sets the size of this {@code Rectangle} to the specified
 614      * width and height.
 615      * <p>
 616      * This method is included for completeness, to parallel the
 617      * {@code setSize} method of {@code Component}.
 618      * @param width the new width for this {@code Rectangle}
 619      * @param height the new height for this {@code Rectangle}
 620      * @see       java.awt.Component#setSize(int, int)
 621      * @see       #getSize
 622      * @since     1.1
 623      */
 624     public void setSize(int width, int height) {
 625         resize(width, height);
 626     }
 627 
 628     /**
 629      * Sets the size of this {@code Rectangle} to the specified
 630      * width and height.
 631      *
 632      * @param width the new width for this {@code Rectangle}
 633      * @param height the new height for this {@code Rectangle}
 634      * @deprecated As of JDK version 1.1,
 635      * replaced by {@code setSize(int, int)}.
 636      */
 637     @Deprecated
 638     public void resize(int width, int height) {
 639         this.width = width;
 640         this.height = height;
 641     }
 642 
 643     /**
 644      * Checks whether or not this {@code Rectangle} contains the
 645      * specified {@code Point}.
 646      * @param p the {@code Point} to test
 647      * @return    {@code true} if the specified {@code Point}
 648      *            is inside this {@code Rectangle};
 649      *            {@code false} otherwise.
 650      * @since     1.1
 651      */
 652     public boolean contains(Point p) {
 653         return contains(p.x, p.y);
 654     }
 655 
 656     /**
 657      * Checks whether or not this {@code Rectangle} contains the
 658      * point at the specified location {@code (x,y)}.
 659      *
 660      * @param  x the specified X coordinate
 661      * @param  y the specified Y coordinate
 662      * @return    {@code true} if the point
 663      *            {@code (x,y)} is inside this
 664      *            {@code Rectangle};
 665      *            {@code false} otherwise.
 666      * @since     1.1
 667      */
 668     public boolean contains(int x, int y) {
 669         return inside(x, y);
 670     }
 671 
 672     /**
 673      * Checks whether or not this {@code Rectangle} entirely contains
 674      * the specified {@code Rectangle}.
 675      *
 676      * @param     r   the specified {@code Rectangle}
 677      * @return    {@code true} if the {@code Rectangle}
 678      *            is contained entirely inside this {@code Rectangle};
 679      *            {@code false} otherwise
 680      * @since     1.2
 681      */
 682     public boolean contains(Rectangle r) {
 683         return contains(r.x, r.y, r.width, r.height);
 684     }
 685 
 686     /**
 687      * Checks whether this {@code Rectangle} entirely contains
 688      * the {@code Rectangle}
 689      * at the specified location {@code (X,Y)} with the
 690      * specified dimensions {@code (W,H)}.
 691      * @param     X the specified X coordinate
 692      * @param     Y the specified Y coordinate
 693      * @param     W   the width of the {@code Rectangle}
 694      * @param     H   the height of the {@code Rectangle}
 695      * @return    {@code true} if the {@code Rectangle} specified by
 696      *            {@code (X, Y, W, H)}
 697      *            is entirely enclosed inside this {@code Rectangle};
 698      *            {@code false} otherwise.
 699      * @since     1.1
 700      */
 701     public boolean contains(int X, int Y, int W, int H) {
 702         int w = this.width;
 703         int h = this.height;
 704         if ((w | h | W | H) < 0) {
 705             // At least one of the dimensions is negative...
 706             return false;
 707         }
 708         // Note: if any dimension is zero, tests below must return false...
 709         int x = this.x;
 710         int y = this.y;
 711         if (X < x || Y < y) {
 712             return false;
 713         }
 714         w += x;
 715         W += X;
 716         if (W <= X) {
 717             // X+W overflowed or W was zero, return false if...
 718             // either original w or W was zero or
 719             // x+w did not overflow or
 720             // the overflowed x+w is smaller than the overflowed X+W
 721             if (w >= x || W > w) return false;
 722         } else {
 723             // X+W did not overflow and W was not zero, return false if...
 724             // original w was zero or
 725             // x+w did not overflow and x+w is smaller than X+W
 726             if (w >= x && W > w) return false;
 727         }
 728         h += y;
 729         H += Y;
 730         if (H <= Y) {
 731             if (h >= y || H > h) return false;
 732         } else {
 733             if (h >= y && H > h) return false;
 734         }
 735         return true;
 736     }
 737 
 738     /**
 739      * Checks whether or not this {@code Rectangle} contains the
 740      * point at the specified location {@code (X,Y)}.
 741      *
 742      * @param  X the specified X coordinate
 743      * @param  Y the specified Y coordinate
 744      * @return    {@code true} if the point
 745      *            {@code (X,Y)} is inside this
 746      *            {@code Rectangle};
 747      *            {@code false} otherwise.
 748      * @deprecated As of JDK version 1.1,
 749      * replaced by {@code contains(int, int)}.
 750      */
 751     @Deprecated
 752     public boolean inside(int X, int Y) {
 753         int w = this.width;
 754         int h = this.height;
 755         if ((w | h) < 0) {
 756             // At least one of the dimensions is negative...
 757             return false;
 758         }
 759         // Note: if either dimension is zero, tests below must return false...
 760         int x = this.x;
 761         int y = this.y;
 762         if (X < x || Y < y) {
 763             return false;
 764         }
 765         w += x;
 766         h += y;
 767         //    overflow || intersect
 768         return ((w < x || w > X) &&
 769                 (h < y || h > Y));
 770     }
 771 
 772     /**
 773      * Determines whether or not this {@code Rectangle} and the specified
 774      * {@code Rectangle} intersect. Two rectangles intersect if
 775      * their intersection is nonempty.
 776      *
 777      * @param r the specified {@code Rectangle}
 778      * @return    {@code true} if the specified {@code Rectangle}
 779      *            and this {@code Rectangle} intersect;
 780      *            {@code false} otherwise.
 781      */
 782     public boolean intersects(Rectangle r) {
 783         int tw = this.width;
 784         int th = this.height;
 785         int rw = r.width;
 786         int rh = r.height;
 787         if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
 788             return false;
 789         }
 790         int tx = this.x;
 791         int ty = this.y;
 792         int rx = r.x;
 793         int ry = r.y;
 794         rw += rx;
 795         rh += ry;
 796         tw += tx;
 797         th += ty;
 798         //      overflow || intersect
 799         return ((rw < rx || rw > tx) &&
 800                 (rh < ry || rh > ty) &&
 801                 (tw < tx || tw > rx) &&
 802                 (th < ty || th > ry));
 803     }
 804 
 805     /**
 806      * Computes the intersection of this {@code Rectangle} with the
 807      * specified {@code Rectangle}. Returns a new {@code Rectangle}
 808      * that represents the intersection of the two rectangles.
 809      * If the two rectangles do not intersect, the result will be
 810      * an empty rectangle.
 811      *
 812      * @param     r   the specified {@code Rectangle}
 813      * @return    the largest {@code Rectangle} contained in both the
 814      *            specified {@code Rectangle} and in
 815      *            this {@code Rectangle}; or if the rectangles
 816      *            do not intersect, an empty rectangle.
 817      */
 818     public Rectangle intersection(Rectangle r) {
 819         int tx1 = this.x;
 820         int ty1 = this.y;
 821         int rx1 = r.x;
 822         int ry1 = r.y;
 823         long tx2 = tx1; tx2 += this.width;
 824         long ty2 = ty1; ty2 += this.height;
 825         long rx2 = rx1; rx2 += r.width;
 826         long ry2 = ry1; ry2 += r.height;
 827         if (tx1 < rx1) tx1 = rx1;
 828         if (ty1 < ry1) ty1 = ry1;
 829         if (tx2 > rx2) tx2 = rx2;
 830         if (ty2 > ry2) ty2 = ry2;
 831         tx2 -= tx1;
 832         ty2 -= ty1;
 833         // tx2,ty2 will never overflow (they will never be
 834         // larger than the smallest of the two source w,h)
 835         // they might underflow, though...
 836         if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
 837         if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
 838         return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
 839     }
 840 
 841     /**
 842      * Computes the union of this {@code Rectangle} with the
 843      * specified {@code Rectangle}. Returns a new
 844      * {@code Rectangle} that
 845      * represents the union of the two rectangles.
 846      * <p>
 847      * If either {@code Rectangle} has any dimension less than zero
 848      * the rules for <a href=#NonExistent>non-existent</a> rectangles
 849      * apply.
 850      * If only one has a dimension less than zero, then the result
 851      * will be a copy of the other {@code Rectangle}.
 852      * If both have dimension less than zero, then the result will
 853      * have at least one dimension less than zero.
 854      * <p>
 855      * If the resulting {@code Rectangle} would have a dimension
 856      * too large to be expressed as an {@code int}, the result
 857      * will have a dimension of {@code Integer.MAX_VALUE} along
 858      * that dimension.
 859      * @param r the specified {@code Rectangle}
 860      * @return    the smallest {@code Rectangle} containing both
 861      *            the specified {@code Rectangle} and this
 862      *            {@code Rectangle}.
 863      */
 864     public Rectangle union(Rectangle r) {
 865         long tx2 = this.width;
 866         long ty2 = this.height;
 867         if ((tx2 | ty2) < 0) {
 868             // This rectangle has negative dimensions...
 869             // If r has non-negative dimensions then it is the answer.
 870             // If r is non-existent (has a negative dimension), then both
 871             // are non-existent and we can return any non-existent rectangle
 872             // as an answer.  Thus, returning r meets that criterion.
 873             // Either way, r is our answer.
 874             return new Rectangle(r);
 875         }
 876         long rx2 = r.width;
 877         long ry2 = r.height;
 878         if ((rx2 | ry2) < 0) {
 879             return new Rectangle(this);
 880         }
 881         int tx1 = this.x;
 882         int ty1 = this.y;
 883         tx2 += tx1;
 884         ty2 += ty1;
 885         int rx1 = r.x;
 886         int ry1 = r.y;
 887         rx2 += rx1;
 888         ry2 += ry1;
 889         if (tx1 > rx1) tx1 = rx1;
 890         if (ty1 > ry1) ty1 = ry1;
 891         if (tx2 < rx2) tx2 = rx2;
 892         if (ty2 < ry2) ty2 = ry2;
 893         tx2 -= tx1;
 894         ty2 -= ty1;
 895         // tx2,ty2 will never underflow since both original rectangles
 896         // were already proven to be non-empty
 897         // they might overflow, though...
 898         if (tx2 > Integer.MAX_VALUE) tx2 = Integer.MAX_VALUE;
 899         if (ty2 > Integer.MAX_VALUE) ty2 = Integer.MAX_VALUE;
 900         return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
 901     }
 902 
 903     /**
 904      * Adds a point, specified by the integer arguments {@code newx,newy}
 905      * to the bounds of this {@code Rectangle}.
 906      * <p>
 907      * If this {@code Rectangle} has any dimension less than zero,
 908      * the rules for <a href=#NonExistent>non-existent</a>
 909      * rectangles apply.
 910      * In that case, the new bounds of this {@code Rectangle} will
 911      * have a location equal to the specified coordinates and
 912      * width and height equal to zero.
 913      * <p>
 914      * After adding a point, a call to {@code contains} with the
 915      * added point as an argument does not necessarily return
 916      * {@code true}. The {@code contains} method does not
 917      * return {@code true} for points on the right or bottom
 918      * edges of a {@code Rectangle}. Therefore, if the added point
 919      * falls on the right or bottom edge of the enlarged
 920      * {@code Rectangle}, {@code contains} returns
 921      * {@code false} for that point.
 922      * If the specified point must be contained within the new
 923      * {@code Rectangle}, a 1x1 rectangle should be added instead:
 924      * <pre>
 925      *     r.add(new Rectangle(newx, newy, 1, 1));
 926      * </pre>
 927      * @param newx the X coordinate of the new point
 928      * @param newy the Y coordinate of the new point
 929      */
 930     public void add(int newx, int newy) {
 931         if ((width | height) < 0) {
 932             this.x = newx;
 933             this.y = newy;
 934             this.width = this.height = 0;
 935             return;
 936         }
 937         int x1 = this.x;
 938         int y1 = this.y;
 939         long x2 = this.width;
 940         long y2 = this.height;
 941         x2 += x1;
 942         y2 += y1;
 943         if (x1 > newx) x1 = newx;
 944         if (y1 > newy) y1 = newy;
 945         if (x2 < newx) x2 = newx;
 946         if (y2 < newy) y2 = newy;
 947         x2 -= x1;
 948         y2 -= y1;
 949         if (x2 > Integer.MAX_VALUE) x2 = Integer.MAX_VALUE;
 950         if (y2 > Integer.MAX_VALUE) y2 = Integer.MAX_VALUE;
 951         reshape(x1, y1, (int) x2, (int) y2);
 952     }
 953 
 954     /**
 955      * Adds the specified {@code Point} to the bounds of this
 956      * {@code Rectangle}.
 957      * <p>
 958      * If this {@code Rectangle} has any dimension less than zero,
 959      * the rules for <a href=#NonExistent>non-existent</a>
 960      * rectangles apply.
 961      * In that case, the new bounds of this {@code Rectangle} will
 962      * have a location equal to the coordinates of the specified
 963      * {@code Point} and width and height equal to zero.
 964      * <p>
 965      * After adding a {@code Point}, a call to {@code contains}
 966      * with the added {@code Point} as an argument does not
 967      * necessarily return {@code true}. The {@code contains}
 968      * method does not return {@code true} for points on the right
 969      * or bottom edges of a {@code Rectangle}. Therefore if the added
 970      * {@code Point} falls on the right or bottom edge of the
 971      * enlarged {@code Rectangle}, {@code contains} returns
 972      * {@code false} for that {@code Point}.
 973      * If the specified point must be contained within the new
 974      * {@code Rectangle}, a 1x1 rectangle should be added instead:
 975      * <pre>
 976      *     r.add(new Rectangle(pt.x, pt.y, 1, 1));
 977      * </pre>
 978      * @param pt the new {@code Point} to add to this
 979      *           {@code Rectangle}
 980      */
 981     public void add(Point pt) {
 982         add(pt.x, pt.y);
 983     }
 984 
 985     /**
 986      * Adds a {@code Rectangle} to this {@code Rectangle}.
 987      * The resulting {@code Rectangle} is the union of the two
 988      * rectangles.
 989      * <p>
 990      * If either {@code Rectangle} has any dimension less than 0, the
 991      * result will have the dimensions of the other {@code Rectangle}.
 992      * If both {@code Rectangle}s have at least one dimension less
 993      * than 0, the result will have at least one dimension less than 0.
 994      * <p>
 995      * If either {@code Rectangle} has one or both dimensions equal
 996      * to 0, the result along those axes with 0 dimensions will be
 997      * equivalent to the results obtained by adding the corresponding
 998      * origin coordinate to the result rectangle along that axis,
 999      * similar to the operation of the {@link #add(Point)} method,
1000      * but contribute no further dimension beyond that.
1001      * <p>
1002      * If the resulting {@code Rectangle} would have a dimension
1003      * too large to be expressed as an {@code int}, the result
1004      * will have a dimension of {@code Integer.MAX_VALUE} along
1005      * that dimension.
1006      * @param  r the specified {@code Rectangle}
1007      */
1008     public void add(Rectangle r) {
1009         long tx2 = this.width;
1010         long ty2 = this.height;
1011         if ((tx2 | ty2) < 0) {
1012             reshape(r.x, r.y, r.width, r.height);
1013         }
1014         long rx2 = r.width;
1015         long ry2 = r.height;
1016         if ((rx2 | ry2) < 0) {
1017             return;
1018         }
1019         int tx1 = this.x;
1020         int ty1 = this.y;
1021         tx2 += tx1;
1022         ty2 += ty1;
1023         int rx1 = r.x;
1024         int ry1 = r.y;
1025         rx2 += rx1;
1026         ry2 += ry1;
1027         if (tx1 > rx1) tx1 = rx1;
1028         if (ty1 > ry1) ty1 = ry1;
1029         if (tx2 < rx2) tx2 = rx2;
1030         if (ty2 < ry2) ty2 = ry2;
1031         tx2 -= tx1;
1032         ty2 -= ty1;
1033         // tx2,ty2 will never underflow since both original
1034         // rectangles were non-empty
1035         // they might overflow, though...
1036         if (tx2 > Integer.MAX_VALUE) tx2 = Integer.MAX_VALUE;
1037         if (ty2 > Integer.MAX_VALUE) ty2 = Integer.MAX_VALUE;
1038         reshape(tx1, ty1, (int) tx2, (int) ty2);
1039     }
1040 
1041     /**
1042      * Resizes the {@code Rectangle} both horizontally and vertically.
1043      * <p>
1044      * This method modifies the {@code Rectangle} so that it is
1045      * {@code h} units larger on both the left and right side,
1046      * and {@code v} units larger at both the top and bottom.
1047      * <p>
1048      * The new {@code Rectangle} has {@code (x - h, y - v)}
1049      * as its upper-left corner,
1050      * width of {@code (width + 2h)},
1051      * and a height of {@code (height + 2v)}.
1052      * <p>
1053      * If negative values are supplied for {@code h} and
1054      * {@code v}, the size of the {@code Rectangle}
1055      * decreases accordingly.
1056      * The {@code grow} method will check for integer overflow
1057      * and underflow, but does not check whether the resulting
1058      * values of {@code width} and {@code height} grow
1059      * from negative to non-negative or shrink from non-negative
1060      * to negative.
1061      * @param h the horizontal expansion
1062      * @param v the vertical expansion
1063      */
1064     public void grow(int h, int v) {
1065         long x0 = this.x;
1066         long y0 = this.y;
1067         long x1 = this.width;
1068         long y1 = this.height;
1069         x1 += x0;
1070         y1 += y0;
1071 
1072         x0 -= h;
1073         y0 -= v;
1074         x1 += h;
1075         y1 += v;
1076 
1077         if (x1 < x0) {
1078             // Non-existent in X direction
1079             // Final width must remain negative so subtract x0 before
1080             // it is clipped so that we avoid the risk that the clipping
1081             // of x0 will reverse the ordering of x0 and x1.
1082             x1 -= x0;
1083             if (x1 < Integer.MIN_VALUE) x1 = Integer.MIN_VALUE;
1084             if (x0 < Integer.MIN_VALUE) x0 = Integer.MIN_VALUE;
1085             else if (x0 > Integer.MAX_VALUE) x0 = Integer.MAX_VALUE;
1086         } else { // (x1 >= x0)
1087             // Clip x0 before we subtract it from x1 in case the clipping
1088             // affects the representable area of the rectangle.
1089             if (x0 < Integer.MIN_VALUE) x0 = Integer.MIN_VALUE;
1090             else if (x0 > Integer.MAX_VALUE) x0 = Integer.MAX_VALUE;
1091             x1 -= x0;
1092             // The only way x1 can be negative now is if we clipped
1093             // x0 against MIN and x1 is less than MIN - in which case
1094             // we want to leave the width negative since the result
1095             // did not intersect the representable area.
1096             if (x1 < Integer.MIN_VALUE) x1 = Integer.MIN_VALUE;
1097             else if (x1 > Integer.MAX_VALUE) x1 = Integer.MAX_VALUE;
1098         }
1099 
1100         if (y1 < y0) {
1101             // Non-existent in Y direction
1102             y1 -= y0;
1103             if (y1 < Integer.MIN_VALUE) y1 = Integer.MIN_VALUE;
1104             if (y0 < Integer.MIN_VALUE) y0 = Integer.MIN_VALUE;
1105             else if (y0 > Integer.MAX_VALUE) y0 = Integer.MAX_VALUE;
1106         } else { // (y1 >= y0)
1107             if (y0 < Integer.MIN_VALUE) y0 = Integer.MIN_VALUE;
1108             else if (y0 > Integer.MAX_VALUE) y0 = Integer.MAX_VALUE;
1109             y1 -= y0;
1110             if (y1 < Integer.MIN_VALUE) y1 = Integer.MIN_VALUE;
1111             else if (y1 > Integer.MAX_VALUE) y1 = Integer.MAX_VALUE;
1112         }
1113 
1114         reshape((int) x0, (int) y0, (int) x1, (int) y1);
1115     }
1116 
1117     /**
1118      * {@inheritDoc}
1119      * @since 1.2
1120      */
1121     public boolean isEmpty() {
1122         return (width <= 0) || (height <= 0);
1123     }
1124 
1125     /**
1126      * {@inheritDoc}
1127      * @since 1.2
1128      */
1129     public int outcode(double x, double y) {
1130         /*
1131          * Note on casts to double below.  If the arithmetic of
1132          * x+w or y+h is done in int, then we may get integer
1133          * overflow. By converting to double before the addition
1134          * we force the addition to be carried out in double to
1135          * avoid overflow in the comparison.
1136          *
1137          * See bug 4320890 for problems that this can cause.
1138          */
1139         int out = 0;
1140         if (this.width <= 0) {
1141             out |= OUT_LEFT | OUT_RIGHT;
1142         } else if (x < this.x) {
1143             out |= OUT_LEFT;
1144         } else if (x > this.x + (double) this.width) {
1145             out |= OUT_RIGHT;
1146         }
1147         if (this.height <= 0) {
1148             out |= OUT_TOP | OUT_BOTTOM;
1149         } else if (y < this.y) {
1150             out |= OUT_TOP;
1151         } else if (y > this.y + (double) this.height) {
1152             out |= OUT_BOTTOM;
1153         }
1154         return out;
1155     }
1156 
1157     /**
1158      * {@inheritDoc}
1159      * @since 1.2
1160      */
1161     public Rectangle2D createIntersection(Rectangle2D r) {
1162         if (r instanceof Rectangle) {
1163             return intersection((Rectangle) r);
1164         }
1165         Rectangle2D dest = new Rectangle2D.Double();
1166         Rectangle2D.intersect(this, r, dest);
1167         return dest;
1168     }
1169 
1170     /**
1171      * {@inheritDoc}
1172      * @since 1.2
1173      */
1174     public Rectangle2D createUnion(Rectangle2D r) {
1175         if (r instanceof Rectangle) {
1176             return union((Rectangle) r);
1177         }
1178         Rectangle2D dest = new Rectangle2D.Double();
1179         Rectangle2D.union(this, r, dest);
1180         return dest;
1181     }
1182 
1183     /**
1184      * Checks whether two rectangles are equal.
1185      * <p>
1186      * The result is {@code true} if and only if the argument is not
1187      * {@code null} and is a {@code Rectangle} object that has the
1188      * same upper-left corner, width, and height as
1189      * this {@code Rectangle}.
1190      * @param obj the {@code Object} to compare with
1191      *                this {@code Rectangle}
1192      * @return    {@code true} if the objects are equal;
1193      *            {@code false} otherwise.
1194      */
1195     public boolean equals(Object obj) {
1196         if (obj instanceof Rectangle) {
1197             Rectangle r = (Rectangle)obj;
1198             return ((x == r.x) &&
1199                     (y == r.y) &&
1200                     (width == r.width) &&
1201                     (height == r.height));
1202         }
1203         return super.equals(obj);
1204     }
1205 
1206     /**
1207      * Returns a {@code String} representing this
1208      * {@code Rectangle} and its values.
1209      * @return a {@code String} representing this
1210      *               {@code Rectangle} object's coordinate and size values.
1211      */
1212     public String toString() {
1213         return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]";
1214     }
1215 }