※ 忘備録程度の情報です。
歴史
Unicode には異体字セレクタ (VARIATION SELECTOR) といふ規格がある。
cf. 異体字セレクタ https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF
Unicode は文字の区別をする集合であり、字形 (グリフ) の区別はしないといふ方針で一応は定められてゐる。しかし「それは字形ではなく文字の違ひである、Unicode は実用に耐えない」といふ主張は後を絶たなかった。そこで、文字の直後に数百種類の特殊な不可視コードポイントを付加し、字形の区別をつけられる規格が定められた。このバイト列を異体字セレクタといふ。漢字に附く異体字セレクタを、特にIVS (IDEOGRAPHIC VARIATION SELECTOR) と呼ぶ。(詰まり異体字セレクタはもともと漢字に限るものではない。)
時は経てiOSとAndroidが日本の携帯電話市場に参入したとき、この大きな市場を呑み込む為に、AppleとGoogleは絵文字を扱ふことを余儀なくされた。両社は絵文字を「文字」として扱ふ事に決め、Softbank・docomo・au三社の絵文字を独自に纏め、Unicode に登録する規格を作った。この規格は採用された。Unicode に採用された絵文字は \p{Emoji}
といふ集合で参照できる。
cf. UnicodeSet http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7BEmoji%7D&g=
問題はそれに留まらなかった。「絵文字のやうなもの」は少数だがもともと Unicode に含まれてゐた。Unicode の「文字を区別し、字形は区別しない」といふ方針に巻かれて、Unicode にもともとあった「絵文字のやうなもの」と「同じ文字」とみなされた絵文字は、そこに統合された。
しかしこれでは、それらの「絵文字のやうなもの」をシンボルとして扱ふ従来の文脈と、絵文字としてカラフルに扱ふ絵文字の文脈を区別できない。そこでAppleは、絵文字に異体字セレクタを応用することをかんがへた。そしてこのかんがへは、STANDARDIZED VARIANTS の一部として Unicode の規格となった。
cf. Standardized Variants http://www.unicode.org/Public/7.0.0/ucd/StandardizedVariants.html
Unicode 7.0.0 で107の絵文字が対象となる。
絵文字の STANDARDIZED VARIANTS の仕様
絵文字の STANDARDIZED VARIANTS には、U+FE0E/U+FE0F のふたつのコードポイントを用ゐる。
絵文字 STANDARDIZED VARIANTS | 字形 | 例 |
---|---|---|
無し | デフォルト、従来通り | ‼ |
U+FE0E | テキストっぽい (text style) | ‼︎ |
U+FE0F | 絵文字っぽい (emoji style) | ‼️ |
iOSで対応する絵文字を入力すると、どちらかのコードポイントが付加される。
Androidは実装によるが、基本的には特に付加されない。またちゃんと処理されないことも多い。
絵文字の STANDARDIZED VARIANTS を Ruby で扱ふ
文字 異体字セレクタ
当然だ。何かの文字の異体字を示すものだから。
では、これは一文字か? 二文字か? 当然一文字である。異体字セレクタは文字ではない。前の文字を変化させるフラグに過ぎない。しかし Unicode のコードポイントとしては二個となる。異体字セレクタのコードポイントをちゃんと「異体字セレクタ」として認識できなければ、これを二文字として扱ってしまふ。
Ruby (手元の環境は2.1.2p95) は、少なくとも絵文字の後の異体字セレクタをきちんと認識しない。これは意図的な仕様かもしれないが、注意して使ふ必要がある。
p '‼'.unpack 'U*' # [8252] p '‼︎'.unpack 'U*' # [8252, 65038] p '‼️'.unpack 'U*' # [8252, 65039] p '☀'.unpack 'U*' # [9728] p '☀︎'.unpack 'U*' # [9728, 65038] p '♨'.unpack 'U*' # [9832] p '♨︎'.unpack 'U*' # [9832, 65038] p 'Ⓜ︎'.unpack 'U*' # [9410, 65038] p 'Ⓜ️'.unpack 'U*' # [9410, 65039] p '❕'.unpack 'U*' # [10069] p '❗️'.unpack 'U*' # [10071, 65039] p '⁉︎'.unpack 'U*' # [8256, 65038] p '⁉️'.unpack 'U*' # [8256, 65039]
異体字セレクタ付きの絵文字の length を見ると 2 となってゐる。くっついてない。
正規表現では
str =~ /[\uFE0E\uFE0F]/u
でマッチすることができる。
注意する必要があるのは Ruby に限らない。異体字セレクタを独立した「一文字」として扱って表示しやうとしてしまったりしないやうに、必要なら切り落としてやらねばならない。もちろん切り落とすより、きちんと「異体字セレクタ」として処理し表示できるのが理想ではある。
cf.
経緯は以下。
cf. これからの絵文字の実装指針、UTR #51“Unicode Emoji”とはなにか http://internet.watch.impress.co.jp/docs/special/20150131_686161.html
絵文字のSTANDARDIZED VARIANTSに就いては以下も参考になる。
cf. 絵文字バリエーション・シーケンスとは何か - Mac OS Xの文字コード問題に関するメモ http://d.hatena.ne.jp/NAOI/20120802/1343876603
絵文字処理の更に面倒な話は以下。
cf. 絵文字だョ! 符号化文字集合(前編) http://alpha.mixi.co.jp/entry/2012/10809/
cf. 絵文字だョ! 符号化文字集合(後編) http://alpha.mixi.co.jp/entry/2012/10663/
蛇足。フォントに含まれてゐるグリフ一覧を得る
上の事柄は、あるアプリでiOSからAndroidにある文字データを遣り取りする際、Androidアプリがクラッシュする問題を追い掛けて調査したことだった。始めはフォントの取り扱ひに問題があるのかと思ひ、使ってゐるフォントを調べてゐた。
MacにもFontForgeは入る。brew install fontforge --with-x11
で入れるとよい。
フォントの含むグリフ一覧を得るには以下のスクリプトを使った。
#!/usr/local/bin/fontforge Open($argv[1]) Reencode("unicode") SelectAll() foreach if(GlyphInfo("PointCount") > 0) Print(GlyphInfo("Name"), " ", GlyphInfo("Unicode"), " ", GlyphInfo("Encoding")) endif endloop Close()
if(GlyphInfo("PointCount") > 0)
は、空のグリフを無視する爲。
fontforge -script font.pe "Apple Color Emoji.ttf" > Apple_Color_Emoji.txt
で実行する。
MacにインストールされてゐるフォントはFont BookからFinderに表示できる。