< prev index next >
test/sun/java2d/marlin/CrashNaNTest.java
Print this page
*** 19,46 ****
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import static java.lang.Double.NaN;
import java.util.Locale;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
/**
* @test
! * @bug 8149338
! * @summary Verifies that Marlin supports NaN coordinates and no JVM crash happens !
* @run main CrashNaNTest
*/
public class CrashNaNTest {
static final boolean SAVE_IMAGE = false;
--- 19,55 ----
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+ import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
+ import java.awt.Shape;
+ import java.awt.Stroke;
import java.awt.geom.Path2D;
+ import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
+ import java.awt.image.Raster;
import java.io.File;
import java.io.IOException;
+ import static java.lang.Double.NEGATIVE_INFINITY;
+ import static java.lang.Double.POSITIVE_INFINITY;
import static java.lang.Double.NaN;
+ import java.util.Arrays;
import java.util.Locale;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
/**
* @test
! * @bug 8149338 8144938
! * @summary Verifies that Marlin supports NaN coordinates (no JVM crash)
! * but also it skips properly point coordinates with NaN / Infinity values
* @run main CrashNaNTest
*/
public class CrashNaNTest {
static final boolean SAVE_IMAGE = false;
*** 75,101 ****
// enable Marlin logging & internal checks:
System.setProperty("sun.java2d.renderer.log", "true");
System.setProperty("sun.java2d.renderer.useLogger", "true");
System.setProperty("sun.java2d.renderer.doChecks", "true");
final int width = 400;
final int height = 400;
final BufferedImage image = new BufferedImage(width, height,
! BufferedImage.TYPE_INT_ARGB);
final Graphics2D g2d = (Graphics2D) image.getGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
! RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, width, height);
final Path2D.Double path = new Path2D.Double();
! path.moveTo(30, 30);
! path.lineTo(100, 100);
for (int i = 0; i < 20000; i++) {
path.lineTo(110 + 0.01 * i, 110);
path.lineTo(111 + 0.01 * i, 100);
}
--- 84,118 ----
// enable Marlin logging & internal checks:
System.setProperty("sun.java2d.renderer.log", "true");
System.setProperty("sun.java2d.renderer.useLogger", "true");
System.setProperty("sun.java2d.renderer.doChecks", "true");
+ testFillDefaultAt();
+ testDrawComplexAt();
+
+ testPathClosed();
+
+ testStrokedShapes();
+ }
+
+ private static void testFillDefaultAt() {
final int width = 400;
final int height = 400;
final BufferedImage image = new BufferedImage(width, height,
! BufferedImage.TYPE_INT_ARGB);
final Graphics2D g2d = (Graphics2D) image.getGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
! RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, width, height);
final Path2D.Double path = new Path2D.Double();
! path.moveTo(100, 100);
for (int i = 0; i < 20000; i++) {
path.lineTo(110 + 0.01 * i, 110);
path.lineTo(111 + 0.01 * i, 100);
}
*** 103,143 ****
path.lineTo(NaN, 200);
path.lineTo(200, 200);
path.lineTo(200, NaN);
path.lineTo(300, 300);
path.lineTo(NaN, NaN);
! path.lineTo(100, 100);
path.closePath();
final Path2D.Double path2 = new Path2D.Double();
! path2.moveTo(0,0);
! path2.lineTo(width,height);
! path2.lineTo(10, 10);
path2.closePath();
for (int i = 0; i < 1; i++) {
final long start = System.nanoTime();
g2d.setColor(Color.BLUE);
g2d.fill(path);
!
g2d.fill(path2);
final long time = System.nanoTime() - start;
System.out.println("paint: duration= " + (1e-6 * time) + " ms.");
}
if (SAVE_IMAGE) {
try {
! final File file = new File("CrashNaNTest.png");
System.out.println("Writing file: "
! + file.getAbsolutePath());
ImageIO.write(image, "PNG", file);
} catch (IOException ex) {
System.out.println("Writing file failure:");
ex.printStackTrace();
}
}
} finally {
g2d.dispose();
}
}
}
--- 120,441 ----
path.lineTo(NaN, 200);
path.lineTo(200, 200);
path.lineTo(200, NaN);
path.lineTo(300, 300);
path.lineTo(NaN, NaN);
! path.lineTo(100, 200);
path.closePath();
final Path2D.Double path2 = new Path2D.Double();
! path2.moveTo(0, 0);
! path2.lineTo(100, height);
! path2.lineTo(0, 200);
path2.closePath();
for (int i = 0; i < 1; i++) {
final long start = System.nanoTime();
g2d.setColor(Color.BLUE);
g2d.fill(path);
! g2d.setColor(Color.GREEN);
g2d.fill(path2);
+ g2d.setColor(Color.BLACK);
+ g2d.draw(path);
+ g2d.draw(path2);
+
final long time = System.nanoTime() - start;
System.out.println("paint: duration= " + (1e-6 * time) + " ms.");
}
if (SAVE_IMAGE) {
try {
! final File file = new File("CrashNaNTest-fill.png");
System.out.println("Writing file: "
! + file.getAbsolutePath());
ImageIO.write(image, "PNG", file);
} catch (IOException ex) {
System.out.println("Writing file failure:");
ex.printStackTrace();
}
}
+
+ // Check image on few pixels:
+ final Raster raster = image.getData();
+
+ checkPixel(raster, 200, 195, Color.BLUE.getRGB());
+ checkPixel(raster, 105, 195, Color.BLUE.getRGB());
+ checkPixel(raster, 286, 290, Color.BLUE.getRGB());
+
+ checkPixel(raster, 108, 105, Color.WHITE.getRGB());
+ checkPixel(raster, 205, 200, Color.WHITE.getRGB());
+
+ checkPixel(raster, 5, 200, Color.GREEN.getRGB());
+
} finally {
g2d.dispose();
}
}
+
+ private static void testDrawComplexAt() {
+ final int width = 400;
+ final int height = 400;
+
+ final BufferedImage image = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ final Graphics2D g2d = (Graphics2D) image.getGraphics();
+ try {
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
+ RenderingHints.VALUE_STROKE_PURE);
+
+ g2d.setBackground(Color.WHITE);
+ g2d.clearRect(0, 0, width, height);
+
+ final Path2D.Double path = new Path2D.Double();
+ path.moveTo(100, 100);
+
+ for (int i = 0; i < 20000; i++) {
+ path.lineTo(110 + 0.01 * i, 110);
+ path.lineTo(111 + 0.01 * i, 100);
+ }
+
+ path.lineTo(NaN, 200);
+ path.lineTo(200, 200);
+ path.lineTo(200, NaN);
+ path.lineTo(300, 300);
+ path.lineTo(NaN, NaN);
+ path.lineTo(100, 200);
+ path.closePath();
+
+ final Path2D.Double path2 = new Path2D.Double();
+ path2.moveTo(0, 0);
+ path2.lineTo(100, height);
+ path2.lineTo(0, 200);
+ path2.closePath();
+
+ // Define an non-uniform transform:
+ g2d.scale(0.5, 1.0);
+ g2d.rotate(Math.PI / 31);
+
+ for (int i = 0; i < 1; i++) {
+ final long start = System.nanoTime();
+
+ g2d.setColor(Color.BLACK);
+ g2d.draw(path);
+ g2d.draw(path2);
+
+ final long time = System.nanoTime() - start;
+ System.out.println("paint: duration= " + (1e-6 * time) + " ms.");
+ }
+
+ if (SAVE_IMAGE) {
+ try {
+ final File file = new File("CrashNaNTest-draw.png");
+ System.out.println("Writing file: "
+ + file.getAbsolutePath());
+ ImageIO.write(image, "PNG", file);
+ } catch (IOException ex) {
+ System.out.println("Writing file failure:");
+ ex.printStackTrace();
+ }
+ }
+
+ // Check image on few pixels:
+ final Raster raster = image.getData();
+
+ checkPixelNotWhite(raster, 40, 210);
+ checkPixelNotWhite(raster, 44, 110);
+ checkPixelNotWhite(raster, 60, 120);
+ checkPixelNotWhite(raster, 89, 219);
+ checkPixelNotWhite(raster, 28, 399);
+ checkPixelNotWhite(raster, 134, 329);
+
+ } finally {
+ g2d.dispose();
+ }
+ }
+ private static void testPathClosed() {
+ final int width = 100;
+ final int height = 100;
+
+ final BufferedImage image = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ final Graphics2D g2d = (Graphics2D) image.getGraphics();
+ try {
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ g2d.setBackground(Color.WHITE);
+ g2d.clearRect(0, 0, width, height);
+
+ final Path2D.Double path = new Path2D.Double();
+ path.moveTo(40, 40);
+ path.lineTo(0, 0);
+ path.lineTo(80, 0);
+ path.closePath();
+ path.lineTo(80, 80);
+ path.lineTo(0, 80);
+ path.closePath();
+
+ for (int i = 0; i < 1; i++) {
+ final long start = System.nanoTime();
+ g2d.setColor(Color.BLUE);
+ g2d.fill(path);
+
+ g2d.setColor(Color.BLACK);
+ g2d.draw(path);
+
+ final long time = System.nanoTime() - start;
+ System.out.println("paint: duration= " + (1e-6 * time) + " ms.");
+ }
+
+ if (SAVE_IMAGE) {
+ try {
+ final File file = new File("CrashNaNTest-path-closed.png");
+ System.out.println("Writing file: "
+ + file.getAbsolutePath());
+ ImageIO.write(image, "PNG", file);
+ } catch (IOException ex) {
+ System.out.println("Writing file failure:");
+ ex.printStackTrace();
+ }
+ }
+
+ // Check image on few pixels:
+ final Raster raster = image.getData();
+
+ checkPixel(raster, 10, 05, Color.BLUE.getRGB());
+ checkPixel(raster, 70, 05, Color.BLUE.getRGB());
+ checkPixel(raster, 40, 35, Color.BLUE.getRGB());
+
+ checkPixel(raster, 10, 75, Color.BLUE.getRGB());
+ checkPixel(raster, 70, 75, Color.BLUE.getRGB());
+ checkPixel(raster, 40, 45, Color.BLUE.getRGB());
+
+ } finally {
+ g2d.dispose();
+ }
+ }
+
+ private static void testStrokedShapes() {
+ final Stroke stroke = new BasicStroke();
+
+ final Path2D.Double path = new Path2D.Double();
+ Shape s;
+
+ // Check filtering NaN values:
+ path.reset();
+ path.moveTo(100, NaN);
+ path.lineTo(NaN, 100);
+ path.lineTo(NaN, NaN);
+
+ path.quadTo(NaN, 100, NaN, 100);
+ path.quadTo(100, NaN, 100, NaN);
+ path.quadTo(NaN, NaN, NaN, NaN);
+
+ path.curveTo(NaN, 100, NaN, 100, NaN, 100);
+ path.curveTo(100, NaN, 100, NaN, 100, NaN);
+ path.curveTo(NaN, NaN, NaN, NaN, NaN, NaN);
+ path.closePath();
+
+ s = stroke.createStrokedShape(path);
+ checkEmptyPath(s);
+
+ // Check filtering +Infinity values:
+ path.reset();
+ path.moveTo(100, POSITIVE_INFINITY);
+ path.lineTo(POSITIVE_INFINITY, 100);
+ path.lineTo(POSITIVE_INFINITY, POSITIVE_INFINITY);
+
+ path.quadTo(POSITIVE_INFINITY, 100,
+ POSITIVE_INFINITY, 100);
+ path.quadTo(100, POSITIVE_INFINITY,
+ 100, POSITIVE_INFINITY);
+ path.quadTo(POSITIVE_INFINITY, POSITIVE_INFINITY,
+ POSITIVE_INFINITY, POSITIVE_INFINITY);
+
+ path.curveTo(POSITIVE_INFINITY, 100,
+ POSITIVE_INFINITY, 100,
+ POSITIVE_INFINITY, 100);
+ path.curveTo(100, POSITIVE_INFINITY,
+ 100, POSITIVE_INFINITY,
+ 100, POSITIVE_INFINITY);
+ path.curveTo(POSITIVE_INFINITY, POSITIVE_INFINITY,
+ POSITIVE_INFINITY, POSITIVE_INFINITY,
+ POSITIVE_INFINITY, POSITIVE_INFINITY);
+ path.closePath();
+
+ s = stroke.createStrokedShape(path);
+ checkEmptyPath(s);
+
+ // Check filtering -Infinity values:
+ path.reset();
+ path.moveTo(100, NEGATIVE_INFINITY);
+ path.lineTo(NEGATIVE_INFINITY, 100);
+ path.lineTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY);
+
+ path.quadTo(NEGATIVE_INFINITY, 100,
+ NEGATIVE_INFINITY, 100);
+ path.quadTo(100, NEGATIVE_INFINITY,
+ 100, NEGATIVE_INFINITY);
+ path.quadTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY,
+ NEGATIVE_INFINITY, NEGATIVE_INFINITY);
+
+ path.curveTo(NEGATIVE_INFINITY, 100,
+ NEGATIVE_INFINITY, 100,
+ NEGATIVE_INFINITY, 100);
+ path.curveTo(100, NEGATIVE_INFINITY,
+ 100, NEGATIVE_INFINITY,
+ 100, NEGATIVE_INFINITY);
+ path.curveTo(NEGATIVE_INFINITY, NEGATIVE_INFINITY,
+ NEGATIVE_INFINITY, NEGATIVE_INFINITY,
+ NEGATIVE_INFINITY, NEGATIVE_INFINITY);
+ path.closePath();
+
+ s = stroke.createStrokedShape(path);
+ checkEmptyPath(s);
+ }
+
+ private static void checkEmptyPath(final Shape s) {
+ final float[] coords = new float[6];
+ final PathIterator it = s.getPathIterator(null);
+
+ int n = 0;
+ for (; !it.isDone(); it.next()) {
+ int type = it.currentSegment(coords);
+ System.out.println("unexpected segment type= " + type
+ + " with coords: " + Arrays.toString(coords));
+ n++;
+ }
+ if (n != 0) {
+ System.out.println("path elements = " + n);
+ throw new IllegalStateException("Not empty path: "
+ + n + " path elements !");
+ }
+ }
+
+ private static void checkPixel(final Raster raster,
+ final int x, final int y,
+ final int expected) {
+
+ final int[] rgb = (int[]) raster.getDataElements(x, y, null);
+
+ if (rgb[0] != expected) {
+ throw new IllegalStateException("bad pixel at (" + x + ", " + y
+ + ") = " + rgb[0] + " expected: " + expected);
+ }
+ }
+
+ private static void checkPixelNotWhite(final Raster raster,
+ final int x, final int y) {
+
+ final int[] rgb = (int[]) raster.getDataElements(x, y, null);
+
+ if (rgb[0] == Color.WHITE.getRGB()) {
+ throw new IllegalStateException("bad pixel at (" + x + ", " + y
+ + ") is white (empty)");
+ }
+ }
}
< prev index next >