Replaces the previous heuristic (font_monospace_em_width.is_none() ⇒ 2
cells) which was reviewed as unsound: Arabic, dingbats, math symbols and
other narrow scripts pulled from non-monospace fallback fonts would all
have been forced to 2 cells. It also didn't handle ZWJ emoji clusters
or ambiguous-width chars correctly.
Proper fix, computed at shape time when `line: &str` is in scope:
- new ShapeGlyph.terminal_cells: u8 (0, 1 or 2)
- populated via unicode-width crate applied to the cluster text
line[start..end] (harfrust path, uses UnicodeWidthStr) or to the
single codepoint (no-font fallback path, UnicodeWidthChar)
- layout_to_buffer consumes it when match_mono_width is Some:
x_advance = cells * mono_width
instead of the previous round(x_advance / mono_width) * mono_width
which produced variable cell counts for fallback glyphs.
Covers:
- ASCII + Latin → width 1 (unchanged visual)
- CJK + fullwidth → width 2 ✓
- Emoji (incl. ZWJ) → width 2 ✓ (cluster text handles the ZWJ case)
- Arabic / Hebrew → width 1 ✓ (was wrongly snapped to 2 before)
- Combining marks → width 0 ✓ (zero-advance, matches terminals)
- Variation selectors → width 0 ✓
Limitations: ambiguous-width chars (EAW=A) resolve to 1 via unicode-width
default; a 'cjk' ambiguous mode (unicode-width::UnicodeWidthChar::width_cjk)
could be exposed later as a Buffer flag if needed — not needed for typical
terminal use, matching most wcwidth implementations.
Based on review feedback from lionel@wopr.io on the initial heuristic patch.
|
||
|---|---|---|
| .. | ||
| edit | ||
| font | ||
| attrs.rs | ||
| bidi_para.rs | ||
| buffer.rs | ||
| buffer_line.rs | ||
| cached.rs | ||
| cursor.rs | ||
| glyph_cache.rs | ||
| layout.rs | ||
| lib.rs | ||
| line_ending.rs | ||
| math.rs | ||
| render.rs | ||
| shape.rs | ||
| shape_run_cache.rs | ||
| swash.rs | ||