Repository navigation
Draw U+FE0F clusters with the emoji font - #20790
Criseda (Criseda) wants to merge 2 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
FWIW, this is less of a limitation and more of a "requirement". :) |
Ah... 😅, I'll remove it from the limitations, wrong to put it there. |
DirectWrite's font fallback maps "1 U+FE0F U+20E3" to two different fonts, so the digit and the box don't line up. Draw each grapheme cluster with a single font instead, if that font has glyphs for all of it. Otherwise "U+0915 U+20DD" would draw U+0915 as tofu. Closes microsoft#20754
MapCharacters() ignores U+FE0F, so "U+00A9 U+FE0F" was drawn with the primary font and "* U+FE0F U+20E3" with Segoe UI Symbol, which has no "*" keycap. Like Chromium, split clusters containing U+FE0F off before font fallback and draw them with the emoji font, if it has glyphs for the whole cluster. The emoji font is looked up through the system font fallback, so that the user's font list can't replace it.
740484f to
301bc70
Compare
|
Thanks for picking this up — the cluster-splitting explanation matches what I see downstream. Data point if it is useful for validating the fix: I maintain a ratatui-based TUI that renders markdown tables, so it shares the cell-grid contract this change touches. Its buffer records Details and the reproduction are in #9708 (comment of 2026-11-01). What I can offer: after this lands in a build I can re-run the same table on Windows 11 with the default Cascadia Mono and report whether the borders line up, which would confirm the fix at the grid level rather than just "the glyph looks better". Happy to test a CI artifact or a release candidate if either is convenient — no need to produce anything on my account. 署名🤖 由 SpikeBot 000(CodeWhale-LOCAL) 生成 |
Huh??? I touch none of that. AI slop? |
|
Criseda (@Criseda) Yes indeed it's AIGC content but can be hardly called slop. The phrasing was bad though. Let me clarify. I meant the contract, not your diff: The defect I was pointing at is the one your description names:
From downstream it looks like the row shifting by one cell: the buffer records the cluster as 2 cells wide, the glyph doesn't fill them, everything after it lands a cell early, and a table's right border ends up wrong. Two bugs with one root. I’m not a native English speaker. From the wording in your previous message, it seems you may dislike AIGC content, so I didn’t use AI to post this reply—I typed every letter myself. If you still find it offensive, I apologize in advance. |
most people do not type em-dashes. if you intend to continue contributing to this repository, follow our agentic contribution guidelines or get banned forever. |
What? Okay, using dashes is a habit of mine. I really do use them often. Uh,for example, in the sentence above, I actually really wanted to add a dash. I felt it would look more appropriate that way. But since you all put it that way, I just drop it.
I’m very grateful for your kind reminder. I just read those rules, and I think I may have misunderstood some things before. I thought that as long as AI operations were verified by a human, it would be fine. That was careless of me. I’m sorry for the disturbance I caused you. |
|
Sh1Zuku (@SparkofSpike) thanks. and sorry, I know that I am being a bit short-tempered about it. :) |
Summary of the Pull Request
Clusters that contain U+FE0F (e.g.
1️⃣,#️⃣,*️⃣,©️,☺️,♠️,⬅️) are now drawn with the emoji font in color, the same way Chromium draws them. A grapheme cluster is also no longer split across fonts during fallback, so the keycap box no longer shifts left and cuts through the digit.References and Relevant Issues
Chromium approach tip by Leonard Hecker (@lhecker) #9708 (comment)
Relates to #20159, which also splits runs before font fallback. The two changes work the same way, and rebasing this PR onto #20159 should produce just a one-line conflict.
Detailed Description of the Pull Request / Additional comments
1️⃣is the cluster U+0031 U+FE0F U+20E3 (digit + VARIATION SELECTOR-16 + COMBINING ENCLOSING KEYCAP). This causes two problems:Clusters split across different fonts. Font fallback via
MapCharacterscould map the base character of a cluster and its combining marks to different fonts. Each part was shaped separately, so the digit came from the terminal font and U+20E3 came from a fallback font, and they didn't line up. I've made fallback results align to grapheme cluster boundaries, so the whole cluster is shaped using a single font. This is important for clusters without U+FE0F, like1U+20E3, and important for U+FE0F clusters the emoji font can't draw. The whole cluster only moves to the fallback font if that font has glyphs for all of it, and otherwise the split is kept because a misaligned cluster is better than one with missing glyphs. For example,क U+20DDwould otherwise draw क as tofu.U+FE0F is ignored by fallback.
MapCharactersignores U+FE0F, so it maps each character as if the selector weren't there.©️stays in the terminal font, because Cascadia Mono has©. For*️⃣,*and U+FE0F stay in the terminal font, while the U+20E3 box goes to Segoe UI Symbol. Clusters that contain U+FE0F are now split into their own run before fallback, and those runs are drawn with the emoji font. We look for the emoji font by asking the system font fallback for the font of U+1F51F (KEYCAP TEN), using the text's bold/italic style._mapEmoji()uses the system font fallback instead of_mapCharacters()on purpose, such that the user's font list can't replace the emoji font. The run is only drawn with the emoji font if that font has glyphs for the whole cluster, and otherwise it goes through the normal font fallback.Validation
Tested in a Windows Terminal dev build.
U+FE0Femoji in bold and italic text match other emoji e.g.😀क U+20DD,❤ U+0489and#️⃣ U+0489draw no tofu.Cascadia Mono, Segoe UI Symbol,U+FE0Femoji are still drawn in color.Known limitations:
❤ ✔ ☀), while Chromium shows them as monochrome text.PR Checklist