マクロツイーター

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

upTeX で Unicode できない話

up(La)TeX を使うと、JIS コード(JIS X 0208)にない文字を(和文文字として)出力できる。ただしここで注意すべきことがある。up(La)TeX の“標準”の(TeX 側の)フォント設定を使う場合は、Unicode 文字を「なんでも」使えるわけではないのである。

Unicode できない例

例えば、チョット🍣してみよう*1と思って、次のような文書ソースを作ったとする。(物理フォントが〈🍣〉の字形を持っていない場合は流石に上手くいくはずがないので、「和田研中丸ゴシック」を指定する。)

[sushi.tex]
% upLaTeX 文書
\documentclass[a4paper,uplatex]{jsarticle}
\usepackage{pxchfon}
\setgothicfont{wlcmaru2004emoji.ttf}% ゴシック→和田研中丸ゴシック
\begin{document}
まず\textgt{🍣}より始めよ。
\end{document}

この sushi.tex は、uplatex のコンパイルは正常にできるが、dvipdfmx で PDF を生成しようとすると次の警告メッセージが出て、PDF は出力されるものの肝心の〈🍣〉が消えてしまう。

sushi.dvi -> sushi.pdf
[1
char=0x1f363(127843)
Tried to set a nonexistent character in a virtual font]
5244 bytes written
Unicode できない理由

upTeX エンジン(の和文処理)は Unicode 全域を処理できる。従って、失敗するのは“フォント”設定の問題である。upTeX 利用の作業フローで PDF を出力する場合、「特定の文字が出ない」ことの理由として次の 2 つが考えられる。

  1. TeX 側”のフォント(論理フォント*2)の問題: 論理フォントの対応文字集合に含まれていない。
  2. DVI ウェアのフォントマップ設定の問題: CMap 設定においてマップ元の文字集合に含まれていない。
論理フォントの問題

upLaTeX で標準的に用いられる論理フォント(upjisr-h 等*3)でサポートされているのは次の範囲にある文字である。

U+0000..U+04FF, U+1E00..U+243F, U+2460..U+27BF, U+2900..U+29FF, U+2B00..U+2BFF, U+2E80..U+2FDF, U+3000..U+30FF, U+3190..U+319F, U+31F0..U+4DBF, U+4E00..U+9FFF, U+E000..U+FB4F, U+FE10..U+FE1F, U+FE30..U+FE4F, U+FF00..U+FFEF

これは、「BMP の中で、日本語文字*4が含まれる Unicode ブロックの範囲を合わせたもの」になている。〈🍣〉(U+1F363)は BMP 外にあるので、当然使えないわけである。

BMP 外の文字が使えないとなると、🍣ばかりでなく〈𠮷〉(U+20BB7)も使えないことになりそうだが、実は漢字については対応策がある。「upLaTeX を使おう」の記事で述べられている方法を使うと、upTeX の論理フォントが別のもの(upjpnrm-h 等*5)に変わるので、“Unicode 補助漢字面”にある漢字等*6が使えるようになる。(なお、〈𠮷〉については、otf パッケージを読み込むことでも解決できる。)しかし、残念ながら、〈🍣〉については upjpnrm-h がサポートする集合にも含まれないので、同じ方法では対処できない。

[2018-03-01 追記] uptex-fonts[2018-02-11]以降の版では、標準のフォント(upjisr-h 系列)のサポート範囲が拡大されて、「AJ1 に含まれる BMP 外文字」が使えるようになっている。つまり〈🍣〉は相変わらず使えないが〈𠮷〉は使える。

フォントマップの問題

こちらは少し難解な話なので、dvipdfmx に限定して粗く説明することにする。dvipdfmx の内部処理で日本語(物理)フォントを扱う際には、通常は、“文字コード”として Unicode ではなく Adobe-Japan-1(AJ1)を使用している。(この挙動は変更可能でありマップファイルで設定する。)そのため、論理フォントの文字コード(upTeX の場合は Unicode)から AJ1 への変換が行われる。ところが、〈🍣〉の文字は AJ1 には含まれない。(〈𠮷〉は含まれている。)このような文字は、変換の段階で処理できずに落ちてしまうのである。

残念な結論

以上の理由により、upLaTeX においても“標準の”設定のもとでは「任意の Unicode 文字が使える」とはいえないのである。

もちろん、「使えるように設定」すれば使えるようになる。〈🍣〉については実際に使えるようにする設定が doraTeX 氏のブログ*7で紹介されている。簡単に説明すると、ここで挙げた 2 つの問題を解決するために以下の作業を行っている。

  1. 〈🍣〉などの絵文字の集合をサポートする論理フォント(emoji-h)*8を新たに作成し、それを使用するための LaTeX の設定を行う。
  2. dvipdfmx のマップファイル*9の設定において、先程述べた「内部で AJ1 を使用する」挙動を「内部で Unicode を使用する」挙動に変更している。*10このため、論理フォント(upTeX では Unicode 扱い)からの文字コード変換が起こらず、TeX 側で指定された文字が常に出力されるようになる。

(ちなみに、PXchfon パッケージdirectunicode オプションは、ここの 2 番目に挙げた「dvipdfmx の内部処理を Unicode にする」ことを指示している。)

もちろん、このような“設定”を行うには、TeX エンジンや DVI ウェアのフォントの扱いに対する正しい理解(参照)が必須であり、普通の LaTeX ユーザが気軽に手を出せるものではない、というのは否み難い事実である。

補足

upLaTeX で「ある文字が使えるか」について判断する場合は、奥底の記事で述べられている注意点(全角幅でないとダメ、等)にも留意する必要がある。

*1:別に絵文字の話をしようとしているわけではないので、カラー絵文字としてではなく“普通の”和文文字として出力することを考える。

*2:ここでは VF フォントのことを指す。厳密 VF を .tfm と .vf に分けて考えると、TeX エンジンは .vf は見ないので“TeX 側の問題”ではないことになるが、ここでは .vf と .tfm を一体と考えて、対応文字範囲を“VF フォントの性質”と見做すことにする。

*3:横組では明朝が upjisr-h、ゴシックが upjisg-h。縦組は横組のものの ‘-h’ を ‘-v’ に変えたもの。

*4:正確には“Adobe-Japan-1 の文字”。

*5:横組では明朝が upjpnrm-h、ゴシックが upjpngt-h。縦組は ‘-v’ に変えたもの。

*6:詳しくいうと、以下の範囲が追加される: U+1F100..U+1F2FF, U+20000..U+2A6DF, U+2A700..U+2B81F, U+2F800..U+2FA1F

*7:ちなみに、doraTeX 氏は coloremoji パッケージの作者であり、この記事の“続き”に coloremoji の話がある。

*8:この emoji-h は VF でなく和文 TFM を直接使っている。実は、TFM を直接使うと、使用範囲の制限が無くなって Unicode 全域が使えるようになる。

*9:実際には、dvipdfmx の special 命令を利用して TeX 文書内でマップ行を指定している。

*10:具体的にいうと、マップ行で CMap を UniJIS-UTF16-H でなく unicode としている。