Color Fonts

The popularity of emoji symbols has encouraged a variety of technological innovations, notably fonts with multicolor characters. This is different from just having a text color, which is described in RichEdit Colors. While some colored glyphs were part of the original Japanese emoji standards, colored glyphs got much more elegant when Apple introduced its proprietary color emoji font with two sizes of bitmaps for the characters. Although bitmaps become fuzzy if enlarged a lot, for typical text sizes, the Apple emoji images look really cool.

In Windows 8.1 (October, 2013), Microsoft introduced multicolor characters by adding color layers to traditional OpenType font technology. An advantage of this approach is that the glyphs can be enlarged indefinitely without getting fuzzy. The functionality is useful for both emoji and for icons of various kinds such as those appearing in application ribbons. This post describes how these color fonts work and the functions one needs to call to implement color font support. It also describes skin-tone emoji modifiers, which allow people-related emoji to have five different skin tones. An example is U+1F471 (PERSON WITH BLOND HAIR) followed by the skin tone modifier U+1F3FB (EMOJI MODIFIER FITZPATRICK TYPE-1-2) and U+1F471 followed by U+1F3FE (EMOJI MODIFIER FITZPATRICK TYPE-5)

 

Rendering text on a screen or printed canvas typically consists of

  1. Creating bitmaps from nonlinear glyph outlines scaled to the current font size, a process called rasterization

  2. Drawing the bitmaps at the desired locations on the canvas

Traditionally glyph bitmaps are monochromatic. The difference with color fonts is that a given bitmap is created by superimposing the bitmaps from multiple glyph outlines, each bitmap assigned a color in a color palette. The construction of the multicolor bitmap proceeds in z order, that is, the first layer is at the bottom and subsequent layer glyphs overwrite what’s on the preceding layers. The colors are given in sRGB, for which red, green, and blue components are each represented by a byte (8 bits) and a fourth byte gives the opacity. This opacity allows for blending the contribution with the layers below.

This data is stored in the font according to base glyphs and layer colors. A base glyph is one that you’d use for the usual monochrome display. The OpenType COLR table defines one or more lists of one or more glyphs for each “base glyph”. Each list is associated with an sRGB color entry in the OpenType CPAL table.

While an implementer could write code to read these tables and to render the multicolor glyphs, most of the work is already done in DirectWrite. In DirectWrite, glyphs are rendered by calling ID2D1RenderTarget::DrawGlyphRun(). To render runs of multicolor glyphs, you call DrawGlyphRun() for the set of color glyph runs corresponding to the base glyph run. This set is given by calling IDWriteFactory2::TranslateColorGyphRun() to get an IDWriteColorGlyphRunEnumerator. This interface has two methods (in addition to the three IUnknown methods): GetCurrentRun() and MoveNext(). So you call GetCurrentRun(), set up its brush color, call DrawGlyphRun(), call MoveNext(), etc., until MoveNext() returns no more runs.

If TranslateColorGlyphRun() returns a null IDWriteColorGlyphRunEnumerator, the glyph run doesn’t have a multicolor version, so you call DrawGlyphRun() with the original base glyph run.

The traditional Windows display system based on GDI/Uniscribe doesn’t support color fonts. So if you want multicolored glyphs, you need to switch to DirectWrite to draw multicolor glyph runs or roll your own. The XAML RichEditBox and TextBox run RichEdit in Direct2D/DirectWrite mode and both boxes support multicolor glyphs.

Multicolor glyphs are very nice, but they can create social problems. In particular, people-oriented emoji originally had a single skin tone. As such these emoji didn’t reflect the diversity of people who came to use them. To make the emoji more diverse, five skin-tone modifiers (see Section 2.2 of Unicode Emoji) were added in Unicode 8.0.0 (June, 2015) to allow people-oriented emoji to have skin-tone variations. The modifiers are supported in Windows 10 DirectWrite. Above the DirectWrite level, programs can treat skin-tone modifier sequences the same way as variation selector sequences. A variation selector sequence consists of a base character followed by a variation selector character. The base character may be represented by a surrogate pair and so may the variation selector. These sequences should be treated as single units by the arrow, delete, and backspace keys. Down in DirectWrite, variation selectors are ignored if the current font doesn’t have them, resulting in the base character being displayed unchanged. But if the current emoji font doesn’t have the skin color variations, ideally a rectangle with the appropriate color is displayed after the emoji base character so that the reader knows the intended skin tone. If the font doesn’t have the base character and/or the skin-tone modifier rectangles, missing glyph boxes are displayed. The Segoe UI Emoji font on Windows 10 has skin-tone variants for most people-oriented emoji as illustrated in the images of the person with blond hair above.

Naturally people always want more. Recently on the unicode@unicode.org mailing list, there was an email thread recommending that the skin-tone modifiers be usable with the beer mug emoji 🍺. After all, beer comes in different colors. That usage may or may not happen ☺. And people want modifiers for different hair styles and colors, facial expressions, eye shapes, etc. When will it ever end?! Seems we need an extensible mechanism that allows companies to register custom emoji. But that’s another story…