Displaying emoji on Linux

Emoji were first added to the Unicode 6.0 standard, which was published in 2010. Since then, they have become rather popular—a modern smartphone is likely to support some version of emoji, and modern web browsers will usually at least have a go at displaying them properly.

While Linux-based operating systems technically support emojis quite well these days, the state of support can seem a bit messy and confusing. This post represents my notes on how emoji support is implemented, as well as what can be expected to work, and what probably won't. Note that these are based on my experiences with Ubuntu 18.10 and Ubuntu 19.04.

Emoji font files

Emojis are Unicode codepoints, or combinations of several Unicode codepoints. On a basic level, they are just like any other character in Unicode. This means that if your font features a glyph for a given emoji codepoint, then you can display it.

Of course, emojis are notably in color, and your garden variety font notably does not carry color information. The solution people came up with was to add some extensions to OpenType, thus enabling OpenType files to carry color emojis in some new, extra tables. These tables can be included on top of normal outline font data, so that if your software happens to not support the extension, it can fall back on rendering emojis in single color, like any other glyph.

Note, however, that these were extensions, plural. To make things more entertaining for everyone, there are different ways of embedding colored emojis in font files.

Methods of embedding emojis

All four common ways of embedding emojis in font files utilize OpenType. OpenType files can hold multiple tables of different types, and these techniques involve defining new table types to hold the color emoji information.

Note that the same techniques can also be used to encode arbitrary other characters in color like, say, basic Latin script. Fonts using these techniques are thus sometimes referred to as color fonts.

The methods of embedding colored glyphs are:

SVG in OpenType

This method allows storing SVG vectors in a separate table in the font file. As the table name is "SVG " (that's "SVG" followed by a space), it's frequently referred to as SVG-in-OT, to distinguish it from the general concept of SVGs.

SVG can specify color, so the emojis can be colored. It also has the benefit of being a vector format, so your emojis can scale nicely. Not all SVG features are supported, however, as some of the fancier SVG features would be either out of place, or actually dangerous from a security perspective.

COLR/CPAL

This method adds two tables: one describing a series of shapes to be layered on top of each other, and one describing the colors that can be assigned to those shapes.

Essentially, instead of drawing emojis with SVG, this method draws them with overlaid font glyphs. It is a bit less involved than the SVG method, as it extends existing facilities instead of introducing a whole new way of describing shapes. It is still a vector format, so emojis display nicely at various sizes.

CBDT/CBLC

Instead of describing how to produce colored vector shapes, this method embeds bitmaps in the font file. This does means less crisp results while scaling, but from the perspective of the implementer, it is easier to work with bitmaps when rendering to screen.

These tables resemble EBDT and EBLC tables, which were a pre-existing way of embedding monochromatic bitmap glyphs in OpenType files—the C in the newer method stands for color. Several bitmaps can be used for one character, each at a different size, to help with scaling. The bitmaps themselves are PNGs.

SBIX

This is Apple's format. Once a proprietary extension that Apple used in their operating systems, it is now described in the spec, like the others. Like CBDT/CBLC, it works by embedding raster data. There are some functional differences, like the way this raster data is described, or the fact this method can also embed TIFF or JPEG files.

Software support

The year is 2019 (as of writing), and so of course the two types of software on your computer are web browsers, and everything else.

When it comes to rendering emojis in web browsers, Firefox is notably pretty good. It can support the vector formats and the raster formats. The latter come with a caveat: Firefox will not render raster color web fonts by default, only when gfx.downloadable_fonts.keep_color_bitmaps is set to true; on-disk CBDT/CBLC color fonts work without tweaks. Firefox also ships with an SVG-in-OT font (Twitter Color Emoji), and will use this embedded font if the OS cannot render emojis otherwise. Mozilla was a proponent of the SVG-in-OT solution for OpenType color fonts.

Chrome and Chromium, on the other hand, do not support SVG-in-OT. They do support the CBDT/CBLC method, which is the solution favored by Google. They also support the remaining two methods: Apple's SBIX, as well as the other vector method, COLR/CPAL. All three of these can be used in web fonts.

The text rendering library FreeType supports both of the raster methods: CBDT/CBLC and SBIX. This means that in practice your GTK and Qt apps will work with raster emojis. Generally, color emojis are displayed automatically.

Of course, when you're dealing with fonts on Linux, you'll have to deal with Fontconfig. This is where things can get a bit surprising when it comes to GTK and Qt: GTK will sometimes select a different font for emoji than Qt. In practice, this means that if you have an SVG-in-OT and a CBDT/CBLC font installed, one toolkit may pick the raster font (resulting in emojis rendering in color), and the other may pick the SVG font (resulting in emojis rendering as fallback outlines).

Of course, Fontconfig is, to put gently, a bit of a nightmare. Modifications to Fontconfig configuration files may be required to include an emoji font in the list of fonts software looks for when looking for emoji. It may also work without doing anything. I would like to sincerely wish anyone having to deal with this the best of luck.

Particular fonts

There are thousands of possible emojis, and so it is a serious project to draw all of them. Likely as a result of this, there are not that many freely licensed emoji fonts out there. The two notable projects today are:

  • Twitter Color Emoji SVGinOT – As the name indicates, this is an SVG-in-OT font created from the emoji vectors provided by Twitter as part of the Twemoji project. This is what Firefox ships, although downloading it independently may provide you with a version newer than the one Firefox embeds.
  • NotoColorEmoji – CBDT/CBLC font provided by Google. Part of the Noto project, which stands for No Tofu, tofu here referring to the missing character glyphs which show up when you do not have a font to display a particular Unicode codepoint. Updated whenever Google decides to release a new version. Comes in a well-supported raster format. Unfortunately, it no longer features blobs.

Input

An easier problem is emoji input. I recommend ibus-uniemoji, an ibus module for emoji input. With it, emojis can be inserted by typing all, or part of an emoji name.

There are other input methods which I have not tried. Failing everything else, emoji are Unicode characters, and therefore it should be possible to copy and paste them from elsewhere.

Conclusions and recommendations 👇

It seems that the easiest way to get color emoji on Linux these days is to install the Noto Emoji font. Some Linux distributions ship it via their package repositories, but since the font is a .ttf file, it should also be possible to simply drop it somewhere that Fontconfig will pick it up (such as ~/.fonts, on a lot of systems).

SVG fonts can also be used to provide prettier vector emojis in Firefox. Care has to be taken to ensure that all other software can fall back on raster emojis.

New versions of the Unicode standard are generally released once a year, and these days inevitably include several new emojis. Not everyone's software will immediately support these new emojis after a new Unicode version comes out, but keeping up to do date may be desirable.

Although Linux emoji support today may seem like bit of a mess, it is generally good enough for daily use, so if you want to replace all your spaces with 👏s, the time has never been better.

Further reading

Specs