[graphite] Add coverage logic to AnalyticRoundRectRenderStep
As implemented, this handles the majority of cases correctly. The two
exceptions are when adjacent and/or opposite corner circles intersect
each other (detected but not yet handled in VS), and issues blending
the linear distance with per-pixel distance under extreme perspective.
These issues should be more easily addressed in a follow-up CL after
additional cleanup of the vertex mesh is finished.
The basic strategy is to calculate either a device-space distance to
an edge that's interpolated across the triangle, or to pass down
coords on a normalized circle and a Jacobian to calculate f/fwidth in
the fragment shader. Vertices always calculate edge distance and the
normalized circle coords/derivatives since they can be used by both
linear-filled triangles and per-pixel filled triangles. The
perspective-correct Jacobian ends up being equivalent to what we had
to do for the perspective-correct normal matrix when doing device
normal outsets, so that logic has been consolidated.
Currently edge distance is a single float varying, so the triangle
function for a stroke's coverage: (0 up to stroke-radius, then back
down to 0) is handled by 3 rings of vertices for the outside, center,
and inner stroke edge. This makes other interpolation of parameters
trickier and makes it harder to switch between hairline and
non-hairline modes. In follow up work the plan will be to remove the
center vertex ring and interpolate two opposing edge distances and
then take the minimum in the fragment shader.
The most complex changes to the logic are related to handling strokes
that start to self intersect in various ways. When the stroke is wide
enough that the interior is completely filled, the vertex structure is
adjusted to match that of fills (AA inset for per-pixel corners is
moved to the outer stroke edge). If just the AA insets would
intersect, the center vertices are snapped to the center but the
normal inset vertices are placed on the actual inner stroke edge,
which ensures we preserve miter corners even if the geometry isn't
square (since then the edge from outer corner to center wouldn't pass
through the interior miter intersection anymore). This same general
approach can be used when the actual corner curves intersect each
other, but that hasn't been fully implemented yet.
Bug: b/241403427
Bug: b/241402913
Bug: b/241403207
Bug: b/241403109
Change-Id: I85f70a60a64d85612e3d1695574d153726bb4aff
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/610180
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
1 file changed