マクロツイーター

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

NFD な濁点仮名を XeLaTeX できる謎

某 Qiita の記事の中の以下の記述についての話。

なお、実際に試した限りでは、XeLaTeX で「〈か+結合濁点〉を出力」させると、(フォントが“合成に対応”していなくても)常に〈が〉の文字(グリフ)が出力されるようである。他の濁点・半濁点付きの仮名についても同様である。この辺りの仕組は自分はよく解っていない。

(なお、以前の記事ももちろんこの Qiita の記事に関連する話である。)

濁点するフォント

さて、この話をするために、少し特殊なフォントを例に用いることにする。「にしき的フォント」である。

このフォントは以下のような特質を備えている。

  • 「ん+濁点」のような非標準の濁点付き仮名文字のグリフを持っている。*1そして、仮名文字と結合濁点(U+3099)の並びに対する“合成”(liga フィーチャ)としてそれらのグリフを出力できる。*2
  • しかし、“普通の”濁点付き仮名、例えば〈で〉については、〈て+結合濁点〉を“合成”して〈で〉にする指定は(liga でも他のフィーチャでも)持っていない。(当然〈で〉のグリフはあり U+3067 で出力できる。)
  • 上の図をみると判るが、単独の結合濁点のグリフはゼロ幅で前の文字の右上の位置に濁点を重ね打ちできるようになっている。しかし、“合成”のグリフは最適な位置に濁点が置かれているので、一部の文字では区別が容易に付く。
    以下の出力例を見るときはこの細かい字形の違いに注意してほしい
XeTeX で結合濁点してみる

XeTeX で結合濁点の扱いがどうであるかを調べるために次のような文書を用意した。ここでは、〈て+結合濁点〉、〈ん+結合濁点〉を含む文字列を、liga を有効化した場合と無効化した場合の 2 通りの「にしき的フォント」で出力させている。(なお、この文書では実際の結合濁点の Unicode 文字(U+3099)の代わりに TeX エスケープ形式の「^^^^3099」を用いている。)

% XeLaTeX/LuaLaTeX 文書, 文字コードは UTF-8
\documentclass[a4paper]{article}
\usepackage{fontspec}
\begin{document}

% liga を*有効化*した"にしき的フォント"を使用して
%<で>, <て+結合濁点>, <ん+結合濁点> を出力
\fontspec[Ligatures=Common]{Nishiki-teki}%
でて^^^^3099ーん^^^^3099

% liga を*無効化*した"にしき的フォント"で同じものを出力
\fontspec[Ligatures=NoCommon]{Nishiki-teki}%
でて^^^^3099ーん^^^^3099

\end{document}

なお、以前に紹介した \XeTeXinputnormalization は設定していない((\XeTeXinputnormalization の既定値は 0、つまり正規化変換をしない。))ので、字句解析までの段階で正規化は行われていないことにも注意してほしい。((ちなみに、「^^^^3099」等の TeX エスケープ形式を実際の U+3099 と解釈する処理は、TeX の仕様上は字句解析と同時に行われる。だから、\XeTeXinputnormalization が 1 の場合でも「て^^^^3099」のように書かれたものは正規化されず〈て〉と U+3099 の 2 つの文字トークンになる。))

上掲の文書を XeLaTeX でコンパイルした結果は以下のようになる。

liga の設定を持っている〈ん+結合濁点〉の方を見てみると、liga が有効な場合は合成した字形になっていて、無効な場合は重ね書き(つまり合成されない)になっている。これは完全に想定通りであり、XeTeX の liga 特性の取扱は適切に行われていることが解る。

問題は〈て+結合濁点〉の方である。こちらは liga に合成の設定を持っていないにも関わらず、また、そもそも liga を無効にしていても常に合成された字形で出力される。これはどうも「OpenType の処理」とは別の次元で何らかの正規化が行われている感じがする。

LuaLaTeX してみると

上掲の文書を LuaLaTeX でコンパイルした結果は以下のようになる。

こちらは「OpenType の処理」の想定通りの結果となっている。つまり、liga 指定のない〈て+結合濁点〉は常に非合成になっている。恐らくは「OpenType の処理」だけ行った場合の結果としては、これが正しいのであろう。

まとめ

以上の実験結果から推定できること。

XeTeX では、“文字の出力”の際に、
「OpenType の処理」とは全く別個に
何らかの正規化を行っている。

少なくとも「NFD な濁点・半濁点仮名」については、この「正規化」で「NFC な濁点・半濁点仮名」に置換されるので、わざわざ \XeTeXinputnormalization を使う必要はないのである。

*1:以下の仮名の濁点付きがある: あ う お な ま も わ ゐ ゑ を ん エ ワ ヰ ヱ。

*2:いくつかのグリフは独立した符号位置を PUA の中に有していて、例えば〈ん+濁点〉は U+F42D である。