--- old/modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/DMarlinPrismUtils.java 2017-11-08 22:06:40.936473317 +0100 +++ new/modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/DMarlinPrismUtils.java 2017-11-08 22:06:40.784469740 +0100 @@ -51,17 +51,17 @@ private DMarlinPrismUtils() { } - private static DPathConsumer2D initRenderer( + private static boolean nearZero(final double num) { + return Math.abs(num) < 2.0d * Math.ulp(num); + } + + private static DPathConsumer2D initPipeline( final DRendererContext rdrCtx, final BasicStroke stroke, + final float lineWidth, final BaseTransform tx, - final Rectangle clip, - final int pirule, - final DMarlinRenderer renderer) + final DPathConsumer2D out) { - final int oprule = (stroke == null && pirule == PathIterator.WIND_EVEN_ODD) ? - DMarlinRenderer.WIND_EVEN_ODD : DMarlinRenderer.WIND_NON_ZERO; - // We use strokerat so that in Stroker and Dasher we can work only // with the pre-transformation coordinates. This will repeat a lot of // computations done in the path iterator, but the alternative is to @@ -79,12 +79,12 @@ int dashLen = -1; boolean recycleDashes = false; - + double scale = 1.0d; double width = 0.0f, dashphase = 0.0f; double[] dashesD = null; if (stroke != null) { - width = stroke.getLineWidth(); + width = lineWidth; final float[] dashes = stroke.getDashArray(); dashphase = stroke.getDashPhase(); @@ -95,7 +95,7 @@ dashesD = rdrCtx.dasher.copyDashArray(dashes); } - if (tx != null && !tx.isIdentity()) { + if ((tx != null) && !tx.isIdentity()) { final double a = tx.getMxx(); final double b = tx.getMxy(); final double c = tx.getMyx(); @@ -108,7 +108,7 @@ // a*b == -c*d && a*a+c*c == b*b+d*d. In the actual check below, we // leave a bit of room for error. if (nearZero(a*b + c*d) && nearZero(a*a + c*c - (b*b + d*d))) { - final double scale = Math.sqrt(a*a + c*c); + scale = Math.sqrt(a*a + c*c); if (dashesD != null) { for (int i = 0; i < dashLen; i++) { @@ -140,7 +140,8 @@ } } - DPathConsumer2D pc = renderer.init(clip.x, clip.y, clip.width, clip.height, oprule); + // Prepare the pipeline: + DPathConsumer2D pc = out; if (MarlinConst.USE_SIMPLIFIER) { // Use simplifier after stroker before Renderer @@ -149,19 +150,19 @@ } final DTransformingPathConsumer2D transformerPC2D = rdrCtx.transformerPC2D; - pc = transformerPC2D.deltaTransformConsumer(pc, strokerTx); if (stroke != null) { + pc = transformerPC2D.deltaTransformConsumer(pc, strokerTx); + pc = rdrCtx.stroker.init(pc, width, stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit()); if (dashesD != null) { pc = rdrCtx.dasher.init(pc, dashesD, dashLen, dashphase, recycleDashes); } + pc = transformerPC2D.inverseDeltaTransformConsumer(pc, strokerTx); } - pc = transformerPC2D.inverseDeltaTransformConsumer(pc, strokerTx); - /* * Pipeline seems to be: * shape.getPathIterator(tx) @@ -177,52 +178,68 @@ return pc; } - private static boolean nearZero(final double num) { - return Math.abs(num) < 2.0d * Math.ulp(num); - } - - public static DMarlinRenderer setupRenderer( + private static DPathConsumer2D initRenderer( final DRendererContext rdrCtx, - final Shape shape, final BasicStroke stroke, - final BaseTransform xform, - final Rectangle rclip, - final boolean antialiasedShape) + final BaseTransform tx, + final Rectangle clip, + final int piRule, + final DMarlinRenderer renderer) { - // Test if transform is identity: - final BaseTransform tf = (xform != null && !xform.isIdentity()) ? xform : null; + final int oprule = ((stroke == null) && (piRule == PathIterator.WIND_EVEN_ODD)) ? + DMarlinRenderer.WIND_EVEN_ODD : DMarlinRenderer.WIND_NON_ZERO; - final PathIterator pi = shape.getPathIterator(tf); + renderer.init(clip.x, clip.y, clip.width, clip.height, oprule); - final DMarlinRenderer r = (!FORCE_NO_AA && antialiasedShape) ? - rdrCtx.renderer : rdrCtx.getRendererNoAA(); - - final DPathConsumer2D pc2d = initRenderer(rdrCtx, stroke, tf, rclip, pi.getWindingRule(), r); + float lw = 0.0f; - feedConsumer(rdrCtx, pi, pc2d); + if (stroke != null) { + lw = stroke.getLineWidth(); + } - return r; + return initPipeline(rdrCtx, stroke, lw, tx, renderer); } public static DMarlinRenderer setupRenderer( final DRendererContext rdrCtx, - final Path2D p2d, + final Shape shape, final BasicStroke stroke, final BaseTransform xform, final Rectangle rclip, final boolean antialiasedShape) { // Test if transform is identity: - final BaseTransform tf = (xform != null && !xform.isIdentity()) ? xform : null; + final BaseTransform tf = ((xform != null) && !xform.isIdentity()) ? xform : null; final DMarlinRenderer r = (!FORCE_NO_AA && antialiasedShape) ? rdrCtx.renderer : rdrCtx.getRendererNoAA(); - final DPathConsumer2D pc2d = initRenderer(rdrCtx, stroke, tf, rclip, p2d.getWindingRule(), r); + if (shape instanceof Path2D) { + final Path2D p2d = (Path2D)shape; + final DPathConsumer2D pc2d = initRenderer(rdrCtx, stroke, tf, rclip, p2d.getWindingRule(), r); + feedConsumer(rdrCtx, p2d, tf, pc2d); + } else { + final PathIterator pi = shape.getPathIterator(tf); + final DPathConsumer2D pc2d = initRenderer(rdrCtx, stroke, tf, rclip, pi.getWindingRule(), r); + feedConsumer(rdrCtx, pi, pc2d); + } + return r; + } - feedConsumer(rdrCtx, p2d, tf, pc2d); + public static void strokeTo( + final DRendererContext rdrCtx, + final Shape shape, + final BasicStroke stroke, + final float lineWidth, + final DPathConsumer2D out) + { + final DPathConsumer2D pc2d = initPipeline(rdrCtx, stroke, lineWidth, null, out); - return r; + if (shape instanceof Path2D) { + feedConsumer(rdrCtx, (Path2D)shape, null, pc2d); + } else { + feedConsumer(rdrCtx, shape.getPathIterator(null), pc2d); + } } private static void feedConsumer(final DRendererContext rdrCtx, final PathIterator pi, @@ -359,8 +376,8 @@ // - removed pathClosed (ie subpathStarted not set to false) boolean subpathStarted = false; - final float pCoords[] = p2d.getFloatCoordsNoClone(); - final byte pTypes[] = p2d.getCommandsNoClone(); + final float[] pCoords = p2d.getFloatCoordsNoClone(); + final byte[] pTypes = p2d.getCommandsNoClone(); final int nsegs = p2d.getNumCommands(); for (int i = 0, coff = 0; i < nsegs; i++) {