7

私は通常ghostscript、コマンドラインツールとして見ています。しかし、そこに存在する膨大な量の設定とオプションに驚かされることは決してありません。これghostscriptは、完全な PostScript 言語インタープリターであるという事実によるものです (私はよく忘れます)。

たとえば、出力デバイスのデフォルトのオプション/設定 (「pdfwrite」や「​​tiffg4」など) について、Ghostscript のクエリを実行します。特定の出力デバイスのデフォルト オプションを取得する方法を学習します。しかし、私が知りたいのは、これらのオプションはいわゆる PostScript 辞書に関連しているのでしょうか?

言い換えれば、PostScript 辞書とは何ですか。ghostscriptそして、このデータをクエリ (およびおそらく) 変更するために、 どのような機能がありますか?

4

5 に答える 5

10

最も簡単に言えば、PostScriptでは、辞書は キー(名前)+値のペアのリストです。ディクショナリを使用すると、PostScriptインタプリタはキーが存在するかどうかを検索し、その値をフェッチして任意のプロシージャで使用できます。インタプリタは、キーを作成したり、値を保存または変更したり、完全なカスタム辞書を作成したりすることもできます(PostScriptコードの処理によって指示されます)。キーは通常、タイプ名です(ただし、 nullを除いて、他のタイプでもかまいません)。

PostScriptインタープリターを実装するには、これらの辞書のうち2つが常に存在している必要があります。

  • systemdict これには、事前定義されたPostScript演算子(およびPostScript仕様で期待されていることを実行させるための実装)が含まれています。

  • userdict これは、PostScriptプログラムの変数とプロシージャを保持します(「プロシージャ」は、言語定義の演算子とプログラム定義の値およびパラメータの組み合わせによって構築される関数またはサブルーチンであると考えてください)。

名前に関する一言:名前は他のプログラミング言語にとっては一意の識別子です(大文字と小文字が区別されます)。これらの識別子は、変数またはプロシージャ名の場合があります。これらは、ASCIIの256文字の任意の組み合わせで構成できます(ただし、文字列ではありません)。

ご存知かもしれませんが、PostScriptはスタック指向言語です。いくつかのスタックを使用します。

  • オペランドスタック このスタックは、すべての単一のオペランドと中間演算のすべての結果を保持します(最後の結果を一時的にオペランドスタックの最上位要素に変換します)。

  • 辞書スタック 名前が示すように、このスタックは辞書のみを保持します。そのため、スタックは任意のキー/名前ルックアップの現在のコンテキストを定義します。

  • 実行スタック これは、実行可能オブジェクト、つまり主に現在実行されているプロシージャファイルを保持します。インタプリタが現在のオブジェクトの実行を中断した場合、インタプリタは中断されたオブジェクトをこのスタックに配置します。オブジェクトが完全に実行された後、そのオブジェクトはスタックから削除され、現在最上位のオブジェクトから実行が続行されます。

  • グラフィック状態スタック このスタックは、グラフィック要素を排出するための現在のコンテキストをホストします。現在の線幅設定、現在のフォント、現在の色またはグレースケール値、現在のパス...現在のグラフィック状態は後で保存(gsave)および復元(grestore)できます。最上位のグラフィックス状態は、常に現在のグラフィックス状態です。

これらのスタックはすべて互いに独立しています。ただし、オペランド、ディクショナリ、およびグラフィックスの状態スタックは、PostScriptプログラムの制御下にあります(つまり、PostScriptプログラムによって操作される場合があります)。実行スタックは、インタープリターの唯一のプロパティです。

スタックごとに特定の制限があります(スタックに格納できる要素の数など)。PostScriptは、スタックを操作できる演算子を認識しています。スタックに新しい要素を配置し、最上位の要素を削除し(pop)、最上位の要素を複製し( ) dup、スタック上の要素の順序をシャッフルし(roll)、2つの最上位を入れ替えます-ほとんどの要素(exch)、およびかなり多くの要素(PostScriptプログラミングの優れた入門書はAdobeの「Bluebook」です)。

すでに述べたように、ディクショナリには、PostScriptインタプリタが使用できるすべてのディクショナリを保持する独自のスタックがあります。

そのスタックには、フォントの個別の辞書、PostScriptプログラムが(dictキーワードを使用して)作成してプライベートに使用したい任意の数の辞書、またはGhostscriptなどの特定のPostScriptインタープリターに固有の辞書が存在する場合があります。

systemdict常に一番下にあります。この上にありuserdictます。これら2つはディクショナリスタックから削除できません。他のすべての1つは、スタック操作演算子(popスタックから最上位の要素を削除するなど)の対象となる可能性があります。

インタプリタが名前を検索するときはいつでも、一番上の辞書から始めて、その名前の辞書を検索します。したがってuserdict、の前に検索されsystemdictます。名前(キー)が見つかるとすぐに、インタープリターは検索を停止し、そのキー(つまり、保持している値)を使用します。このアーキテクチャの結果、PostScriptプログラマーは、で事前定義されているPostScript演算子をsystemdict自分のバリアントで上書きする可能性があります。

また、一部の辞書は、PSプログラムの「プライベート」(フォント辞書などのアクセス不可)または「読み取り専用」用にすることができます。


更新 -その他の回答:

于 2012-06-21T14:00:00.047 に答える
8

他の回答はすでに「辞書とは何ですか?」をカバーしています。あなたの質問の一部。では、 「Ghostscript はそれらにどのようにアクセスできますか?」に移りましょう。

おそらく、質問は「私 (パワーユーザー、開発者、ギーク...) がそれらにアクセスするにはどうすればよいですか?」ということになるはずです。

PostScript インタープリター (Ghostscript の場合もあります) が認識しているアクセス可能な辞書の内容は、単純な PostScript プログラムのワンライナーを記述するか、または単にインタープリター (Ghostscript) を呼び出してプログラム コードを渡して出力できます。コマンドライン ( -c ...)。

このために必要なのは、それぞれの辞書の名前だけです。

と呼ばれる興味深い内部 Ghostscript ディクショナリを見てみましょう.distillersettings

gs \
 -dNODISPLAY \
 -c ".distillersettings {exch ==only ( ) print ==} forall quit"

結果:

/default -dict-
/prepress -dict-
/PSL2Printer -dict-
/ebook -dict-
/screen -dict-
/printer -dict-

これは、一見しただけではあまりわかりません。しかし、その辞書のいくつかのキー名に気付くかもしれません: /prepress/printer/screen/ebook...

-sDEVICE=pdfwriteこれらはすべて、Ghostscript コマンドラインで使用して、 (Ghostscript の「Distiller」に似た機能)によって出力が必要な場合に、事前定義された一連の設定を求めることができます。このような一連の設定を要求する-dPDFSETTINGS=/printerには、コマンドラインに追加するだけです。

もう一度見てみると、.distillersettingsディクショナリの内容は本質的に、さらに 6 つのディクショナリのセットであることがわかります。「辞書の辞書」です。

ディクショナリの内容はデフォルトでは出力されません (上記の PostScript コードでは出力されません)。ただし、それらが必要な場合は、上記のコマンドで===標準の PostScript 言語演算子の代わりに呼び出される Ghostscript 固有のプロシージャを使用できます。このプロシージャは、辞書を展開し、それらに含まれるすべてのキーと値のペアも出力するという点で、execpt と==同じように動作します。==

===その手順には注意してください-dict-。拡張しようとしているのは非常に長く、視力を失う可能性があります. :-)

ただし、現在のケースでは、まだ管理可能です。

gs \
 -dNODISPLAY \
 -c ".distillersettings {exch ==only ( ) print ===} forall quit"

出力は次のとおりです。

 /default << /Optimize false /DoThumbnails false /PreserveEPSInfo true /ColorConversionStrategy /LeaveColorUnchanged /DownsampleMonoImages false /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments true /GrayACSImageDict << /HSamples [2 1 1 2] /VSamples [2 1 1 2] /QFactor 0.9 /Blend 1 >> /DownsampleColorImages false /PreserveOverprintSettings true /CreateJobTicket false /AutoRotatePages /PageByPage /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorACSImageDict << /HSamples [2 1 1 2] /VSamples [2 1 1 2] /QFactor 0.9 /Blend 1 >> /DownsampleGrayImages false /UCRandBGInfo /Preserve >>
 /prepress << /DoThumbnails true /MonoImageResolution 1200 /ColorImageDownsampleType /Bicubic /PreserveEPSInfo true /ColorConversionStrategy /LeaveColorUnchanged /GrayImageDownsampleType /Bicubic /EmbedAllFonts true /CannotEmbedFontPolicy /Error /PreserveOPIComments true /GrayImageResolution 300 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /ColorImageResolution 300 /PreserveOverprintSettings true /CreateJobTicket true /AutoRotatePages /None /MonoImageDownsampleType /Bicubic /NeverEmbed [] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /CompatibilityLevel 1.4 /UCRandBGInfo /Preserve >>
 /PSL2Printer << /DoThumbnails false /CompatibilityLevel 1.2 /TransferFunctionInfo /Preserve /MonoImageResolution 1200 /PreserveEPSInfo true /CompressFonts true /ColorImageDownsampleType /Bicubic /GrayImageDownsampleType /Bicubic /ColorConversionStrategy /LeaveColorUnchanged /EmbedAllFonts true /ColorACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /CannotEmbedFontPolicy /Error /PreserveOPIComments true /CompressPages true /GrayImageResolution 600 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.15 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /ColorImageResolution 600 /PreserveOverprintSettings true /AutoRotatePages /None /MonoImageDownsampleType /Bicubic /ASCII85EncodePages true /MaxViewerMemorySize 8000000 /NeverEmbed [] /PreserveHalftoneInfo true /UCRandBGInfo /Preserve >>
 /ebook << /DoThumbnails false /MonoImageResolution 300 /ColorImageDownsampleType /Bicubic /PreserveEPSInfo false /ColorConversionStrategy /sRGB /GrayImageDownsampleType /Bicubic /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments false /GrayImageResolution 150 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /ColorImageResolution 150 /PreserveOverprintSettings false /CreateJobTicket false /AutoRotatePages /All /MonoImageDownsampleType /Bicubic /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /CompatibilityLevel 1.4 /UCRandBGInfo /Remove >>
 /screen << /DoThumbnails false /MonoImageResolution 300 /ColorImageDownsampleType /Average /PreserveEPSInfo false /ColorConversionStrategy /sRGB /GrayImageDownsampleType /Average /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments false /GrayImageResolution 72 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /ColorImageResolution 72 /PreserveOverprintSettings false /CreateJobTicket false /AutoRotatePages /PageByPage /MonoImageDownsampleType /Average /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.76 /Blend 1 /HSamples [2 1 1 2] /VSamples [2 1 1 2] >> /CompatibilityLevel 1.3 /UCRandBGInfo /Remove >>
 /printer << /DoThumbnails false /MonoImageResolution 1200 /ColorImageDownsampleType /Bicubic /PreserveEPSInfo true /ColorConversionStrategy /UseDeviceIndependentColor /GrayImageDownsampleType /Bicubic /EmbedAllFonts true /CannotEmbedFontPolicy /Warning /PreserveOPIComments true /GrayImageResolution 300 /GrayACSImageDict << /ColorTransform 1 /QFactor 0.4 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /ColorImageResolution 300 /PreserveOverprintSettings true /CreateJobTicket true /AutoRotatePages /None /MonoImageDownsampleType /Bicubic /NeverEmbed [] /ColorACSImageDict << /ColorTransform 1 /QFactor 0.4 /Blend 1 /HSamples [1 1 1 1] /VSamples [1 1 1 1] >> /CompatibilityLevel 1.4 /UCRandBGInfo /Preserve >>

まだそれほど良くありません。それでは改善していきましょう。これを行う方法は、PostScript コードを変更することです。ここで、.distillersettings辞書にアクセスし、そこからキーの 1 つの値を取得するように指示します ( を使用しましょう/screen)。値が別のディクショナリであることがわかっているので、以前と同じ方法でフォーマットできるキーと値のペアの別のセットを取得できることがわかります。

gs \
 -q \
 -dNODISPLAY \
 -c ".distillersettings /screen get {exch ==only ( ) print ===} forall quit"

これで見栄えが良くなりましたね。自分自身を見てください:

/DoThumbnails false
/MonoImageResolution 300
/ColorImageDownsampleType /Average
/PreserveEPSInfo false
/ColorConversionStrategy /sRGB
/GrayImageDownsampleType /Average
/EmbedAllFonts true
/CannotEmbedFontPolicy /Warning
/PreserveOPIComments false
/GrayImageResolution 72
/GrayACSImageDict -dict-
/ColorImageResolution 72
/PreserveOverprintSettings false
/CreateJobTicket false
/AutoRotatePages /PageByPage
/MonoImageDownsampleType /Average
/NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica     /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats]
/ColorACSImageDict -dict-
/CompatibilityLevel 1.3
/UCRandBGInfo /Remove

あなたの鋭い目ですでに気づいているかもしれませんが、重要な値のいくつかは再び辞書です。上記のコマンドを再度自由に使用できます。今回===は、2 番目の代わりにa を使用して、隠れ続ける可能性の==ある謎を解決します.../GrayACSImageDict -dict-

いずれにせよ、このディクショナリ-dPDFSETTINGS=/screenに埋め込まれたすべての単一パラメータを列挙する代わりに、単純に使用することで入力を節約できることがわかりました.../screen

また、一般的な「画面」品質の出力が 必要な場合にオーバーライドする必要がある単一の値もわかっていますが、すべてのフォントが埋め込まれているという違いがあります。

gs \
 -o out.pdf \
 -sDEVICE=pdfwrite \
 -dPDFSETTINGS=/screen \
 -c "<</NeverEmbed [ ] /AlwaysEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats]>> setdistillerparams" \
 -f input.pdf

Ghostscript が使用する辞書の名前さえ知っていれば、Ghostscript の内部について、この方法で多くの興味深いことを調べることができます。:-)

于 2012-06-21T15:43:32.487 に答える
6

すでに多くの良い答えがありますが、誰もこれについて言及していません:

Ghostscript を呼び出すと、オプション-d-sオプションによって systemdict に初期定義が作成されます。これにより、postscript プログラムのパラメーター化された呼び出しを行うことができます。

-dname[=token]値を null または数値 (またはその他の単一の PostScript トークン) に設定するために使用します。文字列値を設定するために使用-sname=stringします (ほとんどのコンテキストでは、名前と同様に機能します)。

また、適切なオペレーターを使用して、すべてのスタックをある程度操作できます。

  • token文字列またはファイルからオペランド スタックにプッシュします (これはインタープリター ループがプログラム ストリームを消費するために使用するものであるため、ファイルを介してコードを入力する場合でも、キーボードから直接コードを入力する場合でも、これを使用しています)
  • popオペランド スタックから破棄
  • begin辞書スタックにプッシュ
  • end辞書スタックからポップ
  • run, exec,%procedure-invocation実行スタックにプッシュ
  • exitstop実行スタックのポップまたはクリア
  • gsaveグラフィックス スタックに gstate をプッシュする
  • grestoreポップ グラフィック スタック
  • saveすべての VM コンテンツのコピーをプッシュします (すべての辞書と配列、ただし文字列は除く)
  • restoreメモリを保存された状態に巻き戻します (すべての辞書と配列を前の状態に戻します)

複合オブジェクトである辞書は、すべての複合オブジェクトに共通の多数の演算子を継承します。

  • -typename-オブジェクトを作成します。dict
  • lengthオブジェクトのレポート サイズ
  • put要素を挿入する
  • get要素を取得する
  • copyオブジェクトに別のオブジェクトのコンテンツを移入する
  • forall各要素に何かをする
  • *load代替取得要素 (辞書の場合loadは検索を実行しwhere、次にget; 配列の場合aloadは配列の内容全体をオペランド スタックにスピルします)
  • *store代替挿入要素 (辞書の場合storeは検索を実行し、見つかっwhereput場合は検索を実行し、見つからdefない場合は検索を実行します。配列の場合はastore、スタック上のオブジェクトから配列を埋めます)

このスイートに、辞書が追加されます

  • def現在の辞書に入れる (dict スタックの一番上)
  • known要素のクエリ ディクショナリ
  • where要素のすべての辞書を照会する
  • maxlengthPS レベル 2 で自動拡張辞書と gc が追加された後は、もはや面白くありません。
  • dictstackdictstack を配列にコピーします (ボトムアップで検索したいかもしれません!)
  • スラッシュ/が前に付いていない名前は自動的にload編集され、実行可能な場合は実行されます
  • //whiletokenは postscript オブジェクトを構築しています。二重スラッシュが前にある名前はすべてload編集され、手続き配列に置き換えられます。Lisp マクロを模倣できるため、これは非常に強力です。

編集:もう1つ。ディクショナリを作成する場合、ディクショナリのサイズを選択するときに、時間と空間のトレードオフがあります。辞書はほぼ確実にハッシュテーブルとして実装され (最も単純なインタープリターを除くすべてで)、ほとんどのハッシュ関数は、テーブルが約半分いっぱいになったときに衝突を回避できます (経験則:速度のために倍サイズの辞書を使用します)。もちろん、レベル 2 以降、size+1 要素を追加すると、おそらく k*size (k はおそらく 1.5 または 2) の新しい辞書を割り当てることによって、辞書が自動的に拡張されます。ただし、サイズを手動で制御すると、速度が向上します。レベル 1 では、辞書を複数参照していない場合は、代わりにdictfullinをインストールできます。errordictdictを成長させ、put(またはdefなど)を再実行します。レベル 2 はこれを内部的に行うため、すべての参照を置き換えることができます。

于 2012-07-06T00:07:16.323 に答える
4

systemdictおよび辞書に含まれる他の辞書のリストを取得する場合は、次のコマンドをuserdict実行します。

for _dict in userdict systemdict; \
   do \
   gs \
     -dNODISPLAY \
     -c "${_dict} {exch ==only ( ) print ==} forall quit"; \
done \
| awk '{print $1, $2}' \
| grep -- -dict- \
| sort

これにより、潜在的に「興味深い」名前を調査できる辞書名のソートされたリストが生成されます。

, , , , , , , , , ...のようFontmapな名前が見つかります。localdictAdobeGlyphListuserparams.eexec_param_dict.substitutefamiliesEncodingDirectorycolorspacedict.distillerparamkeysdevicedict.symbol_list

これらの名前のそれぞれについて、fe を実行することで、Ghostscript の内部に関する多かれ少なかれ興味深い情報やちょっとした情報を調べることができます。

gs \
  -q \
  -dNODISPLAY \
  -c "Fontmap {exch ==only ( ) print ==} forall quit"

ご覧のとおり、Ghostscript が使用するFontmapもディクショナリに格納されています。ここでのローカルでの結果の抜粋は次のとおりです。

[....]
/Arial [/ArialMT]
/Arial,Bold [/Arial-BoldMT]
/AvantGarde-Book [/URWGothicL-Book]
/Bookman-Demi [/URWBookmanL-DemiBold]
/Calligraphic-Hiragana [(fhirw.gsf)]
/Calligraphic-Katakana [(fkarw.gsf)]
/Charter-Bold [/CharterBT-Bold]
/CharterBT-Bold [(bchb.pfa)]
/Courier [/NimbusMonL-Regu]
/Courier-Bold [/NimbusMonL-Bold]
/Courier-BoldOblique [/NimbusMonL-BoldObli]
/Courier-Oblique [/NimbusMonL-ReguObli]
/Helvetica [/NimbusSanL-Regu]
/Helvetica-Bold [/NimbusSanL-Bold]
/NewCenturySchlbk-Bold [/CenturySchL-Bold]
/Palatino-Roman [/URWPalladioL-Roma]
/Symbol [/StandardSymL]
/Times-Bold [/NimbusRomNo9L-Medi]
/TimesNewRoman,Bold [/TimesNewRomanPS-BoldMT]
/Utopia-Regular [(putr.pfa)]
/ZapfDingbats [/Dingbats]
[....]

注意: Ghostscript が (一般的に、または特定のジョブのために) 使用する必要がある Fontmapファイルを操作する場合に使用する必要があるため、上記は実際にはファイル形式ではありません。その形式については、Ghostscript に同梱されているサンプル Fontmap ファイルのコメントをお読みください。上記のリストは、Ghostscript が内部辞書に格納するフォントマップ表現です。

于 2012-06-21T18:21:06.233 に答える
2

PostScript のディクショナリは「コンテナ」オブジェクトであり、本質的にキーと値のペアのリストです。詳細については、PostScript 言語リファレンス マニュアル、特に第 3 版のセクション 3.3.9 を参照してください。

ディクショナリは、一連のパラメータを PostScript オペレータまたは関数に渡すためによく使用されます。たとえば、イメージ オペレータはディクショナリ引数を取ることができますが、単純にストレージとして使用することもできます。

辞書にはアクセス許可を設定できるため、値を調べることはできるが変更はできない読み取り専用の辞書を作成したり、フォント辞書を「アクセスなし」にして PostScript でアウトライン データが抽出されないようにすることができます。

読み取り専用またはアクセス不可でない辞書のエントリは、自由に変更できます。

于 2012-06-21T13:00:02.870 に答える