changeset 10490:882cbd9305fc

8180449: Upgrade the Marlin renderer in JavaFX Reviewed-by: flar
author lbourges
date Wed, 17 May 2017 13:44:23 -0700
parents 404ce563c4dd
children 48902e8e83a9
files modules/javafx.graphics/src/main/java/com/sun/marlin/ArrayCacheConst.java modules/javafx.graphics/src/main/java/com/sun/marlin/ByteArrayCache.java modules/javafx.graphics/src/main/java/com/sun/marlin/CollinearSimplifier.java modules/javafx.graphics/src/main/java/com/sun/marlin/Curve.java modules/javafx.graphics/src/main/java/com/sun/marlin/DCollinearSimplifier.java modules/javafx.graphics/src/main/java/com/sun/marlin/DCurve.java modules/javafx.graphics/src/main/java/com/sun/marlin/DDasher.java modules/javafx.graphics/src/main/java/com/sun/marlin/DHelpers.java modules/javafx.graphics/src/main/java/com/sun/marlin/DMarlinRenderingEngine.java modules/javafx.graphics/src/main/java/com/sun/marlin/DRenderer.java modules/javafx.graphics/src/main/java/com/sun/marlin/DRendererContext.java modules/javafx.graphics/src/main/java/com/sun/marlin/DRendererNoAA.java modules/javafx.graphics/src/main/java/com/sun/marlin/DStroker.java modules/javafx.graphics/src/main/java/com/sun/marlin/DTransformingPathConsumer2D.java modules/javafx.graphics/src/main/java/com/sun/marlin/Dasher.java modules/javafx.graphics/src/main/java/com/sun/marlin/DoubleArrayCache.java modules/javafx.graphics/src/main/java/com/sun/marlin/FloatArrayCache.java modules/javafx.graphics/src/main/java/com/sun/marlin/FloatMath.java modules/javafx.graphics/src/main/java/com/sun/marlin/Helpers.java modules/javafx.graphics/src/main/java/com/sun/marlin/IntArrayCache.java modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinConst.java modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinProperties.java modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinRenderingEngine.java modules/javafx.graphics/src/main/java/com/sun/marlin/MaskMarlinAlphaConsumer.java modules/javafx.graphics/src/main/java/com/sun/marlin/Renderer.java modules/javafx.graphics/src/main/java/com/sun/marlin/RendererContext.java modules/javafx.graphics/src/main/java/com/sun/marlin/RendererNoAA.java modules/javafx.graphics/src/main/java/com/sun/marlin/Stroker.java modules/javafx.graphics/src/main/java/com/sun/marlin/TransformingPathConsumer2D.java modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/DMarlinPrismUtils.java modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/MarlinPrismUtils.java modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWContext.java
diffstat 32 files changed, 841 insertions(+), 965 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/ArrayCacheConst.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/ArrayCacheConst.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -242,6 +242,8 @@
             int factor = 1;
             if (name.contains("Int") || name.contains("Float")) {
                 factor = 4;
+            } else if (name.contains("Double")) {
+                factor = 8;
             }
             return factor;
         }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/ByteArrayCache.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/ByteArrayCache.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,13 +38,14 @@
 import com.sun.marlin.ArrayCacheConst.CacheStats;
 
 /*
- * Note that the [BYTE/INT/FLOAT]ArrayCache files are nearly identical except
+ * Note that the [BYTE/INT/FLOAT/DOUBLE]ArrayCache files are nearly identical except
  * for a few type and name differences. Typically, the [BYTE]ArrayCache.java file
- * is edited manually and then [INT]ArrayCache.java and [FLOAT]ArrayCache.java
+ * is edited manually and then [INT/FLOAT/DOUBLE]ArrayCache.java
  * files are generated with the following command lines:
  */
 // % sed -e 's/(b\yte)[ ]*//g' -e 's/b\yte/int/g' -e 's/B\yte/Int/g' < B\yteArrayCache.java > IntArrayCache.java
-// % sed -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0f/g' -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0d/g' -e 's/(b\yte)[ ]*/(double) /g' -e 's/b\yte/double/g' -e 's/B\yte/Double/g' < B\yteArrayCache.java > DoubleArrayCache.java
 
 public final class ByteArrayCache implements MarlinConst {
 
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/CollinearSimplifier.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/CollinearSimplifier.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
 
     private static float getSlope(float x1, float y1, float x2, float y2) {
         float dy = y2 - y1;
-        if (dy == 0f) {
+        if (dy == 0.0f) {
             return (x2 > x1) ? Float.POSITIVE_INFINITY
                    : Float.NEGATIVE_INFINITY;
         }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/Curve.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/Curve.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,31 +56,31 @@
              float x3, float y3,
              float x4, float y4)
     {
-        ax = 3f * (x2 - x3) + x4 - x1;
-        ay = 3f * (y2 - y3) + y4 - y1;
-        bx = 3f * (x1 - 2f * x2 + x3);
-        by = 3f * (y1 - 2f * y2 + y3);
-        cx = 3f * (x2 - x1);
-        cy = 3f * (y2 - y1);
+        ax = 3.0f * (x2 - x3) + x4 - x1;
+        ay = 3.0f * (y2 - y3) + y4 - y1;
+        bx = 3.0f * (x1 - 2.0f * x2 + x3);
+        by = 3.0f * (y1 - 2.0f * y2 + y3);
+        cx = 3.0f * (x2 - x1);
+        cy = 3.0f * (y2 - y1);
         dx = x1;
         dy = y1;
-        dax = 3f * ax; day = 3f * ay;
-        dbx = 2f * bx; dby = 2f * by;
+        dax = 3.0f * ax; day = 3.0f * ay;
+        dbx = 2.0f * bx; dby = 2.0f * by;
     }
 
     void set(float x1, float y1,
              float x2, float y2,
              float x3, float y3)
     {
-        ax = 0f; ay = 0f;
-        bx = x1 - 2f * x2 + x3;
-        by = y1 - 2f * y2 + y3;
-        cx = 2f * (x2 - x1);
-        cy = 2f * (y2 - y1);
+        ax = 0.0f; ay = 0.0f;
+        bx = x1 - 2.0f * x2 + x3;
+        by = y1 - 2.0f * y2 + y3;
+        cx = 2.0f * (x2 - x1);
+        cy = 2.0f * (y2 - y1);
         dx = x1;
         dy = y1;
-        dax = 0f; day = 0f;
-        dbx = 2f * bx; dby = 2f * by;
+        dax = 0.0f; day = 0.0f;
+        dbx = 2.0f * bx; dby = 2.0f * by;
     }
 
     float xat(float t) {
@@ -111,7 +111,7 @@
         // Fortunately, this turns out to be quadratic, so there are at
         // most 2 inflection points.
         final float a = dax * dby - dbx * day;
-        final float b = 2f * (cy * dax - day * cx);
+        final float b = 2.0f * (cy * dax - day * cx);
         final float c = cy * dbx - cx * dby;
 
         return Helpers.quadraticRoots(a, b, c, pts, off);
@@ -126,11 +126,11 @@
         // these are the coefficients of some multiple of g(t) (not g(t),
         // because the roots of a polynomial are not changed after multiplication
         // by a constant, and this way we save a few multiplications).
-        final float a = 2f * (dax*dax + day*day);
-        final float b = 3f * (dax*dbx + day*dby);
-        final float c = 2f * (dax*cx + day*cy) + dbx*dbx + dby*dby;
+        final float a = 2.0f * (dax*dax + day*day);
+        final float b = 3.0f * (dax*dbx + day*dby);
+        final float c = 2.0f * (dax*cx + day*cy) + dbx*dbx + dby*dby;
         final float d = dbx*cx + dby*cy;
-        return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0f, 1f);
+        return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0f, 1.0f);
     }
 
     // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
@@ -151,14 +151,14 @@
         assert off <= 6 && roots.length >= 10;
         int ret = off;
         int numPerpdfddf = perpendiculardfddf(roots, off);
-        float t0 = 0f, ft0 = ROCsq(t0) - w*w;
-        roots[off + numPerpdfddf] = 1f; // always check interval end points
+        float t0 = 0.0f, ft0 = ROCsq(t0) - w*w;
+        roots[off + numPerpdfddf] = 1.0f; // always check interval end points
         numPerpdfddf++;
         for (int i = off; i < off + numPerpdfddf; i++) {
             float t1 = roots[i], ft1 = ROCsq(t1) - w*w;
-            if (ft0 == 0f) {
+            if (ft0 == 0.0f) {
                 roots[ret++] = t0;
-            } else if (ft1 * ft0 < 0f) { // have opposite signs
+            } else if (ft1 * ft0 < 0.0f) { // have opposite signs
                 // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
                 // ROC(t) >= 0 for all t.
                 roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
@@ -218,7 +218,7 @@
 
     private static boolean sameSign(float x, float y) {
         // another way is to test if x*y > 0. This is bad for small x, y.
-        return (x < 0f && y < 0f) || (x > 0f && y > 0f);
+        return (x < 0.0f && y < 0.0f) || (x > 0.0f && y > 0.0f);
     }
 
     // returns the radius of curvature squared at t of this curve
@@ -227,8 +227,8 @@
         // dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency
         final float dx = t * (t * dax + dbx) + cx;
         final float dy = t * (t * day + dby) + cy;
-        final float ddx = 2f * dax * t + dbx;
-        final float ddy = 2f * day * t + dby;
+        final float ddx = 2.0f * dax * t + dbx;
+        final float ddy = 2.0f * day * t + dby;
         final float dx2dy2 = dx*dx + dy*dy;
         final float ddx2ddy2 = ddx*ddx + ddy*ddy;
         final float ddxdxddydy = ddx*dx + ddy*dy;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DCollinearSimplifier.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DCollinearSimplifier.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
 
     private static double getSlope(double x1, double y1, double x2, double y2) {
         double dy = y2 - y1;
-        if (dy == 0d) {
+        if (dy == 0.0d) {
             return (x2 > x1) ? Double.POSITIVE_INFINITY
                    : Double.NEGATIVE_INFINITY;
         }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DCurve.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DCurve.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,31 +56,31 @@
              double x3, double y3,
              double x4, double y4)
     {
-        ax = 3d * (x2 - x3) + x4 - x1;
-        ay = 3d * (y2 - y3) + y4 - y1;
-        bx = 3d * (x1 - 2d * x2 + x3);
-        by = 3d * (y1 - 2d * y2 + y3);
-        cx = 3d * (x2 - x1);
-        cy = 3d * (y2 - y1);
+        ax = 3.0d * (x2 - x3) + x4 - x1;
+        ay = 3.0d * (y2 - y3) + y4 - y1;
+        bx = 3.0d * (x1 - 2.0d * x2 + x3);
+        by = 3.0d * (y1 - 2.0d * y2 + y3);
+        cx = 3.0d * (x2 - x1);
+        cy = 3.0d * (y2 - y1);
         dx = x1;
         dy = y1;
-        dax = 3d * ax; day = 3d * ay;
-        dbx = 2d * bx; dby = 2d * by;
+        dax = 3.0d * ax; day = 3.0d * ay;
+        dbx = 2.0d * bx; dby = 2.0d * by;
     }
 
     void set(double x1, double y1,
              double x2, double y2,
              double x3, double y3)
     {
-        ax = 0d; ay = 0d;
-        bx = x1 - 2d * x2 + x3;
-        by = y1 - 2d * y2 + y3;
-        cx = 2d * (x2 - x1);
-        cy = 2d * (y2 - y1);
+        ax = 0.0d; ay = 0.0d;
+        bx = x1 - 2.0d * x2 + x3;
+        by = y1 - 2.0d * y2 + y3;
+        cx = 2.0d * (x2 - x1);
+        cy = 2.0d * (y2 - y1);
         dx = x1;
         dy = y1;
-        dax = 0d; day = 0d;
-        dbx = 2d * bx; dby = 2d * by;
+        dax = 0.0d; day = 0.0d;
+        dbx = 2.0d * bx; dby = 2.0d * by;
     }
 
     double xat(double t) {
@@ -111,7 +111,7 @@
         // Fortunately, this turns out to be quadratic, so there are at
         // most 2 inflection points.
         final double a = dax * dby - dbx * day;
-        final double b = 2d * (cy * dax - day * cx);
+        final double b = 2.0d * (cy * dax - day * cx);
         final double c = cy * dbx - cx * dby;
 
         return DHelpers.quadraticRoots(a, b, c, pts, off);
@@ -126,11 +126,11 @@
         // these are the coefficients of some multiple of g(t) (not g(t),
         // because the roots of a polynomial are not changed after multiplication
         // by a constant, and this way we save a few multiplications).
-        final double a = 2d * (dax*dax + day*day);
-        final double b = 3d * (dax*dbx + day*dby);
-        final double c = 2d * (dax*cx + day*cy) + dbx*dbx + dby*dby;
+        final double a = 2.0d * (dax*dax + day*day);
+        final double b = 3.0d * (dax*dbx + day*dby);
+        final double c = 2.0d * (dax*cx + day*cy) + dbx*dbx + dby*dby;
         final double d = dbx*cx + dby*cy;
-        return DHelpers.cubicRootsInAB(a, b, c, d, pts, off, 0d, 1d);
+        return DHelpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d);
     }
 
     // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
@@ -151,14 +151,14 @@
         assert off <= 6 && roots.length >= 10;
         int ret = off;
         int numPerpdfddf = perpendiculardfddf(roots, off);
-        double t0 = 0d, ft0 = ROCsq(t0) - w*w;
-        roots[off + numPerpdfddf] = 1d; // always check interval end points
+        double t0 = 0.0d, ft0 = ROCsq(t0) - w*w;
+        roots[off + numPerpdfddf] = 1.0d; // always check interval end points
         numPerpdfddf++;
         for (int i = off; i < off + numPerpdfddf; i++) {
             double t1 = roots[i], ft1 = ROCsq(t1) - w*w;
-            if (ft0 == 0d) {
+            if (ft0 == 0.0d) {
                 roots[ret++] = t0;
-            } else if (ft1 * ft0 < 0d) { // have opposite signs
+            } else if (ft1 * ft0 < 0.0d) { // have opposite signs
                 // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
                 // ROC(t) >= 0 for all t.
                 roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
@@ -218,7 +218,7 @@
 
     private static boolean sameSign(double x, double y) {
         // another way is to test if x*y > 0. This is bad for small x, y.
-        return (x < 0d && y < 0d) || (x > 0d && y > 0d);
+        return (x < 0.0d && y < 0.0d) || (x > 0.0d && y > 0.0d);
     }
 
     // returns the radius of curvature squared at t of this curve
@@ -227,8 +227,8 @@
         // dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency
         final double dx = t * (t * dax + dbx) + cx;
         final double dy = t * (t * day + dby) + cy;
-        final double ddx = 2d * dax * t + dbx;
-        final double ddy = 2d * day * t + dby;
+        final double ddx = 2.0d * dax * t + dbx;
+        final double ddy = 2.0d * day * t + dby;
         final double dx2dy2 = dx*dx + dy*dy;
         final double ddx2ddy2 = ddx*ddx + ddy*ddy;
         final double ddxdxddydy = ddx*dx + ddy*dy;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DDasher.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DDasher.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 import java.util.Arrays;
 
-
 /**
  * The <code>DDasher</code> class takes a series of linear commands
  * (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
@@ -43,12 +42,12 @@
 
     static final int REC_LIMIT = 4;
     static final double ERR = 0.01d;
-    static final double MIN_T_INC = 1d / (1 << REC_LIMIT);
+    static final double MIN_T_INC = 1.0d / (1 << REC_LIMIT);
 
     // More than 24 bits of mantissa means we can no longer accurately
     // measure the number of times cycled through the dash array so we
     // punt and override the phase to just be 0 past that point.
-    static final double MAX_CYCLES = 16000000d;
+    static final double MAX_CYCLES = 16000000.0d;
 
     private DPathConsumer2D out;
     private double[] dash;
@@ -116,21 +115,21 @@
         // Normalize so 0 <= phase < dash[0]
         int sidx = 0;
         dashOn = true;
-        double sum = 0d;
+        double sum = 0.0d;
         for (double d : dash) {
             sum += d;
         }
         double cycles = phase / sum;
-        if (phase < 0d) {
+        if (phase < 0.0d) {
             if (-cycles >= MAX_CYCLES) {
-                phase = 0d;
+                phase = 0.0d;
             } else {
                 int fullcycles = FloatMath.floor_int(-cycles);
                 if ((fullcycles & dash.length & 1) != 0) {
                     dashOn = !dashOn;
                 }
                 phase += fullcycles * sum;
-                while (phase < 0d) {
+                while (phase < 0.0d) {
                     if (--sidx < 0) {
                         sidx = dash.length - 1;
                     }
@@ -140,7 +139,7 @@
             }
         } else if (phase > 0) {
             if (cycles >= MAX_CYCLES) {
-                phase = 0d;
+                phase = 0.0d;
             } else {
                 int fullcycles = FloatMath.floor_int(cycles);
                 if ((fullcycles & dash.length & 1) != 0) {
@@ -177,7 +176,7 @@
     void dispose() {
         if (DO_CLEAN_DIRTY) {
             // Force zero-fill dirty arrays:
-            Arrays.fill(curCurvepts, 0d);
+            Arrays.fill(curCurvepts, 0.0d);
         }
         // Return arrays:
         if (recycleDashes) {
@@ -296,10 +295,10 @@
         double dy = y1 - y0;
 
         double len = dx*dx + dy*dy;
-        if (len == 0d) {
+        if (len == 0.0d) {
             return;
         }
-        len =  Math.sqrt(len);
+        len = Math.sqrt(len);
 
         // The scaling factors needed to get the dx and dy of the
         // transformed dash segments.
@@ -324,7 +323,7 @@
                 phase += len;
                 // TODO: compare double values using epsilon:
                 if (len == leftInThisDashSegment) {
-                    phase = 0d;
+                    phase = 0.0d;
                     idx = (idx + 1) % dashLen;
                     dashOn = !dashOn;
                 }
@@ -334,7 +333,7 @@
             dashdx = _dash[idx] * cx;
             dashdy = _dash[idx] * cy;
 
-            if (phase == 0d) {
+            if (phase == 0.0d) {
                 _curCurvepts[0] = x0 + dashdx;
                 _curCurvepts[1] = y0 + dashdy;
             } else {
@@ -349,7 +348,7 @@
             // Advance to next dash segment
             idx = (idx + 1) % dashLen;
             dashOn = !dashOn;
-            phase = 0d;
+            phase = 0.0d;
         }
     }
 
@@ -366,13 +365,13 @@
 
         // initially the current curve is at curCurvepts[0...type]
         int curCurveoff = 0;
-        double lastSplitT = 0d;
+        double lastSplitT = 0.0d;
         double t;
         double leftInThisDashSegment = dash[idx] - phase;
 
-        while ((t = li.next(leftInThisDashSegment)) < 1d) {
-            if (t != 0d) {
-                DHelpers.subdivideAt((t - lastSplitT) / (1d - lastSplitT),
+        while ((t = li.next(leftInThisDashSegment)) < 1.0d) {
+            if (t != 0.0d) {
+                DHelpers.subdivideAt((t - lastSplitT) / (1.0d - lastSplitT),
                                     curCurvepts, curCurveoff,
                                     curCurvepts, 0,
                                     curCurvepts, type, type);
@@ -383,13 +382,13 @@
             // Advance to next dash segment
             idx = (idx + 1) % dashLen;
             dashOn = !dashOn;
-            phase = 0d;
+            phase = 0.0d;
             leftInThisDashSegment = dash[idx];
         }
         goTo(curCurvepts, curCurveoff+2, type);
         phase += li.lastSegLen();
         if (phase >= dash[idx]) {
-            phase = 0d;
+            phase = 0.0d;
             idx = (idx + 1) % dashLen;
             dashOn = !dashOn;
         }
@@ -444,7 +443,7 @@
 
         // the lengths of the lines of the control polygon. Only its first
         // curveType/2 - 1 elements are valid. This is an optimization. See
-        // next for more detail.
+        // next() for more detail.
         private final double[] curLeafCtrlPolyLengths = new double[3];
 
         LengthIterator() {
@@ -469,13 +468,13 @@
             if (DO_CLEAN_DIRTY) {
                 final int recLimit = recCurveStack.length - 1;
                 for (int i = recLimit; i >= 0; i--) {
-                    Arrays.fill(recCurveStack[i], 0d);
+                    Arrays.fill(recCurveStack[i], 0.0d);
                 }
                 Arrays.fill(sides, Side.LEFT);
-                Arrays.fill(curLeafCtrlPolyLengths, 0d);
-                Arrays.fill(nextRoots, 0d);
-                Arrays.fill(flatLeafCoefCache, 0d);
-                flatLeafCoefCache[2] = -1d;
+                Arrays.fill(curLeafCtrlPolyLengths, 0.0d);
+                Arrays.fill(nextRoots, 0.0d);
+                Arrays.fill(flatLeafCoefCache, 0.0d);
+                flatLeafCoefCache[2] = -1.0d;
             }
         }
 
@@ -484,12 +483,12 @@
             System.arraycopy(pts, 0, recCurveStack[0], 0, 8);
             this.curveType = type;
             this.recLevel = 0;
-            this.lastT = 0d;
-            this.lenAtLastT = 0d;
-            this.nextT = 0d;
-            this.lenAtNextT = 0d;
+            this.lastT = 0.0d;
+            this.lenAtLastT = 0.0d;
+            this.nextT = 0.0d;
+            this.lenAtNextT = 0.0d;
             goLeft(); // initializes nextT and lenAtNextT properly
-            this.lenAtLastSplit = 0d;
+            this.lenAtLastSplit = 0.0d;
             if (recLevel > 0) {
                 this.sides[0] = Side.LEFT;
                 this.done = false;
@@ -498,7 +497,7 @@
                 this.sides[0] = Side.RIGHT;
                 this.done = true;
             }
-            this.lastSegLen = 0d;
+            this.lastSegLen = 0.0d;
         }
 
         // 0 == false, 1 == true, -1 == invalid cached value.
@@ -511,7 +510,7 @@
                 // the test below is equivalent to !within(len1/len2, 1, err).
                 // It is using a multiplication instead of a division, so it
                 // should be a bit faster.
-                if (!DHelpers.within(len1, len2, err*len2)) {
+                if (!DHelpers.within(len1, len2, err * len2)) {
                     cachedHaveLowAcceleration = 0;
                     return false;
                 }
@@ -542,7 +541,7 @@
         // form (see inside next() for what that means). The cache is
         // invalid when it's third element is negative, since in any
         // valid flattened curve, this would be >= 0.
-        private final double[] flatLeafCoefCache = new double[]{0d, 0d, -1d, 0d};
+        private final double[] flatLeafCoefCache = new double[]{0.0d, 0.0d, -1.0d, 0.0d};
 
         // returns the t value where the remaining curve should be split in
         // order for the left subdivided curve to have length len. If len
@@ -552,7 +551,7 @@
             while (lenAtNextT < targetLength) {
                 if (done) {
                     lastSegLen = lenAtNextT - lenAtLastSplit;
-                    return 1d;
+                    return 1.0d;
                 }
                 goToNextLeaf();
             }
@@ -569,19 +568,19 @@
                 // gives us the desired length.
                 final double[] _flatLeafCoefCache = flatLeafCoefCache;
 
-                if (_flatLeafCoefCache[2] < 0d) {
-                    double x = 0d + curLeafCtrlPolyLengths[0],
-                          y = x  + curLeafCtrlPolyLengths[1];
+                if (_flatLeafCoefCache[2] < 0.0d) {
+                    double x =     curLeafCtrlPolyLengths[0],
+                          y = x + curLeafCtrlPolyLengths[1];
                     if (curveType == 8) {
                         double z = y + curLeafCtrlPolyLengths[2];
-                        _flatLeafCoefCache[0] = 3d * (x - y) + z;
-                        _flatLeafCoefCache[1] = 3d * (y - 2d * x);
-                        _flatLeafCoefCache[2] = 3d * x;
+                        _flatLeafCoefCache[0] = 3.0d * (x - y) + z;
+                        _flatLeafCoefCache[1] = 3.0d * (y - 2.0d * x);
+                        _flatLeafCoefCache[2] = 3.0d * x;
                         _flatLeafCoefCache[3] = -z;
                     } else if (curveType == 6) {
-                        _flatLeafCoefCache[0] = 0d;
-                        _flatLeafCoefCache[1] = y - 2d * x;
-                        _flatLeafCoefCache[2] = 2d * x;
+                        _flatLeafCoefCache[0] = 0.0d;
+                        _flatLeafCoefCache[1] = y - 2.0d * x;
+                        _flatLeafCoefCache[2] = 2.0d * x;
                         _flatLeafCoefCache[3] = -y;
                     }
                 }
@@ -593,7 +592,7 @@
                 // we use cubicRootsInAB here, because we want only roots in 0, 1,
                 // and our quadratic root finder doesn't filter, so it's just a
                 // matter of convenience.
-                int n = DHelpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0d, 1d);
+                int n = DHelpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0.0d, 1.0d);
                 if (n == 1 && !Double.isNaN(nextRoots[0])) {
                     t = nextRoots[0];
                 }
@@ -601,8 +600,8 @@
             // t is relative to the current leaf, so we must make it a valid parameter
             // of the original curve.
             t = t * (nextT - lastT) + lastT;
-            if (t >= 1d) {
-                t = 1d;
+            if (t >= 1.0d) {
+                t = 1.0d;
                 done = true;
             }
             // even if done = true, if we're here, that means targetLength
@@ -649,13 +648,13 @@
         // go to the leftmost node from the current node. Return its length.
         private void goLeft() {
             double len = onLeaf();
-            if (len >= 0d) {
+            if (len >= 0.0d) {
                 lastT = nextT;
                 lenAtLastT = lenAtNextT;
                 nextT += (1 << (REC_LIMIT - recLevel)) * MIN_T_INC;
                 lenAtNextT += len;
                 // invalidate caches
-                flatLeafCoefCache[2] = -1d;
+                flatLeafCoefCache[2] = -1.0d;
                 cachedHaveLowAcceleration = -1;
             } else {
                 DHelpers.subdivide(recCurveStack[recLevel], 0,
@@ -671,7 +670,7 @@
         // the length of the leaf if we are on a leaf.
         private double onLeaf() {
             double[] curve = recCurveStack[recLevel];
-            double polyLen = 0d;
+            double polyLen = 0.0d;
 
             double x0 = curve[0], y0 = curve[1];
             for (int i = 2; i < curveType; i += 2) {
@@ -687,9 +686,9 @@
                                                   curve[curveType-2],
                                                   curve[curveType-1]);
             if ((polyLen - lineLen) < ERR || recLevel == REC_LIMIT) {
-                return (polyLen + lineLen) / 2d;
+                return (polyLen + lineLen) / 2.0d;
             }
-            return -1d;
+            return -1.0d;
         }
     }
 
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DHelpers.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DHelpers.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,27 +47,27 @@
     {
         int ret = off;
         double t;
-        if (a != 0d) {
+        if (a != 0.0d) {
             final double dis = b*b - 4*a*c;
-            if (dis > 0d) {
+            if (dis > 0.0d) {
                 final double sqrtDis = Math.sqrt(dis);
                 // depending on the sign of b we use a slightly different
                 // algorithm than the traditional one to find one of the roots
                 // so we can avoid adding numbers of different signs (which
                 // might result in loss of precision).
-                if (b >= 0d) {
-                    zeroes[ret++] = (2d * c) / (-b - sqrtDis);
-                    zeroes[ret++] = (-b - sqrtDis) / (2d * a);
+                if (b >= 0.0d) {
+                    zeroes[ret++] = (2.0d * c) / (-b - sqrtDis);
+                    zeroes[ret++] = (-b - sqrtDis) / (2.0d * a);
                 } else {
-                    zeroes[ret++] = (-b + sqrtDis) / (2d * a);
-                    zeroes[ret++] = (2d * c) / (-b + sqrtDis);
+                    zeroes[ret++] = (-b + sqrtDis) / (2.0d * a);
+                    zeroes[ret++] = (2.0d * c) / (-b + sqrtDis);
                 }
-            } else if (dis == 0d) {
-                t = (-b) / (2d * a);
+            } else if (dis == 0.0d) {
+                t = (-b) / (2.0d * a);
                 zeroes[ret++] = t;
             }
         } else {
-            if (b != 0d) {
+            if (b != 0.0d) {
                 t = (-c) / b;
                 zeroes[ret++] = t;
             }
@@ -80,7 +80,7 @@
                               double[] pts, final int off,
                               final double A, final double B)
     {
-        if (d == 0d) {
+        if (d == 0.0d) {
             int num = quadraticRoots(a, b, c, pts, off);
             return filterOutNotInAB(pts, off, num, A, B) - off;
         }
@@ -104,8 +104,8 @@
         // q = Q/2
         // instead and use those values for simplicity of the code.
         double sq_A = a * a;
-        double p = (1.0/3.0) * ((-1.0/3.0) * sq_A + b);
-        double q = (1.0/2.0) * ((2.0/27.0) * a * sq_A - (1.0/3.0) * a * b + c);
+        double p = (1.0d/3.0d) * ((-1.0d/3.0d) * sq_A + b);
+        double q = (1.0d/2.0d) * ((2.0d/27.0d) * a * sq_A - (1.0d/3.0d) * a * b + c);
 
         // use Cardano's formula
 
@@ -113,14 +113,14 @@
         double D = q * q + cb_p;
 
         int num;
-        if (D < 0.0) {
+        if (D < 0.0d) {
             // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
-            final double phi = (1.0/3.0) * acos(-q / sqrt(-cb_p));
-            final double t = 2.0 * sqrt(-p);
+            final double phi = (1.0d/3.0d) * acos(-q / sqrt(-cb_p));
+            final double t = 2.0d * sqrt(-p);
 
-            pts[ off+0 ] =  ( t * cos(phi));
-            pts[ off+1 ] =  (-t * cos(phi + (PI / 3.0)));
-            pts[ off+2 ] =  (-t * cos(phi - (PI / 3.0)));
+            pts[ off+0 ] = ( t * cos(phi));
+            pts[ off+1 ] = (-t * cos(phi + (PI / 3.0d)));
+            pts[ off+2 ] = (-t * cos(phi - (PI / 3.0d)));
             num = 3;
         } else {
             final double sqrt_D = sqrt(D);
@@ -130,13 +130,13 @@
             pts[ off ] = (u + v);
             num = 1;
 
-            if (within(D, 0.0, 1e-8)) {
-                pts[off+1] = -(pts[off] / 2d);
+            if (within(D, 0.0d, 1e-8d)) {
+                pts[off+1] = -(pts[off] / 2.0d);
                 num = 2;
             }
         }
 
-        final double sub = (1d/3d) * a;
+        final double sub = (1.0d/3.0d) * a;
 
         for (int i = 0; i < num; ++i) {
             pts[ off+i ] -= sub;
@@ -173,7 +173,7 @@
 
     static double polyLineLength(double[] poly, final int off, final int nCoords) {
         assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
-        double acc = 0d;
+        double acc = 0.0d;
         for (int i = off + 2; i < off + nCoords; i += 2) {
             acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
         }
@@ -213,8 +213,8 @@
     }
 
     // Most of these are copied from classes in java.awt.geom because we need
-    // double versions of these functions, and Line2D, CubicCurve2D,
-    // QuadCurve2D don't provide them.
+    // both single and double precision variants of these functions, and Line2D,
+    // CubicCurve2D, QuadCurve2D don't provide them.
     /**
      * Subdivides the cubic curve specified by the coordinates
      * stored in the <code>src</code> array at indices <code>srcoff</code>
@@ -263,18 +263,18 @@
             right[rightoff + 6] = x2;
             right[rightoff + 7] = y2;
         }
-        x1 = (x1 + ctrlx1) / 2d;
-        y1 = (y1 + ctrly1) / 2d;
-        x2 = (x2 + ctrlx2) / 2d;
-        y2 = (y2 + ctrly2) / 2d;
-        double centerx = (ctrlx1 + ctrlx2) / 2d;
-        double centery = (ctrly1 + ctrly2) / 2d;
-        ctrlx1 = (x1 + centerx) / 2d;
-        ctrly1 = (y1 + centery) / 2d;
-        ctrlx2 = (x2 + centerx) / 2d;
-        ctrly2 = (y2 + centery) / 2d;
-        centerx = (ctrlx1 + ctrlx2) / 2d;
-        centery = (ctrly1 + ctrly2) / 2d;
+        x1 = (x1 + ctrlx1) / 2.0d;
+        y1 = (y1 + ctrly1) / 2.0d;
+        x2 = (x2 + ctrlx2) / 2.0d;
+        y2 = (y2 + ctrly2) / 2.0d;
+        double centerx = (ctrlx1 + ctrlx2) / 2.0d;
+        double centery = (ctrly1 + ctrly2) / 2.0d;
+        ctrlx1 = (x1 + centerx) / 2.0d;
+        ctrly1 = (y1 + centery) / 2.0d;
+        ctrlx2 = (x2 + centerx) / 2.0d;
+        ctrly2 = (y2 + centery) / 2.0d;
+        centerx = (ctrlx1 + ctrlx2) / 2.0d;
+        centery = (ctrly1 + ctrly2) / 2.0d;
         if (left != null) {
             left[leftoff + 2] = x1;
             left[leftoff + 3] = y1;
@@ -362,12 +362,12 @@
             right[rightoff + 4] = x2;
             right[rightoff + 5] = y2;
         }
-        x1 = (x1 + ctrlx) / 2d;
-        y1 = (y1 + ctrly) / 2d;
-        x2 = (x2 + ctrlx) / 2d;
-        y2 = (y2 + ctrly) / 2d;
-        ctrlx = (x1 + x2) / 2d;
-        ctrly = (y1 + y2) / 2d;
+        x1 = (x1 + ctrlx) / 2.0d;
+        y1 = (y1 + ctrly) / 2.0d;
+        x2 = (x2 + ctrlx) / 2.0d;
+        y2 = (y2 + ctrly) / 2.0d;
+        ctrlx = (x1 + x2) / 2.0d;
+        ctrly = (y1 + y2) / 2.0d;
         if (left != null) {
             left[leftoff + 2] = x1;
             left[leftoff + 3] = y1;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DMarlinRenderingEngine.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DMarlinRenderingEngine.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
 /**
  * Marlin RendererEngine implementation (derived from Pisces)
  */
-public class DMarlinRenderingEngine implements MarlinConst
+public final class DMarlinRenderingEngine implements MarlinConst
 {
     /**
      * Private constructor to prevent instantiation.
@@ -48,12 +48,12 @@
     static {
         if (PathIterator.WIND_NON_ZERO != DMarlinRenderer.WIND_NON_ZERO ||
             PathIterator.WIND_EVEN_ODD != DMarlinRenderer.WIND_EVEN_ODD ||
-            BasicStroke.JOIN_MITER != Stroker.JOIN_MITER ||
-            BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND ||
-            BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL ||
-            BasicStroke.CAP_BUTT != Stroker.CAP_BUTT ||
-            BasicStroke.CAP_ROUND != Stroker.CAP_ROUND ||
-            BasicStroke.CAP_SQUARE != Stroker.CAP_SQUARE)
+            BasicStroke.JOIN_MITER != DStroker.JOIN_MITER ||
+            BasicStroke.JOIN_ROUND != DStroker.JOIN_ROUND ||
+            BasicStroke.JOIN_BEVEL != DStroker.JOIN_BEVEL ||
+            BasicStroke.CAP_BUTT != DStroker.CAP_BUTT ||
+            BasicStroke.CAP_ROUND != DStroker.CAP_ROUND ||
+            BasicStroke.CAP_SQUARE != DStroker.CAP_SQUARE)
         {
             throw new InternalError("mismatched renderer constants");
         }
@@ -198,8 +198,14 @@
                 + MarlinConst.LOG_UNSAFE_MALLOC);
 
         // quality settings
+        logInfo("prism.marlin.cubic_dec_d2     = "
+                + MarlinProperties.getCubicDecD2());
+        logInfo("prism.marlin.cubic_inc_d1     = "
+                + MarlinProperties.getCubicIncD1());
+        logInfo("prism.marlin.quad_dec_d2      = "
+                + MarlinProperties.getQuadDecD2());
+
         logInfo("Renderer settings:");
-        logInfo("CUB_COUNT_LG = " + DRenderer.CUB_COUNT_LG);
         logInfo("CUB_DEC_BND  = " + DRenderer.CUB_DEC_BND);
         logInfo("CUB_INC_BND  = " + DRenderer.CUB_INC_BND);
         logInfo("QUAD_DEC_BND = " + DRenderer.QUAD_DEC_BND);
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DRenderer.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DRenderer.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,23 +35,14 @@
     private static final int ALL_BUT_LSB = 0xFFFFFFFE;
     private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1
 
-    private static final double POWER_2_TO_32 = 0x1.0p32;
+    private static final double POWER_2_TO_32 = 0x1.0p32d;
 
     // use double to make tosubpix methods faster (no int to double conversion)
-    static final double F_SUBPIXEL_POSITIONS_X
-        =  SUBPIXEL_POSITIONS_X;
-    static final double F_SUBPIXEL_POSITIONS_Y
-        =  SUBPIXEL_POSITIONS_Y;
+    static final double SUBPIXEL_SCALE_X = SUBPIXEL_POSITIONS_X;
+    static final double SUBPIXEL_SCALE_Y = SUBPIXEL_POSITIONS_Y;
     static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1;
     static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1;
 
-    // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
-    static final int INITIAL_BUCKET_ARRAY
-        = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y;
-
-    // crossing capacity = edges count / 4 ~ 1024
-    static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
-
     // common to all types of input path segments.
     // OFFSET as bytes
     // only integer values:
@@ -68,19 +59,20 @@
     // curve break into lines
     // cubic error in subpixels to decrement step
     private static final double CUB_DEC_ERR_SUBPIX
-        = 1d * (NORM_SUBPIXELS / 8d); // 1 pixel
+        = MarlinProperties.getCubicDecD2() * (NORM_SUBPIXELS / 8.0d); // 1 pixel
     // cubic error in subpixels to increment step
     private static final double CUB_INC_ERR_SUBPIX
-        = 0.4d * (NORM_SUBPIXELS / 8d); // 0.4 pixel
+        = MarlinProperties.getCubicIncD1() * (NORM_SUBPIXELS / 8.0d); // 0.4 pixel
 
+    // TestNonAARasterization (JDK-8170879): cubics
     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
 
     // cubic bind length to decrement step
     public static final double CUB_DEC_BND
-        = 8d * CUB_DEC_ERR_SUBPIX;
+        = 8.0d * CUB_DEC_ERR_SUBPIX;
     // cubic bind length to increment step
     public static final double CUB_INC_BND
-        = 8d * CUB_INC_ERR_SUBPIX;
+        = 8.0d * CUB_INC_ERR_SUBPIX;
 
     // cubic countlg
     public static final int CUB_COUNT_LG = 2;
@@ -91,22 +83,23 @@
     // cubic count^3 = 8^countlg
     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
     // cubic dt = 1 / count
-    private static final double CUB_INV_COUNT = 1d / CUB_COUNT;
+    private static final double CUB_INV_COUNT = 1.0d / CUB_COUNT;
     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
-    private static final double CUB_INV_COUNT_2 = 1d / CUB_COUNT_2;
+    private static final double CUB_INV_COUNT_2 = 1.0d / CUB_COUNT_2;
     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
-    private static final double CUB_INV_COUNT_3 = 1d / CUB_COUNT_3;
+    private static final double CUB_INV_COUNT_3 = 1.0d / CUB_COUNT_3;
 
     // quad break into lines
     // quadratic error in subpixels
     private static final double QUAD_DEC_ERR_SUBPIX
-        = 0.5d * (NORM_SUBPIXELS / 8d); // 0.5 pixel
+        = MarlinProperties.getQuadDecD2() * (NORM_SUBPIXELS / 8.0d); // 0.5 pixel
 
+    // TestNonAARasterization (JDK-8170879): quads
     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
 
     // quadratic bind length to decrement step
     public static final double QUAD_DEC_BND
-        = 8d * QUAD_DEC_ERR_SUBPIX;
+        = 8.0d * QUAD_DEC_ERR_SUBPIX;
 
 //////////////////////////////////////////////////////////////////////////////
 //  SCAN LINE
@@ -177,7 +170,7 @@
 
         while (maxDD >= _DEC_BND) {
             // divide step by half:
-            maxDD /= 4d; // error divided by 2^2 = 4
+            maxDD /= 4.0d; // error divided by 2^2 = 4
 
             count <<= 1;
             if (DO_STATS) {
@@ -187,7 +180,7 @@
 
         int nL = 0; // line count
         if (count > 1) {
-            final double icount = 1d / count; // dt
+            final double icount = 1.0d / count; // dt
             final double icount2 = icount * icount; // dt^2
 
             final double ddx = c.dbx * icount2;
@@ -234,8 +227,8 @@
         // the dx and dy refer to forward differencing variables, not the last
         // coefficients of the "points" polynomial
         double dddx, dddy, ddx, ddy, dx, dy;
-        dddx = 2d * c.dax * icount3;
-        dddy = 2d * c.day * icount3;
+        dddx = 2.0d * c.dax * icount3;
+        dddy = 2.0d * c.day * icount3;
         ddx = dddx + c.dbx * icount2;
         ddy = dddy + c.dby * icount2;
         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
@@ -251,12 +244,12 @@
         while (count > 0) {
             // divide step by half:
             while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) {
-                dddx /= 8d;
-                dddy /= 8d;
-                ddx = ddx/4d - dddx;
-                ddy = ddy/4d - dddy;
-                dx = (dx - ddx) / 2d;
-                dy = (dy - ddy) / 2d;
+                dddx /= 8.0d;
+                dddy /= 8.0d;
+                ddx = ddx / 4.0d - dddx;
+                ddy = ddy / 4.0d - dddy;
+                dx = (dx - ddx) / 2.0d;
+                dy = (dy - ddy) / 2.0d;
 
                 count <<= 1;
                 if (DO_STATS) {
@@ -265,19 +258,16 @@
             }
 
             // double step:
-            // TODO: why use first derivative dX|Y instead of second ddX|Y ?
-            // both scale changes should use speed or acceleration to have the same metric.
-
             // can only do this on even "count" values, because we must divide count by 2
             while (count % 2 == 0
                    && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
             {
-                dx = 2d * dx + ddx;
-                dy = 2d * dy + ddy;
-                ddx = 4d * (ddx + dddx);
-                ddy = 4d * (ddy + dddy);
-                dddx *= 8d;
-                dddy *= 8d;
+                dx = 2.0d * dx + ddx;
+                dy = 2.0d * dy + ddy;
+                ddx = 4.0d * (ddx + dddx);
+                ddy = 4.0d * (ddy + dddy);
+                dddx *= 8.0d;
+                dddy *= 8.0d;
 
                 count >>= 1;
                 if (DO_STATS) {
@@ -349,7 +339,7 @@
             return;
         }
 
-        // edge min/max X/Y are in subpixel space (inclusive) within bounds:
+        // edge min/max X/Y are in subpixel space (half-open interval):
         // note: Use integer crossings to ensure consistent range within
         // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0)
         if (firstCrossing < edgeMinY) {
@@ -359,12 +349,9 @@
             edgeMaxY = lastCrossing;
         }
 
-        // Use double-precision for improved accuracy:
-        final double x1d   = x1;
-        final double y1d   = y1;
-        final double slope = (x1d - x2) / (y1d - y2);
+        final double slope = (x1 - x2) / (y1 - y2);
 
-        if (slope >= 0.0) { // <==> x1 < x2
+        if (slope >= 0.0d) { // <==> x1 < x2
             if (x1 < edgeMinX) {
                 edgeMinX = x1;
             }
@@ -429,7 +416,7 @@
         //                 = fixed_floor(x1_fixed + 2^31 - 1)
         //                 = fixed_floor(x1_fixed + 0x7FFFFFFF)
         // and error       = fixed_fract(x1_fixed + 0x7FFFFFFF)
-        final double x1_intercept = x1d + (firstCrossing - y1d) * slope;
+        final double x1_intercept = x1 + (firstCrossing - y1) * slope;
 
         // inlined scalb(x1_intercept, 32):
         final long x1_fixed_biased = ((long) (POWER_2_TO_32 * x1_intercept))
@@ -462,7 +449,7 @@
         // pointer from bucket
         _unsafe.putInt(addr, _edgeBuckets[bucketIdx]);
         addr += SIZE_INT;
-        // y max (inclusive)
+        // y max (exclusive)
         _unsafe.putInt(addr,  lastCrossing);
 
         // Update buckets:
@@ -517,32 +504,30 @@
 
     DRenderer(final DRendererContext rdrCtx) {
         this.rdrCtx = rdrCtx;
-
-        this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
-
         this.curve = rdrCtx.curve;
 
-        edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
-        edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+        this.edges = rdrCtx.rdrMem.edges;
+
+        edgeBuckets_ref      = rdrCtx.rdrMem.edgeBuckets_ref;
+        edgeBucketCounts_ref = rdrCtx.rdrMem.edgeBucketCounts_ref;
 
         edgeBuckets      = edgeBuckets_ref.initial;
         edgeBucketCounts = edgeBucketCounts_ref.initial;
 
-        // 2048 (pixelsize) pixel large
-        alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
+        alphaLine_ref = rdrCtx.rdrMem.alphaLine_ref;
         alphaLine     = alphaLine_ref.initial;
 
-        crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+        crossings_ref     = rdrCtx.rdrMem.crossings_ref;
+        aux_crossings_ref = rdrCtx.rdrMem.aux_crossings_ref;
+        edgePtrs_ref      = rdrCtx.rdrMem.edgePtrs_ref;
+        aux_edgePtrs_ref  = rdrCtx.rdrMem.aux_edgePtrs_ref;
 
         crossings     = crossings_ref.initial;
         aux_crossings = aux_crossings_ref.initial;
         edgePtrs      = edgePtrs_ref.initial;
         aux_edgePtrs  = aux_edgePtrs_ref.initial;
 
-        blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
+        blkFlags_ref = rdrCtx.rdrMem.blkFlags_ref;
         blkFlags     = blkFlags_ref.initial;
     }
 
@@ -654,12 +639,12 @@
     }
 
     private static double tosubpixx(final double pix_x) {
-        return F_SUBPIXEL_POSITIONS_X * pix_x;
+        return SUBPIXEL_SCALE_X * pix_x;
     }
 
     private static double tosubpixy(final double pix_y) {
         // shift y by -0.5 for fast ceil(y - 0.5):
-        return F_SUBPIXEL_POSITIONS_Y * pix_y - 0.5d;
+        return SUBPIXEL_SCALE_Y * pix_y - 0.5d;
     }
 
     @Override
@@ -1181,8 +1166,8 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
                                     }
                                 } else {
                                     tmp = (x0 & _SUBPIXEL_MASK_X);
@@ -1201,10 +1186,9 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x         >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1)    >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[ pix_xmax      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_xmax + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
+                                        _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1;
                                     }
                                 }
                             }
@@ -1252,8 +1236,8 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
                                     }
                                 } else {
                                     tmp = (x0 & _SUBPIXEL_MASK_X);
@@ -1272,10 +1256,9 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x         >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1)    >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[ pix_xmax      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_xmax + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
+                                        _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1;
                                     }
                                 }
                             }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DRendererContext.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DRendererContext.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,8 @@
     final DCurve curve = new DCurve();
     // MarlinRenderingEngine.TransformingPathConsumer2D
     public final DTransformingPathConsumer2D transformerPC2D;
+    // shared memory between renderer instances:
+    final DRendererSharedMemory rdrMem;
     public final DRenderer renderer;
     private DRendererNoAA rendererNoAA = null;
     public final DStroker stroker;
@@ -74,8 +76,8 @@
     public MaskMarlinAlphaConsumer consumer = null;
 
     // Array caches:
-    /* clean int[] cache (zero-filled) = 5 refs */
-    private final IntArrayCache cleanIntCache = new IntArrayCache(true, 5);
+    /* clean int[] cache (zero-filled) = 4 refs */
+    private final IntArrayCache cleanIntCache = new IntArrayCache(true, 4);
     /* dirty int[] cache = 4 refs */
     private final IntArrayCache dirtyIntCache = new IntArrayCache(false, 4);
     /* dirty double[] cache = 3 refs */
@@ -111,6 +113,9 @@
         // MarlinRenderingEngine.TransformingPathConsumer2D
         transformerPC2D = new DTransformingPathConsumer2D();
 
+        // Renderer shared memory:
+        rdrMem = new DRendererSharedMemory(this);
+
         // Renderer:
         renderer = new DRenderer(this);
 
@@ -174,4 +179,48 @@
     ByteArrayCache.Reference newDirtyByteArrayRef(final int initialSize) {
         return dirtyByteCache.createRef(initialSize);
     }
+
+    static final class DRendererSharedMemory {
+
+        // edges [ints] stored in off-heap memory
+        final OffHeapArray edges;
+
+        // edgeBuckets ref (clean)
+        final IntArrayCache.Reference edgeBuckets_ref;
+        // edgeBucketCounts ref (clean)
+        final IntArrayCache.Reference edgeBucketCounts_ref;
+
+        // alphaLine ref (clean)
+        final IntArrayCache.Reference alphaLine_ref;
+
+        // crossings ref (dirty)
+        final IntArrayCache.Reference crossings_ref;
+        // edgePtrs ref (dirty)
+        final IntArrayCache.Reference edgePtrs_ref;
+        // merge sort initial arrays
+        // aux_crossings ref (dirty)
+        final IntArrayCache.Reference aux_crossings_ref;
+        // aux_edgePtrs ref (dirty)
+        final IntArrayCache.Reference aux_edgePtrs_ref;
+
+        // blkFlags ref (clean)
+        final IntArrayCache.Reference blkFlags_ref;
+
+        DRendererSharedMemory(final DRendererContext rdrCtx) {
+            edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
+
+            edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+            edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+
+            // 2048 (pixelsize) pixel large
+            alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
+
+            crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+            aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+            edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+            aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+
+            blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
+        }
+    }
 }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DRendererNoAA.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DRendererNoAA.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,13 +35,7 @@
     private static final int ALL_BUT_LSB = 0xFFFFFFFE;
     private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1
 
-    private static final double POWER_2_TO_32 = 0x1.0p32;
-
-    // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
-    static final int INITIAL_BUCKET_ARRAY = INITIAL_PIXEL_DIM;
-
-    // crossing capacity = edges count / 4 ~ 1024
-    static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
+    private static final double POWER_2_TO_32 = 0x1.0p32d;
 
     // common to all types of input path segments.
     // OFFSET as bytes
@@ -59,19 +53,20 @@
     // curve break into lines
     // cubic error in subpixels to decrement step
     private static final double CUB_DEC_ERR_SUBPIX
-        = 1d * (1d / 8d); // 1 pixel
+        = MarlinProperties.getCubicDecD2() * (1.0d / 8.0d); // 1 pixel
     // cubic error in subpixels to increment step
     private static final double CUB_INC_ERR_SUBPIX
-        = 0.4d * (1d / 8d); // 0.4 pixel
+        = MarlinProperties.getCubicIncD1() * (1.0d / 8.0d); // 0.4 pixel
 
+    // TestNonAARasterization (JDK-8170879): cubics
     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
 
     // cubic bind length to decrement step
     public static final double CUB_DEC_BND
-        = 8d * CUB_DEC_ERR_SUBPIX;
+        = 8.0d * CUB_DEC_ERR_SUBPIX;
     // cubic bind length to increment step
     public static final double CUB_INC_BND
-        = 8d * CUB_INC_ERR_SUBPIX;
+        = 8.0d * CUB_INC_ERR_SUBPIX;
 
     // cubic countlg
     public static final int CUB_COUNT_LG = 2;
@@ -82,22 +77,23 @@
     // cubic count^3 = 8^countlg
     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
     // cubic dt = 1 / count
-    private static final double CUB_INV_COUNT = 1d / CUB_COUNT;
+    private static final double CUB_INV_COUNT = 1.0d / CUB_COUNT;
     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
-    private static final double CUB_INV_COUNT_2 = 1d / CUB_COUNT_2;
+    private static final double CUB_INV_COUNT_2 = 1.0d / CUB_COUNT_2;
     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
-    private static final double CUB_INV_COUNT_3 = 1d / CUB_COUNT_3;
+    private static final double CUB_INV_COUNT_3 = 1.0d / CUB_COUNT_3;
 
     // quad break into lines
     // quadratic error in subpixels
     private static final double QUAD_DEC_ERR_SUBPIX
-        = 0.5d * (1d / 8d); // 0.5 pixel
+        = MarlinProperties.getQuadDecD2() * (1.0d / 8.0d); // 0.5 pixel
 
+    // TestNonAARasterization (JDK-8170879): quads
     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
 
     // quadratic bind length to decrement step
     public static final double QUAD_DEC_BND
-        = 8d * QUAD_DEC_ERR_SUBPIX;
+        = 8.0d * QUAD_DEC_ERR_SUBPIX;
 
 //////////////////////////////////////////////////////////////////////////////
 //  SCAN LINE
@@ -168,7 +164,7 @@
 
         while (maxDD >= _DEC_BND) {
             // divide step by half:
-            maxDD /= 4d; // error divided by 2^2 = 4
+            maxDD /= 4.0d; // error divided by 2^2 = 4
 
             count <<= 1;
             if (DO_STATS) {
@@ -178,7 +174,7 @@
 
         int nL = 0; // line count
         if (count > 1) {
-            final double icount = 1d / count; // dt
+            final double icount = 1.0d / count; // dt
             final double icount2 = icount * icount; // dt^2
 
             final double ddx = c.dbx * icount2;
@@ -225,8 +221,8 @@
         // the dx and dy refer to forward differencing variables, not the last
         // coefficients of the "points" polynomial
         double dddx, dddy, ddx, ddy, dx, dy;
-        dddx = 2d * c.dax * icount3;
-        dddy = 2d * c.day * icount3;
+        dddx = 2.0d * c.dax * icount3;
+        dddy = 2.0d * c.day * icount3;
         ddx = dddx + c.dbx * icount2;
         ddy = dddy + c.dby * icount2;
         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
@@ -242,12 +238,12 @@
         while (count > 0) {
             // divide step by half:
             while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) {
-                dddx /= 8d;
-                dddy /= 8d;
-                ddx = ddx/4d - dddx;
-                ddy = ddy/4d - dddy;
-                dx = (dx - ddx) / 2d;
-                dy = (dy - ddy) / 2d;
+                dddx /= 8.0d;
+                dddy /= 8.0d;
+                ddx = ddx / 4.0d - dddx;
+                ddy = ddy / 4.0d - dddy;
+                dx = (dx - ddx) / 2.0d;
+                dy = (dy - ddy) / 2.0d;
 
                 count <<= 1;
                 if (DO_STATS) {
@@ -256,19 +252,16 @@
             }
 
             // double step:
-            // TODO: why use first derivative dX|Y instead of second ddX|Y ?
-            // both scale changes should use speed or acceleration to have the same metric.
-
             // can only do this on even "count" values, because we must divide count by 2
             while (count % 2 == 0
                    && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
             {
-                dx = 2d * dx + ddx;
-                dy = 2d * dy + ddy;
-                ddx = 4d * (ddx + dddx);
-                ddy = 4d * (ddy + dddy);
-                dddx *= 8d;
-                dddy *= 8d;
+                dx = 2.0d * dx + ddx;
+                dy = 2.0d * dy + ddy;
+                ddx = 4.0d * (ddx + dddx);
+                ddy = 4.0d * (ddy + dddy);
+                dddx *= 8.0d;
+                dddy *= 8.0d;
 
                 count >>= 1;
                 if (DO_STATS) {
@@ -340,7 +333,7 @@
             return;
         }
 
-        // edge min/max X/Y are in subpixel space (inclusive) within bounds:
+        // edge min/max X/Y are in subpixel space (half-open interval):
         // note: Use integer crossings to ensure consistent range within
         // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0)
         if (firstCrossing < edgeMinY) {
@@ -350,12 +343,9 @@
             edgeMaxY = lastCrossing;
         }
 
-        // Use double-precision for improved accuracy:
-        final double x1d   = x1;
-        final double y1d   = y1;
-        final double slope = (x1d - x2) / (y1d - y2);
+        final double slope = (x1 - x2) / (y1 - y2);
 
-        if (slope >= 0.0) { // <==> x1 < x2
+        if (slope >= 0.0d) { // <==> x1 < x2
             if (x1 < edgeMinX) {
                 edgeMinX = x1;
             }
@@ -420,7 +410,7 @@
         //                 = fixed_floor(x1_fixed + 2^31 - 1)
         //                 = fixed_floor(x1_fixed + 0x7FFFFFFF)
         // and error       = fixed_fract(x1_fixed + 0x7FFFFFFF)
-        final double x1_intercept = x1d + (firstCrossing - y1d) * slope;
+        final double x1_intercept = x1 + (firstCrossing - y1) * slope;
 
         // inlined scalb(x1_intercept, 32):
         final long x1_fixed_biased = ((long) (POWER_2_TO_32 * x1_intercept))
@@ -453,7 +443,7 @@
         // pointer from bucket
         _unsafe.putInt(addr, _edgeBuckets[bucketIdx]);
         addr += SIZE_INT;
-        // y max (inclusive)
+        // y max (exclusive)
         _unsafe.putInt(addr,  lastCrossing);
 
         // Update buckets:
@@ -508,32 +498,30 @@
 
     DRendererNoAA(final DRendererContext rdrCtx) {
         this.rdrCtx = rdrCtx;
-
-        this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
-
         this.curve = rdrCtx.curve;
 
-        edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
-        edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+        this.edges = rdrCtx.rdrMem.edges;
+
+        edgeBuckets_ref      = rdrCtx.rdrMem.edgeBuckets_ref;
+        edgeBucketCounts_ref = rdrCtx.rdrMem.edgeBucketCounts_ref;
 
         edgeBuckets      = edgeBuckets_ref.initial;
         edgeBucketCounts = edgeBucketCounts_ref.initial;
 
-        // 2048 (pixelsize) pixel large
-        alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
+        alphaLine_ref = rdrCtx.rdrMem.alphaLine_ref;
         alphaLine     = alphaLine_ref.initial;
 
-        crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+        crossings_ref     = rdrCtx.rdrMem.crossings_ref;
+        aux_crossings_ref = rdrCtx.rdrMem.aux_crossings_ref;
+        edgePtrs_ref      = rdrCtx.rdrMem.edgePtrs_ref;
+        aux_edgePtrs_ref  = rdrCtx.rdrMem.aux_edgePtrs_ref;
 
         crossings     = crossings_ref.initial;
         aux_crossings = aux_crossings_ref.initial;
         edgePtrs      = edgePtrs_ref.initial;
         aux_edgePtrs  = aux_edgePtrs_ref.initial;
 
-        blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
+        blkFlags_ref = rdrCtx.rdrMem.blkFlags_ref;
         blkFlags     = blkFlags_ref.initial;
     }
 
@@ -1158,6 +1146,7 @@
 
                                 if (useBlkFlags) {
                                     // flag used blocks:
+                                    // note: block processing handles extra pixel:
                                     _blkFlags[x0 >> _BLK_SIZE_LG] = 1;
                                     _blkFlags[x1 >> _BLK_SIZE_LG] = 1;
                                 }
@@ -1200,6 +1189,7 @@
 
                                 if (useBlkFlags) {
                                     // flag used blocks:
+                                    // note: block processing handles extra pixel:
                                     _blkFlags[x0 >> _BLK_SIZE_LG] = 1;
                                     _blkFlags[x1 >> _BLK_SIZE_LG] = 1;
                                 }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DStroker.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DStroker.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,6 @@
 
 import java.util.Arrays;
 
-
-
 // TODO: some of the arithmetic here is too verbose and prone to hard to
 // debug typos. We should consider making a small Point/Vector class that
 // has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such
@@ -71,7 +69,7 @@
     // pisces used to use fixed point arithmetic with 16 decimal digits. I
     // didn't want to change the values of the constant below when I converted
     // it to floating point, so that's why the divisions by 2^16 are there.
-    private static final double ROUND_JOIN_THRESHOLD = 1000/65536d;
+    private static final double ROUND_JOIN_THRESHOLD = 1000.0d/65536.0d;
 
     private static final double C = 0.5522847498307933d;
 
@@ -109,7 +107,7 @@
 
     // This is where the curve to be processed is put. We give it
     // enough room to store all curves.
-    private final double[] middle = new double[MAX_N_CURVES * 8];
+    private final double[] middle = new double[MAX_N_CURVES * 6 + 2];
     private final double[] lp = new double[8];
     private final double[] rp = new double[8];
     private final double[] subdivTs = new double[MAX_N_CURVES - 1];
@@ -153,8 +151,8 @@
     {
         this.out = pc2d;
 
-        this.lineWidth2 = lineWidth / 2d;
-        this.invHalfLineWidth2Sq = 1d / (2d * lineWidth2 * lineWidth2);
+        this.lineWidth2 = lineWidth / 2.0d;
+        this.invHalfLineWidth2Sq = 1.0d / (2.0d * lineWidth2 * lineWidth2);
         this.capStyle = capStyle;
         this.joinStyle = joinStyle;
 
@@ -177,14 +175,14 @@
 
         if (DO_CLEAN_DIRTY) {
             // Force zero-fill dirty arrays:
-            Arrays.fill(offset0, 0d);
-            Arrays.fill(offset1, 0d);
-            Arrays.fill(offset2, 0d);
-            Arrays.fill(miter, 0d);
-            Arrays.fill(middle, 0d);
-            Arrays.fill(lp, 0d);
-            Arrays.fill(rp, 0d);
-            Arrays.fill(subdivTs, 0d);
+            Arrays.fill(offset0, 0.0d);
+            Arrays.fill(offset1, 0.0d);
+            Arrays.fill(offset2, 0.0d);
+            Arrays.fill(miter, 0.0d);
+            Arrays.fill(middle, 0.0d);
+            Arrays.fill(lp, 0.0d);
+            Arrays.fill(rp, 0.0d);
+            Arrays.fill(subdivTs, 0.0d);
         }
     }
 
@@ -192,11 +190,11 @@
                                       final double w, final double[] m)
     {
         double len = lx*lx + ly*ly;
-        if (len == 0d) {
-            m[0] = 0d;
-            m[1] = 0d;
+        if (len == 0.0d) {
+            m[0] = 0.0d;
+            m[1] = 0.0d;
         } else {
-            len =  Math.sqrt(len);
+            len = Math.sqrt(len);
             m[0] =  (ly * w) / len;
             m[1] = -(lx * w) / len;
         }
@@ -221,7 +219,7 @@
                                boolean rev,
                                double threshold)
     {
-        if ((omx == 0d && omy == 0d) || (mx == 0d && my == 0d)) {
+        if ((omx == 0.0d && omy == 0.0d) || (mx == 0.0d && my == 0.0d)) {
             return;
         }
 
@@ -253,7 +251,7 @@
         // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only
         // need 1 curve to approximate the circle section that joins omx,omy
         // and mx,my.
-        final int numCurves = (cosext >= 0d) ? 1 : 2;
+        final int numCurves = (cosext >= 0.0d) ? 1 : 2;
 
         switch (numCurves) {
         case 1:
@@ -275,7 +273,7 @@
             // this normal's length is at least 0.5 and at most sqrt(2)/2 (because
             // we know the angle of the arc is > 90 degrees).
             double nx = my - omy, ny = omx - mx;
-            double nlen =  Math.sqrt(nx*nx + ny*ny);
+            double nlen = Math.sqrt(nx*nx + ny*ny);
             double scale = lineWidth2/nlen;
             double mmx = nx * scale, mmy = ny * scale;
 
@@ -313,8 +311,8 @@
         // define the bezier curve we're computing.
         // It is computed using the constraints that P1-P0 and P3-P2 are parallel
         // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|.
-        double cv =  ((4.0 / 3.0) * Math.sqrt(0.5 - cosext2) /
-                            (1.0 + Math.sqrt(cosext2 + 0.5)));
+        double cv = ((4.0d / 3.0d) * Math.sqrt(0.5d - cosext2) /
+                            (1.0d + Math.sqrt(cosext2 + 0.5d)));
         // if clockwise, we need to negate cv.
         if (rev) { // rev is equivalent to isCW(omx, omy, mx, my)
             cv = -cv;
@@ -344,7 +342,7 @@
     }
 
     // Return the intersection point of the lines (x0, y0) -> (x1, y1)
-    // and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
+    // and (x0p, y0p) -> (x1p, y1p) in m[off] and m[off+1]
     private static void computeMiter(final double x0, final double y0,
                                      final double x1, final double y1,
                                      final double x0p, final double y0p,
@@ -373,8 +371,8 @@
     }
 
     // Return the intersection point of the lines (x0, y0) -> (x1, y1)
-    // and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
-    private static void safecomputeMiter(final double x0, final double y0,
+    // and (x0p, y0p) -> (x1p, y1p) in m[off] and m[off+1]
+    private static void safeComputeMiter(final double x0, final double y0,
                                          final double x1, final double y1,
                                          final double x0p, final double y0p,
                                          final double x1p, final double y1p,
@@ -395,9 +393,9 @@
         // (mx == omx && my == omy) will be true, and drawMiter will return
         // immediately).
         double den = x10*y10p - x10p*y10;
-        if (den == 0d) {
-            m[off++] = (x0 + x0p) / 2d;
-            m[off] = (y0 + y0p) / 2d;
+        if (den == 0.0d) {
+            m[off++] = (x0 + x0p) / 2.0d;
+            m[off]   = (y0 + y0p) / 2.0d;
             return;
         }
         double t = x10p*(y0-y0p) - y10p*(x0-x0p);
@@ -413,8 +411,8 @@
                            boolean rev)
     {
         if ((mx == omx && my == omy) ||
-            (pdx == 0d && pdy == 0d) ||
-            (dx == 0d && dy == 0d))
+            (pdx == 0.0d && pdy == 0.0d) ||
+            (dx == 0.0d && dy == 0.0d))
         {
             return;
         }
@@ -451,8 +449,8 @@
         }
         this.sx0 = this.cx0 = x0;
         this.sy0 = this.cy0 = y0;
-        this.cdx = this.sdx = 1d;
-        this.cdy = this.sdy = 0d;
+        this.cdx = this.sdx = 1.0d;
+        this.cdy = this.sdy = 0.0d;
         this.prev = MOVE_TO;
     }
 
@@ -460,8 +458,8 @@
     public void lineTo(double x1, double y1) {
         double dx = x1 - cx0;
         double dy = y1 - cy0;
-        if (dx == 0d && dy == 0d) {
-            dx = 1d;
+        if (dx == 0.0d && dy == 0.0d) {
+            dx = 1.0d;
         }
         computeOffset(dx, dy, lineWidth2, offset0);
         final double mx = offset0[0];
@@ -491,10 +489,10 @@
                 return;
             }
             emitMoveTo(cx0, cy0 - lineWidth2);
-            this.cmx = this.smx = 0d;
+            this.cmx = this.smx = 0.0d;
             this.cmy = this.smy = -lineWidth2;
-            this.cdx = this.sdx = 1d;
-            this.cdy = this.sdy = 0d;
+            this.cdx = this.sdx = 1.0d;
+            this.cdy = this.sdy = 0.0d;
             finish();
             return;
         }
@@ -677,7 +675,7 @@
     {
         // if p1=p2 or p3=p4 it means that the derivative at the endpoint
         // vanishes, which creates problems with computeOffset. Usually
-        // this happens when this stroker object is trying to winden
+        // this happens when this stroker object is trying to widen
         // a curve with a cusp. What happens is that curveTo splits
         // the input curve at the cusp, and passes it to this function.
         // because of inaccuracies in the splitting, we consider points
@@ -694,8 +692,8 @@
 
         // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
         // in which case ignore if p1 == p2
-        final boolean p1eqp2 = within(x1,y1,x2,y2, 6d * Math.ulp(y2));
-        final boolean p3eqp4 = within(x3,y3,x4,y4, 6d * Math.ulp(y4));
+        final boolean p1eqp2 = within(x1, y1, x2, y2, 6.0d * Math.ulp(y2));
+        final boolean p3eqp4 = within(x3, y3, x4, y4, 6.0d * Math.ulp(y4));
         if (p1eqp2 && p3eqp4) {
             getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
             return 4;
@@ -711,7 +709,7 @@
         double dotsq = (dx1 * dx4 + dy1 * dy4);
         dotsq *= dotsq;
         double l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
-        if (DHelpers.within(dotsq, l1sq * l4sq, 4d * Math.ulp(dotsq))) {
+        if (DHelpers.within(dotsq, l1sq * l4sq, 4.0d * Math.ulp(dotsq))) {
             getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
             return 4;
         }
@@ -763,8 +761,8 @@
 //      getting the inverse of the matrix above. Then we use [c1,c2] to compute
 //      p2p and p3p.
 
-        double x = (x1 + 3d * (x2 + x3) + x4) / 8d;
-        double y = (y1 + 3d * (y2 + y3) + y4) / 8d;
+        double x = (x1 + 3.0d * (x2 + x3) + x4) / 8.0d;
+        double y = (y1 + 3.0d * (y2 + y3) + y4) / 8.0d;
         // (dxm,dym) is some tangent of B at t=0.5. This means it's equal to
         // c*B'(0.5) for some constant c.
         double dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
@@ -782,10 +780,10 @@
         double x4p = x4 + offset2[0]; // end
         double y4p = y4 + offset2[1]; // point
 
-        double invdet43 = 4d / (3d * (dx1 * dy4 - dy1 * dx4));
+        double invdet43 = 4.0d / (3.0d * (dx1 * dy4 - dy1 * dx4));
 
-        double two_pi_m_p1_m_p4x = 2d * xi - x1p - x4p;
-        double two_pi_m_p1_m_p4y = 2d * yi - y1p - y4p;
+        double two_pi_m_p1_m_p4x = 2.0d * xi - x1p - x4p;
+        double two_pi_m_p1_m_p4y = 2.0d * yi - y1p - y4p;
         double c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
         double c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
 
@@ -801,11 +799,11 @@
         leftOff[6] = x4p; leftOff[7] = y4p;
 
         x1p = x1 - offset0[0]; y1p = y1 - offset0[1];
-        xi = xi - 2d * offset1[0]; yi = yi - 2d * offset1[1];
+        xi = xi - 2.0d * offset1[0]; yi = yi - 2.0d * offset1[1];
         x4p = x4 - offset2[0]; y4p = y4 - offset2[1];
 
-        two_pi_m_p1_m_p4x = 2d * xi - x1p - x4p;
-        two_pi_m_p1_m_p4y = 2d * yi - y1p - y4p;
+        two_pi_m_p1_m_p4x = 2.0d * xi - x1p - x4p;
+        two_pi_m_p1_m_p4y = 2.0d * yi - y1p - y4p;
         c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
         c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
 
@@ -838,7 +836,7 @@
 
         // if p1=p2 or p3=p4 it means that the derivative at the endpoint
         // vanishes, which creates problems with computeOffset. Usually
-        // this happens when this stroker object is trying to winden
+        // this happens when this stroker object is trying to widen
         // a curve with a cusp. What happens is that curveTo splits
         // the input curve at the cusp, and passes it to this function.
         // because of inaccuracies in the splitting, we consider points
@@ -846,8 +844,8 @@
 
         // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
         // in which case ignore.
-        final boolean p1eqp2 = within(x1,y1,x2,y2, 6d * Math.ulp(y2));
-        final boolean p2eqp3 = within(x2,y2,x3,y3, 6d * Math.ulp(y3));
+        final boolean p1eqp2 = within(x1, y1, x2, y2, 6.0d * Math.ulp(y2));
+        final boolean p2eqp3 = within(x2, y2, x3, y3, 6.0d * Math.ulp(y3));
         if (p1eqp2 || p2eqp3) {
             getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
             return 4;
@@ -857,7 +855,7 @@
         double dotsq = (dx1 * dx3 + dy1 * dy3);
         dotsq *= dotsq;
         double l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3;
-        if (DHelpers.within(dotsq, l1sq * l3sq, 4d * Math.ulp(dotsq))) {
+        if (DHelpers.within(dotsq, l1sq * l3sq, 4.0d * Math.ulp(dotsq))) {
             getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
             return 4;
         }
@@ -872,124 +870,18 @@
         double y1p = y1 + offset0[1]; // point
         double x3p = x3 + offset1[0]; // end
         double y3p = y3 + offset1[1]; // point
-        safecomputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
+        safeComputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
         leftOff[0] = x1p; leftOff[1] = y1p;
         leftOff[4] = x3p; leftOff[5] = y3p;
 
         x1p = x1 - offset0[0]; y1p = y1 - offset0[1];
         x3p = x3 - offset1[0]; y3p = y3 - offset1[1];
-        safecomputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
+        safeComputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
         rightOff[0] = x1p; rightOff[1] = y1p;
         rightOff[4] = x3p; rightOff[5] = y3p;
         return 6;
     }
 
-    // If this class is compiled with ecj, then Hotspot crashes when OSR
-    // compiling this function. See bugs 7004570 and 6675699
-    // TODO: until those are fixed, we should work around that by
-    // manually inlining this into curveTo and quadTo.
-/******************************* WORKAROUND **********************************
-    private void somethingTo(final int type) {
-        // need these so we can update the state at the end of this method
-        final double xf = middle[type-2], yf = middle[type-1];
-        double dxs = middle[2] - middle[0];
-        double dys = middle[3] - middle[1];
-        double dxf = middle[type - 2] - middle[type - 4];
-        double dyf = middle[type - 1] - middle[type - 3];
-        switch(type) {
-        case 6:
-            if ((dxs == 0d && dys == 0d) ||
-                (dxf == 0d && dyf == 0d)) {
-               dxs = dxf = middle[4] - middle[0];
-               dys = dyf = middle[5] - middle[1];
-            }
-            break;
-        case 8:
-            boolean p1eqp2 = (dxs == 0d && dys == 0d);
-            boolean p3eqp4 = (dxf == 0d && dyf == 0d);
-            if (p1eqp2) {
-                dxs = middle[4] - middle[0];
-                dys = middle[5] - middle[1];
-                if (dxs == 0d && dys == 0d) {
-                    dxs = middle[6] - middle[0];
-                    dys = middle[7] - middle[1];
-                }
-            }
-            if (p3eqp4) {
-                dxf = middle[6] - middle[2];
-                dyf = middle[7] - middle[3];
-                if (dxf == 0d && dyf == 0d) {
-                    dxf = middle[6] - middle[0];
-                    dyf = middle[7] - middle[1];
-                }
-            }
-        }
-        if (dxs == 0d && dys == 0d) {
-            // this happens iff the "curve" is just a point
-            lineTo(middle[0], middle[1]);
-            return;
-        }
-        // if these vectors are too small, normalize them, to avoid future
-        // precision problems.
-        if (Math.abs(dxs) < 0.1d && Math.abs(dys) < 0.1d) {
-            double len =  Math.sqrt(dxs*dxs + dys*dys);
-            dxs /= len;
-            dys /= len;
-        }
-        if (Math.abs(dxf) < 0.1d && Math.abs(dyf) < 0.1d) {
-            double len =  Math.sqrt(dxf*dxf + dyf*dyf);
-            dxf /= len;
-            dyf /= len;
-        }
-
-        computeOffset(dxs, dys, lineWidth2, offset0);
-        final double mx = offset0[0];
-        final double my = offset0[1];
-        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
-
-        int nSplits = findSubdivPoints(curve, middle, subdivTs, type, lineWidth2);
-
-        int kind = 0;
-        BreakPtrIterator it = curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
-        while(it.hasNext()) {
-            int curCurveOff = it.next();
-
-            switch (type) {
-            case 8:
-                kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
-                break;
-            case 6:
-                kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
-                break;
-            }
-            emitLineTo(lp[0], lp[1]);
-            switch(kind) {
-            case 8:
-                emitCurveTo(lp[2], lp[3], lp[4], lp[5], lp[6], lp[7]);
-                emitCurveToRev(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5]);
-                break;
-            case 6:
-                emitQuadTo(lp[2], lp[3], lp[4], lp[5]);
-                emitQuadToRev(rp[0], rp[1], rp[2], rp[3]);
-                break;
-            case 4:
-                emitLineTo(lp[2], lp[3]);
-                emitLineTo(rp[0], rp[1], true);
-                break;
-            }
-            emitLineTo(rp[kind - 2], rp[kind - 1], true);
-        }
-
-        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
-        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
-        this.cdx = dxf;
-        this.cdy = dyf;
-        this.cx0 = xf;
-        this.cy0 = yf;
-        this.prev = DRAWING_OP_TO;
-    }
-****************************** END WORKAROUND *******************************/
-
     // finds values of t where the curve in pts should be subdivided in order
     // to get good offset curves a distance of w away from the middle curve.
     // Stores the points in ts, and returns how many of them there were.
@@ -1000,11 +892,11 @@
         final double y12 = pts[3] - pts[1];
         // if the curve is already parallel to either axis we gain nothing
         // from rotating it.
-        if (y12 != 0d && x12 != 0d) {
+        if (y12 != 0.0d && x12 != 0.0d) {
             // we rotate it so that the first vector in the control polygon is
             // parallel to the x-axis. This will ensure that rotated quarter
             // circles won't be subdivided.
-            final double hypot =  Math.sqrt(x12 * x12 + y12 * y12);
+            final double hypot = Math.sqrt(x12 * x12 + y12 * y12);
             final double cos = x12 / hypot;
             final double sin = y12 / hypot;
             final double x1 = cos * pts[0] + sin * pts[1];
@@ -1060,9 +952,6 @@
         mid[4] = x2;  mid[5] = y2;
         mid[6] = x3;  mid[7] = y3;
 
-        // inlined version of somethingTo(8);
-        // See the TODO on somethingTo
-
         // need these so we can update the state at the end of this method
         final double xf = mid[6], yf = mid[7];
         double dxs = mid[2] - mid[0];
@@ -1070,12 +959,12 @@
         double dxf = mid[6] - mid[4];
         double dyf = mid[7] - mid[5];
 
-        boolean p1eqp2 = (dxs == 0d && dys == 0d);
-        boolean p3eqp4 = (dxf == 0d && dyf == 0d);
+        boolean p1eqp2 = (dxs == 0.0d && dys == 0.0d);
+        boolean p3eqp4 = (dxf == 0.0d && dyf == 0.0d);
         if (p1eqp2) {
             dxs = mid[4] - mid[0];
             dys = mid[5] - mid[1];
-            if (dxs == 0d && dys == 0d) {
+            if (dxs == 0.0d && dys == 0.0d) {
                 dxs = mid[6] - mid[0];
                 dys = mid[7] - mid[1];
             }
@@ -1083,12 +972,12 @@
         if (p3eqp4) {
             dxf = mid[6] - mid[2];
             dyf = mid[7] - mid[3];
-            if (dxf == 0d && dyf == 0d) {
+            if (dxf == 0.0d && dyf == 0.0d) {
                 dxf = mid[6] - mid[0];
                 dyf = mid[7] - mid[1];
             }
         }
-        if (dxs == 0d && dys == 0d) {
+        if (dxs == 0.0d && dys == 0.0d) {
             // this happens if the "curve" is just a point
             lineTo(mid[0], mid[1]);
             return;
@@ -1097,12 +986,12 @@
         // if these vectors are too small, normalize them, to avoid future
         // precision problems.
         if (Math.abs(dxs) < 0.1d && Math.abs(dys) < 0.1d) {
-            double len =  Math.sqrt(dxs*dxs + dys*dys);
+            double len = Math.sqrt(dxs*dxs + dys*dys);
             dxs /= len;
             dys /= len;
         }
         if (Math.abs(dxf) < 0.1d && Math.abs(dyf) < 0.1d) {
-            double len =  Math.sqrt(dxf*dxf + dyf*dyf);
+            double len = Math.sqrt(dxf*dxf + dyf*dyf);
             dxf /= len;
             dyf /= len;
         }
@@ -1112,10 +1001,10 @@
 
         final int nSplits = findSubdivPoints(curve, mid, subdivTs, 8, lineWidth2);
 
-        double prevT = 0d;
+        double prevT = 0.0d;
         for (int i = 0, off = 0; i < nSplits; i++, off += 6) {
             final double t = subdivTs[i];
-            DHelpers.subdivideCubicAt((t - prevT) / (1d - prevT),
+            DHelpers.subdivideCubicAt((t - prevT) / (1.0d - prevT),
                                      mid, off, mid, off, mid, off + 6);
             prevT = t;
         }
@@ -1143,8 +1032,8 @@
             emitLineToRev(r[kind - 2], r[kind - 1]);
         }
 
-        this.cmx = (l[kind - 2] - r[kind - 2]) / 2d;
-        this.cmy = (l[kind - 1] - r[kind - 1]) / 2d;
+        this.cmx = (l[kind - 2] - r[kind - 2]) / 2.0d;
+        this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0d;
         this.cdx = dxf;
         this.cdy = dyf;
         this.cx0 = xf;
@@ -1159,20 +1048,17 @@
         mid[2] = x1;  mid[3] = y1;
         mid[4] = x2;  mid[5] = y2;
 
-        // inlined version of somethingTo(8);
-        // See the TODO on somethingTo
-
         // need these so we can update the state at the end of this method
         final double xf = mid[4], yf = mid[5];
         double dxs = mid[2] - mid[0];
         double dys = mid[3] - mid[1];
         double dxf = mid[4] - mid[2];
         double dyf = mid[5] - mid[3];
-        if ((dxs == 0d && dys == 0d) || (dxf == 0d && dyf == 0d)) {
+        if ((dxs == 0.0d && dys == 0.0d) || (dxf == 0.0d && dyf == 0.0d)) {
             dxs = dxf = mid[4] - mid[0];
             dys = dyf = mid[5] - mid[1];
         }
-        if (dxs == 0d && dys == 0d) {
+        if (dxs == 0.0d && dys == 0.0d) {
             // this happens if the "curve" is just a point
             lineTo(mid[0], mid[1]);
             return;
@@ -1180,12 +1066,12 @@
         // if these vectors are too small, normalize them, to avoid future
         // precision problems.
         if (Math.abs(dxs) < 0.1d && Math.abs(dys) < 0.1d) {
-            double len =  Math.sqrt(dxs*dxs + dys*dys);
+            double len = Math.sqrt(dxs*dxs + dys*dys);
             dxs /= len;
             dys /= len;
         }
         if (Math.abs(dxf) < 0.1d && Math.abs(dyf) < 0.1d) {
-            double len =  Math.sqrt(dxf*dxf + dyf*dyf);
+            double len = Math.sqrt(dxf*dxf + dyf*dyf);
             dxf /= len;
             dyf /= len;
         }
@@ -1195,10 +1081,10 @@
 
         int nSplits = findSubdivPoints(curve, mid, subdivTs, 6, lineWidth2);
 
-        double prevt = 0d;
+        double prevt = 0.0d;
         for (int i = 0, off = 0; i < nSplits; i++, off += 4) {
             final double t = subdivTs[i];
-            DHelpers.subdivideQuadAt((t - prevt) / (1d - prevt),
+            DHelpers.subdivideQuadAt((t - prevt) / (1.0d - prevt),
                                     mid, off, mid, off, mid, off + 4);
             prevt = t;
         }
@@ -1226,8 +1112,8 @@
             emitLineToRev(r[kind - 2], r[kind - 1]);
         }
 
-        this.cmx = (l[kind - 2] - r[kind - 2]) / 2d;
-        this.cmy = (l[kind - 1] - r[kind - 1]) / 2d;
+        this.cmx = (l[kind - 2] - r[kind - 2]) / 2.0d;
+        this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0d;
         this.cdx = dxf;
         this.cdy = dyf;
         this.cx0 = xf;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DTransformingPathConsumer2D.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DTransformingPathConsumer2D.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,13 +44,13 @@
         if (at == null) {
             return out;
         }
-        double mxx =  at.getMxx();
-        double mxy =  at.getMxy();
-        double myx =  at.getMyx();
-        double myy =  at.getMyy();
+        double mxx = at.getMxx();
+        double mxy = at.getMxy();
+        double myx = at.getMyx();
+        double myy = at.getMyy();
 
-        if (mxy == 0d && myx == 0d) {
-            if (mxx == 1d && myy == 1d) {
+        if (mxy == 0.0d && myx == 0.0d) {
+            if (mxx == 1.0d && myy == 1.0d) {
                 return out;
             } else {
                 return dt_DeltaScaleFilter.init(out, mxx, myy);
@@ -70,13 +70,13 @@
         if (at == null) {
             return out;
         }
-        double mxx =  at.getMxx();
-        double mxy =  at.getMxy();
-        double myx =  at.getMyx();
-        double myy =  at.getMyy();
+        double mxx = at.getMxx();
+        double mxy = at.getMxy();
+        double myx = at.getMyx();
+        double myy = at.getMyy();
 
-        if (mxy == 0d && myx == 0d) {
-            if (mxx == 1d && myy == 1d) {
+        if (mxy == 0.0d && myx == 0.0d) {
+            if (mxx == 1.0d && myy == 1.0d) {
                 return out;
             } else {
                 return iv_DeltaScaleFilter.init(out, 1.0d/mxx, 1.0d/myy);
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/Dasher.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/Dasher.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,12 +43,12 @@
 
     static final int REC_LIMIT = 4;
     static final float ERR = 0.01f;
-    static final float MIN_T_INC = 1f / (1 << REC_LIMIT);
+    static final float MIN_T_INC = 1.0f / (1 << REC_LIMIT);
 
     // More than 24 bits of mantissa means we can no longer accurately
     // measure the number of times cycled through the dash array so we
     // punt and override the phase to just be 0 past that point.
-    static final float MAX_CYCLES = 16000000f;
+    static final float MAX_CYCLES = 16000000.0f;
 
     private PathConsumer2D out;
     private float[] dash;
@@ -116,21 +116,21 @@
         // Normalize so 0 <= phase < dash[0]
         int sidx = 0;
         dashOn = true;
-        float sum = 0f;
+        float sum = 0.0f;
         for (float d : dash) {
             sum += d;
         }
         float cycles = phase / sum;
-        if (phase < 0f) {
+        if (phase < 0.0f) {
             if (-cycles >= MAX_CYCLES) {
-                phase = 0f;
+                phase = 0.0f;
             } else {
                 int fullcycles = FloatMath.floor_int(-cycles);
                 if ((fullcycles & dash.length & 1) != 0) {
                     dashOn = !dashOn;
                 }
                 phase += fullcycles * sum;
-                while (phase < 0f) {
+                while (phase < 0.0f) {
                     if (--sidx < 0) {
                         sidx = dash.length - 1;
                     }
@@ -140,7 +140,7 @@
             }
         } else if (phase > 0) {
             if (cycles >= MAX_CYCLES) {
-                phase = 0f;
+                phase = 0.0f;
             } else {
                 int fullcycles = FloatMath.floor_int(cycles);
                 if ((fullcycles & dash.length & 1) != 0) {
@@ -177,7 +177,7 @@
     void dispose() {
         if (DO_CLEAN_DIRTY) {
             // Force zero-fill dirty arrays:
-            Arrays.fill(curCurvepts, 0f);
+            Arrays.fill(curCurvepts, 0.0f);
         }
         // Return arrays:
         if (recycleDashes) {
@@ -296,7 +296,7 @@
         float dy = y1 - y0;
 
         float len = dx*dx + dy*dy;
-        if (len == 0f) {
+        if (len == 0.0f) {
             return;
         }
         len = (float) Math.sqrt(len);
@@ -324,7 +324,7 @@
                 phase += len;
                 // TODO: compare float values using epsilon:
                 if (len == leftInThisDashSegment) {
-                    phase = 0f;
+                    phase = 0.0f;
                     idx = (idx + 1) % dashLen;
                     dashOn = !dashOn;
                 }
@@ -334,7 +334,7 @@
             dashdx = _dash[idx] * cx;
             dashdy = _dash[idx] * cy;
 
-            if (phase == 0f) {
+            if (phase == 0.0f) {
                 _curCurvepts[0] = x0 + dashdx;
                 _curCurvepts[1] = y0 + dashdy;
             } else {
@@ -349,7 +349,7 @@
             // Advance to next dash segment
             idx = (idx + 1) % dashLen;
             dashOn = !dashOn;
-            phase = 0f;
+            phase = 0.0f;
         }
     }
 
@@ -366,13 +366,13 @@
 
         // initially the current curve is at curCurvepts[0...type]
         int curCurveoff = 0;
-        float lastSplitT = 0f;
+        float lastSplitT = 0.0f;
         float t;
         float leftInThisDashSegment = dash[idx] - phase;
 
-        while ((t = li.next(leftInThisDashSegment)) < 1f) {
-            if (t != 0f) {
-                Helpers.subdivideAt((t - lastSplitT) / (1f - lastSplitT),
+        while ((t = li.next(leftInThisDashSegment)) < 1.0f) {
+            if (t != 0.0f) {
+                Helpers.subdivideAt((t - lastSplitT) / (1.0f - lastSplitT),
                                     curCurvepts, curCurveoff,
                                     curCurvepts, 0,
                                     curCurvepts, type, type);
@@ -383,13 +383,13 @@
             // Advance to next dash segment
             idx = (idx + 1) % dashLen;
             dashOn = !dashOn;
-            phase = 0f;
+            phase = 0.0f;
             leftInThisDashSegment = dash[idx];
         }
         goTo(curCurvepts, curCurveoff+2, type);
         phase += li.lastSegLen();
         if (phase >= dash[idx]) {
-            phase = 0f;
+            phase = 0.0f;
             idx = (idx + 1) % dashLen;
             dashOn = !dashOn;
         }
@@ -444,7 +444,7 @@
 
         // the lengths of the lines of the control polygon. Only its first
         // curveType/2 - 1 elements are valid. This is an optimization. See
-        // next(float) for more detail.
+        // next() for more detail.
         private final float[] curLeafCtrlPolyLengths = new float[3];
 
         LengthIterator() {
@@ -469,13 +469,13 @@
             if (DO_CLEAN_DIRTY) {
                 final int recLimit = recCurveStack.length - 1;
                 for (int i = recLimit; i >= 0; i--) {
-                    Arrays.fill(recCurveStack[i], 0f);
+                    Arrays.fill(recCurveStack[i], 0.0f);
                 }
                 Arrays.fill(sides, Side.LEFT);
-                Arrays.fill(curLeafCtrlPolyLengths, 0f);
-                Arrays.fill(nextRoots, 0f);
-                Arrays.fill(flatLeafCoefCache, 0f);
-                flatLeafCoefCache[2] = -1f;
+                Arrays.fill(curLeafCtrlPolyLengths, 0.0f);
+                Arrays.fill(nextRoots, 0.0f);
+                Arrays.fill(flatLeafCoefCache, 0.0f);
+                flatLeafCoefCache[2] = -1.0f;
             }
         }
 
@@ -484,12 +484,12 @@
             System.arraycopy(pts, 0, recCurveStack[0], 0, 8);
             this.curveType = type;
             this.recLevel = 0;
-            this.lastT = 0f;
-            this.lenAtLastT = 0f;
-            this.nextT = 0f;
-            this.lenAtNextT = 0f;
+            this.lastT = 0.0f;
+            this.lenAtLastT = 0.0f;
+            this.nextT = 0.0f;
+            this.lenAtNextT = 0.0f;
             goLeft(); // initializes nextT and lenAtNextT properly
-            this.lenAtLastSplit = 0f;
+            this.lenAtLastSplit = 0.0f;
             if (recLevel > 0) {
                 this.sides[0] = Side.LEFT;
                 this.done = false;
@@ -498,7 +498,7 @@
                 this.sides[0] = Side.RIGHT;
                 this.done = true;
             }
-            this.lastSegLen = 0f;
+            this.lastSegLen = 0.0f;
         }
 
         // 0 == false, 1 == true, -1 == invalid cached value.
@@ -511,7 +511,7 @@
                 // the test below is equivalent to !within(len1/len2, 1, err).
                 // It is using a multiplication instead of a division, so it
                 // should be a bit faster.
-                if (!Helpers.within(len1, len2, err*len2)) {
+                if (!Helpers.within(len1, len2, err * len2)) {
                     cachedHaveLowAcceleration = 0;
                     return false;
                 }
@@ -542,7 +542,7 @@
         // form (see inside next() for what that means). The cache is
         // invalid when it's third element is negative, since in any
         // valid flattened curve, this would be >= 0.
-        private final float[] flatLeafCoefCache = new float[]{0f, 0f, -1f, 0f};
+        private final float[] flatLeafCoefCache = new float[]{0.0f, 0.0f, -1.0f, 0.0f};
 
         // returns the t value where the remaining curve should be split in
         // order for the left subdivided curve to have length len. If len
@@ -552,7 +552,7 @@
             while (lenAtNextT < targetLength) {
                 if (done) {
                     lastSegLen = lenAtNextT - lenAtLastSplit;
-                    return 1f;
+                    return 1.0f;
                 }
                 goToNextLeaf();
             }
@@ -569,19 +569,19 @@
                 // gives us the desired length.
                 final float[] _flatLeafCoefCache = flatLeafCoefCache;
 
-                if (_flatLeafCoefCache[2] < 0f) {
-                    float x = 0f + curLeafCtrlPolyLengths[0],
-                          y = x  + curLeafCtrlPolyLengths[1];
+                if (_flatLeafCoefCache[2] < 0.0f) {
+                    float x =     curLeafCtrlPolyLengths[0],
+                          y = x + curLeafCtrlPolyLengths[1];
                     if (curveType == 8) {
                         float z = y + curLeafCtrlPolyLengths[2];
-                        _flatLeafCoefCache[0] = 3f * (x - y) + z;
-                        _flatLeafCoefCache[1] = 3f * (y - 2f * x);
-                        _flatLeafCoefCache[2] = 3f * x;
+                        _flatLeafCoefCache[0] = 3.0f * (x - y) + z;
+                        _flatLeafCoefCache[1] = 3.0f * (y - 2.0f * x);
+                        _flatLeafCoefCache[2] = 3.0f * x;
                         _flatLeafCoefCache[3] = -z;
                     } else if (curveType == 6) {
-                        _flatLeafCoefCache[0] = 0f;
-                        _flatLeafCoefCache[1] = y - 2f * x;
-                        _flatLeafCoefCache[2] = 2f * x;
+                        _flatLeafCoefCache[0] = 0.0f;
+                        _flatLeafCoefCache[1] = y - 2.0f * x;
+                        _flatLeafCoefCache[2] = 2.0f * x;
                         _flatLeafCoefCache[3] = -y;
                     }
                 }
@@ -593,7 +593,7 @@
                 // we use cubicRootsInAB here, because we want only roots in 0, 1,
                 // and our quadratic root finder doesn't filter, so it's just a
                 // matter of convenience.
-                int n = Helpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0f, 1f);
+                int n = Helpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0.0f, 1.0f);
                 if (n == 1 && !Float.isNaN(nextRoots[0])) {
                     t = nextRoots[0];
                 }
@@ -601,8 +601,8 @@
             // t is relative to the current leaf, so we must make it a valid parameter
             // of the original curve.
             t = t * (nextT - lastT) + lastT;
-            if (t >= 1f) {
-                t = 1f;
+            if (t >= 1.0f) {
+                t = 1.0f;
                 done = true;
             }
             // even if done = true, if we're here, that means targetLength
@@ -649,13 +649,13 @@
         // go to the leftmost node from the current node. Return its length.
         private void goLeft() {
             float len = onLeaf();
-            if (len >= 0f) {
+            if (len >= 0.0f) {
                 lastT = nextT;
                 lenAtLastT = lenAtNextT;
                 nextT += (1 << (REC_LIMIT - recLevel)) * MIN_T_INC;
                 lenAtNextT += len;
                 // invalidate caches
-                flatLeafCoefCache[2] = -1f;
+                flatLeafCoefCache[2] = -1.0f;
                 cachedHaveLowAcceleration = -1;
             } else {
                 Helpers.subdivide(recCurveStack[recLevel], 0,
@@ -671,7 +671,7 @@
         // the length of the leaf if we are on a leaf.
         private float onLeaf() {
             float[] curve = recCurveStack[recLevel];
-            float polyLen = 0f;
+            float polyLen = 0.0f;
 
             float x0 = curve[0], y0 = curve[1];
             for (int i = 2; i < curveType; i += 2) {
@@ -687,9 +687,9 @@
                                                   curve[curveType-2],
                                                   curve[curveType-1]);
             if ((polyLen - lineLen) < ERR || recLevel == REC_LIMIT) {
-                return (polyLen + lineLen) / 2f;
+                return (polyLen + lineLen) / 2.0f;
             }
-            return -1f;
+            return -1.0f;
         }
     }
 
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/DoubleArrayCache.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/DoubleArrayCache.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,13 +38,14 @@
 import com.sun.marlin.ArrayCacheConst.CacheStats;
 
 /*
- * Note that the [BYTE/INT/FLOAT]ArrayCache files are nearly identical except
+ * Note that the [BYTE/INT/FLOAT/DOUBLE]ArrayCache files are nearly identical except
  * for a few type and name differences. Typically, the [BYTE]ArrayCache.java file
- * is edited manually and then [INT]ArrayCache.java and [FLOAT]ArrayCache.java
+ * is edited manually and then [INT/FLOAT/DOUBLE]ArrayCache.java
  * files are generated with the following command lines:
  */
 // % sed -e 's/(b\yte)[ ]*//g' -e 's/b\yte/int/g' -e 's/B\yte/Int/g' < B\yteArrayCache.java > IntArrayCache.java
-// % sed -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0f/g' -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0d/g' -e 's/(b\yte)[ ]*/(double) /g' -e 's/b\yte/double/g' -e 's/B\yte/Double/g' < B\yteArrayCache.java > DoubleArrayCache.java
 
 public final class DoubleArrayCache implements MarlinConst {
 
@@ -160,7 +161,7 @@
             if (array.length <= MAX_ARRAY_SIZE) {
                 if ((clean || DO_CLEAN_DIRTY) && (toIndex != 0)) {
                     // clean-up array of dirty part[fromIndex; toIndex[
-                    fill(array, fromIndex, toIndex, (double) 0);
+                    fill(array, fromIndex, toIndex, 0.0d);
                 }
                 // ensure to never store initial arrays in cache:
                 if (array != initial) {
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/FloatArrayCache.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/FloatArrayCache.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,13 +38,14 @@
 import com.sun.marlin.ArrayCacheConst.CacheStats;
 
 /*
- * Note that the [BYTE/INT/FLOAT]ArrayCache files are nearly identical except
+ * Note that the [BYTE/INT/FLOAT/DOUBLE]ArrayCache files are nearly identical except
  * for a few type and name differences. Typically, the [BYTE]ArrayCache.java file
- * is edited manually and then [INT]ArrayCache.java and [FLOAT]ArrayCache.java
+ * is edited manually and then [INT/FLOAT/DOUBLE]ArrayCache.java
  * files are generated with the following command lines:
  */
 // % sed -e 's/(b\yte)[ ]*//g' -e 's/b\yte/int/g' -e 's/B\yte/Int/g' < B\yteArrayCache.java > IntArrayCache.java
-// % sed -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0f/g' -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0d/g' -e 's/(b\yte)[ ]*/(double) /g' -e 's/b\yte/double/g' -e 's/B\yte/Double/g' < B\yteArrayCache.java > DoubleArrayCache.java
 
 public final class FloatArrayCache implements MarlinConst {
 
@@ -160,7 +161,7 @@
             if (array.length <= MAX_ARRAY_SIZE) {
                 if ((clean || DO_CLEAN_DIRTY) && (toIndex != 0)) {
                     // clean-up array of dirty part[fromIndex; toIndex[
-                    fill(array, fromIndex, toIndex, (float) 0);
+                    fill(array, fromIndex, toIndex, 0.0f);
                 }
                 // ensure to never store initial arrays in cache:
                 if (array != initial) {
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/FloatMath.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/FloatMath.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,16 +39,6 @@
     }
 
     // faster inlined min/max functions in the branch prediction is high
-    static float max(final float a, final float b) {
-        // no NaN handling
-        return (a >= b) ? a : b;
-    }
-
-    static double max(final double a, final double b) {
-        // no NaN handling
-        return (a >= b) ? a : b;
-    }
-
     public static int max(final int a, final int b) {
         return (a >= b) ? a : b;
     }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/Helpers.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/Helpers.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,27 +52,27 @@
     {
         int ret = off;
         float t;
-        if (a != 0f) {
+        if (a != 0.0f) {
             final float dis = b*b - 4*a*c;
-            if (dis > 0f) {
-                final float sqrtDis = (float)Math.sqrt(dis);
+            if (dis > 0.0f) {
+                final float sqrtDis = (float) Math.sqrt(dis);
                 // depending on the sign of b we use a slightly different
                 // algorithm than the traditional one to find one of the roots
                 // so we can avoid adding numbers of different signs (which
                 // might result in loss of precision).
-                if (b >= 0f) {
-                    zeroes[ret++] = (2f * c) / (-b - sqrtDis);
-                    zeroes[ret++] = (-b - sqrtDis) / (2f * a);
+                if (b >= 0.0f) {
+                    zeroes[ret++] = (2.0f * c) / (-b - sqrtDis);
+                    zeroes[ret++] = (-b - sqrtDis) / (2.0f * a);
                 } else {
-                    zeroes[ret++] = (-b + sqrtDis) / (2f * a);
-                    zeroes[ret++] = (2f * c) / (-b + sqrtDis);
+                    zeroes[ret++] = (-b + sqrtDis) / (2.0f * a);
+                    zeroes[ret++] = (2.0f * c) / (-b + sqrtDis);
                 }
-            } else if (dis == 0f) {
-                t = (-b) / (2f * a);
+            } else if (dis == 0.0f) {
+                t = (-b) / (2.0f * a);
                 zeroes[ret++] = t;
             }
         } else {
-            if (b != 0f) {
+            if (b != 0.0f) {
                 t = (-c) / b;
                 zeroes[ret++] = t;
             }
@@ -85,7 +85,7 @@
                               float[] pts, final int off,
                               final float A, final float B)
     {
-        if (d == 0f) {
+        if (d == 0.0f) {
             int num = quadraticRoots(a, b, c, pts, off);
             return filterOutNotInAB(pts, off, num, A, B) - off;
         }
@@ -109,8 +109,8 @@
         // q = Q/2
         // instead and use those values for simplicity of the code.
         double sq_A = a * a;
-        double p = (1.0/3.0) * ((-1.0/3.0) * sq_A + b);
-        double q = (1.0/2.0) * ((2.0/27.0) * a * sq_A - (1.0/3.0) * a * b + c);
+        double p = (1.0d/3.0d) * ((-1.0d/3.0d) * sq_A + b);
+        double q = (1.0d/2.0d) * ((2.0d/27.0d) * a * sq_A - (1.0d/3.0d) * a * b + c);
 
         // use Cardano's formula
 
@@ -118,30 +118,30 @@
         double D = q * q + cb_p;
 
         int num;
-        if (D < 0.0) {
+        if (D < 0.0d) {
             // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
-            final double phi = (1.0/3.0) * acos(-q / sqrt(-cb_p));
-            final double t = 2.0 * sqrt(-p);
+            final double phi = (1.0d/3.0d) * acos(-q / sqrt(-cb_p));
+            final double t = 2.0d * sqrt(-p);
 
-            pts[ off+0 ] =  (float)( t * cos(phi));
-            pts[ off+1 ] =  (float)(-t * cos(phi + (PI / 3.0)));
-            pts[ off+2 ] =  (float)(-t * cos(phi - (PI / 3.0)));
+            pts[ off+0 ] = (float) ( t * cos(phi));
+            pts[ off+1 ] = (float) (-t * cos(phi + (PI / 3.0d)));
+            pts[ off+2 ] = (float) (-t * cos(phi - (PI / 3.0d)));
             num = 3;
         } else {
             final double sqrt_D = sqrt(D);
             final double u = cbrt(sqrt_D - q);
             final double v = - cbrt(sqrt_D + q);
 
-            pts[ off ] = (float)(u + v);
+            pts[ off ] = (float) (u + v);
             num = 1;
 
-            if (within(D, 0.0, 1e-8)) {
-                pts[off+1] = -(pts[off] / 2f);
+            if (within(D, 0.0d, 1e-8d)) {
+                pts[off+1] = -(pts[off] / 2.0f);
                 num = 2;
             }
         }
 
-        final float sub = (1f/3f) * a;
+        final float sub = (1.0f/3.0f) * a;
 
         for (int i = 0; i < num; ++i) {
             pts[ off+i ] -= sub;
@@ -178,7 +178,7 @@
 
     static float polyLineLength(float[] poly, final int off, final int nCoords) {
         assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
-        float acc = 0f;
+        float acc = 0.0f;
         for (int i = off + 2; i < off + nCoords; i += 2) {
             acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
         }
@@ -188,7 +188,7 @@
     static float linelen(float x1, float y1, float x2, float y2) {
         final float dx = x2 - x1;
         final float dy = y2 - y1;
-        return (float)Math.sqrt(dx*dx + dy*dy);
+        return (float) Math.sqrt(dx*dx + dy*dy);
     }
 
     static void subdivide(float[] src, int srcoff, float[] left, int leftoff,
@@ -218,8 +218,8 @@
     }
 
     // Most of these are copied from classes in java.awt.geom because we need
-    // float versions of these functions, and Line2D, CubicCurve2D,
-    // QuadCurve2D don't provide them.
+    // both single and double precision variants of these functions, and Line2D,
+    // CubicCurve2D, QuadCurve2D don't provide them.
     /**
      * Subdivides the cubic curve specified by the coordinates
      * stored in the <code>src</code> array at indices <code>srcoff</code>
@@ -268,18 +268,18 @@
             right[rightoff + 6] = x2;
             right[rightoff + 7] = y2;
         }
-        x1 = (x1 + ctrlx1) / 2f;
-        y1 = (y1 + ctrly1) / 2f;
-        x2 = (x2 + ctrlx2) / 2f;
-        y2 = (y2 + ctrly2) / 2f;
-        float centerx = (ctrlx1 + ctrlx2) / 2f;
-        float centery = (ctrly1 + ctrly2) / 2f;
-        ctrlx1 = (x1 + centerx) / 2f;
-        ctrly1 = (y1 + centery) / 2f;
-        ctrlx2 = (x2 + centerx) / 2f;
-        ctrly2 = (y2 + centery) / 2f;
-        centerx = (ctrlx1 + ctrlx2) / 2f;
-        centery = (ctrly1 + ctrly2) / 2f;
+        x1 = (x1 + ctrlx1) / 2.0f;
+        y1 = (y1 + ctrly1) / 2.0f;
+        x2 = (x2 + ctrlx2) / 2.0f;
+        y2 = (y2 + ctrly2) / 2.0f;
+        float centerx = (ctrlx1 + ctrlx2) / 2.0f;
+        float centery = (ctrly1 + ctrly2) / 2.0f;
+        ctrlx1 = (x1 + centerx) / 2.0f;
+        ctrly1 = (y1 + centery) / 2.0f;
+        ctrlx2 = (x2 + centerx) / 2.0f;
+        ctrly2 = (y2 + centery) / 2.0f;
+        centerx = (ctrlx1 + ctrlx2) / 2.0f;
+        centery = (ctrly1 + ctrly2) / 2.0f;
         if (left != null) {
             left[leftoff + 2] = x1;
             left[leftoff + 3] = y1;
@@ -367,12 +367,12 @@
             right[rightoff + 4] = x2;
             right[rightoff + 5] = y2;
         }
-        x1 = (x1 + ctrlx) / 2f;
-        y1 = (y1 + ctrly) / 2f;
-        x2 = (x2 + ctrlx) / 2f;
-        y2 = (y2 + ctrly) / 2f;
-        ctrlx = (x1 + x2) / 2f;
-        ctrly = (y1 + y2) / 2f;
+        x1 = (x1 + ctrlx) / 2.0f;
+        y1 = (y1 + ctrly) / 2.0f;
+        x2 = (x2 + ctrlx) / 2.0f;
+        y2 = (y2 + ctrly) / 2.0f;
+        ctrlx = (x1 + x2) / 2.0f;
+        ctrly = (y1 + y2) / 2.0f;
         if (left != null) {
             left[leftoff + 2] = x1;
             left[leftoff + 3] = y1;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/IntArrayCache.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/IntArrayCache.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,13 +38,14 @@
 import com.sun.marlin.ArrayCacheConst.CacheStats;
 
 /*
- * Note that the [BYTE/INT/FLOAT]ArrayCache files are nearly identical except
+ * Note that the [BYTE/INT/FLOAT/DOUBLE]ArrayCache files are nearly identical except
  * for a few type and name differences. Typically, the [BYTE]ArrayCache.java file
- * is edited manually and then [INT]ArrayCache.java and [FLOAT]ArrayCache.java
+ * is edited manually and then [INT/FLOAT/DOUBLE]ArrayCache.java
  * files are generated with the following command lines:
  */
 // % sed -e 's/(b\yte)[ ]*//g' -e 's/b\yte/int/g' -e 's/B\yte/Int/g' < B\yteArrayCache.java > IntArrayCache.java
-// % sed -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0f/g' -e 's/(b\yte)[ ]*/(float) /g' -e 's/b\yte/float/g' -e 's/B\yte/Float/g' < B\yteArrayCache.java > FloatArrayCache.java
+// % sed -e 's/(b\yte)[ ]*0/0.0d/g' -e 's/(b\yte)[ ]*/(double) /g' -e 's/b\yte/double/g' -e 's/B\yte/Double/g' < B\yteArrayCache.java > DoubleArrayCache.java
 
 public final class IntArrayCache implements MarlinConst {
 
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinConst.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinConst.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -100,6 +100,9 @@
     // edges capacity = 24 x initial edges = 24 * edges count (4096) = 96K
     static final int INITIAL_EDGES_CAPACITY = INITIAL_EDGES_COUNT * 24;
 
+    // crossing capacity = edges count / 4 ~ 1024
+    static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
+
     // zero value as byte
     static final byte BYTE_0 = (byte) 0;
 
@@ -113,9 +116,13 @@
     public static final int SUBPIXEL_POSITIONS_X = 1 << (SUBPIXEL_LG_POSITIONS_X);
     public static final int SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
 
+    // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
+    static final int INITIAL_BUCKET_ARRAY
+        = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y;
+
     public static final float NORM_SUBPIXELS
-        = (float)Math.sqrt(( SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_X
-                           + SUBPIXEL_POSITIONS_Y * SUBPIXEL_POSITIONS_Y)/2.0);
+        = (float) Math.sqrt(( SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_X
+                            + SUBPIXEL_POSITIONS_Y * SUBPIXEL_POSITIONS_Y) / 2.0d);
 
     public static final int MAX_AA_ALPHA
         = SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinProperties.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinProperties.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
     /**
      * Return the log(2) corresponding to subpixel on x-axis (
      *
-     * @return 0 (1 subpixels) < initial pixel size < 4 (256 subpixels)
+     * @return 0 (1 subpixels) < initial pixel size < 8 (256 subpixels)
      * (3 by default ie 8 subpixels)
      */
     public static int getSubPixel_Log2_X() {
@@ -156,6 +156,20 @@
         return getBoolean("prism.marlin.logUnsafeMalloc", "false");
     }
 
+    // quality settings
+
+    public static float getCubicDecD2() {
+        return getFloat("prism.marlin.cubic_dec_d2", 1.0f, 0.01f, 4.0f);
+    }
+
+    public static float getCubicIncD1() {
+        return getFloat("prism.marlin.cubic_inc_d1", 0.4f, 0.01f, 2.0f);
+    }
+
+    public static float getQuadDecD2() {
+        return getFloat("prism.marlin.quad_dec_d2", 0.5f, 0.01f, 4.0f);
+    }
+
     // system property utilities
     static boolean getBoolean(final String key, final String def) {
         return Boolean.valueOf(AccessController.doPrivileged(
@@ -190,7 +204,36 @@
     }
 
     static int align(final int val, final int norm) {
-        final int ceil = FloatMath.ceil_int( ((float)val) / norm);
+        final int ceil = FloatMath.ceil_int( ((float) val) / norm);
         return ceil * norm;
     }
+
+    public static double getDouble(final String key, final double def,
+                                   final double min, final double max)
+    {
+        double value = def;
+        final String property = AccessController.doPrivileged(
+                    (PrivilegedAction<String>) () -> System.getProperty(key));
+
+        if (property != null) {
+            try {
+                value = Double.parseDouble(property);
+            } catch (NumberFormatException nfe) {
+                logInfo("Invalid value for " + key + " = " + property + " !");
+            }
+        }
+        // check for invalid values
+        if (value < min || value > max) {
+            logInfo("Invalid value for " + key + " = " + value
+                    + "; expect value in range[" + min + ", " + max + "] !");
+            value = def;
+        }
+        return value;
+    }
+
+    public static float getFloat(final String key, final float def,
+                                 final float min, final float max)
+    {
+        return (float)getDouble(key, def, min, max);
+    }
 }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinRenderingEngine.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/MarlinRenderingEngine.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
 /**
  * Marlin RendererEngine implementation (derived from Pisces)
  */
-public class MarlinRenderingEngine implements MarlinConst
+public final class MarlinRenderingEngine implements MarlinConst
 {
     /**
      * Private constructor to prevent instantiation.
@@ -198,8 +198,14 @@
                 + MarlinConst.LOG_UNSAFE_MALLOC);
 
         // quality settings
+        logInfo("prism.marlin.cubic_dec_d2     = "
+                + MarlinProperties.getCubicDecD2());
+        logInfo("prism.marlin.cubic_inc_d1     = "
+                + MarlinProperties.getCubicIncD1());
+        logInfo("prism.marlin.quad_dec_d2      = "
+                + MarlinProperties.getQuadDecD2());
+
         logInfo("Renderer settings:");
-        logInfo("CUB_COUNT_LG = " + Renderer.CUB_COUNT_LG);
         logInfo("CUB_DEC_BND  = " + Renderer.CUB_DEC_BND);
         logInfo("CUB_INC_BND  = " + Renderer.CUB_INC_BND);
         logInfo("QUAD_DEC_BND = " + Renderer.QUAD_DEC_BND);
@@ -207,7 +213,7 @@
         logInfo("INITIAL_EDGES_CAPACITY        = "
                 + MarlinConst.INITIAL_EDGES_CAPACITY);
         logInfo("INITIAL_CROSSING_COUNT        = "
-                + Renderer.INITIAL_CROSSING_COUNT);
+                + MarlinConst.INITIAL_CROSSING_COUNT);
 
         logInfo("=========================================================="
                 + "=====================");
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/MaskMarlinAlphaConsumer.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/MaskMarlinAlphaConsumer.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,10 +77,6 @@
         return height;
     }
 
-    public byte[] getAlphasNoClone() {
-        return alphas;
-    }
-
     public int getAlphaLength() {
         return alphas.length;
     }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/Renderer.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/Renderer.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,23 +35,14 @@
     private static final int ALL_BUT_LSB = 0xFFFFFFFE;
     private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1
 
-    private static final double POWER_2_TO_32 = 0x1.0p32;
+    private static final double POWER_2_TO_32 = 0x1.0p32d;
 
     // use float to make tosubpix methods faster (no int to float conversion)
-    static final float F_SUBPIXEL_POSITIONS_X
-        = (float) SUBPIXEL_POSITIONS_X;
-    static final float F_SUBPIXEL_POSITIONS_Y
-        = (float) SUBPIXEL_POSITIONS_Y;
+    static final float SUBPIXEL_SCALE_X = (float) SUBPIXEL_POSITIONS_X;
+    static final float SUBPIXEL_SCALE_Y = (float) SUBPIXEL_POSITIONS_Y;
     static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1;
     static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1;
 
-    // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
-    static final int INITIAL_BUCKET_ARRAY
-        = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y;
-
-    // crossing capacity = edges count / 4 ~ 1024
-    static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
-
     // common to all types of input path segments.
     // OFFSET as bytes
     // only integer values:
@@ -68,19 +59,20 @@
     // curve break into lines
     // cubic error in subpixels to decrement step
     private static final float CUB_DEC_ERR_SUBPIX
-        = 1f * (NORM_SUBPIXELS / 8f); // 1 pixel
+        = MarlinProperties.getCubicDecD2() * (NORM_SUBPIXELS / 8.0f); // 1 pixel
     // cubic error in subpixels to increment step
     private static final float CUB_INC_ERR_SUBPIX
-        = 0.4f * (NORM_SUBPIXELS / 8f); // 0.4 pixel
+        = MarlinProperties.getCubicIncD1() * (NORM_SUBPIXELS / 8.0f); // 0.4 pixel
 
+    // TestNonAARasterization (JDK-8170879): cubics
     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
 
     // cubic bind length to decrement step
     public static final float CUB_DEC_BND
-        = 8f * CUB_DEC_ERR_SUBPIX;
+        = 8.0f * CUB_DEC_ERR_SUBPIX;
     // cubic bind length to increment step
     public static final float CUB_INC_BND
-        = 8f * CUB_INC_ERR_SUBPIX;
+        = 8.0f * CUB_INC_ERR_SUBPIX;
 
     // cubic countlg
     public static final int CUB_COUNT_LG = 2;
@@ -91,22 +83,23 @@
     // cubic count^3 = 8^countlg
     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
     // cubic dt = 1 / count
-    private static final float CUB_INV_COUNT = 1f / CUB_COUNT;
+    private static final float CUB_INV_COUNT = 1.0f / CUB_COUNT;
     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
-    private static final float CUB_INV_COUNT_2 = 1f / CUB_COUNT_2;
+    private static final float CUB_INV_COUNT_2 = 1.0f / CUB_COUNT_2;
     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
-    private static final float CUB_INV_COUNT_3 = 1f / CUB_COUNT_3;
+    private static final float CUB_INV_COUNT_3 = 1.0f / CUB_COUNT_3;
 
     // quad break into lines
     // quadratic error in subpixels
     private static final float QUAD_DEC_ERR_SUBPIX
-        = 0.5f * (NORM_SUBPIXELS / 8f); // 0.5 pixel
+        = MarlinProperties.getQuadDecD2() * (NORM_SUBPIXELS / 8.0f); // 0.5 pixel
 
+    // TestNonAARasterization (JDK-8170879): quads
     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
 
     // quadratic bind length to decrement step
     public static final float QUAD_DEC_BND
-        = 8f * QUAD_DEC_ERR_SUBPIX;
+        = 8.0f * QUAD_DEC_ERR_SUBPIX;
 
 //////////////////////////////////////////////////////////////////////////////
 //  SCAN LINE
@@ -177,7 +170,7 @@
 
         while (maxDD >= _DEC_BND) {
             // divide step by half:
-            maxDD /= 4f; // error divided by 2^2 = 4
+            maxDD /= 4.0f; // error divided by 2^2 = 4
 
             count <<= 1;
             if (DO_STATS) {
@@ -187,7 +180,7 @@
 
         int nL = 0; // line count
         if (count > 1) {
-            final float icount = 1f / count; // dt
+            final float icount = 1.0f / count; // dt
             final float icount2 = icount * icount; // dt^2
 
             final float ddx = c.dbx * icount2;
@@ -234,8 +227,8 @@
         // the dx and dy refer to forward differencing variables, not the last
         // coefficients of the "points" polynomial
         float dddx, dddy, ddx, ddy, dx, dy;
-        dddx = 2f * c.dax * icount3;
-        dddy = 2f * c.day * icount3;
+        dddx = 2.0f * c.dax * icount3;
+        dddy = 2.0f * c.day * icount3;
         ddx = dddx + c.dbx * icount2;
         ddy = dddy + c.dby * icount2;
         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
@@ -251,12 +244,12 @@
         while (count > 0) {
             // divide step by half:
             while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) {
-                dddx /= 8f;
-                dddy /= 8f;
-                ddx = ddx/4f - dddx;
-                ddy = ddy/4f - dddy;
-                dx = (dx - ddx) / 2f;
-                dy = (dy - ddy) / 2f;
+                dddx /= 8.0f;
+                dddy /= 8.0f;
+                ddx = ddx / 4.0f - dddx;
+                ddy = ddy / 4.0f - dddy;
+                dx = (dx - ddx) / 2.0f;
+                dy = (dy - ddy) / 2.0f;
 
                 count <<= 1;
                 if (DO_STATS) {
@@ -265,19 +258,16 @@
             }
 
             // double step:
-            // TODO: why use first derivative dX|Y instead of second ddX|Y ?
-            // both scale changes should use speed or acceleration to have the same metric.
-
             // can only do this on even "count" values, because we must divide count by 2
             while (count % 2 == 0
                    && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
             {
-                dx = 2f * dx + ddx;
-                dy = 2f * dy + ddy;
-                ddx = 4f * (ddx + dddx);
-                ddy = 4f * (ddy + dddy);
-                dddx *= 8f;
-                dddy *= 8f;
+                dx = 2.0f * dx + ddx;
+                dy = 2.0f * dy + ddy;
+                ddx = 4.0f * (ddx + dddx);
+                ddy = 4.0f * (ddy + dddy);
+                dddx *= 8.0f;
+                dddy *= 8.0f;
 
                 count >>= 1;
                 if (DO_STATS) {
@@ -349,7 +339,7 @@
             return;
         }
 
-        // edge min/max X/Y are in subpixel space (inclusive) within bounds:
+        // edge min/max X/Y are in subpixel space (half-open interval):
         // note: Use integer crossings to ensure consistent range within
         // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0)
         if (firstCrossing < edgeMinY) {
@@ -364,7 +354,7 @@
         final double y1d   = y1;
         final double slope = (x1d - x2) / (y1d - y2);
 
-        if (slope >= 0.0) { // <==> x1 < x2
+        if (slope >= 0.0d) { // <==> x1 < x2
             if (x1 < edgeMinX) {
                 edgeMinX = x1;
             }
@@ -462,7 +452,7 @@
         // pointer from bucket
         _unsafe.putInt(addr, _edgeBuckets[bucketIdx]);
         addr += SIZE_INT;
-        // y max (inclusive)
+        // y max (exclusive)
         _unsafe.putInt(addr,  lastCrossing);
 
         // Update buckets:
@@ -517,32 +507,30 @@
 
     Renderer(final RendererContext rdrCtx) {
         this.rdrCtx = rdrCtx;
-
-        this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
-
         this.curve = rdrCtx.curve;
 
-        edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
-        edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+        this.edges = rdrCtx.rdrMem.edges;
+
+        edgeBuckets_ref      = rdrCtx.rdrMem.edgeBuckets_ref;
+        edgeBucketCounts_ref = rdrCtx.rdrMem.edgeBucketCounts_ref;
 
         edgeBuckets      = edgeBuckets_ref.initial;
         edgeBucketCounts = edgeBucketCounts_ref.initial;
 
-        // 2048 (pixelsize) pixel large
-        alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
+        alphaLine_ref = rdrCtx.rdrMem.alphaLine_ref;
         alphaLine     = alphaLine_ref.initial;
 
-        crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+        crossings_ref     = rdrCtx.rdrMem.crossings_ref;
+        aux_crossings_ref = rdrCtx.rdrMem.aux_crossings_ref;
+        edgePtrs_ref      = rdrCtx.rdrMem.edgePtrs_ref;
+        aux_edgePtrs_ref  = rdrCtx.rdrMem.aux_edgePtrs_ref;
 
         crossings     = crossings_ref.initial;
         aux_crossings = aux_crossings_ref.initial;
         edgePtrs      = edgePtrs_ref.initial;
         aux_edgePtrs  = aux_edgePtrs_ref.initial;
 
-        blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
+        blkFlags_ref = rdrCtx.rdrMem.blkFlags_ref;
         blkFlags     = blkFlags_ref.initial;
     }
 
@@ -654,12 +642,12 @@
     }
 
     private static float tosubpixx(final float pix_x) {
-        return F_SUBPIXEL_POSITIONS_X * pix_x;
+        return SUBPIXEL_SCALE_X * pix_x;
     }
 
     private static float tosubpixy(final float pix_y) {
         // shift y by -0.5 for fast ceil(y - 0.5):
-        return F_SUBPIXEL_POSITIONS_Y * pix_y - 0.5f;
+        return SUBPIXEL_SCALE_Y * pix_y - 0.5f;
     }
 
     @Override
@@ -1181,8 +1169,8 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
                                     }
                                 } else {
                                     tmp = (x0 & _SUBPIXEL_MASK_X);
@@ -1201,10 +1189,9 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x         >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1)    >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[ pix_xmax      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_xmax + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
+                                        _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1;
                                     }
                                 }
                             }
@@ -1252,8 +1239,8 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
                                     }
                                 } else {
                                     tmp = (x0 & _SUBPIXEL_MASK_X);
@@ -1272,10 +1259,9 @@
 
                                     if (useBlkFlags) {
                                         // flag used blocks:
-                                        _blkFlags[ pix_x         >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_x + 1)    >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[ pix_xmax      >> _BLK_SIZE_LG] = 1;
-                                        _blkFlags[(pix_xmax + 1) >> _BLK_SIZE_LG] = 1;
+                                        // note: block processing handles extra pixel:
+                                        _blkFlags[pix_x    >> _BLK_SIZE_LG] = 1;
+                                        _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1;
                                     }
                                 }
                             }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/RendererContext.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/RendererContext.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,8 @@
     final Curve curve = new Curve();
     // MarlinRenderingEngine.TransformingPathConsumer2D
     public final TransformingPathConsumer2D transformerPC2D;
+    // shared memory between renderer instances:
+    final RendererSharedMemory rdrMem;
     public final Renderer renderer;
     private RendererNoAA rendererNoAA = null;
     public final Stroker stroker;
@@ -74,8 +76,8 @@
     public MaskMarlinAlphaConsumer consumer = null;
 
     // Array caches:
-    /* clean int[] cache (zero-filled) = 5 refs */
-    private final IntArrayCache cleanIntCache = new IntArrayCache(true, 5);
+    /* clean int[] cache (zero-filled) = 4 refs */
+    private final IntArrayCache cleanIntCache = new IntArrayCache(true, 4);
     /* dirty int[] cache = 4 refs */
     private final IntArrayCache dirtyIntCache = new IntArrayCache(false, 4);
     /* dirty float[] cache = 3 refs */
@@ -111,6 +113,9 @@
         // MarlinRenderingEngine.TransformingPathConsumer2D
         transformerPC2D = new TransformingPathConsumer2D();
 
+        // Renderer shared memory:
+        rdrMem = new RendererSharedMemory(this);
+
         // Renderer:
         renderer = new Renderer(this);
 
@@ -174,4 +179,48 @@
     ByteArrayCache.Reference newDirtyByteArrayRef(final int initialSize) {
         return dirtyByteCache.createRef(initialSize);
     }
+
+    static final class RendererSharedMemory {
+
+        // edges [ints] stored in off-heap memory
+        final OffHeapArray edges;
+
+        // edgeBuckets ref (clean)
+        final IntArrayCache.Reference edgeBuckets_ref;
+        // edgeBucketCounts ref (clean)
+        final IntArrayCache.Reference edgeBucketCounts_ref;
+
+        // alphaLine ref (clean)
+        final IntArrayCache.Reference alphaLine_ref;
+
+        // crossings ref (dirty)
+        final IntArrayCache.Reference crossings_ref;
+        // edgePtrs ref (dirty)
+        final IntArrayCache.Reference edgePtrs_ref;
+        // merge sort initial arrays
+        // aux_crossings ref (dirty)
+        final IntArrayCache.Reference aux_crossings_ref;
+        // aux_edgePtrs ref (dirty)
+        final IntArrayCache.Reference aux_edgePtrs_ref;
+
+        // blkFlags ref (clean)
+        final IntArrayCache.Reference blkFlags_ref;
+
+        RendererSharedMemory(final RendererContext rdrCtx) {
+            edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
+
+            edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+            edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+
+            // 2048 (pixelsize) pixel large
+            alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
+
+            crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+            aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+            edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+            aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+
+            blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
+        }
+    }
 }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/RendererNoAA.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/RendererNoAA.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,13 +35,7 @@
     private static final int ALL_BUT_LSB = 0xFFFFFFFE;
     private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1
 
-    private static final double POWER_2_TO_32 = 0x1.0p32;
-
-    // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
-    static final int INITIAL_BUCKET_ARRAY = INITIAL_PIXEL_DIM;
-
-    // crossing capacity = edges count / 4 ~ 1024
-    static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
+    private static final double POWER_2_TO_32 = 0x1.0p32d;
 
     // common to all types of input path segments.
     // OFFSET as bytes
@@ -59,19 +53,20 @@
     // curve break into lines
     // cubic error in subpixels to decrement step
     private static final float CUB_DEC_ERR_SUBPIX
-        = 1f * (1f / 8f); // 1 pixel
+        = MarlinProperties.getCubicDecD2() * (1.0f / 8.0f); // 1 pixel
     // cubic error in subpixels to increment step
     private static final float CUB_INC_ERR_SUBPIX
-        = 0.4f * (1f / 8f); // 0.4 pixel
+        = MarlinProperties.getCubicIncD1() * (1.0f / 8.0f); // 0.4 pixel
 
+    // TestNonAARasterization (JDK-8170879): cubics
     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
 
     // cubic bind length to decrement step
     public static final float CUB_DEC_BND
-        = 8f * CUB_DEC_ERR_SUBPIX;
+        = 8.0f * CUB_DEC_ERR_SUBPIX;
     // cubic bind length to increment step
     public static final float CUB_INC_BND
-        = 8f * CUB_INC_ERR_SUBPIX;
+        = 8.0f * CUB_INC_ERR_SUBPIX;
 
     // cubic countlg
     public static final int CUB_COUNT_LG = 2;
@@ -82,22 +77,23 @@
     // cubic count^3 = 8^countlg
     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
     // cubic dt = 1 / count
-    private static final float CUB_INV_COUNT = 1f / CUB_COUNT;
+    private static final float CUB_INV_COUNT = 1.0f / CUB_COUNT;
     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
-    private static final float CUB_INV_COUNT_2 = 1f / CUB_COUNT_2;
+    private static final float CUB_INV_COUNT_2 = 1.0f / CUB_COUNT_2;
     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
-    private static final float CUB_INV_COUNT_3 = 1f / CUB_COUNT_3;
+    private static final float CUB_INV_COUNT_3 = 1.0f / CUB_COUNT_3;
 
     // quad break into lines
     // quadratic error in subpixels
     private static final float QUAD_DEC_ERR_SUBPIX
-        = 0.5f * (1f / 8f); // 0.5 pixel
+        = MarlinProperties.getQuadDecD2() * (1.0f / 8.0f); // 0.5 pixel
 
+    // TestNonAARasterization (JDK-8170879): quads
     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
 
     // quadratic bind length to decrement step
     public static final float QUAD_DEC_BND
-        = 8f * QUAD_DEC_ERR_SUBPIX;
+        = 8.0f * QUAD_DEC_ERR_SUBPIX;
 
 //////////////////////////////////////////////////////////////////////////////
 //  SCAN LINE
@@ -168,7 +164,7 @@
 
         while (maxDD >= _DEC_BND) {
             // divide step by half:
-            maxDD /= 4f; // error divided by 2^2 = 4
+            maxDD /= 4.0f; // error divided by 2^2 = 4
 
             count <<= 1;
             if (DO_STATS) {
@@ -178,7 +174,7 @@
 
         int nL = 0; // line count
         if (count > 1) {
-            final float icount = 1f / count; // dt
+            final float icount = 1.0f / count; // dt
             final float icount2 = icount * icount; // dt^2
 
             final float ddx = c.dbx * icount2;
@@ -225,8 +221,8 @@
         // the dx and dy refer to forward differencing variables, not the last
         // coefficients of the "points" polynomial
         float dddx, dddy, ddx, ddy, dx, dy;
-        dddx = 2f * c.dax * icount3;
-        dddy = 2f * c.day * icount3;
+        dddx = 2.0f * c.dax * icount3;
+        dddy = 2.0f * c.day * icount3;
         ddx = dddx + c.dbx * icount2;
         ddy = dddy + c.dby * icount2;
         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
@@ -242,12 +238,12 @@
         while (count > 0) {
             // divide step by half:
             while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) {
-                dddx /= 8f;
-                dddy /= 8f;
-                ddx = ddx/4f - dddx;
-                ddy = ddy/4f - dddy;
-                dx = (dx - ddx) / 2f;
-                dy = (dy - ddy) / 2f;
+                dddx /= 8.0f;
+                dddy /= 8.0f;
+                ddx = ddx / 4.0f - dddx;
+                ddy = ddy / 4.0f - dddy;
+                dx = (dx - ddx) / 2.0f;
+                dy = (dy - ddy) / 2.0f;
 
                 count <<= 1;
                 if (DO_STATS) {
@@ -256,19 +252,16 @@
             }
 
             // double step:
-            // TODO: why use first derivative dX|Y instead of second ddX|Y ?
-            // both scale changes should use speed or acceleration to have the same metric.
-
             // can only do this on even "count" values, because we must divide count by 2
             while (count % 2 == 0
                    && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
             {
-                dx = 2f * dx + ddx;
-                dy = 2f * dy + ddy;
-                ddx = 4f * (ddx + dddx);
-                ddy = 4f * (ddy + dddy);
-                dddx *= 8f;
-                dddy *= 8f;
+                dx = 2.0f * dx + ddx;
+                dy = 2.0f * dy + ddy;
+                ddx = 4.0f * (ddx + dddx);
+                ddy = 4.0f * (ddy + dddy);
+                dddx *= 8.0f;
+                dddy *= 8.0f;
 
                 count >>= 1;
                 if (DO_STATS) {
@@ -340,7 +333,7 @@
             return;
         }
 
-        // edge min/max X/Y are in subpixel space (inclusive) within bounds:
+        // edge min/max X/Y are in subpixel space (half-open interval):
         // note: Use integer crossings to ensure consistent range within
         // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0)
         if (firstCrossing < edgeMinY) {
@@ -355,7 +348,7 @@
         final double y1d   = y1;
         final double slope = (x1d - x2) / (y1d - y2);
 
-        if (slope >= 0.0) { // <==> x1 < x2
+        if (slope >= 0.0d) { // <==> x1 < x2
             if (x1 < edgeMinX) {
                 edgeMinX = x1;
             }
@@ -453,7 +446,7 @@
         // pointer from bucket
         _unsafe.putInt(addr, _edgeBuckets[bucketIdx]);
         addr += SIZE_INT;
-        // y max (inclusive)
+        // y max (exclusive)
         _unsafe.putInt(addr,  lastCrossing);
 
         // Update buckets:
@@ -508,32 +501,30 @@
 
     RendererNoAA(final RendererContext rdrCtx) {
         this.rdrCtx = rdrCtx;
-
-        this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
-
         this.curve = rdrCtx.curve;
 
-        edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
-        edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
+        this.edges = rdrCtx.rdrMem.edges;
+
+        edgeBuckets_ref      = rdrCtx.rdrMem.edgeBuckets_ref;
+        edgeBucketCounts_ref = rdrCtx.rdrMem.edgeBucketCounts_ref;
 
         edgeBuckets      = edgeBuckets_ref.initial;
         edgeBucketCounts = edgeBucketCounts_ref.initial;
 
-        // 2048 (pixelsize) pixel large
-        alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
+        alphaLine_ref = rdrCtx.rdrMem.alphaLine_ref;
         alphaLine     = alphaLine_ref.initial;
 
-        crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
-        aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
+        crossings_ref     = rdrCtx.rdrMem.crossings_ref;
+        aux_crossings_ref = rdrCtx.rdrMem.aux_crossings_ref;
+        edgePtrs_ref      = rdrCtx.rdrMem.edgePtrs_ref;
+        aux_edgePtrs_ref  = rdrCtx.rdrMem.aux_edgePtrs_ref;
 
         crossings     = crossings_ref.initial;
         aux_crossings = aux_crossings_ref.initial;
         edgePtrs      = edgePtrs_ref.initial;
         aux_edgePtrs  = aux_edgePtrs_ref.initial;
 
-        blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
+        blkFlags_ref = rdrCtx.rdrMem.blkFlags_ref;
         blkFlags     = blkFlags_ref.initial;
     }
 
@@ -1158,6 +1149,7 @@
 
                                 if (useBlkFlags) {
                                     // flag used blocks:
+                                    // note: block processing handles extra pixel:
                                     _blkFlags[x0 >> _BLK_SIZE_LG] = 1;
                                     _blkFlags[x1 >> _BLK_SIZE_LG] = 1;
                                 }
@@ -1200,6 +1192,7 @@
 
                                 if (useBlkFlags) {
                                     // flag used blocks:
+                                    // note: block processing handles extra pixel:
                                     _blkFlags[x0 >> _BLK_SIZE_LG] = 1;
                                     _blkFlags[x1 >> _BLK_SIZE_LG] = 1;
                                 }
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/Stroker.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/Stroker.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,7 @@
     // pisces used to use fixed point arithmetic with 16 decimal digits. I
     // didn't want to change the values of the constant below when I converted
     // it to floating point, so that's why the divisions by 2^16 are there.
-    private static final float ROUND_JOIN_THRESHOLD = 1000/65536f;
+    private static final float ROUND_JOIN_THRESHOLD = 1000.0f/65536.0f;
 
     private static final float C = 0.5522847498307933f;
 
@@ -109,7 +109,7 @@
 
     // This is where the curve to be processed is put. We give it
     // enough room to store all curves.
-    private final float[] middle = new float[MAX_N_CURVES * 8];
+    private final float[] middle = new float[MAX_N_CURVES * 6 + 2];
     private final float[] lp = new float[8];
     private final float[] rp = new float[8];
     private final float[] subdivTs = new float[MAX_N_CURVES - 1];
@@ -153,8 +153,8 @@
     {
         this.out = pc2d;
 
-        this.lineWidth2 = lineWidth / 2f;
-        this.invHalfLineWidth2Sq = 1f / (2f * lineWidth2 * lineWidth2);
+        this.lineWidth2 = lineWidth / 2.0f;
+        this.invHalfLineWidth2Sq = 1.0f / (2.0f * lineWidth2 * lineWidth2);
         this.capStyle = capStyle;
         this.joinStyle = joinStyle;
 
@@ -177,14 +177,14 @@
 
         if (DO_CLEAN_DIRTY) {
             // Force zero-fill dirty arrays:
-            Arrays.fill(offset0, 0f);
-            Arrays.fill(offset1, 0f);
-            Arrays.fill(offset2, 0f);
-            Arrays.fill(miter, 0f);
-            Arrays.fill(middle, 0f);
-            Arrays.fill(lp, 0f);
-            Arrays.fill(rp, 0f);
-            Arrays.fill(subdivTs, 0f);
+            Arrays.fill(offset0, 0.0f);
+            Arrays.fill(offset1, 0.0f);
+            Arrays.fill(offset2, 0.0f);
+            Arrays.fill(miter, 0.0f);
+            Arrays.fill(middle, 0.0f);
+            Arrays.fill(lp, 0.0f);
+            Arrays.fill(rp, 0.0f);
+            Arrays.fill(subdivTs, 0.0f);
         }
     }
 
@@ -192,9 +192,9 @@
                                       final float w, final float[] m)
     {
         float len = lx*lx + ly*ly;
-        if (len == 0f) {
-            m[0] = 0f;
-            m[1] = 0f;
+        if (len == 0.0f) {
+            m[0] = 0.0f;
+            m[1] = 0.0f;
         } else {
             len = (float) Math.sqrt(len);
             m[0] =  (ly * w) / len;
@@ -221,7 +221,7 @@
                                boolean rev,
                                float threshold)
     {
-        if ((omx == 0f && omy == 0f) || (mx == 0f && my == 0f)) {
+        if ((omx == 0.0f && omy == 0.0f) || (mx == 0.0f && my == 0.0f)) {
             return;
         }
 
@@ -253,7 +253,7 @@
         // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only
         // need 1 curve to approximate the circle section that joins omx,omy
         // and mx,my.
-        final int numCurves = (cosext >= 0f) ? 1 : 2;
+        final int numCurves = (cosext >= 0.0f) ? 1 : 2;
 
         switch (numCurves) {
         case 1:
@@ -313,8 +313,8 @@
         // define the bezier curve we're computing.
         // It is computed using the constraints that P1-P0 and P3-P2 are parallel
         // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|.
-        float cv = (float) ((4.0 / 3.0) * Math.sqrt(0.5 - cosext2) /
-                            (1.0 + Math.sqrt(cosext2 + 0.5)));
+        float cv = (float) ((4.0d / 3.0d) * Math.sqrt(0.5d - cosext2) /
+                            (1.0d + Math.sqrt(cosext2 + 0.5d)));
         // if clockwise, we need to negate cv.
         if (rev) { // rev is equivalent to isCW(omx, omy, mx, my)
             cv = -cv;
@@ -344,7 +344,7 @@
     }
 
     // Return the intersection point of the lines (x0, y0) -> (x1, y1)
-    // and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
+    // and (x0p, y0p) -> (x1p, y1p) in m[off] and m[off+1]
     private static void computeMiter(final float x0, final float y0,
                                      final float x1, final float y1,
                                      final float x0p, final float y0p,
@@ -373,8 +373,8 @@
     }
 
     // Return the intersection point of the lines (x0, y0) -> (x1, y1)
-    // and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
-    private static void safecomputeMiter(final float x0, final float y0,
+    // and (x0p, y0p) -> (x1p, y1p) in m[off] and m[off+1]
+    private static void safeComputeMiter(final float x0, final float y0,
                                          final float x1, final float y1,
                                          final float x0p, final float y0p,
                                          final float x1p, final float y1p,
@@ -395,9 +395,9 @@
         // (mx == omx && my == omy) will be true, and drawMiter will return
         // immediately).
         float den = x10*y10p - x10p*y10;
-        if (den == 0f) {
-            m[off++] = (x0 + x0p) / 2f;
-            m[off] = (y0 + y0p) / 2f;
+        if (den == 0.0f) {
+            m[off++] = (x0 + x0p) / 2.0f;
+            m[off]   = (y0 + y0p) / 2.0f;
             return;
         }
         float t = x10p*(y0-y0p) - y10p*(x0-x0p);
@@ -413,8 +413,8 @@
                            boolean rev)
     {
         if ((mx == omx && my == omy) ||
-            (pdx == 0f && pdy == 0f) ||
-            (dx == 0f && dy == 0f))
+            (pdx == 0.0f && pdy == 0.0f) ||
+            (dx == 0.0f && dy == 0.0f))
         {
             return;
         }
@@ -451,8 +451,8 @@
         }
         this.sx0 = this.cx0 = x0;
         this.sy0 = this.cy0 = y0;
-        this.cdx = this.sdx = 1f;
-        this.cdy = this.sdy = 0f;
+        this.cdx = this.sdx = 1.0f;
+        this.cdy = this.sdy = 0.0f;
         this.prev = MOVE_TO;
     }
 
@@ -460,8 +460,8 @@
     public void lineTo(float x1, float y1) {
         float dx = x1 - cx0;
         float dy = y1 - cy0;
-        if (dx == 0f && dy == 0f) {
-            dx = 1f;
+        if (dx == 0.0f && dy == 0.0f) {
+            dx = 1.0f;
         }
         computeOffset(dx, dy, lineWidth2, offset0);
         final float mx = offset0[0];
@@ -491,10 +491,10 @@
                 return;
             }
             emitMoveTo(cx0, cy0 - lineWidth2);
-            this.cmx = this.smx = 0f;
+            this.cmx = this.smx = 0.0f;
             this.cmy = this.smy = -lineWidth2;
-            this.cdx = this.sdx = 1f;
-            this.cdy = this.sdy = 0f;
+            this.cdx = this.sdx = 1.0f;
+            this.cdy = this.sdy = 0.0f;
             finish();
             return;
         }
@@ -677,7 +677,7 @@
     {
         // if p1=p2 or p3=p4 it means that the derivative at the endpoint
         // vanishes, which creates problems with computeOffset. Usually
-        // this happens when this stroker object is trying to winden
+        // this happens when this stroker object is trying to widen
         // a curve with a cusp. What happens is that curveTo splits
         // the input curve at the cusp, and passes it to this function.
         // because of inaccuracies in the splitting, we consider points
@@ -694,8 +694,8 @@
 
         // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
         // in which case ignore if p1 == p2
-        final boolean p1eqp2 = within(x1,y1,x2,y2, 6f * Math.ulp(y2));
-        final boolean p3eqp4 = within(x3,y3,x4,y4, 6f * Math.ulp(y4));
+        final boolean p1eqp2 = within(x1, y1, x2, y2, 6.0f * Math.ulp(y2));
+        final boolean p3eqp4 = within(x3, y3, x4, y4, 6.0f * Math.ulp(y4));
         if (p1eqp2 && p3eqp4) {
             getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
             return 4;
@@ -711,7 +711,7 @@
         float dotsq = (dx1 * dx4 + dy1 * dy4);
         dotsq *= dotsq;
         float l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
-        if (Helpers.within(dotsq, l1sq * l4sq, 4f * Math.ulp(dotsq))) {
+        if (Helpers.within(dotsq, l1sq * l4sq, 4.0f * Math.ulp(dotsq))) {
             getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
             return 4;
         }
@@ -763,8 +763,8 @@
 //      getting the inverse of the matrix above. Then we use [c1,c2] to compute
 //      p2p and p3p.
 
-        float x = (x1 + 3f * (x2 + x3) + x4) / 8f;
-        float y = (y1 + 3f * (y2 + y3) + y4) / 8f;
+        float x = (x1 + 3.0f * (x2 + x3) + x4) / 8.0f;
+        float y = (y1 + 3.0f * (y2 + y3) + y4) / 8.0f;
         // (dxm,dym) is some tangent of B at t=0.5. This means it's equal to
         // c*B'(0.5) for some constant c.
         float dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
@@ -782,10 +782,10 @@
         float x4p = x4 + offset2[0]; // end
         float y4p = y4 + offset2[1]; // point
 
-        float invdet43 = 4f / (3f * (dx1 * dy4 - dy1 * dx4));
+        float invdet43 = 4.0f / (3.0f * (dx1 * dy4 - dy1 * dx4));
 
-        float two_pi_m_p1_m_p4x = 2f * xi - x1p - x4p;
-        float two_pi_m_p1_m_p4y = 2f * yi - y1p - y4p;
+        float two_pi_m_p1_m_p4x = 2.0f * xi - x1p - x4p;
+        float two_pi_m_p1_m_p4y = 2.0f * yi - y1p - y4p;
         float c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
         float c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
 
@@ -801,11 +801,11 @@
         leftOff[6] = x4p; leftOff[7] = y4p;
 
         x1p = x1 - offset0[0]; y1p = y1 - offset0[1];
-        xi = xi - 2f * offset1[0]; yi = yi - 2f * offset1[1];
+        xi = xi - 2.0f * offset1[0]; yi = yi - 2.0f * offset1[1];
         x4p = x4 - offset2[0]; y4p = y4 - offset2[1];
 
-        two_pi_m_p1_m_p4x = 2f * xi - x1p - x4p;
-        two_pi_m_p1_m_p4y = 2f * yi - y1p - y4p;
+        two_pi_m_p1_m_p4x = 2.0f * xi - x1p - x4p;
+        two_pi_m_p1_m_p4y = 2.0f * yi - y1p - y4p;
         c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
         c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
 
@@ -838,7 +838,7 @@
 
         // if p1=p2 or p3=p4 it means that the derivative at the endpoint
         // vanishes, which creates problems with computeOffset. Usually
-        // this happens when this stroker object is trying to winden
+        // this happens when this stroker object is trying to widen
         // a curve with a cusp. What happens is that curveTo splits
         // the input curve at the cusp, and passes it to this function.
         // because of inaccuracies in the splitting, we consider points
@@ -846,8 +846,8 @@
 
         // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
         // in which case ignore.
-        final boolean p1eqp2 = within(x1,y1,x2,y2, 6f * Math.ulp(y2));
-        final boolean p2eqp3 = within(x2,y2,x3,y3, 6f * Math.ulp(y3));
+        final boolean p1eqp2 = within(x1, y1, x2, y2, 6.0f * Math.ulp(y2));
+        final boolean p2eqp3 = within(x2, y2, x3, y3, 6.0f * Math.ulp(y3));
         if (p1eqp2 || p2eqp3) {
             getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
             return 4;
@@ -857,7 +857,7 @@
         float dotsq = (dx1 * dx3 + dy1 * dy3);
         dotsq *= dotsq;
         float l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3;
-        if (Helpers.within(dotsq, l1sq * l3sq, 4f * Math.ulp(dotsq))) {
+        if (Helpers.within(dotsq, l1sq * l3sq, 4.0f * Math.ulp(dotsq))) {
             getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
             return 4;
         }
@@ -872,124 +872,18 @@
         float y1p = y1 + offset0[1]; // point
         float x3p = x3 + offset1[0]; // end
         float y3p = y3 + offset1[1]; // point
-        safecomputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
+        safeComputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
         leftOff[0] = x1p; leftOff[1] = y1p;
         leftOff[4] = x3p; leftOff[5] = y3p;
 
         x1p = x1 - offset0[0]; y1p = y1 - offset0[1];
         x3p = x3 - offset1[0]; y3p = y3 - offset1[1];
-        safecomputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
+        safeComputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
         rightOff[0] = x1p; rightOff[1] = y1p;
         rightOff[4] = x3p; rightOff[5] = y3p;
         return 6;
     }
 
-    // If this class is compiled with ecj, then Hotspot crashes when OSR
-    // compiling this function. See bugs 7004570 and 6675699
-    // TODO: until those are fixed, we should work around that by
-    // manually inlining this into curveTo and quadTo.
-/******************************* WORKAROUND **********************************
-    private void somethingTo(final int type) {
-        // need these so we can update the state at the end of this method
-        final float xf = middle[type-2], yf = middle[type-1];
-        float dxs = middle[2] - middle[0];
-        float dys = middle[3] - middle[1];
-        float dxf = middle[type - 2] - middle[type - 4];
-        float dyf = middle[type - 1] - middle[type - 3];
-        switch(type) {
-        case 6:
-            if ((dxs == 0f && dys == 0f) ||
-                (dxf == 0f && dyf == 0f)) {
-               dxs = dxf = middle[4] - middle[0];
-               dys = dyf = middle[5] - middle[1];
-            }
-            break;
-        case 8:
-            boolean p1eqp2 = (dxs == 0f && dys == 0f);
-            boolean p3eqp4 = (dxf == 0f && dyf == 0f);
-            if (p1eqp2) {
-                dxs = middle[4] - middle[0];
-                dys = middle[5] - middle[1];
-                if (dxs == 0f && dys == 0f) {
-                    dxs = middle[6] - middle[0];
-                    dys = middle[7] - middle[1];
-                }
-            }
-            if (p3eqp4) {
-                dxf = middle[6] - middle[2];
-                dyf = middle[7] - middle[3];
-                if (dxf == 0f && dyf == 0f) {
-                    dxf = middle[6] - middle[0];
-                    dyf = middle[7] - middle[1];
-                }
-            }
-        }
-        if (dxs == 0f && dys == 0f) {
-            // this happens iff the "curve" is just a point
-            lineTo(middle[0], middle[1]);
-            return;
-        }
-        // if these vectors are too small, normalize them, to avoid future
-        // precision problems.
-        if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
-            float len = (float) Math.sqrt(dxs*dxs + dys*dys);
-            dxs /= len;
-            dys /= len;
-        }
-        if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
-            float len = (float) Math.sqrt(dxf*dxf + dyf*dyf);
-            dxf /= len;
-            dyf /= len;
-        }
-
-        computeOffset(dxs, dys, lineWidth2, offset0);
-        final float mx = offset0[0];
-        final float my = offset0[1];
-        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
-
-        int nSplits = findSubdivPoints(curve, middle, subdivTs, type, lineWidth2);
-
-        int kind = 0;
-        BreakPtrIterator it = curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
-        while(it.hasNext()) {
-            int curCurveOff = it.next();
-
-            switch (type) {
-            case 8:
-                kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
-                break;
-            case 6:
-                kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
-                break;
-            }
-            emitLineTo(lp[0], lp[1]);
-            switch(kind) {
-            case 8:
-                emitCurveTo(lp[2], lp[3], lp[4], lp[5], lp[6], lp[7]);
-                emitCurveToRev(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5]);
-                break;
-            case 6:
-                emitQuadTo(lp[2], lp[3], lp[4], lp[5]);
-                emitQuadToRev(rp[0], rp[1], rp[2], rp[3]);
-                break;
-            case 4:
-                emitLineTo(lp[2], lp[3]);
-                emitLineTo(rp[0], rp[1], true);
-                break;
-            }
-            emitLineTo(rp[kind - 2], rp[kind - 1], true);
-        }
-
-        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
-        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
-        this.cdx = dxf;
-        this.cdy = dyf;
-        this.cx0 = xf;
-        this.cy0 = yf;
-        this.prev = DRAWING_OP_TO;
-    }
-****************************** END WORKAROUND *******************************/
-
     // finds values of t where the curve in pts should be subdivided in order
     // to get good offset curves a distance of w away from the middle curve.
     // Stores the points in ts, and returns how many of them there were.
@@ -1000,7 +894,7 @@
         final float y12 = pts[3] - pts[1];
         // if the curve is already parallel to either axis we gain nothing
         // from rotating it.
-        if (y12 != 0f && x12 != 0f) {
+        if (y12 != 0.0f && x12 != 0.0f) {
             // we rotate it so that the first vector in the control polygon is
             // parallel to the x-axis. This will ensure that rotated quarter
             // circles won't be subdivided.
@@ -1060,9 +954,6 @@
         mid[4] = x2;  mid[5] = y2;
         mid[6] = x3;  mid[7] = y3;
 
-        // inlined version of somethingTo(8);
-        // See the TODO on somethingTo
-
         // need these so we can update the state at the end of this method
         final float xf = mid[6], yf = mid[7];
         float dxs = mid[2] - mid[0];
@@ -1070,12 +961,12 @@
         float dxf = mid[6] - mid[4];
         float dyf = mid[7] - mid[5];
 
-        boolean p1eqp2 = (dxs == 0f && dys == 0f);
-        boolean p3eqp4 = (dxf == 0f && dyf == 0f);
+        boolean p1eqp2 = (dxs == 0.0f && dys == 0.0f);
+        boolean p3eqp4 = (dxf == 0.0f && dyf == 0.0f);
         if (p1eqp2) {
             dxs = mid[4] - mid[0];
             dys = mid[5] - mid[1];
-            if (dxs == 0f && dys == 0f) {
+            if (dxs == 0.0f && dys == 0.0f) {
                 dxs = mid[6] - mid[0];
                 dys = mid[7] - mid[1];
             }
@@ -1083,12 +974,12 @@
         if (p3eqp4) {
             dxf = mid[6] - mid[2];
             dyf = mid[7] - mid[3];
-            if (dxf == 0f && dyf == 0f) {
+            if (dxf == 0.0f && dyf == 0.0f) {
                 dxf = mid[6] - mid[0];
                 dyf = mid[7] - mid[1];
             }
         }
-        if (dxs == 0f && dys == 0f) {
+        if (dxs == 0.0f && dys == 0.0f) {
             // this happens if the "curve" is just a point
             lineTo(mid[0], mid[1]);
             return;
@@ -1112,10 +1003,10 @@
 
         final int nSplits = findSubdivPoints(curve, mid, subdivTs, 8, lineWidth2);
 
-        float prevT = 0f;
+        float prevT = 0.0f;
         for (int i = 0, off = 0; i < nSplits; i++, off += 6) {
             final float t = subdivTs[i];
-            Helpers.subdivideCubicAt((t - prevT) / (1f - prevT),
+            Helpers.subdivideCubicAt((t - prevT) / (1.0f - prevT),
                                      mid, off, mid, off, mid, off + 6);
             prevT = t;
         }
@@ -1143,8 +1034,8 @@
             emitLineToRev(r[kind - 2], r[kind - 1]);
         }
 
-        this.cmx = (l[kind - 2] - r[kind - 2]) / 2f;
-        this.cmy = (l[kind - 1] - r[kind - 1]) / 2f;
+        this.cmx = (l[kind - 2] - r[kind - 2]) / 2.0f;
+        this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0f;
         this.cdx = dxf;
         this.cdy = dyf;
         this.cx0 = xf;
@@ -1159,20 +1050,17 @@
         mid[2] = x1;  mid[3] = y1;
         mid[4] = x2;  mid[5] = y2;
 
-        // inlined version of somethingTo(8);
-        // See the TODO on somethingTo
-
         // need these so we can update the state at the end of this method
         final float xf = mid[4], yf = mid[5];
         float dxs = mid[2] - mid[0];
         float dys = mid[3] - mid[1];
         float dxf = mid[4] - mid[2];
         float dyf = mid[5] - mid[3];
-        if ((dxs == 0f && dys == 0f) || (dxf == 0f && dyf == 0f)) {
+        if ((dxs == 0.0f && dys == 0.0f) || (dxf == 0.0f && dyf == 0.0f)) {
             dxs = dxf = mid[4] - mid[0];
             dys = dyf = mid[5] - mid[1];
         }
-        if (dxs == 0f && dys == 0f) {
+        if (dxs == 0.0f && dys == 0.0f) {
             // this happens if the "curve" is just a point
             lineTo(mid[0], mid[1]);
             return;
@@ -1195,10 +1083,10 @@
 
         int nSplits = findSubdivPoints(curve, mid, subdivTs, 6, lineWidth2);
 
-        float prevt = 0f;
+        float prevt = 0.0f;
         for (int i = 0, off = 0; i < nSplits; i++, off += 4) {
             final float t = subdivTs[i];
-            Helpers.subdivideQuadAt((t - prevt) / (1f - prevt),
+            Helpers.subdivideQuadAt((t - prevt) / (1.0f - prevt),
                                     mid, off, mid, off, mid, off + 4);
             prevt = t;
         }
@@ -1226,8 +1114,8 @@
             emitLineToRev(r[kind - 2], r[kind - 1]);
         }
 
-        this.cmx = (l[kind - 2] - r[kind - 2]) / 2f;
-        this.cmy = (l[kind - 1] - r[kind - 1]) / 2f;
+        this.cmx = (l[kind - 2] - r[kind - 2]) / 2.0f;
+        this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0f;
         this.cdx = dxf;
         this.cdy = dyf;
         this.cx0 = xf;
--- a/modules/javafx.graphics/src/main/java/com/sun/marlin/TransformingPathConsumer2D.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/marlin/TransformingPathConsumer2D.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,8 +49,8 @@
         float myx = (float) at.getMyx();
         float myy = (float) at.getMyy();
 
-        if (mxy == 0f && myx == 0f) {
-            if (mxx == 1f && myy == 1f) {
+        if (mxy == 0.0f && myx == 0.0f) {
+            if (mxx == 1.0f && myy == 1.0f) {
                 return out;
             } else {
                 return dt_DeltaScaleFilter.init(out, mxx, myy);
@@ -75,8 +75,8 @@
         float myx = (float) at.getMyx();
         float myy = (float) at.getMyy();
 
-        if (mxy == 0f && myx == 0f) {
-            if (mxx == 1f && myy == 1f) {
+        if (mxy == 0.0f && myx == 0.0f) {
+            if (mxx == 1.0f && myy == 1.0f) {
                 return out;
             } else {
                 return iv_DeltaScaleFilter.init(out, 1.0f/mxx, 1.0f/myy);
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/DMarlinPrismUtils.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/DMarlinPrismUtils.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,7 @@
         int dashLen = -1;
         boolean recycleDashes = false;
 
-        double width = 0f, dashphase = 0f;
+        double width = 0.0f, dashphase = 0.0f;
         double[] dashesD = null;
 
         if (stroke != null) {
@@ -178,7 +178,7 @@
     }
 
     private static boolean nearZero(final double num) {
-        return Math.abs(num) < 2.0 * Math.ulp(num);
+        return Math.abs(num) < 2.0d * Math.ulp(num);
     }
 
     public static DMarlinRenderer setupRenderer(
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/MarlinPrismUtils.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/MarlinPrismUtils.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,7 @@
         int dashLen = -1;
         boolean recycleDashes = false;
 
-        float width = 0f, dashphase = 0f;
+        float width = 0.0f, dashphase = 0.0f;
         float[] dashes = null;
 
         if (stroke != null) {
@@ -177,7 +177,7 @@
     }
 
     private static boolean nearZero(final double num) {
-        return Math.abs(num) < 2.0 * Math.ulp(num);
+        return Math.abs(num) < 2.0d * Math.ulp(num);
     }
 
     public static MarlinRenderer setupRenderer(
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWContext.java	Tue May 16 14:58:02 2017 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWContext.java	Wed May 17 13:44:23 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,6 @@
 import com.sun.prism.Texture;
 import com.sun.prism.impl.PrismSettings;
 import com.sun.prism.impl.shape.DMarlinPrismUtils;
-import com.sun.prism.impl.shape.DMarlinRasterizer;
 import com.sun.prism.impl.shape.MarlinPrismUtils;
 import com.sun.prism.impl.shape.MaskData;
 import com.sun.prism.impl.shape.OpenPiscesPrismUtils;
@@ -112,7 +111,7 @@
         }
     }
 
-    class JavaShapeRenderer implements ShapeRenderer {
+    static final class JavaShapeRenderer implements ShapeRenderer {
         private final DirectRTPiscesAlphaConsumer alphaConsumer = new DirectRTPiscesAlphaConsumer();
 
         public void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape) {