Path: blob/master/test/jdk/sun/java2d/marlin/CrashTest.java
41149 views
/*1* Copyright (c) 2015, 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.geom.Path2D;28import static java.awt.geom.Path2D.WIND_NON_ZERO;29import java.awt.image.BufferedImage;30import java.io.File;31import java.io.IOException;32import javax.imageio.ImageIO;3334/**35* @test36* @summary Simple crash rendering test using huge GeneralPaths with the Marlin renderer37* @run main/othervm -mx512m CrashTest38* @ignore tests that take a long time and consumes 5Gb memory39* @run main/othervm -ms4g -mx4g CrashTest -slow40*/41public class CrashTest {4243static final boolean SAVE_IMAGE = false;44static boolean USE_ROUND_CAPS_AND_JOINS = true;4546public static void main(String[] args) {47boolean runSlowTests = (args.length != 0 && "-slow".equals(args[0]));4849// First display which renderer is tested:50System.setProperty("sun.java2d.renderer.verbose", "true");5152// try insane image sizes:5354// subpixel coords may overflow:55// check MAX_VALUE / (8 * 2); overflow may happen due to orientation flag56// But as it is impossible to allocate an image larger than 2Gb (byte) then57// it is also impossible to have rowAAChunk larger than 2Gb !5859// Disabled test as it consumes 4GB heap + offheap (2Gb) ie > 6Gb !60if (runSlowTests) {61testHugeImage((Integer.MAX_VALUE >> 4) - 100, 16);62}6364// larger than 23 bits: (RLE)65testHugeImage(8388608 + 1, 10);6667if (runSlowTests) {68test(0.1f, false, 0);69test(0.1f, true, 7f);70}7172// Exceed 2Gb OffHeap buffer for edges:73try {74USE_ROUND_CAPS_AND_JOINS = true;75test(0.1f, true, 0.1f);76System.out.println("Exception MISSING.");77}78catch (Throwable th) {79if (th instanceof ArrayIndexOutOfBoundsException) {80System.out.println("ArrayIndexOutOfBoundsException expected.");81} else {82throw new RuntimeException("Unexpected exception", th);83}84}85}8687private static void test(final float lineStroke,88final boolean useDashes,89final float dashMinLen)90throws ArrayIndexOutOfBoundsException91{92System.out.println("---\n" + "test: "93+ "lineStroke=" + lineStroke94+ ", useDashes=" + useDashes95+", dashMinLen=" + dashMinLen96);9798final BasicStroke stroke = createStroke(lineStroke, useDashes, dashMinLen);99100// TODO: test Dasher.firstSegmentsBuffer resizing ?101// array.dasher.firstSegmentsBuffer.d_float[2] sum: 6 avg: 3.0 [3 | 3]102/*103// Marlin growable arrays:104= new StatLong("array.dasher.firstSegmentsBuffer.d_float");105= new StatLong("array.stroker.polystack.curves.d_float");106= new StatLong("array.stroker.polystack.curveTypes.d_byte");107= new StatLong("array.marlincache.rowAAChunk.d_byte");108= new StatLong("array.marlincache.touchedTile.int");109= new StatLong("array.renderer.alphaline.int");110= new StatLong("array.renderer.crossings.int");111= new StatLong("array.renderer.aux_crossings.int");112= new StatLong("array.renderer.edgeBuckets.int");113= new StatLong("array.renderer.edgeBucketCounts.int");114= new StatLong("array.renderer.edgePtrs.int");115= new StatLong("array.renderer.aux_edgePtrs.int");116*/117// size > 8192 (exceed both tile and buckets arrays)118final int size = 9000;119System.out.println("image size = " + size);120121final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);122123final Graphics2D g2d = (Graphics2D) image.getGraphics();124try {125g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);126g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);127128g2d.setClip(0, 0, size, size);129g2d.setBackground(Color.WHITE);130g2d.clearRect(0, 0, size, size);131132g2d.setStroke(stroke);133g2d.setColor(Color.BLACK);134135final long start = System.nanoTime();136137paint(g2d, size - 10f);138139final long time = System.nanoTime() - start;140141System.out.println("paint: duration= " + (1e-6 * time) + " ms.");142143if (SAVE_IMAGE) {144try {145final File file = new File("CrashTest-dash-" + useDashes + ".bmp");146147System.out.println("Writing file: " + file.getAbsolutePath());148ImageIO.write(image, "BMP", file);149} catch (IOException ex) {150System.out.println("Writing file failure:");151ex.printStackTrace();152}153}154} finally {155g2d.dispose();156}157}158159private static void testHugeImage(final int width, final int height)160throws ArrayIndexOutOfBoundsException161{162System.out.println("---\n" + "testHugeImage: "163+ "width=" + width + ", height=" + height);164165final BasicStroke stroke = createStroke(2.5f, false, 0);166167// size > 24bits (exceed both tile and buckets arrays)168System.out.println("image size = " + width + " x "+height);169170final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);171172final Graphics2D g2d = (Graphics2D) image.getGraphics();173try {174g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);175g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);176177g2d.setBackground(Color.WHITE);178g2d.clearRect(0, 0, width, height);179180g2d.setStroke(stroke);181g2d.setColor(Color.BLACK);182183final Path2D.Float path = new Path2D.Float(WIND_NON_ZERO, 32);184path.moveTo(0, 0);185path.lineTo(width, 0);186path.lineTo(width, height);187path.lineTo(0, height);188path.lineTo(0, 0);189190final long start = System.nanoTime();191192g2d.draw(path);193194final long time = System.nanoTime() - start;195196System.out.println("paint: duration= " + (1e-6 * time) + " ms.");197198if (SAVE_IMAGE) {199try {200final File file = new File("CrashTest-huge-"201+ width + "x" +height + ".bmp");202203System.out.println("Writing file: " + file.getAbsolutePath());204ImageIO.write(image, "BMP", file);205} catch (IOException ex) {206System.out.println("Writing file failure:");207ex.printStackTrace();208}209}210} finally {211g2d.dispose();212}213}214215private static void paint(final Graphics2D g2d, final float size) {216final double halfSize = size / 2.0;217218final Path2D.Float path = new Path2D.Float(WIND_NON_ZERO, 32 * 1024);219220// show cross:221path.moveTo(0, 0);222path.lineTo(size, size);223224path.moveTo(size, 0);225path.lineTo(0, size);226227path.moveTo(0, 0);228path.lineTo(size, 0);229230path.moveTo(0, 0);231path.lineTo(0, size);232233path.moveTo(0, 0);234235double r = size;236237final int ratio = 100;238int repeats = 1;239240int n = 0;241242while (r > 1.0) {243repeats *= ratio;244245if (repeats > 10000) {246repeats = 10000;247}248249for (int i = 0; i < repeats; i++) {250path.lineTo(halfSize - 0.5 * r + i * r / repeats,251halfSize - 0.5 * r);252n++;253path.lineTo(halfSize - 0.5 * r + i * r / repeats + 0.1,254halfSize + 0.5 * r);255n++;256}257258r -= halfSize;259}260System.out.println("draw : " + n + " lines.");261g2d.draw(path);262}263264private static BasicStroke createStroke(final float width,265final boolean useDashes,266final float dashMinLen) {267final float[] dashes;268269if (useDashes) {270// huge dash array (exceed Dasher.INITIAL_ARRAY)271dashes = new float[512];272273float cur = dashMinLen;274float step = 0.01f;275276for (int i = 0; i < dashes.length; i += 2) {277dashes[i] = cur;278dashes[i + 1] = cur;279cur += step;280}281} else {282dashes = null;283}284285if (USE_ROUND_CAPS_AND_JOINS) {286// Use both round Caps & Joins:287return new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 100.0f, dashes, 0.0f);288}289return new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 100.0f, dashes, 0.0f);290}291}292293294