This adds support for dash patterns to Path::stroke_to_fill().
This is used in PDFs, <canvas>, and <svg>.
The implementation is based on the <canvas> spec. It seems to do
the right thing for PDF files too.
(This commit only adds the feature to LibGfx. Future commits will
hook this up for PDF, <canvas>, and <svg>.)
This makes several calling sites shorter, and makes it easier
to add a miter limit with less plumbing in the future.
This also exposed a bug in AffineDisplayListPlayerCPU.cpp: We weren't
passing path linecap style on. I added a FIXME for that for now.
No intended behavior change.
PDF 1.7 spec, p231, 4.4.2 Path-Painting Operators, Stroking:
"If a subpath is degenerate (consists of a single-point closed path or
of two or more points at the same coordinates), the S operator paints it
only if round line caps have been specified, producing a filled circle
centered at the single point. If butt or projecting square line caps
have been specified, S produces no output, because the orientation of
the caps would be indeterminate. (This rule applies only to zero-length
subpaths of the path being stroked, and not to zero-length dashes in a
dash pattern. In the latter case, the line caps are always painted,
since their orientation is determined by the direction of the underlying
path.) A single-point open subpath (specified by a trailing m operator)
produces no output."
In practice, Chrome, Firefox, and Preview all also draw a square
for square line endings (Preview a square rotated 45 degrees). Chrome
even draws something weird-looking for butt caps. (Acrobat only draws
the round cap, per spec.)
https://html.spec.whatwg.org/multipage/canvas.html#trace-a-path sounds
like zero-lengths paths should be ignored for canvas, but in practice
Chrome and Firefox do draw them. (Safari doesn't.)
We don't do linecaps in SVGs yet, but
https://www.w3.org/TR/SVG/paths.html#ZeroLengthSegments says:
"As mentioned in Stroke Properties, linecaps must be painted for
zero-length subpaths when stroke-linecap has a value of round or
square."
With this commit, we now draw round and square linecaps for
zero-lengths paths, which is what's apparently desired most of the
time. Maybe we can add a setting to pick different behavior for
PDF (only draw round caps), canvas (don't draw caps on zero-length
paths), and SVG (draw round and square caps) in the future.
We now put butt line cap vertices in the correct position,
vertical to line direction. We still pretend we're walking on the
pen polygon though, so it's probably possible to make this produce
weird-looking output by making the line cap line segments very
short. In practice, for butt line caps of real-world paths,
it's a big improvement though.
A stroked path that has the same start and end point looks different
depending on if it's closed or not: If it's closed, the start/end point
is drawn as a line join; if it's not closed, the start/end point is
drawn as a cap.
(It has an effect only for stroked paths, but not for filled paths.)
So make Path remember if it's closed or not by adding a ClosePath
segment type.
This matches the canvas, pdf, svg specs.
(TinyVG doesn't have strokes yet.)
This fixes the apparent rendering regression from #25040 / #25044
(which just made an existing bug visible).
(We should probably make an inner and an outer path when stroking a
closed path instead of just giving closed paths a round cap. When
filled, both look identical, but the current approach produces more
geometry. For now, this is good enough.)