Honour the emoji presentation selector (VS16) in font selection - #692
Open
taladar wants to merge 1 commit into
Open
Honour the emoji presentation selector (VS16) in font selection#692taladar wants to merge 1 commit into
taladar wants to merge 1 commit into
Conversation
A cluster carrying `U+FE0F` (VS16) explicitly requests the emoji presentation per UTS linebender#51, but font selection ignored the request: the emoji family is appended *after* the requested families, so a text font that happens to cover the base codepoint wins and the cluster renders as a monochrome text glyph. `❤️` (`U+2764 U+FE0F`) is the motivating case. `U+2764` has a dingbat glyph in common UI text fonts (DejaVu Sans, Inter, …), so the text font matches first and the emoji family is never reached — the selector that asks for emoji presentation has no effect. Emoji with no text-font glyph (`🎉`, `🇯🇵`) are unaffected, which is why this is easy to miss. The emoji family cannot simply be tried first in general: `is_emoji` is the raw Emoji/Extended_Pictographic property, which is also true for `5`, `#` and `▶` — codepoints whose default presentation is text and which would then wrongly render as emoji. The request has to be honoured only where it is actually made. So track which presentation, if either, a cluster explicitly asks for, and put the emoji family first only for VS16: - Add `Presentation` (`Unspecified` / `Text` / `Emoji`) and record it on `CharCluster` while filling it. This is deliberately finer-grained than the existing `is_variation_selector()`, which cannot distinguish the two emoji variation selectors — they request *opposite* presentations. - In `select_font`, order the emoji family before the requested families when the cluster requests `Presentation::Emoji`. `U+FE0E` (VS15) requests the text presentation, so it keeps the existing ordering, which already prefers the text font whenever one covers the codepoint. Verified against a bundled CBDT emoji font with Inter as the primary family: `❤️` now resolves to the emoji font while `❤` (no selector), `5`, `#` and Latin text all still resolve to Inter. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
|
Apparently that macOS failure does point towards a real bug with the approach that might be worth further consideration. In particular it now prioritizes an emoji font over an explicitly configured font family that happens to also have emoji versions of the character. So what we would need to know to solve this properly is how a given font renders it so we can decide if that font is a valid candidate, that seems related to the #695 issue I opened too where the selection logic also doesn't have all the information to make an informed decision. |
Contributor
Collaborator
|
We may well also want to support font-variant-emoji as a style. |
Member
|
(#693 (comment) also applies here). I do suspect that the approach in #620 is more complete; I'm reviewing that PR now. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A cluster carrying
U+FE0F(VS16) explicitly requests the emoji presentation per UTS #51, but font selection ignored the request: the emoji family is appended after the requested families, so a text font that happens to cover the base codepoint wins and the cluster renders as a monochrome text glyph.❤️(U+2764 U+FE0F) is the motivating case.U+2764has a dingbat glyph in common UI text fonts (DejaVu Sans, Inter, …), so the text font matches first and the emoji family is never reached — the selector that asks for emoji presentation has no effect. Emoji with no text-font glyph (🎉,🇯🇵) are unaffected, which is why this is easy to miss.The emoji family cannot simply be tried first in general:
is_emojiis the raw Emoji/Extended_Pictographic property, which is also true for5,#and▶— codepoints whose default presentation is text and which would then wrongly render as emoji. The request has to be honoured only where it is actually made.So track which presentation, if either, a cluster explicitly asks for, and put the emoji family first only for VS16:
Presentation(Unspecified/Text/Emoji) and record it onCharClusterwhile filling it. This is deliberately finer-grained than the existingis_variation_selector(), which cannot distinguish the two emoji variation selectors — they request opposite presentations.select_font, order the emoji family before the requested families when the cluster requestsPresentation::Emoji.U+FE0E(VS15) requests the text presentation, so it keeps the existing ordering, which already prefers the text font whenever one covers the codepoint.Verified against a bundled CBDT emoji font with Inter as the primary family:
❤️now resolves to the emoji font while❤(no selector),5,#and Latin text all still resolve to Inter.