feat: legible ReaSampler 9000 editor — bigger knobs, ms time constants, per-ring double-click reset, and an antialiased draw pass

This commit is contained in:
2026-08-01 09:16:30 -04:00
parent 213ecfafe6
commit 7f74b11dce
27 changed files with 859 additions and 285 deletions
+61
View File
@@ -761,3 +761,64 @@ re-skin).**
font obligation.
- **Phase S is not gated on Phase L** — S7S13 proceeded in parallel; they adopted the
kit via L3 when it landed. Phase L is complete (L1L7 all landed).
---
## 8. Antialiasing disposition — the drawn-surface audit
A standing inventory of every class of drawn surface and how it answers antialiasing, so the
audit is re-runnable rather than a one-off sweep. **The rule the table applies:** an
axis-aligned fill or hairline has no aliasing to remove — LICE's `aa` flag is inert on a pure
horizontal or vertical run — so "already clean" there is a statement about geometry, not a
concession. Everything with a slope or a curve must draw through a primitive that antialiases.
**Primitive gotchas this audit established (verified in `vendor/WDL/WDL/lice/`):**
- `LICE_Line` takes INTEGER endpoints. `aa=true` antialiases the span, but the endpoints are
still quantized; `LICE_FLine` keeps float endpoints and `LICE_ThickFLine` is *always*
antialiased and adds width.
- `LICE_FillTriangle` takes **no** `aa` parameter at all — its sloped edges alias, and the
only fix inside the kit is to re-stroke those edges with an AA line in the same ink.
- LICE has no thick-arc primitive. A wider ring is drawn as adjacent 1 px `LICE_Arc` calls at
stepped radii, which keeps every ring antialiased.
- A min/max waveform column plot cannot be antialiased by the column fill itself (the columns
are vertical). The outline is what reads as jagged, so it is stroked separately.
| Surface | Where | Disposition |
|---|---|---|
| Radial knob track + value arc | `editor_internal.h` `drawKnobFace` | Was AA (`LICE_Arc`, 1 px). **Widened** to a 3 px stacked-radius ring; the bigger knob is what made 1 px read thin. |
| Knob needle | `drawKnobFace` | **Fixed** — was integer-endpoint `LICE_Line`; now `LICE_ThickFLine` (always AA, float endpoints, 2 px). |
| Inner curve dial arc + needle | `drawInnerDial` | **Fixed** — 2 px stacked-radius arc; needle moved to `LICE_FLine` with float endpoints. |
| Staged envelope segment slopes | `editor_paint_waveform.cpp` | **Fixed**`LICE_ThickFLine` at 2 px, replacing integer-endpoint `LICE_Line`. |
| Spline (drawn EG) contour | `editor_paint_waveform.cpp` `paintSplineOverlay` | **Fixed** — same treatment, one trace grammar. |
| Velocity-curve popup trace | `editor_paint_curve.cpp` | **Fixed** — same treatment. |
| Velocity-curve mini thumbnail | `editor_paint_curve.cpp` | Left at 1 px AA `LICE_Line` — a 2 px trace blots at thumbnail scale. |
| Waveform min/max columns | `draw_kit.cpp` `drawWaveform` | **Fixed** — column fill unchanged (it cannot alias), plus an AA `LICE_FLine` stroke joining each column's extremes to its neighbour's, in the same ink. Shared with the docked bank panel and the browser cards. |
| Preview play triangle | `editor_paint_chrome.cpp` | **Fixed**`LICE_FillTriangle` has no `aa`; its two sloped edges are re-stroked with AA `LICE_FLine`. |
| Envelope/spline node handles (squares) | `editor_paint_waveform.cpp` | Already clean — axis-aligned `LICE_FillRect`. |
| Envelope curve knots (circles) | `editor_paint_waveform.cpp` | Already clean — `LICE_FillCircle` with `aa=true`. |
| Knob body disc | `drawKnobFace` / `drawInnerDial` | Already clean — `LICE_FillCircle` with `aa=true`. |
| Buttons | `draw_kit.cpp` `drawButton` | Already clean — `LICE_RoundRect` with `aa=true`. |
| Piano key faces + edges | `editor_paint_chrome.cpp` `drawKeyboard` | Already clean — axis-aligned fills and a vertical hairline. **See §8.1.** |
| Loop span, crossfade region, marker bars, grab tab | `editor_paint_waveform.cpp` | Already clean — axis-aligned fills. |
| Group fences, card/tab/tooltip borders, focus rings | deck, browse, panel painters | Already clean — `LICE_DrawRect`, axis-aligned. |
| Surface fills + inner edge highlights | `draw_kit.cpp` `fillSurface` | Already clean — `LICE_GradRect` + axis-aligned hairlines. |
| Embed strip (TCP/MCP) | `reasampler_embed.cpp` | Already clean — axis-aligned fills only. |
| Docked bank panel chrome | `panel_render.cpp` | Already clean — axis-aligned fills, rects and hairlines. Its only exposure to this pass is the shared `drawWaveform`. |
| Text | `draw_kit.cpp` `text` | Already clean — `LICE_CachedFont` AA glyph cache (§1.1). |
### 8.1 Was the piano-key width defect an aliasing artifact?
**No.** Every piano key is an axis-aligned `LICE_FillRect` with an integer width, so there is
no sloped or curved edge for aliasing to act on — the defect could not have had that cause.
It was integer-division residue: `keyboard_strip` tiles same-class keys at one integer width
and the indivisible remainder of the band width has to go *somewhere*. The fix put it in
symmetric end margins instead of in a key, which is arithmetic, not rasterization.
**Does the fix survive DPI scaling?** At the client-pixel level, yes — key widths are uniform
by construction at every client width the strip's test sweep covers. Above that level it is
**unverified**, and for a structural reason worth keeping visible: nothing in the instrument
implements `IPlugViewContentScaleSupport`, so a host that scales the plugin window resamples
the already-rasterized uniform widths at the physical-pixel level, where the guarantee no
longer applies. That is a host-scaling question, not an antialiasing one, and it is recorded
as a gotcha in `src/core/instrument/CLAUDE.md`.