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通りの同じ字形 まず、この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はこんな「使えない仕様」になっているのでしょうか?