PostScriptのスタック操作と手続きの合成

私は日本語訳の本を見ているのですが、PostScript TUTORIAL and COOKBOOKの39ページに内部でexchを使ってスタックの状態を入れ替えている手続きの定義がわかりづらかったので追ってみました。

  • x 座標、y 座標をスタックに積んで showGorilla を呼ぶと指定された座標に移動してGorillaを表示する手続きです。
/showGorilla                   % stack: x y
{ moveto (Gorilla) show }def
  • フォントサイズを指定してscaleTimesを呼ぶとフォントをTimes-Romanの指定された大きさに設定する手続き。
/scaleTimes                       % stack: scale
{ /Times-Roman findfont
  exch scalefont %scale, using # on stk
  setfont } def

GhostScript でscaleTimesの定義部分を確認してみます。

% フォントサイズを指定して呼ばれるので 6をスタックに積みます。<1>はスタックに積まれた数です。
GS>6
% /Times-Roman findfontを実行するとフォントを探してきます。Loading Nimb・・・の表示は2度目から
% はありません。
GS<1>/Times-Roman findfont
Loading NimbusRomNo9L-Regu font from C:\Program Files\gs\gs9.06\Resource/Font/Ni
mbusRomNo9L-Regu... 2590840 1237788 2756072 1463353 1 done.

% スタックの内容を表示してみます。-dict-がフォントのようです。
GS<2>pstack
-dict-
6

% exchを実行するとスタックの内容が入れ替わります。
GS<2>exch
GS<2>pstack
6
-dict-

% この状態でscalefontを実行するとスタックが消費され、6ポイントに指定されます。
GS<2>scalefont
GS<1>pstack
-dict-
% setfontを実行するとスタックが消費され、フォントが設定されます。
GS<1>setfont
GS>

scaleTimesは手続きの中でスタックに積みますから、scalefontが呼ばれるまえに積まれた値を使うにはexchを実行しなければならないのです。
この状態で

6 scaleTimes 100 100 showGorilla

を実行すると 100 100の位置にTimes-Roman 6 ポイントでGorillaと表示されます。

ここから先はちょっと遊んでみます。

% 30 がスタックに積まれ scaleTimes が消費し、100と100が積まれ、showGorillaが消費します。
30 scaleTimes 100 100 showGorilla

スタックの状態を考えると次のように書き換えられます。

% 100 100 30 が積まれ、scaleTimesが30を消費し、100 100をshowGorillaが消費します。
100 100 30 scaleTimes showGorilla

スタックに積むのを前半に、消費する手続きを後半にまとめると手続きと手続き合成できます。

表示位置、フォントサイズを指定するとGorillaと表示する手続きの定義は以下になります。

% stack: x y scale
/scaleTimesShowGorilla {scaleTimes showGorilla} def

100 100 30 scaleTimesShowGorilla
showpage