我通常將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)?
回答
說得最簡單:在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程序的「私人」(不可訪問,如字體字典)或「只讀」。
更新 - 更多的答案:
PostScript中的詞典是一個'容器'對象,它們本質上是一個對,一個鍵和一個值的列表。有關更多詳細信息,請參閱PostScript語言參考手冊,特別是第三版中的第3.3.9節。
詞典通常用於將一組參數傳遞給PostScript運算符或函數,例如圖像操作符可以採用字典參數,但它們同樣可以簡單地存儲。
字典可以擁有訪問權限,因此可以使用只讀字典,其值可以被檢查但不能修改,並且字體字典可能無法訪問,以防止在PostScript中提取輪廓數據。
字典中不是隻讀或不可訪問的條目可以隨意修改。
非常感謝您的回答@KenS;這裏也是鏈接到當前的[PostScript語言參考手冊(PLRM.pdf)](http://www.adobe.com/products/postscript/pdfs/PLRM.pdf) - 乾杯! – sdaau
其他的答案已經涵蓋了「什麼是字典?」你的問題的一部分。現在我們來看「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內部。:-)
太棒了,@皮皮塔斯 - 現在**這個**是我想知道的一段時間;特別是'=='的意思,以及如何使用它;對長詞典的警告也表示讚賞 - 好吧,整個帖子是!編輯標題 - 如果你可以在接受的結尾處鏈接這個答案,那會很棒!很多,非常感謝 - 乾杯! – sdaau
如果你想獲得其包含在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
,localdict
,AdobeGlyphList
,userparams
,.eexec_param_dict
,.substitutefamilies
,EncodingDirectory
,colorspacedict
,.distillerparamkeys
,devicedict
,.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在其內部存儲的字體映射表示字典。
很多很好的答案的了,但沒有人提到了這一點:
當調用ghostscript的,在-d
和-s
選項創建systemdict初始定義。這允許你做parameterized invocation of your postscript program。
使用-dname[=token]
將該值設置爲空或數字(或任何其他單個postscript標記)。使用-sname=string
來設置字符串值(在大多數情況下,它的作用和名稱一樣)。
而且您可以在一定程度上使用正確的操作符來操作所有堆棧。
token
推從字符串或文件操作數堆棧(這是什麼解釋循環使用消耗節目流,所以這是你所使用的是否通過文件或直接從鍵盤上輸入代碼) 從操作數堆棧
pop
丟棄begin
推到堆棧字典end
從字典堆棧彈出run
,exec
,%procedure-invocation
推EXEC堆exit
,stop
彈出或明確EXEC堆gsave
推gstate上圖形棧grestore
彈出圖形棧save
推的所有VM-內容的副本(所有類型的字典和數組,但不是字符串)restore
退內存來保存狀態(恢復所有類型的字典和數組到以前的狀態)
作爲複合對象的字典繼承了所有複合對象通用的許多運算符。
-typename-
創建對象,例如對象put
的dict
length
報告大小插入一個元素get
檢索元素copy
從另一個目的forall
填充內容對象對每個元素做些什麼*load
備用檢索元素(用於字典,load
用where
執行搜索,然後執行get
;爲陣列,aload
溢出的操作數堆棧上的陣列)*store
交替插入元件的全部內容(對於字典,store
執行與where
搜索,然後put
如果找到,或def
如果不是;對於陣列,astore
填充從對象堆棧中的數組)
向該套件,詞典添加
def
投產當前字典(字典棧頂)known
查詢字典元素where
查詢所有字典對於元素maxlength
不再有趣後PS Level 2增加自動擴展詞典和GCdictstack
複製dictstack到一個數組(也許你想搜索自下而上,你可以!)不是由斜線/
之前名稱是自動
load
版,如果可執行,執行//
而token
正在構造一個後記對象任何名稱前面加雙斜槓的是load
ed並代入過程數組中。這是非常強大的,因爲你可以模仿Lisp宏。
編輯:一兩件事。創建字典時,如果選擇字典的大小,則會有時間/空間的折衷。字典幾乎可以當作散列表來實現(除了最簡單的解釋器之外),大多數散列函數可以避免表在大約半滿時發生衝突(經驗法則:使用雙倍大小的字典來提高速度) 。因爲2級,當然,當你添加大小+1的元素時,字典會自動增長,大概是通過分配一個新的k *大小的字典(其中k可能是1.5或2);但手動控制尺寸可以提高速度。在1級中,如果不是多參考字典,可以在errordict
中安裝dictfull
的替代品來增加字典並重新執行put(或def或其他)。由於level-2在內部執行此操作,因此它可以替換所有引用。
真棒,@luserdroog - 非常感謝您的澄清!乾杯! – sdaau
- 1. 通過屬性遞歸訪問字典以及索引訪問?
- 2. Python:詞典以及它們如何用iteritems存儲和訪問()
- 3. 標準字段,如何以及如何訪問它們?
- 4. WOFF字體,它們是什麼以及爲什麼要關心?
- 5. ObjectSpace - 它是什麼以及人們如何使用它?
- 6. Python中的嵌套字典:如何使它們以及如何使用它們?
- 7. 字體:什麼,何時以及如何使用它們?
- 8. 如何通過my_dict.my_key訪問字典?
- 9. 通過$ state.go傳遞數據以及如何訪問它
- 10. 符號常數:它們如何存儲以及它們的類型是什麼?
- 11. 什麼是(void(**)())以及如何typedef它?
- 12. 什麼是IntelliJ中的「手錶」以及如何使用它們?
- 13. 什麼是NULL值,以及如何在SQLite中處理它們
- 14. 什麼是intvectors以及如何閱讀/使用它們?
- 15. 什麼是默認的ReflectPermissions以及如何更改它們?
- 16. 什麼是StringIndexer,VectorIndexer以及如何使用它們?
- 17. 什麼是BitBucket中的分支以及如何管理它們
- 18. Android:這些菜單是什麼以及如何構建它們?
- 19. 什麼是sqlite開發標題以及如何安裝它們?
- 20. 這些是什麼以及如何使用Ruby刪除它們?
- 21. 什麼是cufon和畫布以及如何覆蓋它們
- 22. 什麼是ResourceContainers以及如何將它們用於雲端點?
- 23. 什麼是服務器日誌以及如何生成它們?
- 24. PHP庫 - 它們是什麼,以及如何創建一個
- 25. 通過字典訪問值
- 26. SQL,Postgres OID,它們是什麼以及它們爲什麼有用?
- 27. 更大以及它們是如何典型地處理
- 28. 什麼是armeabi以及他們爲什麼使用它
- 29. GhostScript PDF到PostScript
- 30. 爲什麼在PostScript中關閉字典?
非常感謝您的詳細解答@pipitas!如果/當你有時間的時候,你還可以添加一個簡短的'ghostscript'終端示例,「_the interpreter []查找一個name_」(它也可以顯示「_'userdict'在'systemdict'_」之前被搜索到,並可能覆蓋操作員)?非常感謝 - 歡呼! – sdaau
@sdaau:我的另一個答案顯示瞭如何在字典'.distillersettings'中查找名稱/鍵'/ screen':就像'.distillersettings/screen get'一樣簡單。 'get'操作符將鍵的值(如果找到)放到操作數堆棧中(如果未找到,則將打印「未定義」錯誤)。現在密鑰的價值在堆棧上,其餘的代碼片段只是將其提取到那裏,將其格式化一點以使其看起來更加漂亮並打印出其內容...... –
非常感謝,@pipitas - 非常感謝! – sdaau