Commit Graph

8 Commits

Author SHA1 Message Date
Nico Weber
d569238896 LibGfx: Add support for stroke dash patterns
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>.)
2024-11-07 09:12:13 -05:00
Nico Weber
d6e325ef6b LibGfx+Clients: Make Path::stroke_path() take a parameter struct
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.
2024-10-25 20:35:23 -04:00
Nico Weber
cc5c332c2e LibGfx+Tests: Implement miter join for path stroking
The miter limit is hardcoded for now.
2024-10-25 18:12:58 -04:00
Nico Weber
66378471a0 LibGfx: When stroking zero-lengths paths, draw round and square end caps
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.
2024-10-16 18:18:43 -04:00
Nico Weber
e90e4b4f25 LibGfx: Add support for square linecaps when stroking paths
This is now easy :^)
2024-10-16 18:18:43 -04:00
Nico Weber
03eda80d99 LibGfx: Make path stroke butt line caps look less janky
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.
2024-10-16 18:18:43 -04:00
Nico Weber
b113ce62b5 LibGfx: Store if a subpath is closed, and use that when stroking
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.)
2024-10-06 18:05:39 -04:00
Nico Weber
c1ea8fa01c LibGfx+Tests: Fix infinite loop in butt line cap drawing
Sometimes going across would put is one active range away from
being in-bounds, so check the two neighboring ranges too.
2024-09-27 20:18:55 -04:00