Unlike literally any other platform or OS, Windows never had flag emojis, and that always irked me a little bit. Having to guess what flag someone else is trying to send by just two letters isn't a great user experience, you know. And I always just kinda sighed at it, helplessly.
But not this time... Last week, the absence of flag emojis in Windows has triggered me like never before, and I've spent 14+ hours hyperfocused on the task of bringing flag emojis to Windows (while keeping all its original emojis). I experimented with fonts, and made one that works. And you can download it too!
TL;DR: Install this font for all users, restart your PC, and enjoy! (more details here)
(as usual, I'll only document my journey here; this is not meant as a guide)
Digging around in FontForge
After googling for a bit, I found out that Windows uses Segoe UI Emoji (or to be more specific, C:\Windows\Fonts\seguiemj.ttf
) as a sort of a fallback font to render emojis that couldn't be rendered by any other active font. I wasn't sure how I would get to the end result yet, but I thoght the most obvious first step would be extracting the flag emojis, that I want to insert into Segoe UI Emoji, from another font that does support them.
The first font that came to mind was Google's Noto Color Emoji, since during my research I came upon an issue in some WPF library that adds an emoji picker, and someone there proposed using Noto Color Emoji. I downloaded the font, opened it in FontForge and started looking for whatever makes country flag emojis work in there.
FontForge's UI (in lookup subtable area in particular) was... tedious to use. I needed to remove any sequences that weren't flags, so that I'd have a font with just flags and nothing else. But FontForge didn't provide a "remove selected range" button, so... I just had to click the "Delete" button several thousands times, until I got rid of everything but flags.
And then it turned out that FontForge doesn't support importing/exporting whatever metadata was needed for the flags to render correctly, so everything I needed was lost even before I started manipulating the font...
Also, I think I saw a 🦺+🐒 ligature in there?.. Dunno, I can't be bothered to find out more.
Using fontTools
I did some more research, and found two projects similar to mine:
- Country-Flag-Emojis-for-Windows by perguto.
- broken-flag-emojis-win11-twemoji by quarrel.
The first one, by perguto, completely replaces Segoe UI Emoji with Google's Noto Color Emoji. The second one, by quarrel, does the same but with Twitter Color Emoji.
One huuuuge downside to this (subjective) is that you lose all of Microsoft's Fluent 3D emojis! And I really like them! A touch of 3D shading looks really nice and it brings some life to the emojis. Fluent 3D's people emojis have actual eyes, while others' have creepy dot eyes and blank stares. Also, as someone with entomophobia, Fluent 3D's bug emoji is the easiest to look at, and as a developer I have to look at it pretty often. And look at Fluent 3D's animals! So cute!
As for the flags, I decided to use Twitter's flag emojis, since Noto's wavy ones just look weird — straight lines become curves, circles become ovals, there's a weird gray glow around the flags, and they also don't downscale well. I got the font file from quarrel's broken-flag-emojis-win11-twemoji project, where they updated and compiled it for Unicode 16.0 and added COLR1 data.
Let's get back to the fonts. Both of the projects above used the ttx
tool from a fonttools
suite, but they didn't utilize it to its full potential. ttx
essentially decompiles any TTF font into an enormous XML document, allowing you to edit anything you want, and then losslessly recompile it back into a TTF. And those projects only edited the name
table in the fonts, disguising a font of their choice as Segoe UI Emoji, tricking the system into using it instead of the original one.
And so, I decided to simply merge the two decompiled XML documents of Segoe UI Emoji and Twitter Color Emoji into one. To make merging (and studying the structure of a TTF file) simpler, I subsetted the Twitter Color Emoji font using the fonttools subset
command (a much simpler way of what I was trying to achieve earlier in FontForge).
fonttools.exe subset twemoji.ttf --glyphs-file=flags-glyphs.txt
fonttools.exe ttx seguiemj.ttf
fonttools.exe ttx twemoji.subset.ttf
Here flags-glyphs.txt
is a file I generated from the file paths in 13rac1/twemoji-color-font
, containing all required flag-related glyph names, e.g. u1F1E6
-u1F1FF
(regional indicator symbol codepoints), 1f1e6-1f1e8
-1f1ff-1f1fc
(emoji flag sequences).
Then I started working on a script to merge the two huge (250 MiB and 10 MiB) XML files.
Writing a merge script
Since the XML files were millions of lines long, navigating them proved to be hard. Wrapping and folding would require the entire file to be loaded into memory, and then tokenized and parsed, so I had to make do with just the Search function.
It was also tough figuring out how to properly merge each table and map/re-assign the new glyphs' ids and values. And when I thought I finally did everything (at this time the C# script, that I spent 6 hours on, was about 200 lines long), a new problem surfaced. The colors ran out.
There was a hard limit on the amount of colors you can store in the COLR table — no more than 65536. And Segoe UI Emoji used a total of 64831 of them (probably for all the 3D shading and accent lighting), leaving only 705 for the flags. I wrote some color deduplication code, and had to settle for flag color tones that are 1 to 2 values off.
I finally managed to produce the first merged font file, and... it didn't work. I tried several more things with scripts, features and ligatures, and when I was close to giving up, I opened the DevTools on the Regional indicator symbol Wikipedia page... And it worked there!
Issues with scripts and features
Now knowing that the font does indeed sometimes work, I experimented a bit more and found out that the flags render properly only when they're in the same "word" as latin letters.
Looking for a "font debugger" I came across HarfBuzz, a command line tool to preview and debug fonts, glyphs, offsets, ligatures, textshaping, etc. It's really easy to use, and it just clarified to me so much stuff about how scripts and features work.
Turns out the issue was with the latn
script I copied over from Twitter Color Emoji. It worked there because latn
was the only script in the list, and the implicit default. And Segoe UI Emoji also had a different script, DFLT
, that was the default one, and latn
only triggered when there were latin characters in the text.
I removed the latn
script from the font, and added the liga
feature to the DFLT
script instead. And after recompiling the font, all the flags rendered almost correctly!
Some of the colors were wrong though — that was because I expected lowercase latin letters instead of uppercase when parsing and comparing color hex codes. It was a quick fix.
System inconsistencies
Now I only had to figure out how to fix flag emojis in a few certain places: Notepad++ didn't render the flag emojis, but did render all Fluent 3D emojis, and VS Code for some reason only rendered the flag emojis in non-input areas.
I struggled with this one for a while, because Windows suddenly stopped updating the font files in real-time, for some reason. Previously I only needed to restart the apps where I wanted to see the changes, but now I had to restart my PC to see the changes.
In the end, I think I just needed to use the ccmp
feature (Glyph Composition/Decomposition) instead of liga
(Ligature Substitution). Or maybe it was because I installed the font through the "Install for all users" option? Well, doesn't matter now. And, either way, using the ccmp
feature is more "compatible", since that's what Fluent 3D glyphs use.
Conclusion
And with this, the project was completed. There are a few more quirks to work out though, like alignment and spacing, but for the most part it's done, and I can do the rest later.
You can find the project here, with download links, scripts, full instructions, and more screenshots: https://github.com/Chasmical/flag-emojis-for-windows.
Subscribe to the blog's RSS feed if you wanna know what next thing I'll get up to. 😎