なんだか「マクロツイーター」っぽくなってきましたね!
MetaPost
前回は PostScript を用いてナベアツを実装した。描画言語を利用するというアイデアは有望であるが、しかし残念ながら PostScript ではフォントをアホにすることができなかった。*1そうすると「TeX のフォントが自由に使える描画言語」の使用という考えに自然と行き着くであろう。というわけで、MetaPost を使うことにする。
MetaPost のコードを LaTeX の文書に挿入するためのパッケージを CTAN で探すと、emp というものが見つかった。これを使うと、次のようなことができる。*2(パッケージの使用法はマニュアルを参照されたい。「小さなパッケージ」なので容易に理解できる。)
\documentclass[dvips]{article} \usepackage{emp} \begin{document} \begin{empfile} % 設定やマクロ定義(beginfig〜endfig 外のもの)を % empcmds 環境に記述する. \begin{empcmds} def char_ol (expr x, y, fnt, fsiz, ch) = for item within glyph ch of fnt scaled .001fsiz: draw pathpart item shifted (x,y); endfor enddef; \end{empcmds} % 各々の図を emp 環境に記述する. % (0,0)はMetaPostに引き渡される「図の大きさ」だが, % ここでは利用しないのでゼロにした. \begin{emp}(0,0) pickup pencircle scaled .4pt; string fnt; fnt := "cmbx10"; char_ol( 0.00pt, 0.00pt,fnt,10pt,"T"); char_ol( 6.56pt,-2.68pt,fnt,10pt,"E"); char_ol(12.68pt, 0.00pt,fnt,10pt,"X"); \end{emp}% \end{empfile} \end{document}
ただ残念なことに、このパッケージでは、「LaTeX のユーザ定義命令に利用する」ことを想定していないので、以下のような制限があって、「ナベアツ問題」の解決には使えない。
- MetaPost のコード記述について、verbatim に書く方法(環境)しか用意されていない。だから、命令の引数(
#1
)を MetaPost 側に渡すことができない。 - 一連の emp や empcmds 環境を empfile 環境に含めることが要求される。*3これだと、MetaPost のコードがプレアンブル((ユーザ定義命令(
\NabeAzz
)の定義は当然プレアンブルに書きたい!))と本体に分散する場合に対応できない。
あれこれ悩むよりも、作る方が早いので……
- bxemp パッケージ(Gist/zr-tex8r)
このパッケージは次の機能を提供する。
- emp 環境、empcmds 環境の「命令版」を提供する。((
\doempdef
もある。))\doemp[<名前>](<幅>,<高さ>){<MetaPostコード>}
\doempcmds{<MetaPostコード>}
\empfixedfile[<ファイルベース名>]
を実行すると、文書のそれ以降を\begin{empfile}[<ファイルベース名>]〜\end{empfile}
で囲ったのと同等の動作をする。元々の empfile と異なり、\begin{document}
を跨ぐことが可能である。- pdfTeX に対応させた。
これで無事にナベアツできるようになる。
\documentclass[a4paper]{article}% when using pdfTeX %\documentclass[a4paper,dvips]{article}% when using dvips \usepackage{emp,bxemp} \empfixedfile \newcommand*\NabeAzz[1]{% \doemp(0,0){nabeazz(#1);}% } %!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BEGIN MetaPost code \begin{empcmds} prologues := 3; nazunit = 12; nazwidth = 144; string nazfont; nazfont = "cmr10"; nazfsize = 10pt; string nazahofont; nazahofont = "cmfi10"; nazahofsize = 14.4pt; nazsep = 5pt; vardef nazaho primary n = save i, n_, s, r; n_ = n; if n mod 3 = 0: true else: boolean r; r = false; string s; s = decimal n_; for i = 1 upto length s: r := r or ((substring (i-1,i) of s) = "3"); endfor r fi enddef; vardef naznumber(expr n) = naznumberin(n, nazaho n) enddef; naznht = ypart(urcorner("3" infont nazahofont scaled (nazahofsize / fontsize nazahofont))); vardef naznumberin(expr n, a) = save n_, fnt, fsiz, pic; n_ = n; string fnt; if a: fnt = nazahofont; fsiz = nazahofsize; else: fnt = nazfont; fsiz = nazfsize; fi nazsetheight(decimal n_ infont fnt scaled (fsiz / fontsize fnt), naznht) enddef; vardef nazsetheight(expr pic, ht) = save pic_, wd; picture pic_; pic_ := pic; wd = xpart(urcorner pic_); setbounds pic_ to (0,0)--(wd,0)--(wd,ht)--(0,ht)--cycle; pic_ enddef; path nazpath; def nazmakepath(expr m) = begingroup save m_, u, np, npx, npy, nplen; m_ = m; nplen = xpart(urcorner(naznumberin(m_, true))) * 1.5m_; npx = npy = 0; u = nazunit; npx3 = nazwidth; npx3-npx2 = npx1 = u; path np; np = (u, 0); forever: np := np--(npx2,npy)..(npx3,npy-u)..(npx2,npy-2u) --(npx1,npy-2u)..(0,npy-3u)..(npx1,npy-4u); exitif arclength np >= nplen; npy := npy-4u; endfor nazpath = np; endgroup enddef; def nabeazz(expr m) = begingroup save m_, n, t, p, d, pic, cur; m_ = m; nazmakepath(m_); cur = 0; for n = 1 upto m: picture pic; pic := naznumber(n); forever: t := arctime cur of nazpath; pair p; p := point t of nazpath; pair d; d := direction t of nazpath; exitif abs d > 0; cur := cur + eps; endfor label(pic rotated angle(d), p); cur := cur + xpart(urcorner(pic)) + nazsep; endfor endgroup enddef; \end{empcmds} %!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! END MetaPost code % \begin{document} \NabeAzz{40} \end{document}
pdfTeX エンジンを使う場合は次の手順でコンパイルする。
pdflatex nabeazz-metapost mpost nabeazz-metapost pdflatex nabeazz-metapost
dvips を使う場合は、クラスオプションにドライバ指定 dvips
を追加したうえで、次の手順でコンパイルする。(出力は PostScript 文書。)
latex nabeazz-metapost mpost nabeazz-metapost latex nabeazz-metapost dvips nabeazz-metapost
なお、原理上は dvipdfmx を使用する((もちろんドライバオプション dvipdfmx
の指定が必要。))ことも可能なはずなのだが、上掲の文書では何故か異常な出力になってしまった。*4残念!
正常にコンパイルされた場合は以下の出力が得られる。
これまでのナベアツの出力とは若干違ってるようにも見えるが、気にしないことにしよう。
*1:何か細工をすればできそうな気もするが。
*2:この文書のコンパイルの方法は、後で説明する nabeazz-metapost.tex の dvips 版のものと同じである。オリジナルの emp パッケージは pdfTeX に非対応である。
*3:この環境で囲った部分が example-emp.mp というファイルの出力と対応する。empfile 環境はオプション引数をもち、そこには出力ファイルベース名が指定できる。つまり、「複数の MetaPost ファイルに分割して出力する」ことが想定されているわけである。
*4:MetaPost の出力形式は EPS の一種である。ところが dvipdfmx は MetaPost の出力については Ghostscript に渡さずに自前で処理を行う。多分このあたりの処理が怪しいんだと思う。