< prev index next >
test/jdk/sun/java2d/marlin/ClipShapeTest.java
Print this page
*** 52,68 ****
/**
* @test
* @bug 8191814
* @summary Verifies that Marlin rendering generates the same
* images with and without clipping optimization with all possible
! * stroke (cap/join) and fill modes (EO rules)
* Note: Use the argument -slow to run more intensive tests (too much time)
! * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest
! * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest
! */
public final class ClipShapeTest {
static final boolean TEST_STROKER = true;
static final boolean TEST_FILLER = true;
// complementary tests in slow mode:
static boolean USE_DASHES = false;
--- 52,79 ----
/**
* @test
* @bug 8191814
* @summary Verifies that Marlin rendering generates the same
* images with and without clipping optimization with all possible
! * stroke (cap/join) and/or dashes or fill modes (EO rules)
! * for paths made of either 9 lines, 4 quads, 2 cubics (random)
* Note: Use the argument -slow to run more intensive tests (too much time)
! *
! * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -poly
! * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -poly -doDash
! * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -cubic
! * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -cubic -doDash
! * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -poly
! * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -poly -doDash
! * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -cubic
! * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -cubic -doDash
! */
public final class ClipShapeTest {
+ static boolean TX_SCALE = false;
+ static boolean TX_SHEAR = false;
+
static final boolean TEST_STROKER = true;
static final boolean TEST_FILLER = true;
// complementary tests in slow mode:
static boolean USE_DASHES = false;
*** 71,92 ****
static int NUM_TESTS = 5000;
static final int TESTW = 100;
static final int TESTH = 100;
// shape settings:
! static final ShapeMode SHAPE_MODE = ShapeMode.NINE_LINE_POLYS;
static final boolean SHAPE_REPEAT = true;
// dump path on console:
static final boolean DUMP_SHAPE = true;
! static final boolean SHOW_DETAILS = true;
static final boolean SHOW_OUTLINE = true;
static final boolean SHOW_POINTS = true;
static final boolean SHOW_INFO = false;
static final int MAX_SHOW_FRAMES = 10;
// use fixed seed to reproduce always same polygons between tests
static final boolean FIXED_SEED = false;
static final double RAND_SCALE = 3.0;
static final double RANDW = TESTW * RAND_SCALE;
--- 82,108 ----
static int NUM_TESTS = 5000;
static final int TESTW = 100;
static final int TESTH = 100;
// shape settings:
! static ShapeMode SHAPE_MODE = ShapeMode.NINE_LINE_POLYS;
!
! static int THRESHOLD_DELTA;
! static long THRESHOLD_NBPIX;
!
static final boolean SHAPE_REPEAT = true;
// dump path on console:
static final boolean DUMP_SHAPE = true;
! static final boolean SHOW_DETAILS = false; // disabled
static final boolean SHOW_OUTLINE = true;
static final boolean SHOW_POINTS = true;
static final boolean SHOW_INFO = false;
static final int MAX_SHOW_FRAMES = 10;
+ static final int MAX_SAVE_FRAMES = 100;
// use fixed seed to reproduce always same polygons between tests
static final boolean FIXED_SEED = false;
static final double RAND_SCALE = 3.0;
static final double RANDW = TESTW * RAND_SCALE;
*** 107,134 ****
// Fixed seed to avoid any difference between runs:
static final Random RANDOM = new Random(SEED);
static final File OUTPUT_DIR = new File(".");
! /**
! * Test
! * @param args
! */
! public static void main(String[] args) {
! boolean runSlowTests = (args.length != 0 && "-slow".equals(args[0]));
!
! if (runSlowTests) {
! NUM_TESTS = 20000; // or 100000 (very slow)
! USE_DASHES = true;
! USE_VAR_STROKE = true;
! }
Locale.setDefault(Locale.US);
! // Get Marlin runtime state from its log:
! final AtomicBoolean isMarlin = new AtomicBoolean();
! final AtomicBoolean isClipRuntime = new AtomicBoolean();
// initialize j.u.l Looger:
final Logger log = Logger.getLogger("sun.java2d.marlin");
log.addHandler(new Handler() {
@Override
--- 123,139 ----
// Fixed seed to avoid any difference between runs:
static final Random RANDOM = new Random(SEED);
static final File OUTPUT_DIR = new File(".");
! static final AtomicBoolean isMarlin = new AtomicBoolean();
! static final AtomicBoolean isClipRuntime = new AtomicBoolean();
+ static {
Locale.setDefault(Locale.US);
! // FIRST: Get Marlin runtime state from its log:
// initialize j.u.l Looger:
final Logger log = Logger.getLogger("sun.java2d.marlin");
log.addHandler(new Handler() {
@Override
*** 169,194 ****
// disable static clipping setting:
System.setProperty("sun.java2d.renderer.clip", "false");
System.setProperty("sun.java2d.renderer.clip.runtime.enable", "true");
System.out.println("ClipShapeTests: image = " + TESTW + " x " + TESTH);
int failures = 0;
final long start = System.nanoTime();
try {
// TODO: test affine transforms ?
if (TEST_STROKER) {
! final float[][] dashArrays = (USE_DASHES)
! ? new float[][]{null, new float[]{1f, 2f}}
: new float[][]{null};
! System.out.println("dashes: " + Arrays.toString(dashArrays));
final float[] strokeWidths = (USE_VAR_STROKE)
! ? new float[5] : new float[]{8f};
int nsw = 0;
if (USE_VAR_STROKE) {
for (float width = 0.1f; width < 110f; width *= 5f) {
strokeWidths[nsw++] = width;
--- 174,295 ----
// disable static clipping setting:
System.setProperty("sun.java2d.renderer.clip", "false");
System.setProperty("sun.java2d.renderer.clip.runtime.enable", "true");
+ // enable subdivider:
+ System.setProperty("sun.java2d.renderer.clip.subdivider", "true");
+
+ // disable min length check: always subdivide curves at clip edges
+ System.setProperty("sun.java2d.renderer.clip.subdivider.minLength", "-1");
+
+ // If any curve, increase curve accuracy:
+ // curve length max error:
+ System.setProperty("sun.java2d.renderer.curve_len_err", "1e-4");
+
+ // quad max error:
+ System.setProperty("sun.java2d.renderer.quad_dec_d2", "5e-4");
+
+ // cubic min/max error:
+ System.setProperty("sun.java2d.renderer.cubic_dec_d2", "1e-3");
+ System.setProperty("sun.java2d.renderer.cubic_inc_d1", "1e-4"); // or disabled ~ 1e-6
+ }
+
+ /**
+ * Test
+ * @param args
+ */
+ public static void main(String[] args) {
+ boolean runSlowTests = false;
+
+ for (String arg : args) {
+ if ("-slow".equals(arg)) {
+ System.out.println("slow: enabled.");
+ runSlowTests = true;
+ } else if ("-doScale".equals(arg)) {
+ System.out.println("doScale: enabled.");
+ TX_SCALE = true;
+ } else if ("-doShear".equals(arg)) {
+ System.out.println("doShear: enabled.");
+ TX_SHEAR = true;
+ } else if ("-doDash".equals(arg)) {
+ System.out.println("doDash: enabled.");
+ USE_DASHES = true;
+ } else if ("-doVarStroke".equals(arg)) {
+ System.out.println("doVarStroke: enabled.");
+ USE_VAR_STROKE = true;
+ }
+ // shape mode:
+ else if (arg.equalsIgnoreCase("-poly")) {
+ SHAPE_MODE = ShapeMode.NINE_LINE_POLYS;
+ } else if (arg.equalsIgnoreCase("-bigpoly")) {
+ SHAPE_MODE = ShapeMode.FIFTY_LINE_POLYS;
+ } else if (arg.equalsIgnoreCase("-quad")) {
+ SHAPE_MODE = ShapeMode.FOUR_QUADS;
+ } else if (arg.equalsIgnoreCase("-cubic")) {
+ SHAPE_MODE = ShapeMode.TWO_CUBICS;
+ } else if (arg.equalsIgnoreCase("-mixed")) {
+ SHAPE_MODE = ShapeMode.MIXED;
+ }
+ }
+
+ System.out.println("Shape mode: " + SHAPE_MODE);
+
+ // adjust image comparison thresholds:
+ switch(SHAPE_MODE) {
+ case TWO_CUBICS:
+ // Define uncertainty for curves:
+ THRESHOLD_DELTA = 32; // / 256
+ THRESHOLD_NBPIX = 128; // / 10000
+ break;
+ case FOUR_QUADS:
+ case MIXED:
+ // Define uncertainty for quads:
+ // curve subdivision causes curves to be smaller
+ // then curve offsets are different (more accurate)
+ THRESHOLD_DELTA = 64; // 64 / 256
+ THRESHOLD_NBPIX = 256; // 256 / 10000
+ break;
+ default:
+ // Define uncertainty for lines:
+ // float variant have higher uncertainty
+ THRESHOLD_DELTA = 8;
+ THRESHOLD_NBPIX = 8;
+ }
+
+ System.out.println("THRESHOLD_DELTA: "+THRESHOLD_DELTA);
+ System.out.println("THRESHOLD_NBPIX: "+THRESHOLD_NBPIX);
+
+ if (runSlowTests) {
+ NUM_TESTS = 10000; // or 100000 (very slow)
+ USE_DASHES = true;
+ USE_VAR_STROKE = true;
+ }
+
System.out.println("ClipShapeTests: image = " + TESTW + " x " + TESTH);
int failures = 0;
final long start = System.nanoTime();
try {
// TODO: test affine transforms ?
if (TEST_STROKER) {
! final float[][] dashArrays = (USE_DASHES) ?
! // small
! // new float[][]{new float[]{1f, 2f}}
! // normal
! new float[][]{new float[]{13f, 7f}}
! // large (prime)
! // new float[][]{new float[]{41f, 7f}}
! // none
: new float[][]{null};
! System.out.println("dashes: " + Arrays.deepToString(dashArrays));
final float[] strokeWidths = (USE_VAR_STROKE)
! ? new float[5] :
! new float[]{10f};
int nsw = 0;
if (USE_VAR_STROKE) {
for (float width = 0.1f; width < 110f; width *= 5f) {
strokeWidths[nsw++] = width;
*** 288,313 ****
nd++;
final double ratio = (100.0 * testCtx.histPix.count) / testCtx.histAll.count;
System.out.println("Diff ratio: " + testName + " = " + trimTo3Digits(ratio) + " %");
- if (false) {
- saveImage(diffImage, OUTPUT_DIR, testName + "-diff.png");
- }
-
- if (DUMP_SHAPE) {
- dumpShape(p2d);
- }
if (nd < MAX_SHOW_FRAMES) {
if (SHOW_DETAILS) {
paintShapeDetails(g2dOff, p2d);
paintShapeDetails(g2dOn, p2d);
}
! saveImage(imgOff, OUTPUT_DIR, testName + "-off.png");
! saveImage(imgOn, OUTPUT_DIR, testName + "-on.png");
! saveImage(diffImage, OUTPUT_DIR, testName + "-diff.png");
}
}
}
} finally {
g2dOff.dispose();
--- 389,412 ----
nd++;
final double ratio = (100.0 * testCtx.histPix.count) / testCtx.histAll.count;
System.out.println("Diff ratio: " + testName + " = " + trimTo3Digits(ratio) + " %");
if (nd < MAX_SHOW_FRAMES) {
if (SHOW_DETAILS) {
paintShapeDetails(g2dOff, p2d);
paintShapeDetails(g2dOn, p2d);
}
! if (nd < MAX_SAVE_FRAMES) {
! if (DUMP_SHAPE) {
! dumpShape(p2d);
! }
! saveImage(imgOff, OUTPUT_DIR, testName + "-off.png");
! saveImage(imgOn, OUTPUT_DIR, testName + "-on.png");
! saveImage(diffImage, OUTPUT_DIR, testName + "-diff.png");
! }
}
}
}
} finally {
g2dOff.dispose();
*** 349,358 ****
--- 448,466 ----
if (ts.isStroke()) {
g2d.setStroke(createStroke(ts));
}
g2d.setColor(Color.GRAY);
+ // Test scale
+ if (TX_SCALE) {
+ g2d.scale(1.2, 1.2);
+ }
+ // Test shear
+ if (TX_SHEAR) {
+ g2d.shear(0.1, 0.2);
+ }
+
return g2d;
}
private static void reset(final Graphics2D g2d) {
// Disable antialiasing:
*** 468,477 ****
--- 576,587 ----
if (SHOW_POINTS) {
g2d.setColor(COLOR_MOVETO);
}
break;
case PathIterator.SEG_LINETO:
+ case PathIterator.SEG_QUADTO:
+ case PathIterator.SEG_CUBICTO:
if (SHOW_POINTS) {
g2d.setColor((nLine % 2 == 0) ? COLOR_LINETO_ODD : COLOR_LINETO_EVEN);
}
nLine++;
break;
*** 513,522 ****
--- 623,638 ----
System.out.println("p2d.moveTo(" + coords[0] + ", " + coords[1] + ");");
break;
case PathIterator.SEG_LINETO:
System.out.println("p2d.lineTo(" + coords[0] + ", " + coords[1] + ");");
break;
+ case PathIterator.SEG_QUADTO:
+ System.out.println("p2d.quadTo(" + coords[0] + ", " + coords[1] + ", " + coords[2] + ", " + coords[3] + ");");
+ break;
+ case PathIterator.SEG_CUBICTO:
+ System.out.println("p2d.curveTo(" + coords[0] + ", " + coords[1] + ", " + coords[2] + ", " + coords[3] + ", " + coords[4] + ", " + coords[5] + ");");
+ break;
case PathIterator.SEG_CLOSE:
System.out.println("p2d.closePath();");
break;
default:
System.out.println("// Unsupported segment type= " + type);
*** 578,591 ****
return this.strokeWidth > 0f;
}
@Override
public String toString() {
return "TestSetup{id=" + id + ", shapeMode=" + shapeMode + ", closed=" + closed
! + ", strokeWidth=" + strokeWidth + ", strokeCap=" + strokeCap + ", strokeJoin=" + strokeJoin
! + ((dashes != null) ? ", dashes: " + Arrays.toString(dashes) : "")
! + ", windingRule=" + windingRule + '}';
}
}
// --- utilities ---
private static final int DCM_ALPHA_MASK = 0xff000000;
--- 694,751 ----
return this.strokeWidth > 0f;
}
@Override
public String toString() {
+ if (isStroke()) {
+ return "TestSetup{id=" + id + ", shapeMode=" + shapeMode + ", closed=" + closed
+ + ", strokeWidth=" + strokeWidth + ", strokeCap=" + getCap(strokeCap) + ", strokeJoin=" + getJoin(strokeJoin)
+ + ((dashes != null) ? ", dashes: " + Arrays.toString(dashes) : "")
+ + '}';
+ }
return "TestSetup{id=" + id + ", shapeMode=" + shapeMode + ", closed=" + closed
! + ", fill"
! + ", windingRule=" + getWindingRule(windingRule) + '}';
! }
!
! private static String getCap(final int cap) {
! switch (cap) {
! case BasicStroke.CAP_BUTT:
! return "CAP_BUTT";
! case BasicStroke.CAP_ROUND:
! return "CAP_ROUND";
! case BasicStroke.CAP_SQUARE:
! return "CAP_SQUARE";
! default:
! return "";
! }
!
! }
!
! private static String getJoin(final int join) {
! switch (join) {
! case BasicStroke.JOIN_MITER:
! return "JOIN_MITER";
! case BasicStroke.JOIN_ROUND:
! return "JOIN_ROUND";
! case BasicStroke.JOIN_BEVEL:
! return "JOIN_BEVEL";
! default:
! return "";
! }
!
! }
!
! private static String getWindingRule(final int rule) {
! switch (rule) {
! case PathIterator.WIND_EVEN_ODD:
! return "WIND_EVEN_ODD";
! case PathIterator.WIND_NON_ZERO:
! return "WIND_NON_ZERO";
! default:
! return "";
! }
}
}
// --- utilities ---
private static final int DCM_ALPHA_MASK = 0xff000000;
*** 616,635 ****
dg = (r(ref) + g(ref) + b(ref)) - (r(tst) + g(tst) + b(tst));
// max difference on grayscale values:
v = (int) Math.ceil(Math.abs(dg / 3.0));
! aDifPix[i] = toInt(v, v, v);
! localCtx.add(v);
globalCtx.add(v);
}
! if (!localCtx.isDiff()) {
return null;
}
return diffImage;
}
static void saveImage(final BufferedImage image, final File resDirectory, final String imageFileName) throws IOException {
final Iterator<ImageWriter> itWriters = ImageIO.getImageWritersByFormatName("PNG");
--- 776,802 ----
dg = (r(ref) + g(ref) + b(ref)) - (r(tst) + g(tst) + b(tst));
// max difference on grayscale values:
v = (int) Math.ceil(Math.abs(dg / 3.0));
! // TODO: count warnings
! if (v <= THRESHOLD_DELTA) {
! aDifPix[i] = 0;
! } else {
! aDifPix[i] = toInt(v, v, v);
! localCtx.add(v);
! }
globalCtx.add(v);
}
! if (!localCtx.isDiff() || (localCtx.histPix.count <= THRESHOLD_NBPIX)) {
return null;
}
+ localCtx.dump();
+
return diffImage;
}
static void saveImage(final BufferedImage image, final File resDirectory, final String imageFileName) throws IOException {
final Iterator<ImageWriter> itWriters = ImageIO.getImageWritersByFormatName("PNG");
< prev index next >