home *** CD-ROM | disk | FTP | other *** search
- % Copyright (C) 1994, 1996, 1997 Aladdin Enterprises. All rights reserved.
- %
- % This file is part of Aladdin Ghostscript.
- %
- % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- % or distributor accepts any responsibility for the consequences of using it,
- % or for whether it serves any particular purpose or works at all, unless he
- % or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- % License (the "License") for full details.
- %
- % Every copy of Aladdin Ghostscript must include a copy of the License,
- % normally in a plain ASCII text file named PUBLIC. The License grants you
- % the right to copy, modify and redistribute Aladdin Ghostscript, but only
- % under certain conditions described in the License. Among other things, the
- % License requires that the copyright notice and this notice be preserved on
- % all copies.
-
- % Initialization file for Level 2 resource machinery.
- % When this is run, systemdict is still writable,
- % but (almost) everything defined here goes into level2dict.
-
- level2dict begin
-
- (BEGIN RESOURCES) VMDEBUG
-
- % We keep track of (global) instances with another entry in the resource
- % dictionary, an Instances dictionary. For categories with implicit
- % instances, the values in Instances are the same as the keys;
- % for other categories, the values are [instance status size].
-
- % Note that the dictionary that defines a resource category is stored
- % in global memory. The PostScript manual says that each category must
- % manage global and local instances separately. However, objects in
- % global memory other than systemdict can't reference objects in local memory.
- % This means that the resource category dictionary, which would otherwise be
- % the obvious place to keep track of the instances, can't be used to keep
- % track of local instances. Instead, we define a dictionary in local VM
- % called localinstancedict, in which the key is the category name and
- % the value is the analogue of Instances for local instances.
-
- % We don't currently implement automatic resource unloading.
- % When and if we do, it should be hooked to the garbage collector.
- % However, Ed Taft of Adobe says their interpreters don't implement this
- % either, so we aren't going to worry about it for a while.
-
- currentglobal false setglobal systemdict begin
- /localinstancedict 5 dict def
- end true setglobal
- /.emptydict 0 dict readonly def
- setglobal
-
- % Resource category dictionaries have the following keys (those marked with
- % * are optional):
- % Standard, defined in the Red Book:
- % Category (name)
- % *InstanceType (name)
- % DefineResource
- % <key> <instance> DefineResource <instance>
- % UndefineResource
- % <key> UndefineResource -
- % FindResource
- % <key> FindResource <instance>
- % ResourceStatus
- % <key> ResourceStatus <status> <size> true
- % <key> ResourceStatus false
- % ResourceForAll
- % <template> <proc> <scratch> ResourceForAll -
- % *ResourceFileName
- % <key> <scratch> ResourceFileName <filename>
- % Additional, specific to our implementation:
- % Instances (dictionary)
- % .LocalInstances
- % - .LocalInstances <dict>
- % .GetInstance
- % <key> .GetInstance <instance> -true-
- % <key> .GetInstance -false-
- % .CheckResource
- % <key> <value> .CheckResource <key> <value> <ok>
- % (or may give an error if not OK)
- % .DoLoadResource
- % <key> .DoLoadResource - (may give an error)
- % .LoadResource
- % <key> .LoadResource - (may give an error)
- % .ResourceFile
- % <key> .ResourceFile <file> -true-
- % <key> .ResourceFile <key> -false-
- % All the above procedures expect that the top dictionary on the d-stack
- % is the resource dictionary.
-
- % Define enough of the Category category so we can define other categories.
- % The dictionary we're about to create will become the Category
- % category definition dictionary.
-
- /.findcategory % <name> .findcategory <category>
- { { /Category findresource } stopped { pop stop } if
- } bind def
-
- /.resourceexec % <key> /xxxResource .resourceexec -
- { % (also pops the category from the dstack)
- load stopped { Category end stop } if end
- } bind def
-
- 12 dict begin
-
- % Standard entries
-
- /Category /Category def
- /InstanceType /dicttype def
-
- /DefineResource
- { .CheckResource
- { dup /Category 3 index cvlit .growput
- % We would like to make Category dictionaries read-only,
- % and we used to do that here, but we can't do it,
- % because we have to be able to replace the dummy, empty
- % Instances dictionary with the real one later.
- dup [ exch 0 -1 ] exch
- Instances 4 2 roll put
- }
- { /defineresource load /typecheck signalerror
- }
- ifelse
- } bind def
- /FindResource % (redefined below)
- { Instances exch get 0 get
- } bind def
-
- % Additional entries
-
- /Instances 25 dict def
- Instances /Category [currentdict 0 -1] put
-
- /.LocalInstances 0 dict def
- /.GetInstance
- { Instances exch .knownget
- } bind def
- /.CheckResource
- { dup gcheck currentglobal and
- { /DefineResource /FindResource /ResourceForAll /ResourceStatus
- /UndefineResource }
- { 2 index exch known and }
- forall
- not { /defineresource load /invalidaccess signalerror } if
- true
- } bind def
-
- Instances end begin % for the base case of findresource
-
- (END CATEGORY) VMDEBUG
-
- % Define the resource operators. We use the "stack protection" feature of
- % odef to make sure the stacks are restored properly on an error.
- % This requires that the operators not pop anything from the stack until
- % they have executed their logic successfully. We can't make this
- % work for resourceforall, but we can make it work for the others.
-
- mark
- /defineresource { % <key> <instance> <category> defineresource <instance>
- 3 copy .findcategory dup begin
- /InstanceType known {
- dup type InstanceType ne {
- dup type /packedarraytype eq InstanceType /arraytype eq and
- not { /defineresource load /typecheck signalerror } if
- } if
- } if
- /DefineResource .resourceexec
- 4 1 roll pop pop pop
- }
- /findresource { % <key> <category> findresource <instance>
- 2 copy dup /Category eq
- { pop //Category 0 get } { .findcategory } ifelse
- begin
- /FindResource .resourceexec exch pop exch pop
- }
- /resourceforall { % <template> <proc> <scratch> <category> resourceforall -
- .findcategory begin /ResourceForAll .resourceexec
- }
- /resourcestatus { % <key> <category> resourcestatus <status> <size> true
- % <key> <category> resourcestatus false
- 2 copy .findcategory begin /ResourceStatus .resourceexec
- { 4 2 roll pop pop true } { pop pop false } ifelse
- }
- /undefineresource { % <key> <category> undefineresource -
- 2 copy .findcategory begin /UndefineResource .resourceexec pop pop
- }
- end % Instances of Category
- counttomark 2 idiv { bind odef } repeat pop
-
- % Define the system parameters used for the Generic implementation of
- % ResourceFileName.
- systemdict begin
- currentdict /systemparams known not { /systemparams 10 dict readonly def } if
- systemparams
- dup /FontResourceDir (/Resource/Font/) readonly .forceput
- dup /GenericResourceDir (/Resource/) readonly .forceput
- dup /GenericResourcePathSep (/) readonly .forceput
- pop
- end
-
- % Define the generic algorithm for computing resource file names.
- /.rfnstring 100 string def
- /.genericrfn % <key> <scratch> <prefix> .genericrfn <filename>
- { 3 -1 roll //.rfnstring cvs concatstrings exch copy
- } bind def
-
- % Define the Generic category.
-
- /Generic mark
-
- % Standard entries
-
- % We're still running in Level 1 mode, so dictionaries won't expand.
- % Leave room for the /Category entry.
- /Category null
-
- /DefineResource
- { .CheckResource
- { dup [ exch 0 -1 ]
- % Stack: key value instance
- currentglobal
- { false setglobal 2 index UndefineResource % remove local def if any
- true setglobal
- Instances dup //.emptydict eq
- { pop 3 dict /Instances 1 index def
- }
- if
- }
- { .LocalInstances dup //.emptydict eq
- { pop 3 dict localinstancedict Category 2 index put
- }
- if
- }
- ifelse
- % Stack: key value instance instancedict
- 3 index 2 index .growput
- % Now make the resource value read-only.
- 0 2 copy get { readonly } .internalstopped pop
- dup 4 1 roll put exch pop exch pop
- }
- { /defineresource load /typecheck signalerror
- }
- ifelse
- } bind
- /UndefineResource
- { { dup 2 index .knownget
- { dup 1 get 1 ge
- { dup 0 null put 1 2 put pop pop }
- { pop exch .undef }
- ifelse
- }
- { pop pop
- }
- ifelse
- }
- currentglobal
- { 2 copy Instances exch exec
- }
- if .LocalInstances exch exec
- } bind
- /FindResource
- { dup ResourceStatus
- { pop 1 gt % not in VM
- { .DoLoadResource
- }
- if
- .GetInstance pop % can't fail
- 0 get
- }
- { /findresource load /undefinedresource signalerror
- }
- ifelse
- } bind
- /ResourceStatus
- { dup .GetInstance
- { exch pop dup 1 get exch 2 get true }
- { .ResourceFile
- { closefile 2 -1 true }
- { pop false }
- ifelse
- }
- ifelse
- } bind
- /ResourceForAll
- { % **************** Doesn't present instance groups in
- % **************** the correct order yet.
- % We construct a new procedure so we don't have to use
- % static resources to hold the iteration state.
- % Make sure it is in local VM, to avoid an invalidaccess.
- 3 copy .currentglobal 4 1 roll false .setglobal
- 3 packedarray % template, proc, scratch
- { exch pop % stack contains: key, {template, proc, scratch}
- 2 copy 0 get .stringmatch
- { 1 index type dup /stringtype eq exch /nametype eq or
- { 2 copy 2 get cvs
- exch 1 get 3 -1 roll pop
- }
- { 1 get
- }
- ifelse exec
- }
- { pop pop
- }
- ifelse
- } /exec cvx 3 packedarray cvx
- % Stack: template proc scratch global? iterproc
- % We must pop the resource dictionary off the dict stack
- % when doing the actual iteration, and restore it afterwards.
- currentglobal .LocalInstances length 0 eq or not
- { % We must do local instances, and do them first.
- /forall cvx 1 index currentdict 3 packedarray cvx
- .LocalInstances 3 1 roll end exec begin
- }
- if
- exch .setglobal
- Instances exch
- /forall cvx currentdict
- end 2 .execn begin pop pop pop
- } bind
- /ResourceFileName
- { /GenericResourceDir getsystemparam
- Category .namestring concatstrings
- /GenericResourcePathSep getsystemparam concatstrings
- .genericrfn
- } bind
-
- % Additional entries
-
- % Unfortunately, we can't create the real Instances dictionary now,
- % because if someone copies the Generic category (which pp. 95-96 of the
- % 2nd Edition Red Book says is legitimate), they'll wind up sharing
- % the Instances. Instead, we have to create Instances on demand,
- % just like the entry in localinstancedict.
- % We also have to prevent anyone from creating instances of Generic itself.
- /Instances //.emptydict
-
- /.LocalInstances
- { localinstancedict Category .knownget not { //.emptydict } if
- } bind
- /.GetInstance
- { currentglobal
- { Instances exch .knownget }
- { .LocalInstances 1 index .knownget
- { exch pop true }
- { Instances exch .knownget }
- ifelse
- }
- ifelse
- } bind
- /.CheckResource
- { true
- } bind
- /.DoLoadResource
- { dup vmstatus pop exch pop exch
- .LoadResource
- vmstatus pop exch pop exch sub
- 1 index .GetInstance not
- { pop dup /undefinedresource signalerror } % didn't load
- if
- dup 1 1 put
- 2 3 -1 roll put
- } bind
- /.LoadResource
- { dup .ResourceFile
- { exch pop currentglobal
- { run }
- { true setglobal { run } stopped false setglobal { stop } if }
- ifelse
- }
- { dup /undefinedresource signalerror
- }
- ifelse
- } bind
- /.ResourceFile
- { currentdict /ResourceFileName known
- { mark 1 index 100 string { ResourceFileName }
- .internalstopped
- { cleartomark false }
- { exch pop findlibfile
- { exch pop exch pop true }
- { pop false }
- ifelse
- }
- ifelse
- }
- { false }
- ifelse
- } bind
-
- .dicttomark
- /Category defineresource pop
-
- % Fill in the rest of the Category category.
- /Category /Category findresource dup
- /Generic /Category findresource begin
- { /FindResource /ResourceForAll /ResourceStatus /UndefineResource /.ResourceFile }
- { dup load put dup } forall
- pop readonly pop end
-
- (END GENERIC) VMDEBUG
-
- % Define the fixed categories.
-
- mark
- % Things other than types
- /ColorSpaceFamily
- mark colorspacedict { pop } forall .packtomark
- /Emulator
- mark EMULATORS { cvn } forall .packtomark
- /Filter
- mark filterdict { pop } forall .packtomark
- /IODevice
- % Loop until the .getiodevice gets a rangecheck.
- errordict /rangecheck 2 copy get
- errordict /rangecheck { pop stop } put % pop the command
- mark 0 { {dup .getiodevice exch 1 add} loop} .internalstopped
- pop pop pop .packtomark
- 4 1 roll put
- .clearerror
- % Types
- /setcolorrendering where
- { pop /ColorRenderingType
- {1}
- } if
- /FMapType
- { } % These must be deferred, because optional features may add some.
- /FontType
- { } % These must be deferred, because optional features may add some.
- /FormType
- {1}
- /HalftoneType
- {1 2 3 4 5}
- /ImageType
- {1}
- /PatternType
- {1} % should check for Pattern color space
- counttomark 2 idiv
- { mark
-
- % Standard entries
-
- % We'd like to prohibit defineresource,
- % but because optional features may add entries, we can't.
- % We can at least require that the key and value match.
- /DefineResource
- { currentglobal not
- { /defineresource load /invalidaccess signalerror }
- { 2 copy ne
- { /defineresource load /rangecheck signalerror }
- { dup Instances 4 -2 roll .growput }
- ifelse
- }
- ifelse
- } bind
- /UndefineResource
- { /undefineresource load /invalidaccess signalerror } bind
- /FindResource
- { Instances 1 index .knownget
- { exch pop }
- { /findresource load /undefinedresource signalerror }
- ifelse
- } bind
- /ResourceStatus
- { Instances exch known { 0 0 true } { false } ifelse } bind
- /ResourceForAll
- /Generic /Category findresource /ResourceForAll get
-
- % Additional entries
-
- counttomark 2 add -1 roll
- dup length dict dup begin exch { dup def } forall end
- % We'd like to make the Instances readonly here,
- % but because optional features may add entries, we can't.
- /Instances exch
- /.LocalInstances % used by ResourceForAll
- 0 dict def
-
- .dicttomark /Category defineresource pop
- } repeat pop
-
- (END FIXED) VMDEBUG
-
- % Define the other built-in categories.
-
- /.definecategory % <name> -mark- <key1> ... <valuen> .definecategory -
- { counttomark 2 idiv 2 add % Instances, Category
- /Generic /Category findresource dup maxlength 3 -1 roll add
- dict .copydict begin
- counttomark 2 idiv { def } repeat pop % pop the mark
- currentdict end /Category defineresource pop
- } bind def
-
- /ColorRendering mark /InstanceType /dicttype .definecategory
- /ColorSpace mark /InstanceType /arraytype .definecategory
- /Form mark /InstanceType /dicttype .definecategory
- /Halftone mark /InstanceType /dicttype .definecategory
- /Pattern mark /InstanceType /dicttype .definecategory
- /ProcSet mark /InstanceType /dicttype .definecategory
-
- (END MISC) VMDEBUG
-
- % Define the Encoding category.
-
- /Encoding mark
-
- /InstanceType /arraytype
-
- % Handle already-registered encodings, including lazily loaded encodings
- % that aren't loaded yet.
-
- /Instances mark
- EncodingDirectory
- { dup length 256 eq { [ exch readonly 0 -1 ] } { pop [null 2 -1] } ifelse
- } forall
- .dicttomark
-
- /.ResourceFileDict mark
- EncodingDirectory
- { dup length 256 eq { pop pop } { 0 get } ifelse
- } forall
- .dicttomark
-
- /ResourceFileName
- { .ResourceFileDict 2 index .knownget
- { exch copy exch pop }
- { /Generic /Category findresource /ResourceFileName get exec }
- ifelse
- } bind
-
- .definecategory % Encoding
-
- % Make placeholders in level2dict for the redefined Encoding operators,
- % so that they will be swapped properly when we switch language levels.
-
- /.findencoding /.findencoding load def
- /findencoding /findencoding load def
- /.defineencoding /.defineencoding load def
-
- (END ENCODING) VMDEBUG
-
- % Define the Font category.
-
- /Font mark
-
- /InstanceType /dicttype
-
- /DefineResource
- { 2 copy //definefont exch pop
- /Generic /Category findresource /DefineResource get exec
- } bind
- /UndefineResource
- { dup //undefinefont
- /Generic /Category findresource /UndefineResource get exec
- } bind
- /FindResource
- { dup ResourceStatus
- { pop 1 gt { .loadfont } { .GetInstance pop 0 get } ifelse }
- { .loadfont }
- ifelse
- } bind
- /ResourceFileName
- { /FontResourceDir getsystemparam .genericrfn
- } bind
-
- /.loadfont
- { dup vmstatus pop exch pop exch
- //findfont exec exch % findfont is a procedure....
- vmstatus pop exch pop exch sub
- % stack: name font vmused
- % findfont has the prerogative of not calling definefont
- % in certain obscure cases of font substitution.
- 2 index .GetInstance
- { dup 1 1 put
- 2 3 -1 roll put
- }
- { pop
- }
- ifelse exch pop
- } bind
-
- /Instances FontDirectory length 2 mul dict
-
- .definecategory % Font
-
- % Redefine font "operators".
- /.definefontmap
- { /Font /Category findresource /Instances get
- dup 3 index known
- { pop
- }
- { 2 index
- % Make sure we create the array in global VM.
- .currentglobal true .setglobal
- [null 2 -1] exch .setglobal
- .growput
- }
- ifelse
- //.definefontmap exec
- } bind def
-
- % Make sure the old definitions are still in systemdict so that
- % they will get bound properly.
- systemdict begin
- /.origdefinefont /definefont load def
- /.origundefinefont /undefinefont load def
- /.origfindfont /findfont load def
- end
- /definefont {
- /Font defineresource
- } bind odef
- /undefinefont {
- /Font undefineresource
- } bind odef
- % The Red Book requires that findfont be a procedure, not an operator,
- % but it still needs to restore the stacks reliably if it fails.
- /.findfontop {
- /Font findresource
- } bind odef
- /findfont {
- .findfontop
- } bind def % Must be a procedure, not an operator
-
- % Remove initialization utilities.
- currentdict /.definecategory .undef
- currentdict /.emptydict .undef
-
- end % level2dict
-
- % Convert deferred resources after we finally switch to Level 2.
-
- /.fixresources {
- % Encoding resources
- EncodingDirectory
- { dup length 256 eq
- { /Encoding defineresource pop }
- { pop pop }
- ifelse
- } forall
- /.findencoding { /Encoding findresource } bind def
- /findencoding /.findencoding load odef
- /.defineencoding { /Encoding defineresource pop } bind def
- % ColorRendering resources and ProcSet
- systemdict /ColorRendering .knownget {
- /ColorRendering exch /ProcSet defineresource pop
- systemdict /ColorRendering undef
- /DefaultColorRendering currentcolorrendering /ColorRendering
- defineresource pop
- % FontType and FMapType resources
- buildfontdict { pop dup /FontType defineresource pop } forall
- mark
- buildfontdict 0 known { 2 3 4 5 6 7 8 } if
- buildfontdict 9 known { 9 } if
- counttomark { dup /FMapType defineresource pop } repeat pop
- } if
- % Make the fixed resource categories immutable.
- { /ColorSpaceFamily /Emulator /Filter /IODevice /ColorRenderingType
- /FMapType /FontType /FormType /HalftoneType /ImageType /PatternType
- } {
- /Category findresource
- dup /Instances get readonly pop
- .LocalInstances readonly pop
- readonly pop
- } forall
- % clean up
- systemdict /.fixresources undef
- } bind def
-