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 import java.awt.Color; 25 import java.awt.Graphics2D; 26 import java.awt.RenderingHints; 27 import java.awt.geom.Path2D; 28 import java.awt.image.BufferedImage; 29 import java.io.File; 30 import java.io.IOException; 31 import static java.lang.Double.NaN; 32 import java.util.Locale; 33 import java.util.logging.Handler; 34 import java.util.logging.LogRecord; 35 import java.util.logging.Logger; 36 import javax.imageio.ImageIO; 37 38 /** 39 * @test 40 * @bug 8149338 41 * @summary Verifies that Marlin supports NaN coordinates and no JVM crash happens ! 42 * @run main CrashNaNTest 43 */ 44 public class CrashNaNTest { 45 46 static final boolean SAVE_IMAGE = false; 47 48 public static void main(String argv[]) { 49 Locale.setDefault(Locale.US); 50 51 // initialize j.u.l Looger: 52 final Logger log = Logger.getLogger("sun.java2d.marlin"); 53 log.addHandler(new Handler() { 54 @Override 55 public void publish(LogRecord record) { 56 Throwable th = record.getThrown(); 57 // detect any Throwable: 58 if (th != null) { 59 System.out.println("Test failed:\n" + record.getMessage()); 60 th.printStackTrace(System.out); 61 62 throw new RuntimeException("Test failed: ", th); 63 } 64 } 65 66 @Override 67 public void flush() { 68 } 69 70 @Override 71 public void close() throws SecurityException { 72 } 73 }); 74 75 // enable Marlin logging & internal checks: 76 System.setProperty("sun.java2d.renderer.log", "true"); 77 System.setProperty("sun.java2d.renderer.useLogger", "true"); 78 System.setProperty("sun.java2d.renderer.doChecks", "true"); 79 80 final int width = 400; 81 final int height = 400; 82 83 final BufferedImage image = new BufferedImage(width, height, 84 BufferedImage.TYPE_INT_ARGB); 85 86 final Graphics2D g2d = (Graphics2D) image.getGraphics(); 87 try { 88 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 89 RenderingHints.VALUE_ANTIALIAS_ON); 90 91 g2d.setBackground(Color.WHITE); 92 g2d.clearRect(0, 0, width, height); 93 94 final Path2D.Double path = new Path2D.Double(); 95 path.moveTo(30, 30); 96 path.lineTo(100, 100); 97 98 for (int i = 0; i < 20000; i++) { 99 path.lineTo(110 + 0.01 * i, 110); 100 path.lineTo(111 + 0.01 * i, 100); 101 } 102 103 path.lineTo(NaN, 200); 104 path.lineTo(200, 200); 105 path.lineTo(200, NaN); 106 path.lineTo(300, 300); 107 path.lineTo(NaN, NaN); 108 path.lineTo(100, 100); 109 path.closePath(); 110 111 final Path2D.Double path2 = new Path2D.Double(); 112 path2.moveTo(0,0); 113 path2.lineTo(width,height); 114 path2.lineTo(10, 10); 115 path2.closePath(); 116 117 for (int i = 0; i < 1; i++) { 118 final long start = System.nanoTime(); 119 g2d.setColor(Color.BLUE); 120 g2d.fill(path); 121 122 g2d.fill(path2); 123 124 final long time = System.nanoTime() - start; 125 System.out.println("paint: duration= " + (1e-6 * time) + " ms."); 126 } 127 128 if (SAVE_IMAGE) { 129 try { 130 final File file = new File("CrashNaNTest.png"); 131 System.out.println("Writing file: " 132 + file.getAbsolutePath()); 133 ImageIO.write(image, "PNG", file); 134 } catch (IOException ex) { 135 System.out.println("Writing file failure:"); 136 ex.printStackTrace(); 137 } 138 } 139 } finally { 140 g2d.dispose(); 141 } 142 } 143 } | 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 import java.awt.BasicStroke; 25 import java.awt.Color; 26 import java.awt.Graphics2D; 27 import java.awt.RenderingHints; 28 import java.awt.Shape; 29 import java.awt.Stroke; 30 import java.awt.geom.Path2D; 31 import java.awt.geom.PathIterator; 32 import java.awt.image.BufferedImage; 33 import java.awt.image.Raster; 34 import java.io.File; 35 import java.io.IOException; 36 import static java.lang.Double.NEGATIVE_INFINITY; 37 import static java.lang.Double.POSITIVE_INFINITY; 38 import static java.lang.Double.NaN; 39 import java.util.Arrays; 40 import java.util.Locale; 41 import java.util.logging.Handler; 42 import java.util.logging.LogRecord; 43 import java.util.logging.Logger; 44 import javax.imageio.ImageIO; 45 46 /** 47 * @test 48 * @bug 8149338 8144938 49 * @summary Verifies that Marlin supports NaN coordinates (no JVM crash) 50 * but also it skips properly point coordinates with NaN / Infinity values 51 * @run main CrashNaNTest 52 */ 53 public class CrashNaNTest { 54 55 static final boolean SAVE_IMAGE = false; 56 57 public static void main(String argv[]) { 58 Locale.setDefault(Locale.US); 59 60 // initialize j.u.l Looger: 61 final Logger log = Logger.getLogger("sun.java2d.marlin"); 62 log.addHandler(new Handler() { 63 @Override 64 public void publish(LogRecord record) { 65 Throwable th = record.getThrown(); 66 // detect any Throwable: 67 if (th != null) { 68 System.out.println("Test failed:\n" + record.getMessage()); 69 th.printStackTrace(System.out); 70 71 throw new RuntimeException("Test failed: ", th); 72 } 73 } 74 75 @Override 76 public void flush() { 77 } 78 79 @Override 80 public void close() throws SecurityException { 81 } 82 }); 83 84 // enable Marlin logging & internal checks: 85 System.setProperty("sun.java2d.renderer.log", "true"); 86 System.setProperty("sun.java2d.renderer.useLogger", "true"); 87 System.setProperty("sun.java2d.renderer.doChecks", "true"); 88 89 testFillDefaultAt(); 90 testDrawComplexAt(); 91 92 testPathClosed(); 93 94 testStrokedShapes(); 95 } 96 97 private static void testFillDefaultAt() { 98 final int width = 400; 99 final int height = 400; 100 101 final BufferedImage image = new BufferedImage(width, height, 102 BufferedImage.TYPE_INT_ARGB); 103 104 final Graphics2D g2d = (Graphics2D) image.getGraphics(); 105 try { 106 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 107 RenderingHints.VALUE_ANTIALIAS_ON); 108 109 g2d.setBackground(Color.WHITE); 110 g2d.clearRect(0, 0, width, height); 111 112 final Path2D.Double path = new Path2D.Double(); 113 path.moveTo(100, 100); 114 115 for (int i = 0; i < 20000; i++) { 116 path.lineTo(110 + 0.01 * i, 110); 117 path.lineTo(111 + 0.01 * i, 100); 118 } 119 120 path.lineTo(NaN, 200); 121 path.lineTo(200, 200); 122 path.lineTo(200, NaN); 123 path.lineTo(300, 300); 124 path.lineTo(NaN, NaN); 125 path.lineTo(100, 200); 126 path.closePath(); 127 128 final Path2D.Double path2 = new Path2D.Double(); 129 path2.moveTo(0, 0); 130 path2.lineTo(100, height); 131 path2.lineTo(0, 200); 132 path2.closePath(); 133 134 for (int i = 0; i < 1; i++) { 135 final long start = System.nanoTime(); 136 g2d.setColor(Color.BLUE); 137 g2d.fill(path); 138 g2d.setColor(Color.GREEN); 139 g2d.fill(path2); 140 141 g2d.setColor(Color.BLACK); 142 g2d.draw(path); 143 g2d.draw(path2); 144 145 final long time = System.nanoTime() - start; 146 System.out.println("paint: duration= " + (1e-6 * time) + " ms."); 147 } 148 149 if (SAVE_IMAGE) { 150 try { 151 final File file = new File("CrashNaNTest-fill.png"); 152 System.out.println("Writing file: " 153 + file.getAbsolutePath()); 154 ImageIO.write(image, "PNG", file); 155 } catch (IOException ex) { 156 System.out.println("Writing file failure:"); 157 ex.printStackTrace(); 158 } 159 } 160 161 // Check image on few pixels: 162 final Raster raster = image.getData(); 163 164 checkPixel(raster, 200, 195, Color.BLUE.getRGB()); 165 checkPixel(raster, 105, 195, Color.BLUE.getRGB()); 166 checkPixel(raster, 286, 290, Color.BLUE.getRGB()); 167 168 checkPixel(raster, 108, 105, Color.WHITE.getRGB()); 169 checkPixel(raster, 205, 200, Color.WHITE.getRGB()); 170 171 checkPixel(raster, 5, 200, Color.GREEN.getRGB()); 172 173 } finally { 174 g2d.dispose(); 175 } 176 } 177 178 private static void testDrawComplexAt() { 179 final int width = 400; 180 final int height = 400; 181 182 final BufferedImage image = new BufferedImage(width, height, 183 BufferedImage.TYPE_INT_ARGB); 184 185 final Graphics2D g2d = (Graphics2D) image.getGraphics(); 186 try { 187 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 188 RenderingHints.VALUE_ANTIALIAS_ON); 189 g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, 190 RenderingHints.VALUE_STROKE_PURE); 191 192 g2d.setBackground(Color.WHITE); 193 g2d.clearRect(0, 0, width, height); 194 195 final Path2D.Double path = new Path2D.Double(); 196 path.moveTo(100, 100); 197 198 for (int i = 0; i < 20000; i++) { 199 path.lineTo(110 + 0.01 * i, 110); 200 path.lineTo(111 + 0.01 * i, 100); 201 } 202 203 path.lineTo(NaN, 200); 204 path.lineTo(200, 200); 205 path.lineTo(200, NaN); 206 path.lineTo(300, 300); 207 path.lineTo(NaN, NaN); 208 path.lineTo(100, 200); 209 path.closePath(); 210 211 final Path2D.Double path2 = new Path2D.Double(); 212 path2.moveTo(0, 0); 213 path2.lineTo(100, height); 214 path2.lineTo(0, 200); 215 path2.closePath(); 216 217 // Define an non-uniform transform: 218 g2d.scale(0.5, 1.0); 219 g2d.rotate(Math.PI / 31); 220 221 for (int i = 0; i < 1; i++) { 222 final long start = System.nanoTime(); 223 224 g2d.setColor(Color.BLACK); 225 g2d.draw(path); 226 g2d.draw(path2); 227 228 final long time = System.nanoTime() - start; 229 System.out.println("paint: duration= " + (1e-6 * time) + " ms."); 230 } 231 232 if (SAVE_IMAGE) { 233 try { 234 final File file = new File("CrashNaNTest-draw.png"); 235 System.out.println("Writing file: " 236 + file.getAbsolutePath()); 237 ImageIO.write(image, "PNG", file); 238 } catch (IOException ex) { 239 System.out.println("Writing file failure:"); 240 ex.printStackTrace(); 241 } 242 } 243 244 // Check image on few pixels: 245 final Raster raster = image.getData(); 246 247 checkPixelNotWhite(raster, 40, 210); 248 checkPixelNotWhite(raster, 44, 110); 249 checkPixelNotWhite(raster, 60, 120); 250 checkPixelNotWhite(raster, 89, 219); 251 checkPixelNotWhite(raster, 28, 399); 252 checkPixelNotWhite(raster, 134, 329); 253 254 } finally { 255 g2d.dispose(); 256 } 257 } 258 private static void testPathClosed() { 259 final int width = 100; 260 final int height = 100; 261 262 final BufferedImage image = new BufferedImage(width, height, 263 BufferedImage.TYPE_INT_ARGB); 264 265 final Graphics2D g2d = (Graphics2D) image.getGraphics(); 266 try { 267 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 268 RenderingHints.VALUE_ANTIALIAS_ON); 269 270 g2d.setBackground(Color.WHITE); 271 g2d.clearRect(0, 0, width, height); 272 273 final Path2D.Double path = new Path2D.Double(); 274 path.moveTo(40, 40); 275 path.lineTo(0, 0); 276 path.lineTo(80, 0); 277 path.closePath(); 278 path.lineTo(80, 80); 279 path.lineTo(0, 80); 280 path.closePath(); 281 282 for (int i = 0; i < 1; i++) { 283 final long start = System.nanoTime(); 284 g2d.setColor(Color.BLUE); 285 g2d.fill(path); 286 287 g2d.setColor(Color.BLACK); 288 g2d.draw(path); 289 290 final long time = System.nanoTime() - start; 291 System.out.println("paint: duration= " + (1e-6 * time) + " ms."); 292 } 293 294 if (SAVE_IMAGE) { 295 try { 296 final File file = new File("CrashNaNTest-path-closed.png"); 297 System.out.println("Writing file: " 298 + file.getAbsolutePath()); 299 ImageIO.write(image, "PNG", file); 300 } catch (IOException ex) { 301 System.out.println("Writing file failure:"); 302 ex.printStackTrace(); 303 } 304 } 305 306 // Check image on few pixels: 307 final Raster raster = image.getData(); 308 309 checkPixel(raster, 10, 05, Color.BLUE.getRGB()); 310 checkPixel(raster, 70, 05, Color.BLUE.getRGB()); 311 checkPixel(raster, 40, 35, Color.BLUE.getRGB()); 312 313 checkPixel(raster, 10, 75, Color.BLUE.getRGB()); 314 checkPixel(raster, 70, 75, Color.BLUE.getRGB()); 315 checkPixel(raster, 40, 45, Color.BLUE.getRGB()); 316 317 } finally { 318 g2d.dispose(); 319 } 320 } 321 322 private static void testStrokedShapes() { 323 final Stroke stroke = new BasicStroke(); 324 325 final Path2D.Double path = new Path2D.Double(); 326 Shape s; 327 328 // Check filtering NaN values: 329 path.reset(); 330 path.moveTo(100, NaN); 331 path.lineTo(NaN, 100); 332 path.lineTo(NaN, NaN); 333 334 path.quadTo(NaN, 100, NaN, 100); 335 path.quadTo(100, NaN, 100, NaN); 336 path.quadTo(NaN, NaN, NaN, NaN); 337 338 path.curveTo(NaN, 100, NaN, 100, NaN, 100); 339 path.curveTo(100, NaN, 100, NaN, 100, NaN); 340 path.curveTo(NaN, NaN, NaN, NaN, NaN, NaN); 341 path.closePath(); 342 343 s = stroke.createStrokedShape(path); 344 checkEmptyPath(s); 345 346 // Check filtering +Infinity values: 347 path.reset(); 348 path.moveTo(100, POSITIVE_INFINITY); 349 path.lineTo(POSITIVE_INFINITY, 100); 350 path.lineTo(POSITIVE_INFINITY, POSITIVE_INFINITY); 351 352 path.quadTo(POSITIVE_INFINITY, 100, 353 POSITIVE_INFINITY, 100); 354 path.quadTo(100, POSITIVE_INFINITY, 355 100, POSITIVE_INFINITY); 356 path.quadTo(POSITIVE_INFINITY, POSITIVE_INFINITY, 357 POSITIVE_INFINITY, POSITIVE_INFINITY); 358 359 path.curveTo(POSITIVE_INFINITY, 100, 360 POSITIVE_INFINITY, 100, 361 POSITIVE_INFINITY, 100); 362 path.curveTo(100, POSITIVE_INFINITY, 363 100, POSITIVE_INFINITY, 364 100, POSITIVE_INFINITY); 365 path.curveTo(POSITIVE_INFINITY, POSITIVE_INFINITY, 366 POSITIVE_INFINITY, POSITIVE_INFINITY, 367 POSITIVE_INFINITY, POSITIVE_INFINITY); 368 path.closePath(); 369 370 s = stroke.createStrokedShape(path); 371 checkEmptyPath(s); 372 373 // Check filtering -Infinity values: 374 path.reset(); 375 path.moveTo(100, NEGATIVE_INFINITY); 376 path.lineTo(NEGATIVE_INFINITY, 100); 377 path.lineTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY); 378 379 path.quadTo(NEGATIVE_INFINITY, 100, 380 NEGATIVE_INFINITY, 100); 381 path.quadTo(100, NEGATIVE_INFINITY, 382 100, NEGATIVE_INFINITY); 383 path.quadTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY, 384 NEGATIVE_INFINITY, NEGATIVE_INFINITY); 385 386 path.curveTo(NEGATIVE_INFINITY, 100, 387 NEGATIVE_INFINITY, 100, 388 NEGATIVE_INFINITY, 100); 389 path.curveTo(100, NEGATIVE_INFINITY, 390 100, NEGATIVE_INFINITY, 391 100, NEGATIVE_INFINITY); 392 path.curveTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY, 393 NEGATIVE_INFINITY, NEGATIVE_INFINITY, 394 NEGATIVE_INFINITY, NEGATIVE_INFINITY); 395 path.closePath(); 396 397 s = stroke.createStrokedShape(path); 398 checkEmptyPath(s); 399 } 400 401 private static void checkEmptyPath(final Shape s) { 402 final float[] coords = new float[6]; 403 final PathIterator it = s.getPathIterator(null); 404 405 int n = 0; 406 for (; !it.isDone(); it.next()) { 407 int type = it.currentSegment(coords); 408 System.out.println("unexpected segment type= " + type 409 + " with coords: " + Arrays.toString(coords)); 410 n++; 411 } 412 if (n != 0) { 413 System.out.println("path elements = " + n); 414 throw new IllegalStateException("Not empty path: " 415 + n + " path elements !"); 416 } 417 } 418 419 private static void checkPixel(final Raster raster, 420 final int x, final int y, 421 final int expected) { 422 423 final int[] rgb = (int[]) raster.getDataElements(x, y, null); 424 425 if (rgb[0] != expected) { 426 throw new IllegalStateException("bad pixel at (" + x + ", " + y 427 + ") = " + rgb[0] + " expected: " + expected); 428 } 429 } 430 431 private static void checkPixelNotWhite(final Raster raster, 432 final int x, final int y) { 433 434 final int[] rgb = (int[]) raster.getDataElements(x, y, null); 435 436 if (rgb[0] == Color.WHITE.getRGB()) { 437 throw new IllegalStateException("bad pixel at (" + x + ", " + y 438 + ") is white (empty)"); 439 } 440 } 441 } |