Skip to content

feat: color anti-aliasing for subcell-shape charsets - #47

Merged
tamirelazar merged 15 commits into
devfrom
feat/render-color-antialiasing
Jun 20, 2026
Merged

feat: color anti-aliasing for subcell-shape charsets#47
tamirelazar merged 15 commits into
devfrom
feat/render-color-antialiasing

Conversation

@tamirelazar

Copy link
Copy Markdown
Owner

Summary

Subcell-shape charsets (Braille, Quadrant, HalfBlock, Ascii) render shape at 2–4× resolution but carry a single foreground color per terminal cell, so thin diagonal veins staircase in color (visible even in --palette mono — it's brightness-domain, not a hue bug). This pre-blurs the per-cell color signal with a 3×3 kernel so color washes into a gradient while the glyph stays crisp (the shape path reads raw quadrant data, untouched).

What's included

  • AaStrength { Off, Subtle, Strong } per-charset color-AA, stored as [AaStrength; 7] indexed by charset. Default: Braille = Strong, all others Off.
    • Strong = uniform 3×3 box blur; Subtle = weighted-center (0.5·self + 0.5·mean(neighbors)).
    • Blurs BOTH base brightness AND the temporal diff_norm accent field with one kernel.
  • AA-eligible: Braille / Quadrant / HalfBlock / Ascii. Excluded: HalfBlockDual (already 2 colors/cell), Sculpted, Shade, Points.
  • First-class parameter: round-trips undo/redo, reset-to-defaults, and saved configs (defensive on pre-feature configs).
  • Surfaces: CLI --color-aa <off|subtle|strong> (auto: strong for braille, off otherwise), runtime " key (cycles active charset's AA), options-overlay "Color AA" row, --explain + README docs.
  • Guarantee: when AA is Off or the charset is ineligible, output is byte-identical to before (guarded by a test using an ineligible charset at Strong).

Test plan

  • cargo test --lib — 869 green (881 with --all-features)
  • cargo test --test cli_integration / integration_app — green
  • cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --check — clean
  • Visual regression: 54 pass. Regenerated 3 AA-affected goldens (braille_mode, braille_brightness, etching). The lumen_preset golden is a pre-existing macOS-vs-Linux temporal divergence unrelated to this change (CI/Linux is source of truth).
  • No allocations in blur hot loops (one Vec<f32> per blurred field per frame).

Notes

  • The blur kernel is pure f32 add/mul/div (no transcendentals → deterministic cross-platform).
  • Subtle kernel locked to weighted-center after a dev A/B (the directional variant was added then removed).

Make --color-aa a typed Option<AaStrength> via FromStr so clap rejects
invalid values with a helpful error instead of silently falling back to
Off; remove the hand-rolled parse-and-ignore paths in resolved_color_aa
and the runner.

Replace the duplicated [AaStrength; 7] literals with a NUM_CHARSETS const
tied to ALL_CHARSETS.len(), so per-charset arrays stay locked to the
charset count.

Drop two provably-dead per-cell bounds checks in the blur hot loop in
favor of a single debug_assert on the width*height invariant.
@tamirelazar
tamirelazar merged commit 84795cf into dev Jun 20, 2026
3 checks passed
@tamirelazar
tamirelazar deleted the feat/render-color-antialiasing branch June 20, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant