render: fit multi-codepoint clusters to their cells #17

Closed
opened 2026-10-01 12:50:30 +09:00 by natsukium · 0 comments
Owner

#10 shrinks a single-char glyph whose advance overruns its cells, but clusters take composite_cluster → ensure_glyph_id (crates/felis-render-wgpu/src/glyphs.rs) and push_cluster_cell (instances.rs ~606–664), which rasterize at full size and place glyphs by raw pen advance. kitty and WezTerm fit these; felis and Alacritty overlap the next character.

Repros:

  • printf '※́X': one-cell cluster, drawn ~2.5 cells wide over X. Same with ※︎, ①́.
  • printf '🇦🇦X' (no flag glyph), 🐈‍🦀X (non-RGI ZWJ), 😀🏻X, #️⃣X (keycap not ligated by swash): the grid clamps to 2 cells, the shaper returns two full-width glyphs (~3.4 cells).
  • A VS16 widen refused at the last column or before an occupied cell leaves a 2-cell colour glyph in 1 cell: \e[999C❤️, ❤X\e[D️ (see #12).

Fix direction: apply the same advance-vs-footprint fit per cluster, using the cell's actual footprint (its Spacer, or 1 when the widen was refused). Also: docs/explanation/rendering/text-shaping.md "Prior art" describes a ligature-run check that glyph advances match n_graphemes × cell_width with a per-cell fallback; apply_shaped_run has no such check. Either add it or correct the doc.

Depends on #10.

#10 shrinks a single-char glyph whose advance overruns its cells, but clusters take `composite_cluster` → `ensure_glyph_id` (`crates/felis-render-wgpu/src/glyphs.rs`) and `push_cluster_cell` (`instances.rs` ~606–664), which rasterize at full size and place glyphs by raw pen advance. kitty and WezTerm fit these; felis and Alacritty overlap the next character. **Repros:** - `printf '※́X'`: one-cell cluster, drawn ~2.5 cells wide over `X`. Same with `※︎`, `①́`. - `printf '🇦🇦X'` (no flag glyph), `🐈‍🦀X` (non-RGI ZWJ), `😀🏻X`, `#️⃣X` (keycap not ligated by swash): the grid clamps to 2 cells, the shaper returns two full-width glyphs (~3.4 cells). - A VS16 widen refused at the last column or before an occupied cell leaves a 2-cell colour glyph in 1 cell: `\e[999C❤️`, `❤X\e[D️` (see #12). **Fix direction:** apply the same advance-vs-footprint fit per cluster, using the cell's actual footprint (its Spacer, or 1 when the widen was refused). Also: `docs/explanation/rendering/text-shaping.md` "Prior art" describes a ligature-run check that glyph advances match `n_graphemes × cell_width` with a per-cell fallback; `apply_shaped_run` has no such check. Either add it or correct the doc. Depends on #10.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
felis-terminal/felis#17
No description provided.