dvipdfmx / xdvipdfmx の新しい special



dvipdfmx / xdvipdfmx のコマンドラインオプション

TeX をお使いの方にはおなじみの dvipdfmx / xdvipdfmx ですが、 コマンドラインオプションでは指定できるのに、 TeX 文書中では指定できない機能がいくつかありました。例えば、

$ dvipdfmx -z 0 foo.dvi

のように、コマンドラインオプション「-z 0」を指定すると、 PDF の圧縮をしないようにすることができますが、これと同等のことを TeX 文書中で指定することはできない ようでした。

私のやりたいことは、圧縮を抑止する「-z 0」よりは、 LilyPond の PDF ドキュメントで PDF 相互間のリンクが正常に機能するように、 PDF ラベル最適化を抑止する「-C 0x0010」という コマンドラインオプションと同等のことがしたい、というものでした。

これを special や primitive なりで指定できれば、 texinfo.tex 中で指定することにより、 LilyPond や、その他 Texinfo を使った PDF ドキュメント相互間で リンクが機能するようになります。

自分なりに調べてみたりしたのですが、 残念ながらそういう機能は無さそうだ、ということがわかりました。

無ければ作ってしまえ

もちろんほしい機能があれば要望してみるのもいいんですが、 以前、xdvipdfmx のバグ修正パッチを作ってみたことがありましたので、 ほしい機能が「無ければ作ってしまえ」というわけで、 挑戦してみることにしました。

以前のバグ修正

ここで一旦、以前のバグ修正 (TeX Live SVN r39834) について触れておきます。

TeX Live 2015 の dvipdfmx / xdvipdfmx は \special{pdf:dest ...} で指定する文字列(ラベル)が最終的に UTF-16 になる場合、 半角の 1 (U+0031) や ü (U+00FC) のような U+00FF 以下の文字があると、 その前までで切れてしまいリンクがまともに動作しない、という 問題がありました

これは特に XeTeX (xdvipdfmx) の場合、特に何もしなくても 非 US-ASCII 文字が含まれていた場合は UTF-8 から UTF-16 への変換が走るため、 致命的でした。 特に、Texinfo では node 名に US-ASCII の接頭語を連結したものを ラベルに使うようになっているため、node 名に日本語を使うと、 (日本語は非 US-ASCII なので UTF-16 変換が走り、 接頭語の US-ASCII は U+00FF 以下なので切れてしまうという……) 必ず踏んでしまうバグになってしまっていました。

ただし、普通に LaTeX で hyperref パッケージを使っている場合であれば、 ラベルは必ず US-ASCII 文字のみで構成されるようですので、特に問題ありません。 また、TeX Live 2013 以前は、この問題は無さそうです。 TeX Live 2014 と TeX Live 2015 にはこの問題がありますが、 実は本記事の主題である「-C 0x0010」で回避できます。 また、これとは別の修正 (TeX Live SVN r39695, r39753, r39754) により、 UTF-16 への変換が行われなくなるため、とりあえず致命的ではなくなる、 ことにはなりました。

が、気持ち悪いので、試しにソースを眺めていたところ、 ちょっとしたパッチで直せそうだったのです。 そこで、ビルド環境を作って、パッチを作り、 取り込んで (TeX Live SVN r39834) いただきました。

新しい special を追加

話を戻します。 というわけで dvidpfmx / xdvipdfmx のビルド環境はあったので、 新しい special を追加するパッチを作ってみました。 最初は、いちばんやりたかった 「-C 0x0010」相当のラベル最適化抑止ができる pdf special を追加する パッチを作りました。そして、PDF に圧縮がかかっていると、 本当にラベル最適化が抑止できているか確認が難しいため、 デバッグ用に「-z」相当の圧縮率を指定できる pdf special を追加する パッチを作ってみました。

最終的には作者様からアドバイスをいただき、 dvipdfmx.cfg と同様のコマンドラインオプションが指定できるような、 dvipdfmx special を新設することとなりました。

使い方

TeX Live 2016 に間に合ったようですので、TeX Live 2016 であれば使えます。
従来、PDF 圧縮を抑止するには

$ dvipdfmx -z 0 foo.dvi

のようにコマンドラインオプション「-z 0」を指定する必要がありました。
新 special で PDF 圧縮抑止するには、 TeX 文書中に、

\special{dvipdfmx:config z 0}

と書くことで実現できます。
同様に、PDF ラベル最適化抑止をしたければ、従来は、

$ dvipdfmx -C 0x0010 foo.dvi

のようにコマンドラインオプション「-C 0x0010」を指定するなり、 XeTeX であれば、

$ xetex --output-driver='xdvipdfmx -C 0x0010' foo.tex

とか、Texinfo の場合は、

$ PDFTEX="xetex --output-driver='xdvipdfmx -C 0x0010'" texi2pdf foo.texi

等のように指定する必要がありました。
こちらも新 special を使うと、TeX 文書中に、

\special{dvipdfmx:config C 0x0010}

と書くことにより実現できます。

コマンドラインオプションのように - (ハイフン)を付けません。
書式は dvipdfmx.cfg と同じです。

注意

xdvipdfmx (XeTeX) の場合でも、special 名は dvipdfmx です。 xdvipdfmx ではありません。

この \special{dvipdfmx:config ...} は、 最初に読み込まれるだけです。 ですので、文章中で動作を切り替えたりすることはできません。

オマケ

これでコマンドラインオプションは不要になる、のですが、 LilyPond の場合、ビルド環境を TeX Live 2016 に切り替えるには 時間がかかりそうですので、結局、

というわけで、 結局コマンドラインオプションを付けるようにしてしまいました。。。