[OpenJDK 2D-Dev] RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0

Jim Graham james.graham at oracle.com
Sat Aug 26 00:22:18 UTC 2017

Hi Laurent,

I'm just reading through the code now to get a handle on the nature of the changes...(and starting with the 2D version)...

[D]Dasher.java - why the changes from (firstSegIdx > 0) to (firstSegIdx != 0)?
[D]Dasher.java - why is there a new goto_starting() which is only used from one place?  To be able to add final to the 
[D]Dasher.java, line 268ish - why move the call to out.moveto() down a line?

[D]Stroker.java, line 170ish - you added final to the float params, but not the double
[D]Stroker.java, line 196ish - why are ROUND treated differently.  You have a question on that as well in a comment.
[D]Stroker.java, line 196ish - CAP_SQUARE would require more than lw/2 padding.  I think it needs lw*sqrt(2)/2 padding.

I would think the padding would be (max of the CAP/JOIN values below):
CAP_BUTT - lw/2
CAP_ROUND - lw/2
CAP_SQUARE - lw/2 * sqrt(2)
JOIN_MITER - max(lw/2, miter_limit * lw)

In other words:
- lw/2 by default
- if CAP_SQUARE then multiply that by sqrt(2)
- if JOIN_MITER then max it with limit

I'm still looking through the management of the closed path detection coordinates, but I thought I'd get at least these 
questions out first before the weekend...


On 8/25/17 1:09 PM, Laurent Bourgès wrote:
> Hi,
> Please review Marlin/FX upgrades that provide an efficient path clipper in
> Stroker (float / double variants) fixing the bug JDK-8184429
> <https://bugs.openjdk.java.net/browse/JDK-8184429>
> Marlin2D patch (jdk10):
> http://cr.openjdk.java.net/~lbourges/marlin/marlin-080.0/
> MarlinFX patch (openjfx10):
> http://cr.openjdk.java.net/~lbourges/marlinFX/marlin-080.0/
> Path Clipper in (D)Stroker:
> - it uses outcode computation (cohen - sutherland) for segment edges (2 for
> lines, 3 for quads, 4 for cubics)
> - it opens the path when a segment is invisible ie special moveTo() and
> ignore invisible joins; it does not compute any intersection (line /
> curve), it just skips useless segment for better performance and accuracy
> - the ClosedPathDetector is needed to infer if the path is closed or not
> (call to closePath) to produce caps when appropriate. It reuses the former
> PolyStack (moved into Helper classes) to store the forward segments
> - the clip rectangle is adjusted either in Stroker but also in
> Transformer2D to take into account the mitter limit, stroker width and also
> the Renderer offset
> That's why it can not be applied to closed paths (fill operations) as the
> path must remain closed in such case (concave polygon).
> This could be implemented later as it needs to insert corner points when
> needed to avoid artefacts; so the algorithm seem more complicated to me.
> Marlin2D / FX Patches are slightly different to handle the Renderer offsets.
> I tested these patches against my MapBench test with a small clip and
> several affine transforms: it does not produce any artefact (0 pixel
> difference between clip=true/false)
> PS: I also improved the accuracy of Renderer's AFD by using the kaham
> compensated-sum approach (later patch)
> Cheers,
> Laurent Bourgès

More information about the 2d-dev mailing list