マクロツイーター

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

VFがアレでもjfmutilで変換できる話

jfmutilで和文VFの中身を調べる

jfmutilコマンドは、(u)pTeX系エンジンにおける和文用のTFMやVFファイルの作成・編集を支援するための機能を集めたユーティリティプログラムである。欧文TeXにおけるpltotfやvptovfなどのコマンドに対する和文版に相当する。

TeX LiveおよびW32TeXに標準で含まれている。
※詳細については過去の記事も参照してほしい。

例えば、jfmutilの「vf2zvp」サブコマンドを用いると、和文のVF(.tfm.vfの組)をテキスト形式(ZVP形式1)に変換することができる。

> jfmutil vf2zvp upjisr-h

これを実行する2と、upjisr-h(upTeXの標準和文フォントの一つ)の情報をテキストで表した、以下のようなファイルが出力される。

[upjisr-h.zvp]

(VTITLE )
(FAMILY UPJIS KANJI)
(FACE F MRR)
(CODINGSCHEME TEX KANJI TEXT)
(DESIGNSIZE R 10.0)
(CHECKSUM O 0)
(FONTDIMEN
   (SLANT R 0.0)
   (SPACE R 0.0)
   (STRETCH R 0.1)
   (SHRINK R 0.0)
   (XHEIGHT R 1.0)
   (QUAD R 1.0)
   (EXTRASPACE R 0.25)
   (EXTRASTRETCH R 0.2)
   (EXTRASHRINK R 0.125)
   )
(MAPFONT D 0
   (FONTNAME uprml-h)
   (FONTCHECKSUM O 0)
   (FONTAT R 1.0)
   (FONTDSIZE R 10.0)
   )
(MAPFONT D 2
   (FONTNAME upjisr-hq)
   (FONTCHECKSUM O 0)
   (FONTAT R 1.0)
   (FONTDSIZE R 10.0)
   )
(GLUEKERN
   (LABEL D 0)
   (GLUE D 1 R 0.5 R 0.0 R 0.5)
   (GLUE D 3 R 0.25 R 0.0 R 0.25)
   (STOP)
;(…略…)
(TYPE D 0
   (CHARWD R 1.0)
   (CHARHT R 0.88)
   (CHARDP R 0.12)
   (MAP
      (SETCHAR)
      )
   )
(TYPE D 1
   (CHARWD R 0.5)
   (CHARHT R 0.88)
   (CHARDP R 0.12)
   (MAP
      (MOVERIGHT R -0.5)
      (SETCHAR)
      )
   )
;(…略…)

このZVP形式のテキストファイルから本来のVF(.tfm.vfの組)に変換するためのサブコマンド「zvp2vf」も用意されているので、これらを利用することで既存の和文VFの編集が可能になる。

upnmlminr-hを変換しようとするとアレ

ところが、フォントによってはvf2zvpの変換が失敗することがある。例えば、[japanese-otf]パッケージのupTeX用のフォントの一つであるupnmlminr-hの中身を調べたいと思って、vf2zvpを使おうとしても、エラーが出て変換は失敗していしまう。(ちなみに、pTeX用のnmlminr-hは大丈夫である。)

> jfmutil vf2zvp upnmlminr-h
jfmutil: CHARWD value mismatch: code 00B7

このエラーの意味は「符号位置0xB7の文字の幅について、.tfm.vfに記録された値が食い違っている3」ということである。この動作自体は正常であり、実際にupnmlminr-hにおいて、0xB7の文字の幅の値は食い違っている4。従って、厳密に言うと当該のVFは「壊れている」ので変換のしようがない、ということになる。

しかし、実際の運用としては、どのDVIウェアも「.vfの方の文字幅の情報は無視する」という動作をする。なのでupnmlminr-hは「実際にはちゃんと使える」のである。となると、この「.vfの文字幅は無視する」という慣習を前提にした上でとにかく変換はしてほしい、と思うことになるだろう。

アレでもとにかく変換してしまう件(--lenientオプション)

このような事態に対処するため、jfmutilの1.2.0版(2019-02-02付)において、--lenientというオプションが追加された。

  --lenient       ignore non-fatal error on VFs

--lenientを指定すると、「実用上は問題ない軽微なエラー」を無視して(実用に即した)変換を行うようになる。

> jfmutil vf2zvp --lenient upnmlminr-h

[upnmlminr-h.zvp;抜粋]

(CHARSINTYPE D 3
   X00B7 X30FB XFF1A XFF1B
   )
;(…略…)
(TYPE D 3
   (CHARWD R 0.5)
   (CHARHT R 0.88)
   (CHARDP R 0.12)
   (MAP
      (MOVERIGHT R -0.25)
      (SETCHAR)
      )
   )

この結果をみると、0xB7の文字(符号化がUnicodeであるので、これは「U+00B7 MIDDLE DOT」のことである)の文字クラスは3で、.tfmの情報に従って文字幅は0.5zw5となっている。


  1. 欧文のVPL形式に相当するもので、書式はVPL形式とJPL形式を混ぜたようなものになっている。

  2. なお、.vfファイルや.tfmファイルなどの“TeXシステムにおける標準的なファイル形式”に関しては、Kpathseaの検索が有効なので、upjisr-h.tfmやupjisr-h.vfはカレントにある必要はなく、インストールされていれば十分である。jfmutilの独自形式(.zvp等)のファイルはKpathseaの検索対象にならない。

  3. つまり、VFの仕様としては、文字の幅は.vf.tfmの両方に記録されることになっている。なぜそのような仕様であるかはよく解らない。なお、文字の高さと深さの情報は.tfmのみに記録される。

  4. 0xB7の文字の幅は、upnmlminr-h.tfmでは0.5zwでupnmlminr-h.vfでは1zwとなっている。jfmutilの「tfm2zpl」や「vf2zvp0」のサブコマンドを使うと、.tfm.vfを単独でテキスト形式に変換できるので、これらを使うとそれぞれの文字幅の情報が確認できる。

  5. 厳密にいうとCHARWDの0.5は「要求フォントサイズを単位として0.5単位」を表す。upnmlminr-hでは1単位が1zwに等しいので0.5zwということになる。