なんだか「マクロツイーター」っぽくなってきましたね!
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 に渡さずに自前で処理を行う。多分このあたりの処理が怪しいんだと思う。