-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Round join and all cap styles #414
Conversation
@@ -280,39 +280,95 @@ fn flatten_cubic(cubic: Cubic, local_to_device: Transform, offset: f32) { | |||
} | |||
} | |||
|
|||
// Flattens the circular arc that subtends the angle begin-center-end. It is assumed that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not obvious from this comment how the direction is chosen. It must be based on the value of angle
, but it feels like 'pacman' style arcs will be difficult.
I worry that if n_lines is big, the arc would draw the full way around, but if n_lines is small, it would end up drawing the closing part, rather than the full way around
I'm not sure that this is coherent - my last maths education was many years ago.
Maybe this would only be an issue if n_lines is 1, which is impossible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The direction of the arc is always a counter-clockwise rotation starting from begin
, towards end
, centered at center
, and will be subtended by angle
(which is assumed to be positive). If angle
terminates the arc before it smoothly reaches end
, a line will be drawn from the end of the arc towards end
. I will document this.
n_lines
only depends on the radius of the arc and the chosen tolerance. For n_lines
to be theta
must be close to acos
can't return that by definition. If you somehow got n_lines == 1
, basically no arc would be drawn and you'd get a line connecting begin
and end
.
Realistically, n_lines
could be as low as x
is very small, which can happen if tol
and radius
are close to each other (the code prevents radius
from being smaller than tol
, so that case isn't possible). You'd only get into that situation with a sub-pixel radius. At that scale, the coarseness of the approximation won't be easily noticeable. If you increased the tolerance to make this possible at larger radii, with n_lines == 2
you'd get a shape resembling a wedge/triangle (I tested this locally, which works as you'd expect).
That said, this function is meant for drawing caps and joins where angle
begin
, center
, and end
points are chosen carefully (so that the angle and winding make sense).
Though there is something that should get fixed: I think selecting 1u
when theta <= EPS
is the wrong thing to do and this is a bug. That happens when the subdivision count tends to infinity. It's probably better to define a MAX_LINES
and return that instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the very detailed reply!
I hadn't clocked the additional invariants being maintained by the callers
Those pictures are very cool as well!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad they were helpful 🙂. I updated the comment above flatten_arc
in latest commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Exciting to see this all coming together!
5c82590
to
8001151
Compare
Rather than using the `Cubic` struct, the flattening helpers operate on `CubicPts`, path index, and parallel curve offset directly. The older stroke bbox computation was removed since it's no longer used.
Implemented the logic for round join and cap styles. The logic generates lines directly from a circular arc. The arc gets flattened in the curve's local coordinate space and transformed to device-space coordinates post-flattening (just like strokes work in `flatten_arc`). An advantage of flattening an arc directly is that the logic is very simple and involves way less ALU compared to `flatten_cubic`. The disadvantage is that the structure of join/cap style handling is now highly divergent. To reduce divergence, the shader could be restructured to model a (not perfectly circular) arc with cubic Beziers and let the control flow converge at a call to `flatten_cubic`.
Implement butt/square/round start and end cap styles
If the segment angle falls below epsilon, return MAX_LINES instead of 1u for the line segment count. Total number of lines per arc is now capped at 1000.
8dc91f5
to
bae1d1a
Compare
Clarified the function's behavior and input invariants
Implemented the logic for round join and cap styles. The logic generates lines directly from a circular arc. The arc gets flattened in the curve's local coordinate space and gets transformed to device-space coordinates post-flattening.
This completes the initial implementation of all stroke styles. This PR is based on #412.
#303