Acetaminophen’s diary

化学に関すること,TeXに関すること,ゆきだるまに関すること。

pTeX の \dtou と ascmac パッケージの boxnote 環境の話

これは TeX & LaTeX Advent Calendar 2016 の 7 日目の記事です。一昨日(5 日目)に続いて 2 回目の参加です。昨日は doraTeX さんでした。明日も doraTeX さんです。

今年 2016 年は、pLaTeX と upLaTeX が「コミュニティ版」として生まれ変わった記念すべき年です。また、TeX ユーザの集い 2016 での北川さんの講演が「TeX Live 2016 の pTeX 系列のプリミティブ」という題でした。なんだか、2016 年はなにかと「pTeX まわりのあれこれ」が話題になった年だったように思います。

そこで、今回は pLaTeXpTeX に絡んだ話題です。

f:id:acetaminophen:20161207071953p:plain

 

pTeX の “隠し組方向” \dtou の話

pTeX には、オリジナルの TeX にはないプリミティブがいくつも実装されています(pTeX 系列のプリミティブ一覧は、北川さんの講演資料が一目瞭然です)。横組と縦組・和文文字間や和欧文間のスペース・ベースライン補正…といった日本語組版の基本的な機能を提供するプリミティブが代表的ですが、JIS コードから文字へ・数字から漢数字へといった変換プリミティブも日本語の扱いには欠かせません*1

こうした pTeX のプリミティブの多くは、pLaTeX や plain pTeX といった日本語向けフォーマットや関連パッケージで上手に活用されています。ところが、中には全く使われていないプリミティブもあります。それは

\dtou\ifddir\ifdbox

です*2。この 3 つのうち、\if… はいずれも「\dtou かどうか」を判定するプリミティブですから、結局「\dtou なるものが使われていない」という点に帰着します。そこで、今日はこの \dtou について考えてみましょう。

 

\dtou はどれくらい使われていないのか

機能について見ていく前に、どれくらい \dtou がレアなのか調べてみることにしましょう。TeX Live の texmf-dist/tex 以下にある膨大なパッケージなどのマクロを、grep で検索してみます。

$ cd /usr/local/texlive/2016/texmf-dist/tex
$ grep dtou -r .

結果がこちらです。

./latex/l3kernel/expl3-code.tex:  \__kernel_primitive:NN \dtou                        \ptex_dtou:D
./luatex/luatexja/lltjext.sty:       \let\box@dir\dtou\@tempcnta=\dstrutbox
./luatex/luatexja/lltjext.sty:       \or   \let\box@dir\dtou\@tempcnta=\dstrutbox% dtou
./luatex/luatexja/lltjext.sty:\else\ifnum\ltjgetparameter{direction}=1 % dtou
./luatex/luatexja/lltjext.sty:  \else\ifx\box@dir\dtou
./luatex/luatexja/lltjext.sty:  \else\ifx\box@dir\dtou % 180 度回転→vtop, vbox を入れ替える
./luatex/luatexja/lltjext.sty:  \else\if d\caption@dir \let\captiondir\dtou
./luatex/luatexja/lltjext.sty:    \else\if #1d\relax\let\box@dir\dtou
./luatex/luatexja/lltjext.sty:       \or   \let\box@dir\dtou
./luatex/luatexja/lltjext.sty:    \else\if #1d\relax\let\box@dir\dtou
./luatex/luatexja/lltjext.sty:       \or   \let\box@dir\dtou
./luatex/luatexja/lltjext.sty:\else\ifnum\ltjgetparameter{direction}=1 % dtou
./luatex/luatexja/lltjext.sty:  \else\ifx\box@dir\dtou
./luatex/luatexja/lltjext.sty:  \else\ifx\box@dir\dtou % 180 度回転→vtop, vbox を入れ替える
./luatex/luatexja/lltjext.sty:    \else\if #1d\relax\let\box@dir\dtou
./luatex/luatexja/lltjext.sty:       \or   \let\box@dir\dtou
./luatex/luatexja/lltjext.sty:    \else\if #1d\relax\let\box@dir\dtou
./luatex/luatexja/lltjext.sty:       \or   \let\box@dir\dtou
./luatex/luatexja/lltjext.sty:      % 周囲が dtou の場合には,高さ \ltjgetht\tw@, 深さ \ltjgetdp\tw@ のボックスを基準としている.
./luatex/luatexja/lltjext.sty:         \let\box@dir\dtou\@tempcnta=\dstrutbox
./luatex/luatexja/lltjext.sty:         \or   \let\box@dir\dtou\@tempcnta=\tabskip \z@\tabskip \z@\dstrutbox% dtou
./luatex/luatexja/ltj-direction.lua:local dir_dtou = luatexja.dir_table.dir_dtou
./luatex/luatexja/ltj-direction.lua:   for _,i in pairs({dir_tate, dir_yoko, dir_dtou, dir_utod}) do
./luatex/luatexja/ltj-direction.lua:-- \tate, \yoko,\dtou, \utod
./luatex/luatexja/ltj-direction.lua:	 [dir_dtou] = { -- dtou 中で組む
./luatex/luatexja/ltj-direction.lua:	 [dir_dtou] = { -- dtou 中で組む
./luatex/luatexja/ltj-direction.lua:      [dir_dtou] = { -- dtou を
./luatex/luatexja/luatexja-core.sty:%%%%%%%% \yoko, \tate,\dtou
./luatex/luatexja/luatexja-core.sty:\protected\def\dtou{%
./luatex/luatexja/luatexja-core.sty:  \directlua{luatexja.direction.set_list_direction(1, 'dtou')}%
./luatex/luatexja/luatexja.lua:dir_table.dir_dtou = 1
./luatex/luatexja/patches/lltjfont.sty:  \ifnum\ltjgetparameter{direction}=1 % dtou
./luatex/luatexja/patches/lltjfont.sty:      \setbox\dstrutbox\hbox{\dtou

実際の grep の結果にはいくつか addtounicode のような \ナントカdtouナントカ が“邪魔者”として入ってしまいますが、これは \dtou プリミティブと無関係なので省いてあります。2016 年 12 月 7 日現在、出てきたのはなんと LuaTeX-ja のパッケージと LaTeX3 の expl3-code.tex だけでした。

LaTeX3 では「サポート対象の TeX エンジンに存在するすべてのプリミティブを把握する」という方針なので、もれなく e-pTeX / e-upTeX の \dtou も存在を把握されています。しかし、LaTeX3 は機能的には \dtou を運用していませんから、特に役に立っているとはいえません。また、LuaTeX-ja は pTeX ではなく LuaTeX 向けのマクロ集ですから、出てくる \dtou は “Lua スクリプトにより pTeX を真似て作られた命令” にすぎません。結局のところ「真に pTeX のプリミティブ \dtou を運用した例は皆無」という結論に至ります。

 

\dtou とは何か

pTeX を開発したのは株式会社アスキー(現アスキー・メディアワークス)ですが、公式の Web サイトや過去の TeX 関連出版物を見ても、pTeX のプリミティブ \dtou には一切言及されていません

そこで百聞は一見に如かず、例として以下の文書を pLaTeX + dvipdfmx で処理して、得られた結果を見てみましょう。

\documentclass[a6paper,papersize]{jsarticle}
\AtBeginDocument{\dtou}
\begin{document}
吾輩は猫である。名前はまだない。\par
どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめ
した所でニャーニャー泣いていた事だけは記憶している。
\end{document}

f:id:acetaminophen:20161207072732p:plain

このように、横組を左に 90 度回転させたような出力が得られます。文字送りは下から上へ、行送りは左から右へとなっています。この挙動と \dtou という名称から、これは Down-TO-Up であるといわれています。当の pTeX のソースでも、数か所 DtoU という大文字と小文字の使い分けが見うけられることからも、ほぼ間違いないでしょう。

ただ、日本語の文章がこんな方向に書かれているケースを、私は見たことがありません。利用者がいないのも無理はないでしょうし、なぜ \dtou なるプリミティブが実装されたのかも不明です。「pTeX の七不思議」を集めるならば、間違いなく \dtou は入るでしょう。

 

\dtou の由来の謎

そんな \dtou プリミティブは、いったいいつから存在するのでしょうか。

pTeXソースコードアスキー公式サイトアーカイブされています。ここに残っている最古の pTeX 2.1.4 を見てみると… 既に \dtou は定義されていました。さらに古い pTeX のソースは、DVIOUT で知られる大島先生の FTP サーバに残っています。

これは、まだ pTeX が正式にリリースされる前、横組専用で開発された「アスキー日本語 TeX」と、それに“プレリリース版”として付属していた pTeX 2.99 j1.7e p1.0.9F のソースです。眺めてみると、pTeX のほうには既に \dtou プリミティブが実装されていて(!)、「アスキー日本語 TeX」には実装されていませんでした。要するに、アスキー日本語 TeX から pTeX への進化の過程で \dtou が追加されたのでしょうけれど、具体的な時期や目的まではわかりませんでした。

 

\dtou の「再発見」:転機の到来

ほとんど日の目を見ることなく埋もれていた \dtou ですが、転機が訪れたのが TeX Live 2011 のときでした。e-pTeXTeX Live に収録すべく開発を進めていた過程で、pTeXソースコードの中で \dtou が「再発見」されたのです。この経緯は 2012 年の数学ソフトウェアとフリードキュメント XIV での北川さんの講演資料に書かれています。注目すべきは、このとき単に \dtou プリミティブを捨てずに維持しただけでなく、不足分を補って \ifddir\ifdbox まで新たに実装されたことです。

TeX Live 2011 での変化はそれだけではありませんでした。当時、pTeX のドキュメントにない \dtou は DVI ドライバで全くサポートされていませんでした。pTeX が DVI を吐き出しても、その先へ変換できない…という状況を打破すべく、dvipdfmx にも \dtou 対応パッチが追加されたのです (r25139) 。これでようやく、\dtou が“まともに”実用可能な体制が一通り整いました。

 

\dtou をなんとか活用できないか

TeX Live 2011 で \dtou は一応、実用可能な状態になっています。しかし、最初に見たとおり、現在に至るまで \dtou は全く活用されていません。かすかな希望を持って、\dtou を「再発見」した北川さんを中心に開発されている LuaTeX-ja のドキュメント (luatexja.pdf) を見てみると

実は pTeX に同名の命令が(ドキュメントには書かれていないが)存在する.Down-TO-Up の意味なのだろう.\dtou を使用する機会はないだろうが,LuaTeX-ja ではデバッグ用に実装している.

と書かれてしまっています。これはなんだか悔しいので、活用法を考えてみました。

 

回転の代わりに \dtou 使ってみる

既に見たとおり、\dtou は横組と同じものを左に 90 度回転して出力します。ということは、よく「回転」に使われる graphicx パッケージの代わりとして \dtou を使える可能性があります。やってみましょう。

以下の 2 つのソースを、platex + dvipdfmx で処理してみてください。

% graphicx パッケージを使わずに \dtou で回す
\documentclass{jsarticle}
\begin{document}
\newsavebox{\test}
\begin{lrbox}{\test}
\dtou 下から上へ
\end{lrbox}\usebox{\test}\end{document}
% graphicx パッケージで回す
\documentclass[dvipdfmx]{jsarticle}
\usepackage{graphicx}
\begin{document}\rotatebox{90}{下から上へ}\end{document}

f:id:acetaminophen:20161207082302p:plain

どちらも同じ出力になりました。\dtou では左 90 度回転しかできません*3が、「DVI ドライバの機能に頼らず TeX が回転してくれる」と考えると興味深いですね。

とはいえ、180 度ひっくり返したり任意の角度で回転したりするには、やはり graphicx パッケージが楽です。しかも、2016 年現在 \dtou をサポートした DVI ドライバは dvipdfmx しかありません*4ので、安心して用いることはできないでしょう。

DVI ドライバが \dtou に未対応である例として、2016 年現在の dvips を挙げておきます。先ほどの \dtou を使用したソースを pLaTeX + dvips で変換してみると、予期しない結果になります*5

f:id:acetaminophen:20161207082614p:plain

graphicx パッケージは \special{…} という命令を使いますので「ドライバ依存性」をもちますが、多くの DVI ドライバをサポートしている分、\usepackage のオプションにさえ注意すれば安心して使用できます。ところが、\dtou は dvipdfmx でしか現時点でサポートされていない以上、\special とは無関係なのに非常に強いドライバ依存性を持っているといわざるをえません。

 

\dtou の文字の並びを活かした boxnote 環境

先ほどは「回転する」という現象に注目しましたが、これは \dtou の由来と思われる Down-TO-Up にはあまり即していません。「左に 90 度回した状態の文字を下から上に並べる」という仕様を、もっとフルに有効活用できないでしょうか。

そこで私が思いついたのは「ascmac パッケージの boxnote 環境の改変版」です。以下、少し脱線して boxnote 環境の説明をします。

LaTeX の枠作成における ascmac パッケージの位置づけ

LaTeX 文書の中に枠で囲んだ領域を作りたい場合、真っ先に思い浮かぶのはなんでしょうか。最近なら TikZ (pgf) というドライバ依存な描画命令をふんだんに駆使した tcolorbox が有名でしょうか。しかし、昔はこのような高機能な描画パッケージは存在せず、TeX の基本である「文字と線を並べて配置するだけ」という素朴な機能だけを使って枠を書いていました。その代表格が、pLaTeX 標準配布物に 1988 年ごろから含まれているとみられる ascmac パッケージ (ascmac.sty, tascmac.sty) です。中には scrren 環境、itembox 環境、shadebox 環境、boxnote 環境という四種類の枠が定義されていますが、最も興味深いのは間違いなく boxnote 環境でしょう。ノートを破ったような形のユニークな枠は、tcolorbox のような豪華なパッケージが普及した今でも愛用者が多いようです。

どうやってこんなノートの破り線を実現しているのでしょうか。実装を見てみると、驚くべきことに「a と b という文字を並べているだけ」なのです。アスキーが作成した ascgrp という特殊なフォントを testfont で見てみましょう(過去記事参照)。

f:id:acetaminophen:20161207084219p:plain

cmr10 の場合の表と見比べると、a と b のところに破ったノートの穴一つや紙の端の形がグリフとして収録されています。これを TeX マクロで密に並べると、TeX が「文字を並べて配置するだけ」でノートを破った形ができます。

カスタマイズ版 boxnote 環境の事例

この ascgrp フォントを拝借すれば、ほかの向きの破ったノートもできそうな気がします。実際、boxnote 環境の方法をまねて「向きの違う破ったノート」を作る試みは、今までもなされてきたようです。

例として、乙部さんの「pLaTeX2e for Windows Another Manualシリーズにちょっと似た出力ができるためのクラスファイル」を見てみましょう。explan.lzh のなかの column.sty に定義された column 環境は、ascmac パッケージの boxnote 環境と同様に、ascgrp フォントの a,b を並べた破り線を使用しています。ただし、逆さま(180 度回転)になっています。実際のマクロのコードを読んでみると、正立した a, b のノート文字を「テキスト横幅の分だけ」並べたあと、\rotatebox で 180 度回転することにより実際の出力(= 逆さまの破り線)を得ています。

f:id:acetaminophen:20161207085027p:plain

では左右の辺に破り線がくる場合はどうすればよいでしょうか。実は、上下の辺に破り線がくる場合よりは少し複雑になります。というのも、boxnote 環境の横幅(字送り方向)は常にテキスト幅に固定されているのに対し、縦幅(行送り方向)は枠内の文章量によって伸び縮みするからです。したがって、破り線を枠の左右の辺に置く場合、いったん枠内の文章を組んで縦幅を取得してからその長さに合わせる必要があります。

どういうわけか、私はこれを実装したコードを見たことがありません。が、ノート線を左に置きたいという需要は確かにあるようです。たとえば、prosperを使おう(2) ―スタイルファイル作成―という文書には、枠の左の辺に ascgrp フォントで破り線を置く例が載っています(しかし、これは PSTricks を使って手動で座標を与えて枠を書いていて面倒そうです)。

破り線が左にある「varboxnote 環境」の実装

というわけで、これを varboxnote 環境と名付けることにして、実装してみましょう。上の乙部さんと同じように、\rotatebox の回転を利用したコードです。

結果がこちらです。

f:id:acetaminophen:20161207092233p:plain

しかし、\special を使っているわけですので、なんだか ascmac パッケージの「TeX 本来の機能だけで枠を書く」という美しさが損なわれているような気もします。そこでもう少しよく見てみると… ascmac パッケージにある boxnote 環境と比べると、varboxnote 環境は破り線が左に 90 度回転していることに気づきます。破り線は a, b という文字の並びなので… これは \dtou で実現できてしまいます

このマクロもやはり、現在は dvipdfmx 専用となってしまっています。しかし、「TeX 本来の機能だけで枠を書く」という ascmac パッケージの手法により近づけたような気がします。もしかして、アスキーの方々は(日本語のために \dtou を使うのではなく)boxnote 環境の拡張を考えていたのではないか… そんな新説を唱えてみたくなる今日この頃です。

読者への宿題:varboxnote 環境は「横組では左、縦組では上」に破り線があります。では、「横組で右に破り線がある枠」や「縦組で左に破り線がある枠」を実装してみてください。

*1:特に \kansuji や \kansujichar は一見マクロでも実現できそうですが、「プリミティブとして実装されていることにより有用なトリックが生まれる」ことが知られています。

*2:ほかに使われていないものとしては \(no)auto… と \showmode がありますが、これは kanjiskip や xkanjiskip の挿入を行うかどうかという制御に関わるものです。これを意図的に変更する処理は通常の文書作成では必要なく、主にテストやデバッグの目的に存在していると考えて触れないことにします。

*3:似た手法として、右 90 度回転は「縦組中の数式」すなわち“縦数式ディレクション”を利用すれば pTeX で実現できます。興味のある方は遊んでみてください。

*4:Unix 系の一部で細々と使われている pxdvi という DVI ビューアも(同じく北川さんの手によって)\dtou に対応していますが、TeX Live には収録されていませんし、今後収録される予定もないので考えないことにします。

*5:dvips は pTeX の横組と縦組をサポートしていますから、「通常の横組ではない」ことまでは解釈できて、結果的に「pTeX の縦組」として扱われているようです。