<div dir="ltr"><div><div><div><div>Hi,<br><br></div>Please review this webrev of the Marlin renderer 0.8.2 for JDK-10 (jdk/client forrest). It provides an efficient path clipper in both Stroker (float / double variants) & Filler fixing the bug <a class="gmail-issue-link" href="https://bugs.openjdk.java.net/browse/JDK-8191814" id="gmail-key-val" rel="4945424">JDK-8191814</a><br></div><div></div><div>I worked hard on this release since august and several patches were already proposed 0.8.0 (Stroker only clipping) ... and discussed here: <a href="http://mail.openjdk.java.net/pipermail/2d-dev/2017-August/008509.html">http://mail.openjdk.java.net/pipermail/2d-dev/2017-August/008509.html</a><br></div><div><br>Bug: <a href="https://bugs.openjdk.java.net/browse/JDK-8191814">https://bugs.openjdk.java.net/browse/JDK-8191814</a><br>Webrev: <a href="http://cr.openjdk.java.net/~lbourges/marlin/marlin-082-8191814.0/">http://cr.openjdk.java.net/~lbourges/marlin/marlin-082-8191814.0/</a><br><br></div></div><div>Build + tests: OK (see the new jtreg ClipShapeTest)</div><div><br></div><div>(I hope to provide the same upgrade to OpenJFX10 once this patch is reviewed)</div><div><br></div>Detailled change log:<br>JDK-8191814<br><br>Marlin 0.8.2 changelog:<br>- (D)Curve: corrected computation of curve coefficients to minimize error (stable formula)<br>- (D)Dasher: <br>    - lots of syntax changes<br>    - goTo(): use new method goTo_starting() to put slow path in another method (hotspot)<br>    - lineTo() / somethingTo(): use local variables in loops for higher efficiency<br>- (D)Helpers:<br>    - removed imports of Math functions (inlined in cubicRootsInAB)<br>    - removed unused polyLineLength()<br>    - added outcode() copied from GeneralRenderer<br>    - moved PolyStack class from (D)Stroker + use given Stat classes in constructor<br>    - added new IndexStack class to store 'corner' (integer) indices for the new PathClipFilter (Filler case): see push() that removes redundant corners (direction flip) and pullAll() that returns the corner points from all stored indices<br>- (D)MarlinRenderingEngine:<br>    - added new clip settings (doClip / doClipRuntimeFlag)<br>    - strokeTo(): added trace wrapper (disabled) and detectClosedPath() to know in advance if the path is closed and properly handle caps for filled polylines<br>    - getAATileGenerator(): define the initial clip bounds for both Stroker / Filler cases + use the new PathClipFilter (Filler case)<br>- (D)Renderer: <br>    - added constant for subpixel offsets (used to adjust the effective clipping area)<br>    - moveTo() / lineTo() / quadTo() / curveTo() : renamed arguments<br>    - closePath(): skip useless addLine() call if P0 = S0<br>- (D)RendererContext: added clipping state: doClip & closedPath flags, clipRect area (ymin, ymax, xmin, xmax) + increased array cache capacities for new [Poly/Index]Stack instances<br><br>- (D)Stroker: <br>Approach: ignore outside segments (moveTo) without computing intersections ie it opens the path (polyline) so extra care is needed to properly handle visible cap (and joins).<br>    - fixed constants (CAP / JOIN) moved into MarlinConst<br>    - fixed PolyStack usage (moved into (D)Helper)<br>    - added clipping state (current / starting outcodes, opened / capStart flags) <br>    - init(): adjust the clipping rectangle with the stroker margin (miter limit, width) and (scaled) renderer offsets (if delta transformation in use)<br>    - moveTo(): finish() the current opened subpath + compute starting & current outcode<br>    - lineTo() / quadTo() / curveTo() : added clipping = trivial segment rejection based on point outcodes that 'opens' the path and calls moveTo()<br>    - closePath(): tricky (but tested) changes to emit moveTo() or lineTo() if the closing segment is visible or not (and joins) + only emit close if the path is inside<br>    - finish(): if ClosedPathDetector indicated the path is not closed: use the outcode argument (current point) to only emit visible end cap and visible start cap (starting outcode)<br>    - drawJoin(): added outcode argument (current point) to only emit visible round / miter joins<br><br>- (D)TransformingPathConsumer2D: <br>    - moved all fields at the beginning<br>    - added ClosedPathDetector, PathClipFilter, PathTracer instances and wrappers<br>    - deltaTransformConsumer(): adjust clip rectangle to deal with Stroker coordinate transformations on the clipping area (inverse transform)<br>    - adjustClipInverseDelta(): for the shear transformation, the clipping area is set to the bounding box (rectangle) of the 4 transformed points of the initial clipping area<br>    - added the ClosedPathDetector class: simply set rdrCtx.closedPath to true in closePath()<br>    - added the PathClipFilter class: (Filler case)<br>        Approach: clipping closed polygons is more complex than Stroker (opened paths) to ignore outside segments but maintain the polygon closed i.e. insert corner points (on the clip boundary) when an outside segment crosses regions (T / L / B / R)<br>        - init(): adjust the clipping rectangle with the renderer offsets<br>        - finishPath(): totally ignore the path if the accumulated outcode is outside<br>        - finish(): initialize corner points (if needed) and use the index stack to emit all stored corners before emitting lineTo() to the current point<br>        - closePath() / pathDone(): use finishPath() to emit remaining points<br>        - moveTo(): initialize clipping state (outcodes, outside)<br>        - lineTo() / quadTo() / curveTo() : added clipping = trivial segment rejection based on point outcodes and calls clip() to insert corner points if needed + update the accumulated outcode (for finishPath)<br>        - clip(): tricky (but tested) solution to insert 1 or 2 corner points in the index stack when the segment outcodes are different but only on left or right sides<br>    - added the PathTracer class that log PathConsumer2D methods (std out)<br><br>- MarlinCache: fixed syntax of the useRLE flag (shorter conditions)<br>- MarlinConst: moved all WIND / CAP / JOIN constants here + added outcode constants (sides & masks)<br>- MarlinProperties: added system properties for clipping<br>- RendererStats: updated statistics for new features<br>- Version: updated version to "marlin-0.8.2-Unsafe-OpenJDK"<br><br>- added new ClipShapeTest (jtreg) that checks all possible combinations of (cap / join) for random polyline (Stroker) and polygons (Filler) comparing image outputs rendered with clipping enabled vs disabled<br><br></div>Thanks for your time,<br><div><br clear="all"><div><div><div><div>Cheers,</div><div>Laurent Bourgès
</div></div></div></div></div></div>