Path: blob/master/test/jdk/sun/java2d/marlin/CrashNaNTest.java
41149 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.awt.BasicStroke;24import java.awt.Color;25import java.awt.Graphics2D;26import java.awt.RenderingHints;27import java.awt.Shape;28import java.awt.Stroke;29import java.awt.geom.Path2D;30import java.awt.geom.PathIterator;31import java.awt.image.BufferedImage;32import java.awt.image.Raster;33import java.io.File;34import java.io.IOException;35import static java.lang.Double.NEGATIVE_INFINITY;36import static java.lang.Double.POSITIVE_INFINITY;37import static java.lang.Double.NaN;38import java.util.Arrays;39import java.util.Locale;40import java.util.logging.Handler;41import java.util.logging.LogRecord;42import java.util.logging.Logger;43import javax.imageio.ImageIO;4445/**46* @test47* @bug 8149338 814493848* @summary Verifies that Marlin supports NaN coordinates (no JVM crash)49* but also it skips properly point coordinates with NaN / Infinity values50* @run main CrashNaNTest51*/52public class CrashNaNTest {5354static final boolean SAVE_IMAGE = false;5556public static void main(String argv[]) {57Locale.setDefault(Locale.US);5859// initialize j.u.l Looger:60final Logger log = Logger.getLogger("sun.java2d.marlin");61log.addHandler(new Handler() {62@Override63public void publish(LogRecord record) {64Throwable th = record.getThrown();65// detect any Throwable:66if (th != null) {67System.out.println("Test failed:\n" + record.getMessage());68th.printStackTrace(System.out);6970throw new RuntimeException("Test failed: ", th);71}72}7374@Override75public void flush() {76}7778@Override79public void close() throws SecurityException {80}81});8283// enable Marlin logging & internal checks:84System.setProperty("sun.java2d.renderer.log", "true");85System.setProperty("sun.java2d.renderer.useLogger", "true");86System.setProperty("sun.java2d.renderer.doChecks", "true");8788testFillDefaultAt();89testDrawComplexAt();9091testPathClosed();9293testStrokedShapes();94}9596private static void testFillDefaultAt() {97final int width = 400;98final int height = 400;99100final BufferedImage image = new BufferedImage(width, height,101BufferedImage.TYPE_INT_ARGB);102103final Graphics2D g2d = (Graphics2D) image.getGraphics();104try {105g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,106RenderingHints.VALUE_ANTIALIAS_ON);107108g2d.setBackground(Color.WHITE);109g2d.clearRect(0, 0, width, height);110111final Path2D.Double path = new Path2D.Double();112path.moveTo(100, 100);113114for (int i = 0; i < 20000; i++) {115path.lineTo(110 + 0.01 * i, 110);116path.lineTo(111 + 0.01 * i, 100);117}118119path.lineTo(NaN, 200);120path.lineTo(200, 200);121path.lineTo(200, NaN);122path.lineTo(300, 300);123path.lineTo(NaN, NaN);124path.lineTo(100, 200);125path.closePath();126127final Path2D.Double path2 = new Path2D.Double();128path2.moveTo(0, 0);129path2.lineTo(100, height);130path2.lineTo(0, 200);131path2.closePath();132133g2d.setColor(Color.BLUE);134g2d.fill(path);135g2d.setColor(Color.GREEN);136g2d.fill(path2);137138g2d.setColor(Color.BLACK);139g2d.draw(path);140g2d.draw(path2);141142if (SAVE_IMAGE) {143try {144final File file = new File("CrashNaNTest-fill.png");145System.out.println("Writing file: "146+ file.getAbsolutePath());147ImageIO.write(image, "PNG", file);148} catch (IOException ex) {149System.out.println("Writing file failure:");150ex.printStackTrace();151}152}153154// Check image on few pixels:155final Raster raster = image.getData();156157checkPixel(raster, 200, 195, Color.BLUE.getRGB());158checkPixel(raster, 105, 195, Color.BLUE.getRGB());159checkPixel(raster, 286, 290, Color.BLUE.getRGB());160161checkPixel(raster, 108, 105, Color.WHITE.getRGB());162checkPixel(raster, 205, 200, Color.WHITE.getRGB());163164checkPixel(raster, 5, 200, Color.GREEN.getRGB());165166} finally {167g2d.dispose();168}169}170171private static void testDrawComplexAt() {172final int width = 400;173final int height = 400;174175final BufferedImage image = new BufferedImage(width, height,176BufferedImage.TYPE_INT_ARGB);177178final Graphics2D g2d = (Graphics2D) image.getGraphics();179try {180g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,181RenderingHints.VALUE_ANTIALIAS_ON);182g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,183RenderingHints.VALUE_STROKE_PURE);184185g2d.setBackground(Color.WHITE);186g2d.clearRect(0, 0, width, height);187188final Path2D.Double path = new Path2D.Double();189path.moveTo(100, 100);190191for (int i = 0; i < 20000; i++) {192path.lineTo(110 + 0.01 * i, 110);193path.lineTo(111 + 0.01 * i, 100);194}195196path.lineTo(NaN, 200);197path.lineTo(200, 200);198path.lineTo(200, NaN);199path.lineTo(300, 300);200path.lineTo(NaN, NaN);201path.lineTo(100, 200);202path.closePath();203204final Path2D.Double path2 = new Path2D.Double();205path2.moveTo(0, 0);206path2.lineTo(100, height);207path2.lineTo(0, 200);208path2.closePath();209210// Define an non-uniform transform:211g2d.scale(0.5, 1.0);212g2d.rotate(Math.PI / 31);213214g2d.setColor(Color.BLACK);215g2d.draw(path);216g2d.draw(path2);217218if (SAVE_IMAGE) {219try {220final File file = new File("CrashNaNTest-draw.png");221System.out.println("Writing file: "222+ file.getAbsolutePath());223ImageIO.write(image, "PNG", file);224} catch (IOException ex) {225System.out.println("Writing file failure:");226ex.printStackTrace();227}228}229230// Check image on few pixels:231final Raster raster = image.getData();232233checkPixelNotWhite(raster, 40, 210);234checkPixelNotWhite(raster, 44, 110);235checkPixelNotWhite(raster, 60, 120);236checkPixelNotWhite(raster, 89, 219);237checkPixelNotWhite(raster, 28, 399);238checkPixelNotWhite(raster, 134, 329);239240} finally {241g2d.dispose();242}243}244private static void testPathClosed() {245final int width = 100;246final int height = 100;247248final BufferedImage image = new BufferedImage(width, height,249BufferedImage.TYPE_INT_ARGB);250251final Graphics2D g2d = (Graphics2D) image.getGraphics();252try {253g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,254RenderingHints.VALUE_ANTIALIAS_ON);255256g2d.setBackground(Color.WHITE);257g2d.clearRect(0, 0, width, height);258259final Path2D.Double path = new Path2D.Double();260path.moveTo(40, 40);261path.lineTo(0, 0);262path.lineTo(80, 0);263path.closePath();264path.lineTo(80, 80);265path.lineTo(0, 80);266path.closePath();267268g2d.setColor(Color.BLUE);269g2d.fill(path);270271g2d.setColor(Color.BLACK);272g2d.draw(path);273274if (SAVE_IMAGE) {275try {276final File file = new File("CrashNaNTest-path-closed.png");277System.out.println("Writing file: "278+ file.getAbsolutePath());279ImageIO.write(image, "PNG", file);280} catch (IOException ex) {281System.out.println("Writing file failure:");282ex.printStackTrace();283}284}285286// Check image on few pixels:287final Raster raster = image.getData();288289checkPixel(raster, 10, 05, Color.BLUE.getRGB());290checkPixel(raster, 70, 05, Color.BLUE.getRGB());291checkPixel(raster, 40, 35, Color.BLUE.getRGB());292293checkPixel(raster, 10, 75, Color.BLUE.getRGB());294checkPixel(raster, 70, 75, Color.BLUE.getRGB());295checkPixel(raster, 40, 45, Color.BLUE.getRGB());296297} finally {298g2d.dispose();299}300}301302private static void testStrokedShapes() {303final Stroke stroke = new BasicStroke();304305final Path2D.Double path = new Path2D.Double();306Shape s;307308// Check filtering NaN values:309path.reset();310path.moveTo(100, NaN);311path.lineTo(NaN, 100);312path.lineTo(NaN, NaN);313314path.quadTo(NaN, 100, NaN, 100);315path.quadTo(100, NaN, 100, NaN);316path.quadTo(NaN, NaN, NaN, NaN);317318path.curveTo(NaN, 100, NaN, 100, NaN, 100);319path.curveTo(100, NaN, 100, NaN, 100, NaN);320path.curveTo(NaN, NaN, NaN, NaN, NaN, NaN);321path.closePath();322323s = stroke.createStrokedShape(path);324checkEmptyPath(s);325326// Check filtering +Infinity values:327path.reset();328path.moveTo(100, POSITIVE_INFINITY);329path.lineTo(POSITIVE_INFINITY, 100);330path.lineTo(POSITIVE_INFINITY, POSITIVE_INFINITY);331332path.quadTo(POSITIVE_INFINITY, 100,333POSITIVE_INFINITY, 100);334path.quadTo(100, POSITIVE_INFINITY,335100, POSITIVE_INFINITY);336path.quadTo(POSITIVE_INFINITY, POSITIVE_INFINITY,337POSITIVE_INFINITY, POSITIVE_INFINITY);338339path.curveTo(POSITIVE_INFINITY, 100,340POSITIVE_INFINITY, 100,341POSITIVE_INFINITY, 100);342path.curveTo(100, POSITIVE_INFINITY,343100, POSITIVE_INFINITY,344100, POSITIVE_INFINITY);345path.curveTo(POSITIVE_INFINITY, POSITIVE_INFINITY,346POSITIVE_INFINITY, POSITIVE_INFINITY,347POSITIVE_INFINITY, POSITIVE_INFINITY);348path.closePath();349350s = stroke.createStrokedShape(path);351checkEmptyPath(s);352353// Check filtering -Infinity values:354path.reset();355path.moveTo(100, NEGATIVE_INFINITY);356path.lineTo(NEGATIVE_INFINITY, 100);357path.lineTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY);358359path.quadTo(NEGATIVE_INFINITY, 100,360NEGATIVE_INFINITY, 100);361path.quadTo(100, NEGATIVE_INFINITY,362100, NEGATIVE_INFINITY);363path.quadTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY,364NEGATIVE_INFINITY, NEGATIVE_INFINITY);365366path.curveTo(NEGATIVE_INFINITY, 100,367NEGATIVE_INFINITY, 100,368NEGATIVE_INFINITY, 100);369path.curveTo(100, NEGATIVE_INFINITY,370100, NEGATIVE_INFINITY,371100, NEGATIVE_INFINITY);372path.curveTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY,373NEGATIVE_INFINITY, NEGATIVE_INFINITY,374NEGATIVE_INFINITY, NEGATIVE_INFINITY);375path.closePath();376377s = stroke.createStrokedShape(path);378checkEmptyPath(s);379}380381private static void checkEmptyPath(final Shape s) {382final float[] coords = new float[6];383final PathIterator it = s.getPathIterator(null);384385int n = 0;386for (; !it.isDone(); it.next()) {387int type = it.currentSegment(coords);388System.out.println("unexpected segment type= " + type389+ " with coords: " + Arrays.toString(coords));390n++;391}392if (n != 0) {393System.out.println("path elements = " + n);394throw new IllegalStateException("Not empty path: "395+ n + " path elements !");396}397}398399private static void checkPixel(final Raster raster,400final int x, final int y,401final int expected) {402403final int[] rgb = (int[]) raster.getDataElements(x, y, null);404405if (rgb[0] != expected) {406throw new IllegalStateException("bad pixel at (" + x + ", " + y407+ ") = " + rgb[0] + " expected: " + expected);408}409}410411private static void checkPixelNotWhite(final Raster raster,412final int x, final int y) {413414final int[] rgb = (int[]) raster.getDataElements(x, y, null);415416if (rgb[0] == Color.WHITE.getRGB()) {417throw new IllegalStateException("bad pixel at (" + x + ", " + y418+ ") is white (empty)");419}420}421}422423424