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.</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 name="NonExistant">
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-existant 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
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-existant 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</code>.
124 *
125 * @serial
126 * @see #setLocation(int, int)
127 * @see #getLocation()
128 * @since 1.0
129 */
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-existant 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
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</code> with the
843 * specified <code>Rectangle</code>. Returns a new
844 * <code>Rectangle</code> 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=#NonExistant>non-existant</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</code>
860 * @return the smallest <code>Rectangle</code> containing both
861 * the specified <code>Rectangle</code> and this
862 * <code>Rectangle</code>.
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-existant (has a negative dimension), then both
871 // are non-existant and we can return any non-existant 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=#NonExistant>non-existant</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</code> with the
915 * added point as an argument does not necessarily return
916 * <code>true</code>. The <code>contains</code> method does not
917 * return <code>true</code> for points on the right or bottom
918 * edges of a <code>Rectangle</code>. Therefore, if the added point
919 * falls on the right or bottom edge of the enlarged
920 * <code>Rectangle</code>, <code>contains</code> returns
921 * <code>false</code> for that point.
922 * If the specified point must be contained within the new
923 * {@code Rectangle}, a 1x1 rectangle should be added instead:
924 * <pre>
925 * r.add(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
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=#NonExistant>non-existant</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</code>, a call to <code>contains</code>
966 * with the added <code>Point</code> as an argument does not
967 * necessarily return <code>true</code>. The <code>contains</code>
968 * method does not return <code>true</code> for points on the right
969 * or bottom edges of a <code>Rectangle</code>. Therefore if the added
970 * <code>Point</code> falls on the right or bottom edge of the
971 * enlarged <code>Rectangle</code>, <code>contains</code> returns
972 * <code>false</code> for that <code>Point</code>.
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</code> to add to this
979 * <code>Rectangle</code>
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-existant 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-existant 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() {
|
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.</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 name="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
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</code>.
124 *
125 * @serial
126 * @see #setLocation(int, int)
127 * @see #getLocation()
128 * @since 1.0
129 */
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
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</code> with the
843 * specified <code>Rectangle</code>. Returns a new
844 * <code>Rectangle</code> 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</code>
860 * @return the smallest <code>Rectangle</code> containing both
861 * the specified <code>Rectangle</code> and this
862 * <code>Rectangle</code>.
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</code> with the
915 * added point as an argument does not necessarily return
916 * <code>true</code>. The <code>contains</code> method does not
917 * return <code>true</code> for points on the right or bottom
918 * edges of a <code>Rectangle</code>. Therefore, if the added point
919 * falls on the right or bottom edge of the enlarged
920 * <code>Rectangle</code>, <code>contains</code> returns
921 * <code>false</code> for that point.
922 * If the specified point must be contained within the new
923 * {@code Rectangle}, a 1x1 rectangle should be added instead:
924 * <pre>
925 * r.add(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
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</code>, a call to <code>contains</code>
966 * with the added <code>Point</code> as an argument does not
967 * necessarily return <code>true</code>. The <code>contains</code>
968 * method does not return <code>true</code> for points on the right
969 * or bottom edges of a <code>Rectangle</code>. Therefore if the added
970 * <code>Point</code> falls on the right or bottom edge of the
971 * enlarged <code>Rectangle</code>, <code>contains</code> returns
972 * <code>false</code> for that <code>Point</code>.
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</code> to add to this
979 * <code>Rectangle</code>
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() {
|