Since Java 6 there has been a problem with rendering using a dashed stroke with round caps. Under given circumstances attempts to render a shape like this would cause the JVM to crash from a stack overflow. So why is this happening and how can we avoid it?
Why is this happening?
The cause of this issue is due to the way dashed strokes are handled by the JVM. The JVM attempts to split shapes based on the dash array in order to render with the dashed strokes. Each split causes the shape to be handled on a deeper level of the call stack which is not infinite in Java. With some shapes and dash arrays the process to split the shape would flow over the end of the call stack and cause the JVM to crash.
So if this is a bug in the JRE we can’t fix it. Instead we need to work around it.
How can we avoid this?
We need to find an approach to rendering dashed shapes. One approach to this would be to split the shape into smaller segments. Whilst this won’t find 100% of circumstances for this issue, it does handle a vast majority of them.
So how do we do that?
- Get the path iterator from the shape.
- Work through each command from the shape (move, line, quad curve, cube curve).
- Convert each of these commands to a path for each single command.
- Finally append these single command paths to a single command.
The above steps do a few things that may not be immediately obvious:
- Each single command path is significantly smaller than the original shape.
- When you append the smaller paths to the final path they are not merged.
- Each smaller path is treated as a single path with the dash pattern starting at the same point when they should have different phase values to look correct.
- By appending the smaller paths to the final path, the JVM will handle the dash phase offset for each smaller path.
This approach will not fix all cases. If the shape in question has a single segment that is too large for the JVM to split for example. However in all the real world examples we have uncovered we have yet to encounter this case.