Použití barev pleti Emoji v aplikacích

Visual Studio WinUI General

7 years ago

Unicode 8.0 přidal pět znaků tónu pleti - tzv. Modifiers, které umožní změnit barvu kůže u některých Emoji emotikon, které se označují jako Emoji modifier bases. Jak můžeme tuto užitečnou funkčnost využít v našich aplikacích?

Modifiers

Modifier Emoji jsou na většině platforem reprezentovány jako čtvercová nebo kulatá "záplata" vyplněná barvou reprezentující určitý tón pleti. Pro zájemce je třeba uvést, že tyto barvy pleti jsou založeny na takzvané Fitzpatrick škále, která rozděluje barevný rozsah lidské pleti na šest kategorií. První dvě z nich jsou v Emoji reprezentovány stejnou barvou, tedy ve výsledku máme k dispozici pouze pět různých Emoji Modifier znaků. Skvělým zdrojem informací o Emoji je Emojipedia, která má navíc speciální sekci právě pro Modifier znaky..

Popis Modifier znaků na Emojipedii

Kombinování

Existuje skupina znaků, které lze pomocí modifikátorů barvy pleti měnit - takzvané Emoji modifier bases. To jsou klasické emotikony, které obvykle představují nějakou postavu či gesto ruky a které mají výchozí sytě žlutou barvu, která je pro Emoji typická. Ve verzi Unicode 9.0 je k dispozici již 86 různých modifier base Emoji. Prostým přidáním modifier znaku za takové Emoji dostaneme emotikonu s požadovanou barvou pleti:

Použití modifikátorů barvy pleti s modifier base Emoji

V případě, že Emoji není modifier base, ke kombinaci nedojde a budou zobrazeny obě Emoji vedle sebe. To je užitečné, protože to zajistí, že zůstane zachován úmysl změny barvy pleti i na systémech, které funkci zatím nepodporují.

U nepodporovaných Emoji ke změně nedochází

Implementace změny barvy pleti v kódu

Ukážeme si možnou implementaci změny barvy pleti v jazyce C#, ale je snadno možné kód analogicky napsat ve většině jiných programovacích jazyků.

Získání seznamu modifier bases

Nejprve musíme najít seznam všech modifier base Emoji, abychom byli při schopni snadno rozpoznat, kdy změnu máme a kdy nemáme provádět. Kdybychom toto museli dělat ručně, bylo by to samozřejmě velmi vyčerpávající. Naštěstí nám pomůže Unicode! V článku Unicode Technical Report o Emoji (nyní ve verzi 4.0, s návrhem na 5.0), můžeme najít oddíl emoji-data, který obsahuje odkazy na definiční soubory, které popisují rozsahy Emoji znaků. Zahrnuta je také speciální tabulka s Emoji_Modifier_Base rozsahy:

Seznam rozsahů všech Emoji modifier base znaků

V prvním sloupci najdeme buď přímo kód daného znaku nebo rozsah po sobě jdoucích kódů. To zní poměrně parse-ovatelně!

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();
}

Tímto kódem získáme pole všech modifier base znaků z aktuální verze emoji-data.txt .

Barvy pleti

Nyní můžeme připravit výčtový typ, který můžeme použít pro specifikaci barvy pleti:

/// <summary>
/// Všechny barvy pleti. Default je výchozí Emoji žlutá. 
/// </summary>
public enum EmojiSkinTone
{
    Default,
    Type12,
    Type3,
    Type4,
    Type5,
    Type6
}

Můžeme vytvořit rozšiřující metodu, která převede instanci tohoto výčtu na odpovídající Modifier znak:

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);
}

Vše dohromady

Zbývá nám poslední krok - napsání metody, která skutečně provede změnu barvy pleti pro dané Emoji:

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

Všimněme si, že proměnná _modifierBases je výsledné pole po zavolání asynchronní metody GetModifierBasesAsync výše. Protože jsme metodu napsali jako extension method, změna barvy pleti je nyní velmi intuitivní:

Zdrojový kód

Doprovodný kód k tomto článku je k dispozici zde na mém GitHubu. Krom knihovního kódu uvedeného zde navíc obsahuje ukázkovou UWP aplikaci, která jeho použití demonstruje.

Shrnutí

Ukázali jsme si, jak fungují barvy pleti u Emoji a jak je možné snadno využít při psaní aplikací s podporou všech pleťových odstínů. Náš ukázkový kód v jazyce C# je přímočarý a je možné jej snadno přepsat do téměř kteréhokoliv jiného jazyka.