docs: record Θ-W7, the arc-and-spline antialiasing fix, and file the scaled-fallback deferral

This commit is contained in:
2026-08-01 15:18:59 -04:00
parent 806a3037a3
commit 6c982cd617
3 changed files with 129 additions and 5 deletions
+56
View File
@@ -613,3 +613,59 @@ reset semantics unit-testable; `editor_controls.cpp` dropped 469→293 lines.
All visual outcomes remain **pending Daniel's by-eye sign-off on `dev`** — sizes,
arc weight, and whether the waveform stroke improves or thickens the docked panel.
Not recorded as accepted.
### Θ-W7-T1 — arc-and-spline-aa
Two defects Daniel found by eye once Θ-W6-T1's antialiasing pass shipped — diagnosing
both corrected the initial reading of each.
- **Arcs never reached opacity.** `LICE_Arc` rasterizes a whole circle clipped per 90°
chunk and splits ink across two pixels by the fractional part of the radius;
`rOuter = radius - 0.5f` is half-integer, so no pixel in the ring was ever opaque —
measured peak alpha 138/255. The three stacked radii also did not tile: spacing
dilates from 1.0 px to 1.41 px at 45°, leaving partial-coverage holes. It read as
fuzz, but it was a stroke that never fully inked.
- **Splines were fully aliased, not gapped.** The apparent dotting was not missing
ink: `LICE_ThickFLine` steps the major axis and structurally cannot gap. The paint
loop passed **integer** `cx`/`cy`, so LICE had no sub-pixel position to interpolate
— every pixel was full or empty with no AA fringe, and integer `cy` quantized the
slope into an alternating 1/2 px staircase that reads as beading at 100%.
- **The cheap fix was rejected.** Float endpoints plus `LICE_ThickFLine` fixes
opacity and the staircase, but `ThickFLine` lays width along the *minor* axis, so
perpendicular weight is `wid·cosθ` — a measured 42% ripple dipping at every 45°
diagonal.
- **What landed:** one pure analytic thick-stroke rasterizer. Coverage is
distance-to-polyline, accumulated with `max()` into a scratch buffer and blended
**once** — the single blend is what structurally prevents the compositing fringe
build-up behind the first defect. An arc is just a polyline, so one code path
replaces the stacked arcs, both spline traces, and the two needles. Pure coverage
math in a new `core/ui/stroke_aa`; the blend loop in a new
`shell/instrument/editor_stroke`. `shell/panel/draw_kit` was deliberately **not**
touched, keeping the docked bank panel and browse cards entirely out of the blast
radius.
- **Measured, before → after:** arc peak alpha 138/255 → 255/255; arc perpendicular
weight 1.623.24 px (67% ripple) → 2.953.11 px (5%); spline weight 1.412.00 px
(29%) → 1.952.01 px (3%). Cost: **+0.09 ms per full editor repaint** (30 arcs
0.113 → 0.169 ms; 500 px contour 0.013 → 0.047 ms), a knowing regression on an
interaction-driven surface, measured in Release against real LICE in an
uncommitted harness.
- **`velocity_curve` gained `subpixelFromPoint`** — sub-pixel y was unavoidable since
integer `cy` was the root cause. The existing integer map now *rounds* the new
float map rather than forking a second formula, so hit-testing is unchanged.
- **Daniel then ruled that every sub-2 px stroker width be enlarged**, because the
stroker can only guarantee an opaque core at width >= 2 px (an opaque pixel needs
`d <= halfWidth 0.5`, and the worst-case pixel-centre-to-centreline distance is
0.5). The knob track arc, the inner-dial needle, and the deck's mini velocity trace
all moved 1.0 → 2.0 px. A test pinning the sub-opaque behaviour at 1 px was kept as
a guard against reintroduction.
- **The audit's method was the root failure, not its output.**
`docs/product/visual-design-language.md` §8 had claimed stacked 1 px `LICE_Arc`
calls "keep every ring antialiased" — false. The Θ-W6 audit verified *which
primitive was called* rather than *what it rasterized*, which is how both surfaces
were signed off clean while never producing an opaque pixel. That sentence is
deleted, the rows are re-dispositioned with measurements, and the methodological
lesson is recorded in §8 as a standing blockquote.
All visual outcomes remain **pending Daniel's by-eye sign-off on `dev`** — nothing was
verified in a live REAPER window; all measurement was against an offscreen bitmap in a
standalone harness. Not recorded as accepted.