1 /*
2  * Copyright (c) 2006, 2018, 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.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 6409478
27  * @summary Tests all hit testing methods of GeneralPath and Path2D
28  *          for graceful (i.e. non-infinite-loop) returns when any
29  *          of the path coordinates or test coordinates are
30  *          NaN or Infinite or even very large numbers.
31  * @run main/timeout=15 NonFiniteTests
32  */
33 
34 import java.awt.geom.GeneralPath;
35 import java.awt.geom.Path2D;
36 import java.awt.geom.PathIterator;
37 
38 public class NonFiniteTests {
39     public static final double DBL_NaN = Double.NaN;
40     public static final double DBL_POS_INF = Double.POSITIVE_INFINITY;
41     public static final double DBL_NEG_INF = Double.NEGATIVE_INFINITY;
42     public static final double DBL_MAX = Double.MAX_VALUE;
43     public static final double DBL_MIN = -Double.MAX_VALUE;
44     public static final double FLT_MAX = Float.MAX_VALUE;
45     public static final double FLT_MIN = -Float.MAX_VALUE;
46 
47     public static final int SEG_MOVETO = PathIterator.SEG_MOVETO;
48     public static final int SEG_LINETO = PathIterator.SEG_LINETO;
49     public static final int SEG_QUADTO = PathIterator.SEG_QUADTO;
50     public static final int SEG_CUBICTO = PathIterator.SEG_CUBICTO;
51     public static final int SEG_CLOSE = PathIterator.SEG_CLOSE;
52 
53     public static int types[] = {
54         SEG_MOVETO,
55         SEG_LINETO,
56         SEG_QUADTO,
57         SEG_CUBICTO,
58         SEG_CLOSE,
59     };
60 
61     public static double coords[] = {
62         // SEG_MOVETO coords
63           0.0,    0.0,
64 
65         // SEG_LINETO coords
66          50.0,   10.0,
67 
68         // SEG_QUADTO coords
69         100.0,   20.0,
70         100.0,  100.0,
71 
72         // SEG_CUBICTO coords
73          50.0,  150.0,
74           0.0,  100.0,
75         -50.0,   50.0,
76 
77         // SEG_CLOSE coords
78     };
79 
80     public static double testpoints[] = {
81                -100,        -100,
82                   0,           0,
83                  50,          50,
84             DBL_NaN,     DBL_NaN,
85         DBL_POS_INF, DBL_POS_INF,
86         DBL_NEG_INF, DBL_NEG_INF,
87         DBL_POS_INF, DBL_NEG_INF,
88         DBL_NEG_INF, DBL_POS_INF,
89     };
90 
91     public static double testrects[] = {
92                -100,        -100,          10,          10,
93                   0,           0,          10,          10,
94                  50,          50,          10,          10,
95             DBL_NaN,     DBL_NaN,          10,          10,
96                  10,          10,     DBL_NaN,     DBL_NaN,
97             DBL_NaN,     DBL_NaN,     DBL_NaN,     DBL_NaN,
98                  10,          10, DBL_POS_INF, DBL_POS_INF,
99                  10,          10, DBL_NEG_INF, DBL_NEG_INF,
100                  10,          10, DBL_POS_INF, DBL_NEG_INF,
101                  10,          10, DBL_NEG_INF, DBL_POS_INF,
102         DBL_NEG_INF, DBL_NEG_INF, DBL_POS_INF, DBL_POS_INF,
103         DBL_POS_INF, DBL_POS_INF,          10,          10,
104         DBL_NEG_INF, DBL_NEG_INF,          10,          10,
105         DBL_POS_INF, DBL_NEG_INF,          10,          10,
106         DBL_NEG_INF, DBL_POS_INF,          10,          10,
107     };
108 
109     public static double replacecoords[] = {
110         DBL_NEG_INF,
111         DBL_MIN,
112         FLT_MIN,
113         DBL_NaN,
114         FLT_MAX,
115         DBL_MAX,
116         DBL_POS_INF,
117     };
118 
main(String argv[])119     public static void main(String argv[]) {
120         test(types, coords);
121         testNonFinites(types, coords, 2);
122     }
123 
testNonFinites(int types[], double coords[], int numvalues)124     public static void testNonFinites(int types[], double coords[],
125                                       int numvalues)
126     {
127         if (numvalues == 0) {
128             test(types, coords);
129             return;
130         }
131         numvalues--;
132         for (int i = 0; i < coords.length; i++) {
133             double savedval = coords[i];
134 
135             //System.out.println("replacing coord #"+i);
136             for (int j = 0; j < replacecoords.length; j++) {
137                 coords[i] = replacecoords[j];
138                 testNonFinites(types, coords, numvalues);
139             }
140 
141             coords[i] = savedval;
142         }
143     }
144 
test(int types[], double coords[])145     public static void test(int types[], double coords[]) {
146         testGP(new GeneralPath(), types, coords);
147         try {
148             P2DTest.test(types, coords);
149         } catch (NoClassDefFoundError e) {
150             // Skip Path2D tests on older runtimes...
151         }
152     }
153 
testGP(GeneralPath gp, int types[], double coords[])154     public static void testGP(GeneralPath gp, int types[], double coords[]) {
155         int ci = 0;
156         for (int i = 0; i < types.length; i++) {
157             switch (types[i]) {
158             case SEG_MOVETO:
159                 gp.moveTo((float) coords[ci++], (float) coords[ci++]);
160                 break;
161             case SEG_LINETO:
162                 gp.lineTo((float) coords[ci++], (float) coords[ci++]);
163                 break;
164             case SEG_QUADTO:
165                 gp.quadTo((float) coords[ci++], (float) coords[ci++],
166                           (float) coords[ci++], (float) coords[ci++]);
167                 break;
168             case SEG_CUBICTO:
169                 gp.curveTo((float) coords[ci++], (float) coords[ci++],
170                            (float) coords[ci++], (float) coords[ci++],
171                            (float) coords[ci++], (float) coords[ci++]);
172                 break;
173             case SEG_CLOSE:
174                 gp.closePath();
175                 break;
176             }
177         }
178         testGP(gp);
179     }
180 
testGP(GeneralPath gp)181     public static void testGP(GeneralPath gp) {
182         for (int i = 0; i < testpoints.length; i += 2) {
183             gp.contains(testpoints[i+0], testpoints[i+1]);
184         }
185 
186         for (int i = 0; i < testrects.length; i += 4) {
187             gp.contains(testrects[i+0], testrects[i+1],
188                         testrects[i+2], testrects[i+3]);
189             gp.intersects(testrects[i+0], testrects[i+1],
190                           testrects[i+2], testrects[i+3]);
191         }
192     }
193 
194     public static class P2DTest {
test(int types[], double coords[])195         public static void test(int types[], double coords[]) {
196             testPath(new Path2D.Float(), types, coords);
197             testPath(new Path2D.Double(), types, coords);
198         }
199 
testPath(Path2D p2d, int types[], double coords[])200         public static void testPath(Path2D p2d, int types[], double coords[]) {
201             int ci = 0;
202             for (int i = 0; i < types.length; i++) {
203                 switch (types[i]) {
204                 case SEG_MOVETO:
205                     p2d.moveTo(coords[ci++], coords[ci++]);
206                     break;
207                 case SEG_LINETO:
208                     p2d.lineTo(coords[ci++], coords[ci++]);
209                     break;
210                 case SEG_QUADTO:
211                     p2d.quadTo(coords[ci++], coords[ci++],
212                                coords[ci++], coords[ci++]);
213                     break;
214                 case SEG_CUBICTO:
215                     p2d.curveTo(coords[ci++], coords[ci++],
216                                 coords[ci++], coords[ci++],
217                                 coords[ci++], coords[ci++]);
218                     break;
219                 case SEG_CLOSE:
220                     p2d.closePath();
221                     break;
222                 }
223             }
224             testPath(p2d);
225         }
226 
testPath(Path2D p2d)227         public static void testPath(Path2D p2d) {
228             // contains point
229             for (int i = 0; i < testpoints.length; i += 2) {
230                 p2d.contains(testpoints[i+0], testpoints[i+1]);
231                 contains(p2d, testpoints[i+0], testpoints[i+1]);
232             }
233 
234             for (int i = 0; i < testrects.length; i += 4) {
235                 p2d.contains(testrects[i+0], testrects[i+1],
236                              testrects[i+2], testrects[i+3]);
237                 contains(p2d,
238                          testrects[i+0], testrects[i+1],
239                          testrects[i+2], testrects[i+3]);
240                 p2d.intersects(testrects[i+0], testrects[i+1],
241                                testrects[i+2], testrects[i+3]);
242                 intersects(p2d,
243                            testrects[i+0], testrects[i+1],
244                            testrects[i+2], testrects[i+3]);
245             }
246         }
247 
contains(Path2D p2d, double x, double y)248         public static boolean contains(Path2D p2d, double x, double y) {
249             return Path2D.contains(p2d.getPathIterator(null), x, y);
250         }
251 
contains(Path2D p2d, double x, double y, double w, double h)252         public static boolean contains(Path2D p2d,
253                                        double x, double y, double w, double h)
254         {
255             return Path2D.contains(p2d.getPathIterator(null), x, y, w, h);
256         }
257 
intersects(Path2D p2d, double x, double y, double w, double h)258         public static boolean intersects(Path2D p2d,
259                                          double x, double y, double w, double h)
260         {
261             return Path2D.intersects(p2d.getPathIterator(null), x, y, w, h);
262         }
263     }
264 }
265