Hatena::ブログ(Diary)

マクロツイーター このページをアンテナに追加 RSSフィード Twitter

2011-11-05

dviout の欧文フォントの謎が解けた! (1)

今まで、dviout に関してずっと疑問に思ってきたことがあった。それは「欧文の OpenType フォントを使うことための、(開発者が想定している)正しい方法は何なのか」ということである。それが TeX Forum 上のある質問に対する議論を契機にしてようやく理解できたので、(「集い」の記事を休憩にして)ここでまとめておく。

欧文 TFM に対して OpenType フォントを対応させる方法は dviout のヘルプて載っていて特に難しくない。例えば timesnr-r.tfm という TFM に(Windows に標準で入っている)「Times New Roman」を割り当てる場合は、有効なマップファイル*1に以下の記述を書くだけでよい。*2

timesnr-r  "Times New Roman"

しかし、他の DVI ウェアのマップ行の書式と比べてみれば判るが、この中には「エンコーディング」を表す部分がない。*3そして、適当な方法で*4調べると、以下のようなエンコーディングになっていることが判明する。*5

f:id:zrbabbler:20111106040654p:image

これを見ると、0x21〜0xFF の部分は Windows-1252*6 になっている。0x00〜0x20 の部分が異様であるが、これは所謂「remap」が施された TeX 専用の 8 ビットの TrueType フォント(「BaKoMa フォント」等)に対応するための細工であり、*7今回の話とは関係ないのでこれ以上は触れない。基本的に Windows-1252 であるということが大事である。

Windows-1252 というのは無論「非常に有名な」文字コードであるが、(8 ビット欧文)LaTeX におけるフォントエンコーディングとしては全くサポートされていない。(だから「OT1」のような NFSS 名もない。)だから、このままでは非常に扱いづらい。

とすると、一番ありそうな予想は次のものだろう。この「既定エンコーディング」は「TeX 専用 TrueType フォント」を用いるためのもので、「Times New Roman」等の「普通の OpenType フォント(TrueType フォントも含む)」を使う場合は、適切なエンコーディングを指定することが要求されていると。

しかし、実際にはそうはなっていない。少なくとも、dviout は enc ファイルによるエンコーディング指定は全くサポートしていない。その代わり、dviout 独自の「Windows コードページの指定」等が使えるが、8 ビットの(欧文の)コードページの中に LaTeX で普通に用いるようなフォントエンコーディングは存在しない。*8

ではこの仕様の下だと、dviout で「普通の OpenType フォント」を欧文フォントとして用いることは不可能かというとそうではなく、そのための方法は幾らでも考え出せる。だがどれも「想定された方法」とするには不可解な点をもつのである。

  1. VF 利用: とにかく、結果のエンコーディング(前掲の図)は判っているので、それに合わせてエンコーディングファイル(.enc)を作れば TFM は生成できるし、あとは仮想フォント(VF)を通せば「そこにある文字」からなる LaTeXエンコーディングは実現できる。例えば OT1 や LY1 は可能だろうし、グリフ合成を頑張れば T1 も大部分はできそうだ。
    ただ、この方法は「dviout のための特別な方法」という印象が強い。確かに、この方法で設定したものは他の DVI ウェアでも通用するのであるが、他の DVI ウェアでは全く一般的でない方法(と私はこでまで認識していた)なので、「dviout のためにわざわざ変な方法を採っている」という印象を持っていたのである。
  2. Unicode SFD + VF: dviout は .enc ファイルのエンコーディング指定はサポートしないが、実は SFD ファイルはサポートしている。だから、まず Unicode SFD(timesnr-r-u@Unicode@ とか)の TFM を作ると、とにかくフォントにある(BMP の)全文字を出力する手段を得たことになる。だからあとは VF を使えば完全な T1 エンコーディングの設定が作れる。
    これは極めて面倒な方法だから、あまり行いたくない。
  3. 裏技 SFD: SFD ファイルが作れるということは「OpenType する件(SFD 編-7)」で述べた「普通の 8 ビットエンコーディングを SFD で実現する」という「裏技」が使えるということである。
    これが一番簡単なのだが、でもこれが「想定された方法」とはとても思えない。
  4. ttf2pk を使う: ttf2pk の設定を行っておけば、mktexpk でビットマップPK フォント)が生成されるので結果的に dviout でも出力できる。ttf2pk のマップ設定は .enc ファイルもサポートしていて他の DVI ウェア(dvipdfmx 等)と同じ感覚で行える。
    これは至極真っ当な方法だが、これが想定された方法だとすると、「普通の OpenType フォント」を指定する例が dviout のヘルプに書いてある理由が解らない。

だから結局疑問は「何が想定された方法か」に尽きるのである。

実のところ、この疑問を今まで持ち越してきた最大の原因は、「別に解決する必要がなかったから本気で調べなかった」ということだったりする。想定解であろうとなかろうととにかく使えるのだから実用上は困らない。自作のパッケージの欧文 TFM 関連部分で dviout のサポートを行う場合は、実際に上述の方法を用いてきた。*9そして、私自身は dviout は使っていないので、必要以上の興味を持っていなかったのである。

(続く)

*1dviout では既定ではマップファイルは無効になっているので有効化する必要があるが、その手順は eggtoothcroc 氏の資料や後で挙げる資料で説明されている。

*2フォントは「フォント名」で指定する。(WindowsAPI を使用するので。)TrueType フォントの場合はファイル名での指定も可能だが、その場合は内部動作が違うらしい。

*3:例えば dvipdfmx のマップ行は「timesnr-r-t1 ec times.ttf」のような形式で、ここでは ecエンコーディング(ec.enc に書かれたもの)を示している。

*4:例えば、256 文字全部が定義済の TFM を作って、そのフォントで全文字を出力させる TeX 文書をコンパイルして dviout で出力させればよい。メトリックが合わないのでずれて表示されるが、どの文字が出るかは判明する。

*5:この画像自体は dvipdfmx で再現した PDF を変換したもの。

*6:Latin-1 の Microsoft による独自拡張による 8 ビットエンコーディングで、Unicode 以前の英語 Windows の標準の文字コードであった。

*7:0xA1〜0xAA、0xAD〜0xC4 の範囲にあるグリフを 0x00〜0x20、0x7F(通常は制御文字領域である)にコピーしている。

*8:もちろん、入力エンコーディング(inputenc)は、その性質上、種々の Windows コードページをサポートする。例えば、\usepackage[winansi]{inputenc} をプリアンブルに書くとソースの文字コードWindows-1252 にできる。

*9:例えば、PXmika パッケージ(欧文部)では 2 の方法、PXmonja パッケージ(欧文部)では 3 の方法、PXchfon パッケージ(欧文、簡易表示)では 4 の方法を用いている。