マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

NFD な濁点仮名を pLaTeX できる話

結論を言うと、p(La)TeX では、濁点・半濁点付きの仮名に限って、NFC に“正規化”される。

% pLaTeX 文書, 文字コードUTF-8
\documentclass[a4paper]{jsarticle}
\begin{document}
% 1つ目はNFC(30C7)、2つ目はNFD(30C6 3099)
デデーン
\end{document}

pTeX 系では出力の際に(OpenType の機能などを用いて)文字を“合成”する機能はない*1し、また結合濁点(U+3099)は JIS X 0208 の文字ではなく pTeX で扱えるはずがない。従って、入力の際に“正規化”が行われたと考えられる。*2

濁点・半濁点付き仮名文字以外の文字は“正規化”されない。(JIS X 0208 にある文字でかつ「和文として使われる」文字の範囲を考えると、それで十分である。)

% pLaTeX 文書, 文字コードUTF-8
\documentclass[a4paper]{jsarticle}
\begin{document}
ещё     \par% <ё>はNFC(0451)
ещё     \par% <ё>はNFD(0435 0308)
\end{document}

“正規化”は文字コード変換処理(Unicode → JIS*3)の一部として行われるため、upLaTeX ではこの“正規化”は行われない。そして、出力での“合成”は相変わらず行われたいため、結局 NFD の形の濁点・半濁点付き仮名文字は正しく出力されないことになる。

% upLaTeX 文書, 文字コードUTF-8
\documentclass[uplatex,a4paper]{jsarticle}
\begin{document}
% 1つ目はNFC(30C7)、2つ目はNFD(30C6 3099)
デデーン
\end{document}
補足:“正規化”の確認

字句解析の段階で既に“合成”が行われていることを確認しておく。

\def\test#1#2#3;{\message{\number`#1:\number`#2}}
% \test の直後の2文字の符号値を表示する
\test テ&#12441;.;\bye % &lt;デ&gt;はNFD
  • 内部漢字コードが sjis の plain pTeX で実行すると次の表示が得られる。
    33638:46
    sjis で 0x8366 と 0x2E だから〈デ〉と〈.〉である。
  • plain upTeX(内部コードは Unicode)では次の表示が得られる。
    12486:12441
    Unicode で U+30C6 と U+3099 だから〈テ〉と結合濁点である。
さらに補足

upTeX でも合成を行うようになったようだ。

*1:そもそも pTeX は用いる和文フォントが何であるかを知らない(DVI ウェアが知っている)ことに注意。

*2:JIS X 0208 には“NFC”と“NFD”の形に相当する区別がないので、「Unicode → JIS の文字コード変換の際に統合された」と考えることもできる。

*3:厳密にいうと、この“Unicode”は UTF-8 で、“JIS”は内部漢字コード(SJIS または EUC)のスカラー値。