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