2012-06-21 25 views
6

我通常將ghostscript看作是命令行工具;然而,我絕對不會驚訝於那裏存在的大量設置和選項 - 這是由於ghostscript是一個完全成熟的PostScript語言解釋器(我經常忘記)。例如,Querying Ghostscript for the default options/settings of an output device (such as 'pdfwrite' or 'tiffg4');學習如何檢索給定輸出設備的默認選項。但是,我想知道的是 - 這些選項是否與所謂的PostScript字典相關?或者,換句話說 - 什麼是PostScript字典;什麼是PostScript字典? ghostscript有什麼設施來查詢(並可能)修改這些數據?什麼是PostScript字典,以及如何訪問它們(通過Ghostscript)?

回答

8

說得最簡單:在PostScript中,字典是鍵(名稱)+值對的列表。字典允許PostScript解釋器查找是否存在密鑰並獲取其值以在任何過程中使用它。解釋器還可以創建密鑰,存儲或修改值,甚至創建完整的自定義字典(由PostScript代碼處理)。密鑰通常是類型名稱(但它們也可以是任何其他類型,但null除外)。

這些字典中的兩個必須始終存在,對於PostScript解釋的任何實現:

  • systemdict 這一個擁有預先定義的PostScript運營商(和實現,使他們做了什麼PostScript規範期望它們)。

  • userdict 這一個保持的PostScript程序的變量和程序(認爲其由語言定義的操作符和程序定義的值和參數的組合構成「程序」是指從函數或子程序)。

一個字約:名稱是什麼,其他編程語言的uniq 標識符(他們是區分大小寫)。這些標識符可能是變量或過程名稱。它們可以由256個ASCII字符的任意組合組成(但它們不是字符串)。

您可能已經知道,PostScript是一個面向對象的語言,它是一個堆棧。它使用了幾個棧:

  • 操作數棧 這堆擁有的每一個操作數和中間業務的每個結果(開啓最後的結果暫時進入操作數棧的最頂部的元素)。

  • 字典堆棧 顧名思義:這個堆棧只包含字典。因此,堆棧爲任何鍵/名稱查找定義當前上下文。

  • 執行堆棧 這一個保持可執行對象,即主要程序文件當前正被執行的。如果解釋器中斷當前對象的執行,它會將中斷的對象放到這個堆棧上。一個對象完成執行後,它將從堆棧中移除,然後繼續執行最上面的那個。

  • 圖形狀態棧 此堆棧託管用於圖形元素的噴射當前上下文:當前線寬設置,當前字體,當前彩色或灰度值,電流路徑...當前圖形狀態可以被保存(以後恢復(gsave)並恢復(grestore)。最高圖形狀態始終爲當前圖形狀態。

所有這些堆棧是相互獨立的。但是,操作數,字典和圖形狀態堆棧是在PostScript程序的控制之下的(也就是說,可以由它操縱)。執行堆棧是解釋器的唯一屬性。

對於每個堆棧都存在一定的限制(關於可以存儲在其上的元素的數量等)。的PostScript知道哪些可以操縱堆棧操作符:把一個新的元素在棧中,取出最上面的元素(pop),重複最上面的元素(dup),洗牌堆棧元素的順序(roll),調換兩個頂級元素(exch),還有一些(PostScript編程的入門介紹是來自Adobe的'Bluebook')。

正如我已經說過的,字典有自己的堆棧它包含PostScript解釋器可能使用的所有字典。

在該堆棧可以是有字體的單獨的字典,或任何數量的字典爲PostScript程序想要創建(使用dict關鍵字)和私人使用,或一些字典特定於某個PostScript解釋,比如Ghostscript。

systemdict總是最底部的一個;以上是userdict。這兩個字典不能從字典棧中刪除,其他所有字符棧都可以使用任何棧操作操作符(例如pop,它可以從棧中刪除最頂層的元素)。

每當解釋器查找名稱時,都會從最頂端的字典開始搜索該名稱的字典。因此在systemdict之前搜索userdict。一旦找到該名字(一個關鍵字),解釋器就停止搜索並使用該關鍵字(或者說,它保存的值)。這種架構的結果是PostScript程序員可以用他自己的變體覆蓋在systemdict中預先定義的任何PostScript運算符。另外,一些字典可以用於PS程序的「私人」(不可訪問,如字體字典)或「只讀」。


更新 - 更多的答案:

+0

非常感謝您的詳細解答@pipitas!如果/當你有時間的時候,你還可以添加一個簡短的'ghostscript'終端示例,「_the interpreter []查找一個name_」(它也可以顯示「_'userdict'在'systemdict'_」之前被搜索到,並可能覆蓋操作員)?非常感謝 - 歡呼! – sdaau

+1

@sdaau:我的另一個答案顯示瞭如何在字典'.distillersettings'中查找名稱/鍵'/ screen':就像'.distillersettings/screen get'一樣簡單。 'get'操作符將鍵的值(如果找到)放到操作數堆棧中(如果未找到,則將打印「未定義」錯誤)。現在密鑰的價值在堆棧上,其餘的代碼片段只是將其提取到那裏,將其格式化一點以使其看起來更加漂亮並打印出其內容...... –

+0

非常感謝,@pipitas - 非常感謝! – sdaau

2

PostScript中的詞典是一個'容器'對象,它們本質上是一個對,一個鍵和一個值的列表。有關更多詳細信息,請參閱PostScript語言參考手冊,特別是第三版中的第3.3.9節。

詞典通常用於將一組參數傳遞給PostScript運算符或函數,例如圖像操作符可以採用字典參數,但它們同樣可以簡單地存儲。

字典可以擁有訪問權限,因此可以使用只讀字典,其值可以被檢查但不能修改,並且字體字典可能無法訪問,以防止在PostScript中提取輪廓數據。

字典中不是隻讀或不可訪問的條目可以隨意修改。

+0

非常感謝您的回答@KenS;這裏也是鏈接到當前的[PostScript語言參考手冊(PLRM.pdf)](http://www.adobe.com/products/postscript/pdfs/PLRM.pdf) - 乾杯! – sdaau

5

其他的答案已經涵蓋了「什麼是字典?」你的問題的一部分。現在我們來看「Ghostscript如何訪問它們?」

也許這個問題應該是:「我怎麼能(一個高級用戶,一個開發者,一個極客......)訪問它們?」

通過編寫簡單的PostScript程序,您可以打印出PostScript解釋程序(可能是Ghostscript)已知的任何可訪問字典的內容,或者通過簡單地調用解釋程序(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 Distiller相似的功能)時,你可以在Ghostscript命令行中使用所有這些命令來請求預定義的一組設置。要請求這樣一組設置,只需將-dPDFSETTINGS=/printer添加到命令行即可。

乍一看,你會發現.distillersettings字典的內容本質上是一組6個字典。這是一本'字典詞典'。

字典內容默認不打印出來(不是上面的PostScript代碼)。但是,如果您需要它們,則可以使用名爲===的Ghostscript特定過程,而不是上述命令中的標準PostScript語言運算符==。此過程的行爲與==的行爲相同,它還會擴展字典並打印其中包含的所有鍵:值對。

要當心與===程序:-dict-你試圖擴大可veeeeeery長,可能會導致你失去你的視力。 :-)

在我國目前的情況下,但它仍在可控範圍內:

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字典,並從中獲取其中一個密鑰的值(讓我們使用/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 

隨着你銳利的眼睛可能已經發現:一些鍵值再次字典。你可以自由地再次使用上面的命令,此時一個===代替第二==來解決的神祕/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內部。:-)

+0

太棒了,@皮皮塔斯 - 現在**這個**是我想知道的一段時間;特別是'=='的意思,以及如何使用它;對長詞典的警告也表示讚賞 - 好吧,整個帖子是!編輯標題 - 如果你可以在接受的結尾處鏈接這個答案,那會很棒!很多,非常感謝 - 乾杯! – sdaau

4

如果你想獲得其包含在systemdictuserdict詞典等辭書的列表,只需要運行:

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

這將產生字典名稱的排序列表您可以調查潛在的「有趣」名稱。

你會發現這樣的名字,像FontmaplocaldictAdobeGlyphListuserparams.eexec_param_dict.substitutefamiliesEncodingDirectorycolorspacedict.distillerparamkeysdevicedict.symbol_list ...

與這些名字你可以看一下更多以下有趣的信息和花絮約的Ghostscript的內部運行FE:

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] 
[....] 

注:以上是不實際的,你將不得不使用,當你要處理的FONTMAP 文件文件格式Ghostscript應該使用(通常或特定的工作)。對於這種格式,請閱讀Ghostscript提供的示例Fontmap文件中的註釋。以上列表是Ghostscript在其內部存儲的字體映射表示字典

5

很多很好的答案的了,但沒有人提到了這一點:

當調用ghostscript的,在-d-s選項創建systemdict初始定義。這允許你做parameterized invocation of your postscript program

使用-dname[=token]將該值設置爲空或數字(或任何其他單個postscript標記)。使用-sname=string來設置字符串值(在大多數情況下,它的作用和名稱一樣)。

而且您可以在一定程度上使用正確的操作符來操作所有堆棧。

  • token推從字符串或文件操作數堆棧(這是什麼解釋循環使用消耗節目流,所以這是你所使用的是否通過文件或直接從鍵盤上輸入代碼)
  • 從操作數堆棧
  • pop丟棄
  • begin推到堆棧字典
  • end從字典堆棧彈出
  • runexec%procedure-invocation推EXEC堆
  • exitstop彈出或明確EXEC堆
  • gsave推gstate上圖形棧
  • grestore彈出圖形棧
  • save推的所有VM-內容的副本(所有類型的字典和數組,但不是字符串)
  • restore退內存來保存狀態(恢復所有類型的字典和數組到以前的狀態)

作爲複合對象的字典繼承了所有複合對象通用的許多運算符。

  • -typename-創建對象,例如對象
  • putdict
  • length報告大小插入一個元素
  • get檢索元素
  • copy從另一個目的
  • forall填充內容對象對每個元素做些什麼
  • *load備用檢索元素(用於字典,loadwhere執行搜索,然後執行get;爲陣列,aload溢出的操作數堆棧上的陣列)
  • *store交替插入元件的全部內容(對於字典,store執行與where搜索,然後put如果找到,或def如果不是;對於陣列,astore填充從對象堆棧中的數組)

向該套件,詞典添加

  • def投產當前字典(字典棧頂)
  • known查詢字典元素
  • where查詢所有字典對於元素
  • maxlength不再有趣後PS Level 2增加自動擴展詞典和GC
  • dictstack複製dictstack到一個數組(也許你想搜索自下而上,你可以!)不是由斜線/之前
  • 名稱是自動load版,如果可執行,執行
  • //token正在構造一個後記對象任何名稱前面加雙斜槓的是load ed並代入過程數組中。這是非常強大的,因爲你可以模仿Lisp宏。

編輯:一兩件事。創建字典時,如果選擇字典的大小,則會有時間/空間的折衷。字典幾乎可以當作散列表來實現(除了最簡單的解釋器之外),大多數散列函數可以避免表在大約半滿時發生衝突(經驗法則:使用雙倍大小的字典來提高速度) 。因爲2級,當然,當你添加大小+1的元素時,字典會自動增長,大概是通過分配一個新的k *大小的字典(其中k可能是1.5或2);但手動控制尺寸可以提高速度。在1級中,如果不是多參考字典,可以在errordict中安裝dictfull的替代品來增加字典並重新執行put(或def或其他)。由於level-2在內部執行此操作,因此它可以替換所有引用。

+2

真棒,@luserdroog - 非常感謝您的澄清!乾杯! – sdaau

相關問題