これは小波秀雄が
Postscript で図形を描くために書き溜めているメモです。
拙作のライブラリと併用すれば,
簡単な記述で描画を実現できます。
|a|b|
まずは直線を引いたり,円を描くための EPS ファイルを 作成してみます。これで試した後,とにかく早く描画をしたい 人は,小波秀雄作のPostscript ライブラリを利用するとよいでしょう。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 400 300
50 50 moveto 100 90 lineto 100 160 lineto 10 70 lineto
stroke
closepath stroke
fill
変数,手続きを簡単に定義して使うことができる。
/m {moveto} def
/l {lineto} def
これ以降は,moveto, lineto の代わりに m, l だけでよい。
/x1 {100} def
/y1 {120} def
これ以降は,x1, y1 を使って書くことができる。
1 1 0 setrgbcolor
7 setlinewidth
newpath 180 100 15 30 180 arc strokestroke の代わりに fill を使えば塗りつぶしになる。また newpath を省略すると余計な線が描かれることがある。
newpath 280 100 15 0 360 arc stroke
とりあえず簡単な絵を作りたい人は,ここからPostscript ライブラリ の方へ飛んでみるといいでしょう。
EPS(Encapsulated Postscirpt)は,1枚の画像の大きさを決めて出力するタイプの フォーマットで,下のようなヘッダを付けるだけで,EPS になります。 showpage は使いません。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 600 600 %%HiResBoundingBox: 0 0 599.5 600.2
3行目は拡張版用,2行目と併用するらしい。あまり使わないみたい。
|a| dup → |a|a|
|a|b|c| 2 copy → |a|b|c|b|c|
|f|e|d|c|b|a| 5 1 roll → |a|f|e|d|c|b| |f|e|d|c|b|a| 5 2 roll → |b|a|f|e|d|c|
|d|c|b|a| count → |d|c|b|a|4|
x1 dx x2 {proc} for
変数の順序に注意
50 10 200 {50 10 0 360 arc stroke} for
x1 dx x2 {y moveto 0 length rlineto stroke} for
y1 dy y2 {x exch moveto length 0 rlineto stroke} for
[a b c d ...] w setdash
[] 0 setdash
(foo.ps) run
ある PS ファイル foo.ps があったときに,それを直接 描画に使うのではなく, 別ファイル hoge1.ps , hoge2.ps などから上のように読み込んで使うようにするとよい。 dviout だと異なった bmc ファイルになるし, GIMP で加工して書き戻したときにも,原型の方は壊されないですむ。
d c b a 3 array astore → |d|[c b a]|
[c b a] aload → |c|b|a|[c b a]|
このとき,トップには元の配列が残されているので, 不要なら pop して捨てる。
現在の色を変数に保存しておいて,後でまたその色に戻すには, 次のようにするとよい。
currentrgbcolor 3 array astore /rgb exch def 1 0 0 setrgbcolor % 他の色に設定 ... ... rgb aload pop setrgbcolor % 元の色に戻す
gsave, grestore を使うと,現在のパス,色などをセーブしておいて,あとで再利用できる。
塗りつぶしと輪郭描きを同一のパスについて行うには次のようにするとよい。
4 setlinewidth 1 0 0 setrgbcolor 50 50 moveto 150 50 lineto 100 130 lineto % パスを生成 gsave % 上の状態をすべてセーブ。 0.5 setlinewidth 1 1 0 setrgbcolor fill grestore % 線の太さ,描画色,パスが呼び戻される。 closepath stroke
gsave はグラフィック状態をスタックに保存するので, 複数回実行すると,その回数分の状態が記憶される。
1 setlinewidth 1 0 0 setrgbcolor 50 150 moveto 150 150 lineto 100 230 lineto closepath gsave gsave 1 1 0 setrgbcolor fill grestore 4 setlinewidth stroke grestore 1 1 1 setrgbcolor 0.5 setlinewidth stroke
文字列を表示させるためには,次の例のような手続きを必要とします。
上の処理は一度行っておけば,その後の出力は同じ設定のままで行われることになります。
show によって打ち出される文字列は,左下隅がカレントポイントに置かれます。 したがって,moveto などによってカレントポイントが設定されていないと エラーになります。ただし,カレントポイントは文字出力によっても 更新されていきますので,常に moveto を使う必要があるわけではありません。
欧文のフォントは多種類のものがあります。基本的には Times 系を中心にして, Helvetica系, Courier 系のものを適宜取り入れる程度でよいでしょう。
なお,ギリシャ文字を使うためには Symbol が必要です。/Times-Roman findfont 10 scalefont setfont 100 200 moveto (ABC) show
Ghostscript で使える欧文フォントのサンプルは次にありますので,さらに多様な フォントが必要になったら,参考にしてください。
xfigType1.pdf(表示はこちら) xfigType1.ps(ダウンロードして調べて下さい)
和文フォントを利用するには,文字コードの問題を押さえておくことが必要です。 Postscript で使いやすい文字コードは Shift-JIS, EUC-JP, UTF-8 です。JIS(iso-2022-jp)はちょっとめんどうです。
ただし Shift-JIS の場合には,特定の文字で文字化けを起こす現象が知られており,UTF-8 がデフォルトでインストールされていないこともあるようです。 その意味でもっとも安全なのは EUC-JPです。 ps ファイル自体の文字コードもそろえておくことを お忘れなく!
使用する文字コードごとに,上の XXXX の部分を次のようにします。
日本語は縦書きにもできます。この場合,次のようにフォント指定を変更すれば 自動的に縦書きになります。例は明朝体を EUCで使っている場合です。
H は Horizontal V は Vertical からきています。
Ryumin-Light-EUC-H findfont 12 scalefont setfont 100 200 moveto (日本語の表示) show
「表」の字が化けてしまうことに注意してください。
/GothicBBB-Medium-90pv-RKSJ-V findfont 12 scalefont setfont 100 200 moveto (日本語の表示) show
% 型となる図形の定義。ただし fill, stroke は行わない! clip % 図形などを描く。すると型で切り抜かれて描画される。 initclip % clip を解除
/Times-Italic findfont 70 scalefont setfont
45 100 moveto
(QP) false charpath clip
80 3 170 {5 exch moveto 200 0 rlineto stroke} for
initclip
-500 5 1000 {
150 90 90
4 2 roll 2 copy moveto
3 2 roll add 3 1 roll add exch lineto stroke
} for
newpath
200 150 100 0 360 arc
clip
-500 5 1000 {
150 90 90
4 2 roll 2 copy m
3 2 roll add 3 1 roll add exch l s
} for
initclip
図形には輪郭だけを与えて, stroke していないことに注意。
/cm {28.346 mul} def
上のようにしておけば, 12.3 cm と,単位付きの長さを扱うように記述できる。
/localdict 1 dict def
/sampleproc
{ localdict begin
/localvariable const def
end
} def
ここで,/localdict 1 の 1 は常にこの値でよい。この値は
初期の言語仕様で
バッファサイズ
を指定するために使われたのだが,現在の仕様では自動的に
メモリが割り当てられる。
ある手続きを定義して,その中のローカル変数に パラメータを渡したいというのはよく起きる。 このときには上のサンプルの形の中で exch 演算子を使うとよい。
次のサンプルでは,x1, y1 にそれぞれ 10, 20 が, x2, y2 にそれぞれ 100, 190 が代入される。 実行して確かめるとよい。このやり方を使えば, 複雑なスタック操作をやらなくて済む。
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 300 250
/ldict 1 dict def
/proc {
ldict begin
/y2 exch def
/x2 exch def
/y1 exch def
/x1 exch def
x1 y1 10 0 360 arc stroke
x2 y2 5 0 360 arc fill
end
} def
10 20 100 190 proc
(ABC) dup stringwidth pop 2 div neg x add y moveto show
注意:この手続きで縦位置を合わせることはできない。
決められた図形を任意の場所に描画するには, moveto などよりも translate を使ったほうが汎用性が高い。 ただし,この場合には,移動した後で translate による移動を原点に ふたたび戻すことになるので, 多少面倒ではある。
今,原点付近にある図形を描画する手続きを proc とすると,それを任意の場所に描画してから状態を 元に戻す手続き putprocat は次のように 書く。
/putprocat {
2 copy neg exch neg exch 4 2 roll
translate
proc
translate
} def
putprocat は次のように使う。
x y putprocat
gs -q -dEPSCrop -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -r240 -dText AlphaBits=2 -dGraphicsAlphaBits=2 -sOutputFile=hoge.png hoge.ps