Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #46942 ## Problem The terminal's monospace grid forcing logic in `LineLayoutCache` breaks rendering of combining marks in complex scripts. Thai, Lao, Arabic, Hebrew, Myanmar, Khmer, and other scripts use combining characters (vowels, tone marks, diacritics) that should render on top of or below their base character — not in a separate cell. The root cause is in `apply_force_width` within `line_layout.rs`. After HarfBuzz correctly shapes the text (positioning combining marks at the same x coordinate as their base character), the force-width loop blindly increments the cell position counter for **every** glyph — including zero-advance combining marks. This displaces them into the next cell, breaking the visual output. For example, Thai `สวัสดี` renders as `ส ว ั ส ด ี` with vowels and tone marks scattered across separate cells. #39526 previously fixed Latin combining characters (like NFD-normalized é) by handling them at the terminal cell level via `append_zero_width_chars`. That fix works when alacritty's cell model already identifies the characters as zero-width. However, many complex script combining marks still get mispositioned at the shaping layer — which is what this PR addresses. ## Solution Extracted `apply_force_width_to_layout()` in `line_layout.rs` that detects combining marks during the force-width pass by checking whether a glyph's shaped x position has advanced by at least half a cell width beyond the previous base character. Combining marks (which HarfBuzz places at the same x as their base) are kept at their shaped position relative to the forced base, rather than being pushed to the next cell. This approach is **script-agnostic** — it works for all complex scripts (Thai, Arabic, Devanagari, Myanmar, Khmer, etc.) without hardcoding Unicode ranges or disabling the monospace grid. The fix lives at the text shaping layer in GPUI, so it benefits any consumer of `LineLayoutCache` that uses `force_width`. The two duplicate force-width loops (in `layout_line` and `layout_line_by_hash`) are consolidated into the single shared helper. ## Testing **Unit tests** cover the following scenarios: - Latin text positions remain unchanged - A single combining mark stays at its base character's cell - A base character following combining marks gets the correct next cell - Multiple stacked combining marks all stay anchored to cell 0 - Drifted base positions respect the existing 1px tolerance **Manual testing** with the following scripts in the integrated terminal: | Script | Test text | What to look for | |--------|-----------|-----------------| | Thai | `สวัสดีครับ ภาษาไทย ก้อนหิน น้ำตก` | Vowel signs (ั ี) and tone marks (้) render above/below consonants, not in separate cells | | Lao | `ສະບາຍດີ ພາສາລາວ` | Vowel signs stay attached to consonants | | Arabic | `بِسْمِ اللَّهِ الرَّحْمَٰنِ` | Diacritics (harakat) render on their base letters | | Hebrew | `בְּרֵאשִׁית בָּרָא אֱלֹהִים` | Vowel points (nikud) stay under/over their letters | | Hindi | `नमस्ते हिन्दी भाषा` | Vowel matras render correctly on consonants | | Bengali | `বাংলা ভাষা নমস্কার` | Combining marks stay attached | | Tamil | `தமிழ் மொழி வணக்கம்` | Vowel signs render correctly | | Myanmar | `မြန်မာဘာသာ မင်္ဂလာပါ` | Combining marks and medial consonants stay in place | | Khmer | `ភាសាខ្មែរ សួស្តី` | Subscript consonants and vowel signs render correctly | <details> <summary>Script to reproduce</summary> ```sh echo "=== Thai ===" echo "สวัสดีครับ ภาษาไทย ก้อนหิน น้ำตก" echo "" echo "=== Lao ===" echo "ສະບາຍດີ ພາສາລາວ" echo "" echo "=== Arabic ===" echo "بِسْمِ اللَّهِ الرَّحْمَٰنِ" echo "" echo "=== Hebrew ===" echo "בְּרֵאשִׁית בָּרָא אֱלֹהִים" echo "" echo "=== Hindi (Devanagari) ===" echo "नमस्ते हिन्दी भाषा" echo "" echo "=== Bengali ===" echo "বাংলা ভাষা নমস্কার" echo "" echo "=== Tamil ===" echo "தமிழ் மொழி வணக்கம்" echo "" echo "=== Myanmar ===" echo "မြန်မာဘာသာ မင်္ဂလာပါ" echo "" echo "=== Khmer ===" echo "ភាសាខ្មែរ សួស្តី" ``` </details> ### Before <img width="1144" height="740" alt="Screenshot 2569-04-05 at 10 43 00" src="https://github.com/user-attachments/assets/bce2075a-9e19-40dd-81ea-0e29a451b781" /> ### After <img width="1144" height="747" alt="Screenshot 2569-04-05 at 11 22 55" src="https://github.com/user-attachments/assets/e0613bf6-8452-4c65-b893-f9931a471b2e" /> ### Tests passing <img width="1144" height="740" alt="Screenshot 2569-04-05 at 11 20 22" src="https://github.com/user-attachments/assets/9100bd77-4ea6-4f77-ae31-5129484552fd" /> Release Notes: - Fixed terminal rendering of combining marks in complex scripts (Thai, Arabic, Hebrew, Devanagari, Myanmar, Khmer, and others) where vowel signs and tone marks were incorrectly displaced to adjacent cells instead of rendering on their base characters. --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
1 file changedLine totals unavailable