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(intint)
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(intint)
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(intint)
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(intint)
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(intintintint)
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(intintintint)
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(intintintint)}.
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(intint)
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(intint)
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(intint)}.
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(intint)
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(intint)
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(intint)
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(intint)}.
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 trueif 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 trueif 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 trueif 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 trueif 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 trueif 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(intint)}.
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 trueif 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 truefor 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 falsefor 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(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 truefor 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 falsefor 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(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 + (doublethis.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 + (doublethis.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 trueif 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 trueif 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 }
1216