絵文字を実装する
絵文字は漢字のような表意文字の一種だ。Unicode上にコードポイントが定義されていて、それに対応するグリフ(フォントファイル上で定義された文字のアウトライン情報)が表示される。そういう意味では通常の文字となんら変わらない。異なるのは、通常の文字はアウトラインフォントというアウトライン情報(ベジエ曲線)を持っているに対して、絵文字はビットマップになっていることと、一般的に絵文字と呼ばれるものは予め色が決まっている文字(カラーグリフ)であるということだ。(これまでの)文字は活版印刷に適した形態として進化してきたが、絵文字は日本の携帯電話のディスプレイ上で表示されることを目的とした文字のため、複雑な字形や多色を利用した文字が特徴の、まさに現代的な表意文字になっている。絵文字ははじめ、日本の携帯電話メーカーがsjisの拡張エリアに定義した文字だったが、初期のiOSではUnicodeのPUAに定義され、最終的にUnicode Emojiとして正式採用され今や世界中の人々が利用するようになった。
絵文字は、人の電子デバイスでのコミュニケーション量が加速度的に増加するのに伴って、またはそれ以上のスピードで、人々のテレコミュニケーションに利用されている。人が表意文字で表現したい対象は年々増加している。表情、職業、食べ物、アクティビティ、目的地、そしてそれらを彩る感情記号、などなど…。多種多様な要求に伴ってUnicode Emojiの規格は年々複雑化しており、iOS/Androidのメジャーバージョンアップとともに毎年内容が更新されている。
この文章では急激な速度で進化していくUnicode Emojiを正しく実装し、それに追従していく指針を示す。次の章展開を持つ:
- Unicode Emojiを含む文字列の処理
- サロゲートペアを扱う必要があるため、UnicodeのEncoding(UTF-8, UTF-16)を扱える処理系が前提となる
- 内部エンコーディングがUCS2(UTF-16 LE?)であるのが望ましい
- Grapheme Cluster
- codepointとEmojiのグリフは1:1対応ではない
- sequenceが1グリフに対応する場合がある
- 有名なのは肌の色を変えるModifier
- Emoji Sequencesの種類
- Modifier BaseとModifier
- Presentation Selector
- Emoji
- 数字もtext presentationのemojiである
- ZWJ
- Regional Indicator
- Flag Tag Sequence
- Keycap Squence
- サロゲートペアを扱う必要があるため、UnicodeのEncoding(UTF-8, UTF-16)を扱える処理系が前提となる
- 絵文字グリフの定義
- OpenType
- テーブル
- CBDT (Android, Linux)
- FreeType
- sbix (iOS, macOS)
- Core Text
- SVG (Firefox, Opera, Chrome, iOS(>=12))
- FreeType, Core Text?
- ??? (Windows)
- Active Font?
- モノクロフォントにfallbackできる
- CBDT (Android, Linux)
- テーブル
- OpenType
- Emojiの実装
- フォントの選択
- Apple Color Emoji
- Noto Color Emoji
- Twemoji
- (Windowsのやつ)
- その他
- Emoji One
- etc…
- Emoji Sequenceからグリフへの変換
- GSUBテーブルによるEmoji Sequenceからグリフへのマッピングの定義
- harfbuzzなどのshaperによる変換
- Presentationの選択
- 数字([0-9])にもEmoji Presentationは存在する
- 記号はEmojiかどうか
✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌
問題
- Variation Selector-15, 16がつかない場合にどちらを表示させるべきか
- iOS, macOS, Android, ブラウザなどはどうしているか
- 描画の実際
- グリフの描画位置の決定
- origin, width, height, lsb, tsb
- Graphicsバックエンドとの協同
- フォント(グリフ)のキャッシュ
- GPUの活用
- 例: Cairo
- 例: Android
- 縦書き
- CBLCのvertical metricsを使用
- Noto Color Emojiには含まれていなかったので直した話
- CBLCのvertical metricsを使用
- 番外編: Twemoji (JSで置き換えるナイーブな実装)
- グリフの描画位置の決定
- フォントの選択
- 入力とGrapheme Cluster
- バグが引き起こす面白い現象
- 国旗がBSするごとにいれ変わる (Regional Indicator)
- 一家離散 (ZWJ)
- Clusterの開始点を保持する別の配列が必要
- バグが引き起こす面白い現象
- バージョンアップの戦略
- Emoji Sequenceの判定
- テーブルを持たないと無理(PangoもChromeもicuもそうしてる。)
- AndroidでのSupport Libraryの活用(Emoji Compat)
- フォントにグリフが追加されるタイミング
- AcceptされてからiOS/Androidに追加されるまでには
- GoogleやTwitterが更新し続ける限りは大丈夫??
- Emoji Sequenceの判定
- まとめ
- Emojiは今やワールドワイド。需要や文字の種類はこれからもますます増えていくだろう。
- Emojiの世界は奥深い。文字の奥深さに通じる。実装は思っているより大変。でもUnicodeの知見がたまり、国際化対応に強くなれると思う。
- 正しい設計戦略が息の長い実装を生む。腕の見せどころ。やっていきましょう。