Working with Emoji skin tones in apps

Visual Studio WinUI General

7 years ago

Unicode 8.0 has added five skin tone modifier characters, that are able to change the skin color of some Emojis - so-called Emoji modifier bases. How can you utilize this interesting feature in your apps?

Modifiers

The Modifier Emojis are on most platforms represented by a square- or ellipse-shaped patch filled with a color representing a skin tone. For those interested, the skin tones are based on the Fitzpatrick scale, which divides the range of human skin colors into six categories. The two first types are represented with the same color in Emoji, hence there are only five different categories. A great resource on emoji information is the Emojipedia, which has a special section just for this purpose.

Description of Modifiers on Emojipedia

Combining

There is a list of Emoji characters that can be modified using the skin tone modifiers - the Emoji modifier bases. These are just simple emojis that usually depict a character or a hand gesture, where the skin color defaults to the default bright yellow color. As of Unicode 9.0 there are 86 different modifier base Emojis. By appending a modifier character after such emoji modifier base character you will get the emoji with the requested skin color:

Using skin tone modifiers with modifier bases

In case the Emoji character isn't a modifier base, no combination will be created and two Emojis will be displayed. This is useful because it ensures the intention of changing skin color will be preserved on systems that don't support skin tone modification.

No modification is performed with unsupported characters

Implementing Emoji skin tone modification

The following example shows implementation of Emoji skin tone modification in C#, but it can be easily ported to any other language.

Getting the list of modifier bases

The first thing we need is to find a list of all Emoji modifier bases, so that we are able to recognize when the conversion should be performed and when it should not. It would be very tedious to have to find all the supported modifier bases manually. Fortunately, Unicode is here to help us! In theUnicode Technical Report article about Emoji (currently version 4.0, with 5.0 proposed), we can find the emoji-data section, which contains a links to the definition files, that describe the emoji character ranges. Included is a special table of Emoji_Modifier_Base character ranges:

List of Emoji modifier base character ranges

In the first column we have either the character code or a range of such codes. This is fairly parse-able!

private const char CommentCharacter = '#';
private const char NewLineCharacter = '\n';

private const string RangeSplitter = "..";
private const string ModifierBaseDefinition = "; Emoji_Modifier_Base";

private async Task<string[]> GetModifierBasesAsync()
{
    HttpClient emojiDataDownloader = new HttpClient();
    var emojiData = await emojiDataDownloader.GetStringAsync(
       "http://www.unicode.org/Public/emoji/latest/emoji-data.txt");
    List<string> modifierBases = new List<string>();
    var lines = emojiData.Split(NewLineCharacter);
    foreach (var line in lines)
    {
        if (!line.StartsWith(CommentCharacter.ToString()) && //ignore comment lines
                line.Contains(ModifierBaseDefinition)
            )
        {
            //parse line
            var firstColumn = line.Split(';').First().Trim();
            if (firstColumn.Contains(RangeSplitter))
            {
                var indexOfRangeSplitter = firstColumn.IndexOf(RangeSplitter);
                var rangeStartHexadecimal = firstColumn.Substring(0, indexOfRangeSplitter);
                var rangeEndHexadecimal = firstColumn.Substring(indexOfRangeSplitter + RangeSplitter.Length);
                //range, enumerate
                var rangeStart = int.Parse(rangeStartHexadecimal, NumberStyles.HexNumber);
                var rangeEnd = int.Parse(rangeEndHexadecimal, NumberStyles.HexNumber);
                for (var currentCode = rangeStart; currentCode <= rangeEnd; currentCode++)
                {
                    //output emoji character
                    modifierBases.Add(char.ConvertFromUtf32(currentCode));
                }
            }
            else
            {
                //single emoji
                var code = int.Parse(firstColumn, NumberStyles.HexNumber);
                modifierBases.Add(char.ConvertFromUtf32(code));
            }
        }
    }
    return modifierBases.ToArray();
}

This code will retrieve an array of all the modifier bases from the latest version of emoji-data.txt .

Skin tones

Now let's prepare the enumeration that will be used for the skin tone specification:

/// <summary>
/// All emoji skin tones. Default represents the generic yellow color.  
/// </summary>
public enum EmojiSkinTone
{
    Default,
    Type12,
    Type3,
    Type4,
    Type5,
    Type6
}

We can create an extension method, that converts the skin color enum values to the appropriate characters.

public static string ToModifierCharacter(this EmojiSkinTone skinTone)
{
    string hexadecimalCode;
    switch (skinTone)
    {
        case EmojiSkinTone.Type12:
            hexadecimalCode = "1F3FB";
            break;
        case EmojiSkinTone.Type3:
            hexadecimalCode = "1F3FC";
            break;
        case EmojiSkinTone.Type4:
            hexadecimalCode = "1F3FD";
            break;
        case EmojiSkinTone.Type5:
            hexadecimalCode = "1F3FE";
            break;
        case EmojiSkinTone.Type6:
            hexadecimalCode = "1F3FF";
            break;
        default:
            return string.Empty; //generic yellow color, no modifier
    }
    var code = int.Parse(hexadecimalCode, NumberStyles.HexNumber);
    return char.ConvertFromUtf32(code);
}

Putting it together

We have just one thing left to do - write a method that actually changes the skin tone of a given Emoji:

public static string ChangeSkinTone(this string emoji,
                                    EmojiSkinTone skinTone)
    => _modifierBases.Contains(emoji) ?
          emoji + skinTone.ToModifierCharacter() :
          emoji;

Note that the _modifierBases variable is the resulting array of the GetModifierBasesAsync method above. Because we have written the method as an extension method, changing the skin color of a emoji is now as simple as:

Code

The source code for this article is available here on my GitHub. In addition to the library code shown above it also includes a sample UWP app that demonstrates its usage.

Summary

We have shown how Emoji skin colors work and how they can be easily utilized when writing an app to support all skin tones. Our C# sample is quite simple and can be therefore ported into most any other programming language and framework.