Let's PostScript(4) 関係オペレータで比較する
関係オペレータ
制御をおこなうためには、2つのObjectを比較評価する必要があるわけで、このような処理を行うオペレータを関係オペレータ(Relational Operator)といいます。 Post Scriptの比較評価結果はtrueとfalseのみです。
文法は object1 object2 xx となり、2つのObjectの関係を評価します。これは、表にしてしまったほうが分かりやすいかもしれません。
関係オペレータ | 処理内容 |
---|---|
eq | 2つのObjectが等しければOperandStackにtrueを格納する |
ne | 2つのObjectを等しくなければOperandStackにtrueを格納する |
ge | 2つのObjectの>=の大小比較を行い、結果をOperandStackに格納する |
gt | 2つのObjectの>の大小比較を行い、結果をOperandStackに格納する |
le | 2つのObjectの<=の大小比較を行い、結果をOperandStackに格納する |
lt | 2つのObjectの<の大小比較を行い、結果をOperandStackに格納する |
評価可能なオブジェクトは数値と文字列となります。 文字列は一般的なソートのルールが適用されるようです。また文字列はどのような表現方法で指定しても同じ文字列となれば正しく評価されるようです。
GS>(b) (abc) gt == true
GS>(abc) <616263> eq == true
本を見ると、eqオペレータとneオペレータは任意のObjectが比較できるようなのですが、配列でやってみたところ、うまくいきませんでした。 このあたりよくわからないので、後日の課題としたいと思います。
GS>[1 2 3] [1 2 3] eq == false
次回は、手続きオブジェクトと制御オペレータについてみていきたいと思います。
Let's PostScript(3) Operand Stackの操作
今日は久しぶりの飲み会でした。送別会だったのですが。そんなわけで、今日は簡単に済ませます。
StackはLIFO(Last In First Out)
Stackは達磨落としのような感じで最後に入れた(Push)Objectが最初に出てきます(Pop)これをLIFOといいます。 実際に、Ghost Scriptでスタックを積むとこのような感じになります。
GS>1 2 3 4 5 GS<5>stack 5 4 3 2 1
これを取り出すとFILOに基づいて、入れた順番の逆順で取り出されます。
GS<5>== 5 GS<4>== 4 GS<3>== 3 GS<2>== 2 GS<1>== 1
OperandStackの操作をするオペレータ
OperandStackはPostScriptのデータの受け渡しの中核を担い、アルゴリズムによって多様な利用が行われます。 そのため、OperandStackにはたくさんのStack操作用のオペレータが用意されています。
popオペレータ
OperandStackの一番上の要素を破棄する。
GS>1 2 3 4 5 GS<5>pop GS<4>stack 4 3 2 1
exchオペレータ
OperandStackの上位2つのオブジェクトの位置を入れ替える。
GS>1 2 3 4 5 GS<5>exch GS<5>stack 4 5 3 2 1
dupオペレータ
OperandStackの一番上の要素をコピーする。
GS>1 2 3 4 5 GS<5>dup GS<6>stack 5 5 4 3 2 1
copyオペレータ
OperandStackからコピー数を受け取り、OperandStackの一番上からコピー数の要素をコピーする。
GS>1 2 3 4 5 GS<5>3 GS<6>copy GS<8>clear GS>1 2 3 4 5 GS<5>3 copy GS<8>stack 5 4 3 5 4 3 2 1
indexオペレータ
OperandStackから任意の位置を受け取り、OperandStackの上から数えた任意の位置※の要素をコピーする。 ※一番上の要素を0とする。
GS>1 2 3 4 5 GS<5>1 index GS<6>stack 4 5 4 3 2 1
rollオペレータ
OperandStackから要素数と、回転数を受け取り回転させる。
GS>1 2 3 4 5 GS<5>4 1 roll GS<5>stack 4 3 2 5 1
clearオペレータ
OperandStackのObjectを破棄する。
GS>1 2 3 4 5 GS<5>clear GS>
countオペレータ
Operand Stackのオブジェクトをカウントし、カウント数を格納する。
GS>1 2 3 4 5 GS<5>count GS<6>== 5 GS<5>
markオペレータ
mark ObjectをOperandStackにPushする。 markは配列や処理の終了時の不要となったObjectの破棄等、多様な用途で使用することになる。
counttomarkオペレータ
一番上のmarkの上にある要素数をカウントし、カウント数を格納する。
GS>1 2 GS<2>mark GS<3>3 4 5 GS<6>counttomark GS<7>== 3 GS<6>
cleartomarkオペレータ
一番上のmarkの上にある要素とmark自身を破棄する。
GS>1 2 GS<2>mark GS<3>3 4 5 GS<6>cleartomark GS<2>stack 2 1
次は、条件判断や反復等の制御公文についてみていこうと思います。
Let's PostScript(2) ObjectとOperand Stack
前回以下の実行結果で出てくるGS<...>のカッコ内の数字は何者かというところで話を切りましたが、これはいまOperand Stackに積まれているStackの段数を示しています。
GS>/Helvetica GS<1>findfont GS<1>20 GS<2>scalefont GS<1>setfont GS>0 0 GS<2>moveto GS>(Hello World!!) GS<1>show GS>0 0 GS<2>moveto GS><48656C6C6F20576F726C642121> GS<1>show GS>showpage >>showpage, press <return> to continue<<
Operand Stackに積まれるのはObjectです。PostScriptで扱われるすべてObjectとなっています。 それぞれのObjectには属性が存在していますが、そのうちの一つが属性が実行可能とLiteralの属性です。
PostscriptのインタープリタがObjcetを実行する場合、そのObjectの属性が実行可能か、Literalかによりその動作が変わります。
属性 | 動作 |
---|---|
実行可能 | インタープリタによって直ちに実行される |
Literal | Operand StackにPushされる |
OperandStackは実行可能Objectが受け取るLiteralObjectやその結果を格納するために使用されます。 ここで先ほどの実行内容とスタックを整理してみます
GhostScript | コメント |
---|---|
GS>/Helvetica | /で始まるのはLiteralの名前ObjectなのでStackへPush(0->1) |
GS<1>findfont | findfontはオペレータで実行可能。OperandStackからフォント名を受け取り(1->0)、フォント定義を格納したフォント辞書をOperandStackに返す(0->1) |
GS<1>20 | 整数(20)は常にLiteral ObjectなのでStackへPush(1->2) |
GS<2>scalefont | scalefontはオペレータで実行可能、グリフサイズのスケーリングの倍率を受け取り(2->1)、倍率に拡縮したフォント辞書を作成する |
GS<1>setfont | setfontはオペレータで実行可能、フォント辞書を受け取り(1->0)グラフィックスのフォントパラメータへ反映する |
GS>0 0 | 整数のObject2つをStackへ格納する(0->2) |
GS<2>moveto | movetoはオペレータで実行可能、x yをOperandStackから受け取り(2->0)、カレントポイントを設定する |
GS>(Hello World!!) | Literal文字列をOperandStackへPush(0->1) |
GS<1>show | showはオペレータで実行可能、文字列を受け取り(1->0)グラフィックスのフォントパラメータで描画する |
GS>100 100 | |
GS<2>moveto | |
GS><48656C6C6F20576F726C642121> | 16進文字列をOperandStackへPush(0->1) |
GS<1>show | |
GS>showpage | カレントページを出力デバイスへ描画する |
このような感じで、PostscriptはOperandStackを介してObjectをやり取りし、スクリプトを消費していきます。 そのため、PostScriptには豊富なStack操作を目的としたオペレータが用意されています。
次回はOperandStackの操作を方法を見ていきたいと思います。
Let's PostScript(1) Hello World!!
教材と環境
いまさらながら、PostScript(一部PDF)について、ざっくりと勉強していこうと思います。
使用する教材は、いわゆる赤本です。
環境はGhostScriptのVersion9.52を用います。
対話モードで遊ぶ
引数なしでGhostScriptを起動すると、対話モードで起動するので、これを使って描画してみます。
GPL Ghostscript 9.52 (2020-03-19) Copyright (C) 2020 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. GS>
Hello world
PostScriptは文字列の表現方法として3つの種類があります。
- テキスト(Hello World!!)
- 16進データ<48656C6C6F20576F726C642121>
- ASCII85データ※今は扱わない。
ASCII85は対話モードで使うには無理があるので、まずは上記二つのHallo world!!を表示します。
文字を表示するには、"どの書体で、どのサイズで、どこに、何を書くかを示す必要があります。
フォントの選択
findfontオペレータで選択します
書式設定
scalefontオペレータで指定します。
座標指定
movetoオペレータで指定します。
文字指定
テキスト(Hello World!!)
16進データ<48656C6C6F20576F726C642121>
で今回はHello Worldします。
初めてのshowpage
これをGhostScriptの対話モードで入力していくとこのような感じになります。
GS>/Helvetica findfont 20 scalefont setfont GS>0 0 moveto GS>(Hello world!!) show GS>100 100 moveto GS><48656C6C6F20576F726C642121> show GS>showpage >>showpage, press <return> to continue<<
最後のshowpageで画像を出力します。出てくる画像は以下のようなものです。ほとんどが空白なのですが、少し下にスクロールすると、Hello Worldが見えてきます。
リテラルテキストのHello World(座標0,0)が下で、16進データで指定したHellow World(座標100,100)が上です。 違和感を感じますが、この辺りはグラフィックのあたりで勉強していこうと思います。
最後に、先ほどのHello Worldですが、複数のオペレータをまとめて実行しているので、できるだけ細かく指示しなおしてみます。出力される画像は同じです。
GS>/Helvetica GS<1>findfont GS<1>20 GS<2>scalefont GS<1>setfont GS>0 0 GS<2>moveto GS>(Hello World!!) GS<1>show GS>0 0 GS<2>moveto GS><48656C6C6F20576F726C642121> GS<1>show GS>showpage >>showpage, press <return> to continue<<
増減するGS<...>は何なんのかってあたりを次回勉強していこうかと思います。