c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

絵文字の異体字セレクタを扱ひたい扱へない

※ 忘備録程度の情報です。

結論

絵文字には U+FE0E/U+FE0F が異体字セレクタとして付くことがあります。Unicode の STANDARDIZED VARIANTS といふ仕様の一部です。気をつけませう。

歴史

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) と呼ぶ。(詰まり異体字セレクタはもともと漢字に限るものではない。)

時は経てiOSAndroidが日本の携帯電話市場に参入したとき、この大きな市場を呑み込む為に、AppleGoogleは絵文字を扱ふことを余儀なくされた。両社は絵文字を「文字」として扱ふ事に決め、Softbankdocomoau三社の絵文字を独自に纏め、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に表示できる。