「XeTeX で Unicode 正規化する件」に関するプリミティブ。
\XeTeXinputnormalization
:[整数パラメタ・読書可] テキスト行読込の際に適用される正規化の種類を指定する: 0=処理なし、1=NFC、2=NFD。
例えば、
\XeTeXinputnormalization=1 % これ以降はNFCに正規化される
を実行すると、それ以降の行の読込の際に、字句解析より前に NFC 正規化が適用される。(行単位であることに注意。)
「文字列に対して 1 文字ずつ何らかの処理を行う」ようなマクロは、「複数の Unicode 文字の結合で表される文字」(例えば分解された形の濁点付き仮名文字など)が入力に含まれると意図せぬ動作を起こす場合がある。
% plain XeTeX 文書, 文字コードは UTF-8 %\XeTeXinputnormalization=1 % NFCに正規化 \font\fIpxm="IPAexMincho" \fIpxm % \insertDots{<文字列>} \def\insertDots#1{\insertDotsA#1\relax} \def\insertDotsA#1{#1\insertDotsB} \def\insertDotsB#1{\unless\ifx#1\relax ・#1\expandafter\insertDotsB\fi} % 使ってみる \insertDots{おもてなし}\par \insertDots{ろくでなし}\par %<で>はNFC(3067) %↓うまくいきません \insertDots{ろくでなし}\par %<で>はNFD(3066 3099) \bye
こういう場合に NFC への正規化を行うと問題が避けられるかも知れない。*1先のソースの場合、2 行目のコメントアウトを外して
\XeTeXnormalization=1 % NFCに正規化
を有効にすると、全てが期待通りの出力になる。
注意であるが、正規化処理は、XeTeX が最初にソース行を読むときに行われる。だから以下のようなコードは上手くいかない。要するに、カテゴリコード変更(\catcode
)と同様の注意が必要である。
% 一時的に正規化有効にしてマクロを実行したいが… \insertDotsNfc#1{% \XeTeXinputnormalization=1 \insertDots{#1}% \XeTeXinputnormalization=0 }
もちろん、正規化を行う以上、Lost in N11n が不可避であることにも注意が要る。
% plain XeTeX 文書, 文字コードは UTF-8 \font\fIpxm="IPAexMincho" \fIpxm 神 % 互換漢字(FA19) %\XeTeXinputnormalization=1 % NFCに正規化 神 % Lost in normalizaion! \bye
そういうわけなので、この機能を使う機会はあまり無いように思われる。なお、「そもそも文字の出力するのに NFC に正規化しなくてもよいのか」という疑問をもつ人もいると思うが、これについてはまた別の記事に述べたい。