Unicode正規化 その4 (2010.3.22 改訂)
前回までの流れをおさらいしておきます。
・結合文字列は現状、様々な問題を引き起こす。
・問題を防ぐには、結合文字列を合成するしかない。
・結合文字列を合成するには、分解マッピングを利用する。
・分解マッピングを利用することを「Unicode正規化」という。
さて、実際の「Unicode正規化」は、どのようなものでしょうか?
Unicode正規化の種類
これまでの流れだと「Unicode正規化」イコール「結合文字列を合成すること」と思ってしまうでしょうけど、すこし違います。Unicode正規化は合成するだけでなく、分解することにも使われるからです。
Unicode Consortium は、Unicode正規化を4種類に分けて規定しています。
NFC Normalization Form C
NFD Normalization Form D
NFKC Normalization Form KC
NFKD Normalization Form KD
「Normalization Form」は 正規形 と訳されています。「正規化した状態」というような意味です。つまりこの4つは、文字を
合成(Composition)する
分解(Decomposition)する
互換分解(K(C)ompatibility Decomposition)してから合成(Composition)する
互換分解(K(C)ompatibility Decomposition)する
ための方法であるということです。
ここでは、あまり深く掘り下げないことにしているので、「互換分解」には触れません。さらに、話を簡潔にするため、私たちの目的に直接関わる「NFC」だけに限定して見て行くことにします。
NFCの大きな問題
私は上記でNFCをこう説明しました。
合成する
しかしこれは正しくありません。実際にNFCがやっていることはこうです。
分解してから合成する
「その1」に登場した文字で具体的に見てみます。
まず、この3つはまったく同じ字形ですが、データ上は
「01D6」「00FC 0304」「0075 0308 0304」
とどれも異なります。それぞれにNFCを適用してみます。
「01D6」→ 00FC 0304 → 0075 0308 0304 → 00FC 0304 → 01D6
「00FC 0304」→ 0075 0308 0304 → 00FC 0304 → 01D6
「0075 0308 0304」→ 00FC 0304 → 01D6
結果としてはいずれも単一の「01D6」になるのですが、はじめから「01D6」になっている文字も、徹底的に分解されて、再度また合成されます。つまり、分解マッピングで分解可能な文字は、それが単一コードであってもNFCでは処理中に分解されるということです。内実は「NFDC」なんですね。
そして、分解された文字がすべて元通りに合成されれば問題はないのですが、「すべて元通りに合成されるわけではない」ところにNFCの大きな問題があります。つまり、合成をしようとしてNFCを適用したら、かえって1文字がバラバラになったり、別の1文字に変わってしまう文字があるということです。(「その3」で少し触れましたが、「分解」という用語は、1文字をバラバラにするだけでなく、別の1文字にする意味でも使われます)
「分解したあとに合成しない」ことを「合成除外 Composition Exclusion」といいます。Unicode Consortium の「CompositionExclusions.txt」はその合成除外文字の一覧です。一見すると少なそうですが、全部で1000文字以上もあります。
どうしてこんな文字があるのか、調べてみると理由はいくつかあり、なるほどと思うものもあれば、私では理解できないものもあります(チベット語とかヘブライ語なんて分かりませんし…)。そしてこれが遠い外国の文字だけなら、日本で作られるテキストにNFCを適用してもさして問題はないかなとも思うのですが、実は合成除外にもっとも多いのが「漢字」なのですから、困るのです。
NFCで変わってしまう漢字
NAOIさんが「NFCで変わってしまう漢字」を整理されています。
Adobe-Japan1のCJK互換漢字とInDesign CS3
InDesignはCS3から「Unicodeのプレーンテキストをペーストした時にNFCを適用する」ようになっているので、NAOIさんの一覧表はそのまま「NFCで変わってしまう漢字一覧」になっています。
意図しないところで勝手に別の字体に変わってしまうのは、ユーザにしてみれば悪夢のような現実です。
どうしてNFCはこんな「使えない仕様」になっているのでしょうか?