Emoji's have a "default presentation", that can either be "text" or "emoji". This is something we have completely ignored up until now; we've simply been searching the fallback list "as usual", using the first font in the list that has glyphs for the searched-for codepoint.
With this patch, we now ignore emoji fonts when looking for an emoji codepoint whose default presentation is "text", and we ignore non-emoji fonts when looking for a codepoint whose default presentation is "emoji".
On a side not: if one is to generalize, the emojis that have "text" as their default presentation are the same ones that wcwidth() returns 1 for.
Some images: the text used here is "$(echo -e '\u263a xyz \u263a\ufe0e abc \u263a\ufe0f') | اَلْعَرَبِيَّةُ | xyz | ויקיפדיה"
I.e. WHITE SMILING FACE (U+263a) using its default presentation (text), followed by the same emoji again, first with an explicit text presentation selector, and then with an emoji presentation selector. Thus, on each row we expect two text-emojis, and one graphical emoji.
This is then followed by "arabic", "xyz", and "hebrew".
There are three rows in the images: the first row is rendered one codepoint at a time, using fcft_glyph_rasterize().
The second row is rendered one grapheme at a time, using fcft_grapheme_rasterize().
The last row is rendered as a single run, using fcft_text_run_rasterize().
Before
Limited primary font (non-ascii glyphs from fallback font):
https://codeberg.org/attachments/086b3616-32d4-4804-a5b4-f1c9bbed1597
Note how the emojis are wrong: the primary font doesn't have this codepoint, and we're falling back to a colored emoji font. Only fcft_grapheme_rasterize() pays any attention to presentation selectors, and only explicit ones.
We're almost rendering the arabic and hebrew correctly; the only issue is that the last emoji should come before the arabic text.
Large/full primary font (primary font has most glyphs):
https://codeberg.org/attachments/c66571dc-8db9-46ae-b62f-6eae752a2de7
Emojis may appear to look better, but that's just because this primary font has the WHITE SMILING FACE emoji. Again, fcft_grapheme_rasterize() handles explicit presentation selectors, and thus the last emoji in the middle row is correct.
The last row is pretty bad; since this primary font has all glyphs, it is shaped in a single go. This is the reason both the arabic and hebrew is rendered "reversed".
After
Limited primary font (non-ascii glyphs from fallback font):
https://codeberg.org/attachments/c4743550-eea6-4ef7-8b92-29f1dcd0fc7b
Large/full primary font (primary font has most glyphs):
https://codeberg.org/attachments/2264d7bd-b36d-430e-b1a1-9d7ea3f7a380
Both images are rendered as correct as one can expect. The ascii/latin characters look different in the two images since the primary font is different. But LTR/RTL is all correct, emojis are all correct (the last emoji in the first row is incorrect, but this is to be expected with fcft_glyph_rasterize(), since it only takes a single codepoint).
Real world usage
Here's a real-world example; two yambar instances, top one using fcft from master, bottom one using fcft from this PR:
https://codeberg.org/attachments/787c5e74-bfd2-4f42-a79d-c1f220ee8032
The three emojis are using the default presentation, explicit text presentation, and emoji presentation, respectively.
Emoji's have a "default presentation", that can either be "text" or "emoji". This is something we have completely ignored up until now; we've simply been searching the fallback list "as usual", using the first font in the list that has glyphs for the searched-for codepoint.
With this patch, we now ignore emoji fonts when looking for an **emoji** codepoint whose default presentation is "text", and we ignore non-emoji fonts when looking for a codepoint whose default presentation is "emoji".
On a side not: if one is to generalize, the emojis that have "text" as their default presentation are the same ones that `wcwidth()` returns 1 for.
Some images: the text used here is `"$(echo -e '\u263a xyz \u263a\ufe0e abc \u263a\ufe0f') | اَلْعَرَبِيَّةُ | xyz | ויקיפדיה"`
I.e. `WHITE SMILING FACE` (U+263a) using its default presentation (text), followed by the same emoji again, first with an explicit text presentation selector, and then with an emoji presentation selector. Thus, on each row we expect **two** text-emojis, and **one** graphical emoji.
This is then followed by "arabic", "xyz", and "hebrew".
There are three rows in the images: the first row is rendered one codepoint at a time, using `fcft_glyph_rasterize()`.
The second row is rendered one **grapheme** at a time, using `fcft_grapheme_rasterize()`.
The last row is rendered as a single run, using `fcft_text_run_rasterize()`.
## Before
### Limited primary font (non-ascii glyphs from fallback font):

Note how the emojis are wrong: the primary font doesn't have this codepoint, and we're falling back to a colored emoji font. Only `fcft_grapheme_rasterize()` pays any attention to presentation selectors, and only explicit ones.
We're _almost_ rendering the arabic and hebrew correctly; the only issue is that the last emoji should come **before** the arabic text.
### Large/full primary font (primary font has most glyphs):

Emojis may appear to look better, but that's just because this primary font has the `WHITE SMILING FACE` emoji. Again, `fcft_grapheme_rasterize()` handles explicit presentation selectors, and thus the last emoji in the middle row is correct.
The last row is pretty bad; since this primary font has **all** glyphs, it is shaped in a single go. This is the reason both the arabic and hebrew is rendered "reversed".
## After
### Limited primary font (non-ascii glyphs from fallback font):

### Large/full primary font (primary font has most glyphs):

Both images are rendered as correct as one can expect. The ascii/latin characters look different in the two images since the primary font is different. But LTR/RTL is all correct, emojis are all correct (the last emoji in the first row is incorrect, but this is to be expected with `fcft_glyph_rasterize()`, since it only takes a single codepoint).
## Real world usage
Here's a real-world example; two yambar instances, top one using fcft from master, bottom one using fcft from this PR:

The three emojis are using the default presentation, explicit text presentation, and emoji presentation, respectively.