Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Last active December 2, 2021 12:09
Show Gist options
  • Save ufcpp/e5c2450a7e99175aeb49a184e9e8d50e to your computer and use it in GitHub Desktop.
Save ufcpp/e5c2450a7e99175aeb49a184e9e8d50e to your computer and use it in GitHub Desktop.
絵文字の自前処理

絵文字の自前処理

絵文字の数

以下、Unicode 13.1 での話。

単独の絵文字

単独の絵文字は emoji-data の Emoji 属性が付いてる文字。 このテーブルの1列目をパースすればテーブル化可能。

単独で絵文字とされてるのは1367文字。

このうち、Shift JIS 由来のもの(日本の印刷所の外字とか、字幕放送用の文字)は普通に2バイト文字で、それが184文字ある。 これはもしかしたら普通に Unity でも元から表示できるかも。

Shift JIS 由来のものは 2300~27FF 付近、キャリア絵文字由来のものは 1F000 番台(というかこの追加面全体が絵文字用)なので、テーブルを引く前の荒い判定としては「2000 番台 or 1F000 番台」的なものを挟んでもいいかも。

絵文字シーケンス

emoji-sequences に定義あり。 大きく分けると3種類あって、

  • キーキャップ (Emoji Keycap Sequence)
    • 電話の「1, 2, ..., *, #」ボタンみたいなのを「四角で囲んだ1」みたいなグリフで表すやつ
  • 国旗 (Emoji Flag Sequence)
    • 2文字の国コードで表現
    • 5文字以上の地域コードで表現
  • 修飾子シーケンス(Emoji Modifier Sequence)
    • 肌の色選択のこと

キーキャップは「ASCII の 09*, # の後ろに異体字セレクターみたいな構造で、こいつらだけが「絵文字じゃない文字から開始する絵文字」。 これのためだけに分岐が増えるの嫌だしこいつらは無視していいかも。

機械判定で絵文字シーケンス判定を受ける文字の組み合わせはかなり多いけど、最低ラインどのベンダーも実装すべきとされている絵文字(RGI: Recommended for General Interchange)は、以下の通り1000文字いかないくらい。

  • キーキャップ: 12文字
  • 2文字国旗: 258文字
  • 任意地域コード国旗: ぶっちゃけイングランド、スコットランド、ウェールズの3文字だけ
  • 肌色選択: 590文字

もう1個、ゼロ幅接合子(ZWJ、U+ 200D)で絵文字と絵文字をくっつけるっていう仕様(Emoji ZWJ Sequence)があって、 RGI は emoji-zwj-sequences で定義されてる。

  • 家族・恋人系(人種 + ジェンダー配慮) 312文字
  • 職業系(人 + 他の絵文字で表現) 360文字
  • 元々あった絵文字への人種・ジェンダー配慮追加 572文字
  • 髪の毛(赤毛、ハゲ)配慮 72文字
  • その他 13文字

「その他」は例えば「黒猫を 猫 + 黒四角 で表現」、「盲導犬を 犬+安全ベスト で表現」みたいなやつ。

ちなみにこれはほんとに「実装を推奨されている」というだけで、例えば Windows は追加絵文字も意図的に表示しない絵文字もある。

  • 家族の構成に肌色選択を組み込める。(肌色5色×ジェンダー)^家族4人分 で結構えげつない数の絵文字をレンダリングできる
  • 自社キャラの特殊絵文字を持ってる
  • 国旗は絶対に表示しない。国コードのアルファベット2文字で表示される

絵文字バリエーション

一部の絵文字は「テキストとして白黒で表示するか」と「カラー画像で表示するか」を異体字セレクターで切り替え可能。

emoji-variation-sequences で定義されてて、354文字。

正直、これを描き分けできてるシステム見たことないので異体字セレクターは無視していいと思う。

推奨絵文字を外字に置き換えて、外字フォントで表示する案

絵文字シーケンスであること自体は、

  • 絵文字の後ろに肌色セレクター(skin tone) or 異体字セレクター
  • 絵文字と絵文字の間にゼロ幅接合子(ZWJ)
  • 国旗(Region Indicator っていう特殊な文字が2個隣接)

っていうパターンしかないので実は簡単。 絵文字単体かどうかの判定はテーブル式。

GraphemeSplitter は韓国語、タイ語、アクセント付きラテン文字とかにも対応してるので、むしろ絵文字の仕様よりもだいぶ複雑。

そこから先、表示できる絵文字かどうかは単純にテーブルを引くことになる。 前節で挙げたキャリア絵文字 + RGI 絵文字シーケンス、一応全部に対応&バージョンアップで増えるだろうことを考えて余裕を見ても4000~5000文字程度。 (参考: Unicode 13.0 の RGI が3300文字で、最近はバージョンアップのたびに足される文字の数が数十~100程度。)

一方で、Unicode で外字に使っていいとされている領域(private use area)は、

  • 2バイト文字の領域に E000~F8FF の6400文字
  • サロゲートペアが OK なら2面分(65536×2で約13万文字)使える。

結構ギリギリなものの、RGI 中の 4・5000文字を2バイトの私的利用領域6400文字にマッピングして使うのは可能は可能そう。

絵文字シーケンスには対応せず、単独の絵文字1367文字だけでいいならテーブル引きも簡単。

ZWJ シーケンスは、対応してないシーケンスの時は ZWJ を無視してそれぞれの個別の絵文字を表示するみたいな仕様なので、シーケンスが見つからないときは個別にテーブル引き直しみたいな処理が必要。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment