home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / GhostScript / !GhostScr / 6_01 / lib / gs_res.ps < prev    next >
Text File  |  2000-03-09  |  25KB  |  833 lines

  1. %    Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % $Id: gs_res.ps,v 1.2 2000/03/10 04:54:15 lpd Exp $
  16. % Initialization file for Level 2 resource machinery.
  17. % When this is run, systemdict is still writable,
  18. % but (almost) everything defined here goes into level2dict.
  19.  
  20. level2dict begin
  21.  
  22. (BEGIN RESOURCES) VMDEBUG
  23.  
  24. % We keep track of (global) instances with another entry in the resource
  25. % dictionary, an Instances dictionary.  For categories with implicit
  26. % instances, the values in Instances are the same as the keys;
  27. % for other categories, the values are [instance status size].
  28.  
  29. % Note that the dictionary that defines a resource category is stored
  30. % in global VM.  The PostScript manual says that each category must
  31. % manage global and local instances separately.  However, objects in
  32. % global VM other than systemdict can't reference objects in local VM.
  33. % This means that the resource category dictionary, which would otherwise be
  34. % the obvious place to keep track of the instances, can't be used to keep
  35. % track of local instances.  Instead, we define a dictionary in local VM
  36. % called localinstancedict, in which the key is the category name and
  37. % the value is the analogue of Instances for local instances.
  38.  
  39. % We don't currently implement automatic resource unloading.
  40. % When and if we do, it should be hooked to the garbage collector.
  41. % However, Ed Taft of Adobe says their interpreters don't implement this
  42. % either, so we aren't going to worry about it for a while.
  43.  
  44. currentglobal false setglobal systemdict begin
  45.   /localinstancedict 5 dict
  46.   .forcedef    % localinstancedict is local, systemdict is global
  47. end true setglobal
  48. /.emptydict 0 dict readonly def
  49. setglobal
  50.  
  51. % Resource category dictionaries have the following keys (those marked with
  52. % * are optional):
  53. %    Standard, defined in the Red Book:
  54. %        Category (name)
  55. %        *InstanceType (name)
  56. %        DefineResource
  57. %            <key> <instance> DefineResource <instance>
  58. %        UndefineResource
  59. %            <key> UndefineResource -
  60. %        FindResource
  61. %            <key> FindResource <instance>
  62. %        ResourceStatus
  63. %            <key> ResourceStatus <status> <size> true
  64. %            <key> ResourceStatus false
  65. %        ResourceForAll
  66. %            <template> <proc> <scratch> ResourceForAll -
  67. %        *ResourceFileName
  68. %            <key> <scratch> ResourceFileName <filename>
  69. %    Additional, specific to our implementation:
  70. %        Instances (dictionary)
  71. %        .LocalInstances
  72. %            - .LocalInstances <dict>
  73. %        .GetInstance
  74. %            <key> .GetInstance <instance> -true-
  75. %            <key> .GetInstance -false-
  76. %        .CheckResource
  77. %            <key> <value> .CheckResource <key> <value> <ok>
  78. %              (or may give an error if not OK)
  79. %        .DoLoadResource
  80. %            <key> .DoLoadResource - (may give an error)
  81. %        .LoadResource
  82. %            <key> .LoadResource - (may give an error)
  83. %        .ResourceFile
  84. %            <key> .ResourceFile <file> -true-
  85. %            <key> .ResourceFile <key> -false-
  86. % All the above procedures expect that the top dictionary on the d-stack
  87. % is the resource dictionary.
  88.  
  89. % Define enough of the Category category so we can define other categories.
  90. % The dictionary we're about to create will become the Category
  91. % category definition dictionary.
  92.  
  93. % .findcategory and .resourceexec are only called from within the
  94. % implementation of the resource 'operators', so they doesn't have to worry
  95. % about cleaning up the stack if they fail (the interpreter's stack
  96. % protection machinery for pseudo-operators takes care of this).
  97. /.findcategory {    % <name> .findcategory -
  98.             %   (pushes the category on the dstack)
  99.   /Category findresource begin
  100. } bind def
  101.  
  102. /.resourceexec {    % <key> /xxxResource .resourceexec -
  103.             %   (also pops the category from the dstack)
  104.   load exec end
  105. } bind def
  106.  
  107. 15 dict begin
  108.  
  109.         % Standard entries
  110.  
  111. /Category /Category def
  112. /InstanceType /dicttype def
  113.  
  114. /DefineResource
  115.     { .CheckResource
  116.        { dup /Category 3 index cvlit .growput
  117.         % We would like to make Category dictionaries read-only,
  118.         % and we used to do that here, but we can't do it,
  119.         % because we have to be able to replace the dummy, empty
  120.         % Instances dictionary with the real one later.
  121.          dup [ exch 0 -1 ] exch
  122.          Instances 4 2 roll put
  123.        }
  124.        { /defineresource load /typecheck signalerror
  125.        }
  126.       ifelse
  127.     } bind def
  128. /FindResource        % (redefined below)
  129.     { Instances exch get 0 get
  130.     } bind def
  131.  
  132.         % Additional entries
  133.  
  134. /Instances 30 dict def
  135. Instances /Category [currentdict 0 -1] put
  136.  
  137. /.LocalInstances 0 dict def
  138. /.GetInstance
  139.     { Instances exch .knownget
  140.     } bind def
  141. /.CheckResource
  142.     { dup gcheck currentglobal and
  143.        { /DefineResource /FindResource /ResourceForAll /ResourceStatus
  144.          /UndefineResource }
  145.        { 2 index exch known and }
  146.       forall
  147.       not { /defineresource load /invalidaccess signalerror } if
  148.       true
  149.     } bind def
  150.  
  151. Instances end begin    % for the base case of findresource
  152.  
  153. (END CATEGORY) VMDEBUG
  154.  
  155. % Define the resource operators.  We use the "stack protection" feature of
  156. % odef to make sure the stacks are restored properly on an error.
  157. % This requires that the operators not pop anything from the stack until
  158. % they have executed their logic successfully.  We can't make this
  159. % work for resourceforall, because the procedure it executes mustn't see
  160. % the operands of resourceforall on the stack, but we can make it work for
  161. % the others.
  162.  
  163. mark
  164. /defineresource {    % <key> <instance> <category> defineresource <instance>
  165.     3 copy .findcategory
  166.     currentdict /InstanceType known {
  167.       dup type InstanceType ne {
  168.         dup type /packedarraytype eq InstanceType /arraytype eq and
  169.         not { /defineresource load /typecheck signalerror } if
  170.       } if
  171.     } if
  172.     /DefineResource .resourceexec
  173.     4 1 roll pop pop pop
  174. }
  175. /findresource {        % <key> <category> findresource <instance>
  176.     2 copy dup /Category eq
  177.       { pop //Category 0 get begin } { .findcategory } ifelse
  178.     /FindResource .resourceexec exch pop exch pop
  179. }
  180. /resourceforall {    % <template> <proc> <scratch> <category> resourceforall -
  181.     dup /Category findresource begin
  182.     /ResourceForAll load
  183.         % Make sure we can recover the original operands.
  184.         % Stack: ...operands... proc
  185.     5 copy pop 4 packedarray count
  186.         % Stack: ...operands... proc saved count
  187.     4 -1 roll pop        % pop the category
  188.     /stopped load 3 1 roll
  189.     3 .execn
  190.         % Stack: ... stopped saved count
  191.     3 -1 roll {
  192.         % The count is the original stack depth + 2.
  193.       count exch 4 sub sub { exch pop } repeat
  194.       aload pop stop
  195.     } {
  196.       pop pop
  197.     } ifelse end
  198. }
  199. /resourcestatus {    % <key> <category> resourcestatus <status> <size> true
  200.             % <key> <category> resourcestatus false
  201.     2 copy .findcategory /ResourceStatus .resourceexec
  202.      { 4 2 roll pop pop true } { pop pop false } ifelse
  203. }
  204. /undefineresource {    % <key> <category> undefineresource -
  205.     2 copy .findcategory /UndefineResource .resourceexec pop pop
  206. }
  207. end        % Instances of Category
  208. counttomark 2 idiv { bind odef } repeat pop
  209.  
  210. % Define the system parameters used for the Generic implementation of
  211. % ResourceFileName.
  212. systemdict begin
  213. currentdict /pssystemparams known not {
  214.   /pssystemparams 10 dict readonly def
  215. } if
  216. pssystemparams begin
  217.   /FontResourceDir (/Resource/Font/) readonly .forcedef    % pssys'params is r-o
  218.   /GenericResourceDir (/Resource/) readonly .forcedef    % pssys'params is r-o
  219.   /GenericResourcePathSep (/) readonly .forcedef    % pssys'params is r-o
  220. end
  221. end
  222.  
  223. % Define the generic algorithm for computing resource file names.
  224. /.rfnstring 100 string def
  225. /.genericrfn        % <key> <scratch> <prefix> .genericrfn <filename>
  226.  { 3 -1 roll //.rfnstring cvs concatstrings exch copy
  227.  } bind def
  228.  
  229. % Define the Generic category.
  230.  
  231. /Generic mark
  232.  
  233.         % Standard entries
  234.  
  235. % We're still running in Level 1 mode, so dictionaries won't expand.
  236. % Leave room for the /Category entry.
  237. /Category null
  238.  
  239. /DefineResource
  240.     { .CheckResource
  241.        { dup [ exch 0 -1 ]
  242.             % Stack: key value instance
  243.          currentglobal
  244.           { false setglobal 2 index UndefineResource    % remove local def if any
  245.         true setglobal
  246.         Instances dup //.emptydict eq
  247.          { pop 3 dict /Instances 1 index def
  248.          }
  249.         if
  250.           }
  251.           { .LocalInstances dup //.emptydict eq
  252.              { pop 3 dict localinstancedict Category 2 index put
  253.          }
  254.         if
  255.           }
  256.          ifelse
  257.             % Stack: key value instance instancedict
  258.          3 index 2 index .growput
  259.             % Now make the resource value read-only.
  260.          0 2 copy get { readonly } .internalstopped pop
  261.          dup 4 1 roll put exch pop exch pop
  262.        }
  263.        { /defineresource load /typecheck signalerror
  264.        }
  265.       ifelse
  266.     } bind
  267. /UndefineResource
  268.     {  { dup 2 index .knownget
  269.           { dup 1 get 1 ge
  270.          { dup 0 null put 1 2 put pop pop }
  271.          { pop exch .undef }
  272.         ifelse
  273.           }
  274.           { pop pop
  275.           }
  276.          ifelse
  277.        }
  278.       currentglobal
  279.        { 2 copy Instances exch exec
  280.        }
  281.       if .LocalInstances exch exec
  282.     } bind
  283. /FindResource
  284.     { dup ResourceStatus
  285.        { pop 1 gt            % not in VM
  286.           { .DoLoadResource
  287.           }
  288.          if
  289.          .GetInstance pop        % can't fail
  290.          0 get
  291.        }
  292.        { /findresource load /undefinedresource signalerror
  293.        }
  294.       ifelse
  295.     } bind
  296. /ResourceStatus
  297.     { dup .GetInstance
  298.        { exch pop dup 1 get exch 2 get true }
  299.        { .ResourceFile
  300.           { closefile 2 -1 true }
  301.           { pop false }
  302.          ifelse
  303.        }
  304.       ifelse
  305.     } bind
  306. /ResourceForAll
  307.     {    % **************** Doesn't present instance groups in
  308.         % **************** the correct order yet.
  309.         % Construct a new procedure to hold the arguments.
  310.         % It must be in local VM to avoid a possible invalidaccess.
  311.       .currentglobal 4 1 roll false .setglobal
  312.       3 packedarray        % template, proc, scratch
  313.       { exch pop    % stack contains: key, {template, proc, scratch}
  314.         2 copy 0 get .stringmatch
  315.          { 1 index type dup /stringtype eq exch /nametype eq or
  316.         { 2 copy 2 get cvs
  317.           exch 1 get 3 -1 roll pop
  318.         }
  319.         { 1 get
  320.         }
  321.            ifelse exec
  322.          }
  323.          { pop pop
  324.          }
  325.         ifelse
  326.       } /exec cvx 3 packedarray
  327.         % Stack: global? iterproc
  328.         % We must pop the resource dictionary off the dict stack
  329.         % when doing the actual iteration, and restore it afterwards.
  330.       exch {
  331.         true .setglobal
  332.       } {
  333.         .LocalInstances length 0 ne {
  334.         % We must do local instances, and do them first.
  335.           .LocalInstances exch cvx /forall cvx 1 index cvlit
  336.           currentdict end 3 .execn begin
  337.         } if
  338.       } ifelse
  339.       Instances exch cvx
  340.       /forall cvx currentdict end 2 .execn begin
  341.     } bind
  342. /ResourceFileName
  343.     { /GenericResourceDir getsystemparam 
  344.       Category .namestring concatstrings
  345.       /GenericResourcePathSep getsystemparam concatstrings
  346.       .genericrfn
  347.     } bind
  348.  
  349.         % Additional entries
  350.  
  351. % Unfortunately, we can't create the real Instances dictionary now,
  352. % because if someone copies the Generic category (which pp. 95-96 of the
  353. % 2nd Edition Red Book says is legitimate), they'll wind up sharing
  354. % the Instances.  Instead, we have to create Instances on demand,
  355. % just like the entry in localinstancedict.
  356. % We also have to prevent anyone from creating instances of Generic itself.
  357. /Instances //.emptydict
  358.  
  359. /.LocalInstances
  360.     { localinstancedict Category .knownget not { //.emptydict } if
  361.     } bind
  362. /.GetInstance
  363.     { currentglobal
  364.        { Instances exch .knownget }
  365.        { .LocalInstances 1 index .knownget
  366.           { exch pop true }
  367.           { Instances exch .knownget }
  368.          ifelse
  369.        }
  370.       ifelse
  371.     } bind
  372. /.CheckResource
  373.     { true
  374.     } bind
  375. /.DoLoadResource
  376.     { dup vmstatus pop exch pop exch
  377.       .LoadResource
  378.       vmstatus pop exch pop exch sub
  379.       1 index .GetInstance not
  380.        { pop dup /undefinedresource signalerror }    % didn't load
  381.       if
  382.       dup 1 1 put
  383.       2 3 -1 roll put
  384.     } bind
  385. /.LoadResource
  386.     { dup .ResourceFile
  387.        { exch pop currentglobal
  388.           { .runresource }
  389.           { true setglobal { .runresource } stopped false setglobal { stop } if }
  390.          ifelse
  391.        }
  392.        { dup /undefinedresource signalerror
  393.        }
  394.      ifelse
  395.     } bind
  396. /.ResourceFile
  397.     { currentdict /ResourceFileName known
  398.        { mark 1 index 100 string { ResourceFileName }
  399.          .internalstopped
  400.           { cleartomark false }
  401.           { exch pop findlibfile
  402.          { exch pop exch pop true }
  403.          { pop false }
  404.         ifelse
  405.           }
  406.          ifelse
  407.        }
  408.        { false }
  409.       ifelse
  410.     } bind
  411.  
  412. .dicttomark
  413. /Category defineresource pop
  414.  
  415. % Fill in the rest of the Category category.
  416. /Category /Category findresource dup
  417. /Generic /Category findresource begin
  418.  { /FindResource /ResourceForAll /ResourceStatus /UndefineResource
  419.    /ResourceFileName /.ResourceFile /.LoadResource /.DoLoadResource
  420.  }
  421.  { dup load put dup } forall
  422. pop readonly pop end
  423.  
  424. (END GENERIC) VMDEBUG
  425.  
  426. % Define the fixed categories.
  427.  
  428. mark
  429.     % Non-Type categories with existing entries.
  430.  /ColorSpaceFamily
  431.    { }    % These must be deferred, because optional features may add some.
  432.  /Emulator
  433.    mark EMULATORS { cvn } forall .packtomark
  434.  /Filter
  435.    { }    % These must be deferred, because optional features may add some.
  436.  /IODevice
  437.     % Loop until the .getiodevice gets a rangecheck.
  438.    errordict /rangecheck 2 copy get
  439.    errordict /rangecheck { pop stop } put    % pop the command
  440.    mark 0 { {
  441.     dup .getiodevice dup null eq { pop } { exch } ifelse 1 add
  442.    } loop} .internalstopped
  443.    pop pop pop .packtomark
  444.    4 1 roll put
  445.    .clearerror
  446.     % Type categories listed in the Red Book.
  447.  /ColorRenderingType
  448.    { }    % These must be deferred, because optional features may add some.
  449.  /FMapType
  450.    { }    % These must be deferred, because optional features may add some.
  451.  /FontType
  452.    { }    % These must be deferred, because optional features may add some.
  453.  /FormType
  454.    { }    % These must be deferred, because optional features may add some.
  455.  /HalftoneType
  456.    { }    % These must be deferred, because optional features may add some.
  457.  /ImageType
  458.    { }    % Deferred, optional features may add some.
  459.  /PatternType
  460.    { }  % Deferred, optional features may add some.
  461.     % Type categories added since the Red Book.
  462.  /setsmoothness where {
  463.    pop /ShadingType { }    % Deferred, optional features may add some.
  464.  } if
  465. counttomark 2 idiv
  466.  { mark
  467.  
  468.         % Standard entries
  469.  
  470.         % We'd like to prohibit defineresource,
  471.         % but because optional features may add entries, we can't.
  472.         % We can at least require that the key and value match.
  473.    /DefineResource
  474.     { currentglobal not
  475.        { /defineresource load /invalidaccess signalerror }
  476.        { 2 copy ne
  477.           { /defineresource load /rangecheck signalerror }
  478.           { dup Instances 4 -2 roll .growput }
  479.          ifelse
  480.        }
  481.       ifelse
  482.     } bind
  483.    /UndefineResource
  484.     { /undefineresource load /invalidaccess signalerror } bind
  485.    /FindResource
  486.     { Instances 1 index .knownget
  487.        { exch pop }
  488.        { /findresource load /undefinedresource signalerror }
  489.       ifelse
  490.     } bind
  491.    /ResourceStatus
  492.     { Instances exch known { 0 0 true } { false } ifelse } bind
  493.    /ResourceForAll
  494.     /Generic /Category findresource /ResourceForAll get
  495.  
  496.         % Additional entries
  497.  
  498.    counttomark 2 add -1 roll
  499.    dup length dict dup begin exch { dup def } forall end
  500.         % We'd like to make the Instances readonly here,
  501.         % but because optional features may add entries, we can't.
  502.    /Instances exch
  503.    /.LocalInstances    % used by ResourceForAll
  504.     0 dict def
  505.  
  506.    .dicttomark /Category defineresource pop
  507.  } repeat pop
  508.  
  509. (END FIXED) VMDEBUG
  510.  
  511. % Define the other built-in categories.
  512.  
  513. /.definecategory    % <name> -mark- <key1> ... <valuen> .definecategory -
  514.  { counttomark 2 idiv 2 add        % Instances, Category
  515.    /Generic /Category findresource dup maxlength 3 -1 roll add
  516.    dict .copydict begin
  517.    counttomark 2 idiv { def } repeat pop    % pop the mark
  518.    currentdict end /Category defineresource pop
  519.  } bind def
  520.  
  521. /ColorRendering mark /InstanceType /dicttype .definecategory
  522. % ColorSpace is defined below
  523. % Encoding is defined below
  524. % Font is defined below
  525. /Form mark /InstanceType /dicttype .definecategory
  526. /Halftone mark /InstanceType /dicttype .definecategory
  527. /Pattern mark /InstanceType /dicttype .definecategory
  528. /ProcSet mark /InstanceType /dicttype .definecategory
  529. % Added since the Red Book:
  530. /ControlLanguage mark /InstanceType /dicttype .definecategory
  531. /HWOptions mark /InstanceType /dicttype .definecategory
  532. /Localization mark /InstanceType /dicttype .definecategory
  533. /OutputDevice mark /InstanceType /dicttype .definecategory
  534. /PDL mark /InstanceType /dicttype .definecategory
  535. % CIDFont, CIDMap, and CMap are defined in gs_cidfn.ps
  536. % FontSet is defined in gs_cff.ps
  537. % IdiomSet is defined in gs_ll3.ps
  538. % InkParams and TrapParams are defined in gs_trap.ps
  539.  
  540. (END MISC) VMDEBUG
  541.  
  542. % Define the ColorSpace category.
  543.  
  544. /.defaultcsnames mark
  545.   /DefaultGray 0
  546.   /DefaultRGB 1
  547.   /DefaultCMYK 2
  548. .dicttomark readonly def
  549.  
  550. % The "hooks" are no-ops here, redefined in LL3.
  551. /.definedefaultcs {    % <index> <value> .definedefaultcs -
  552.   pop pop
  553. } bind def
  554. /.undefinedefaultcs {    % <index> .undefinedefaultcs -
  555.   pop
  556. } bind def
  557.  
  558. /ColorSpace mark
  559.  
  560. /InstanceType /arraytype
  561.  
  562. % We keep track of whether there are any local definitions for any of
  563. % the Default keys.  This information must get saved and restored in
  564. % parallel with the local instance dictionary, so it must be stored in
  565. % local VM.  Therefore, we use a local array (actually, a procedure)
  566. % to hold the flag.
  567.  
  568. % We'll need to use .forceput to initialize this correctly.
  569. /.LocalDefaults null
  570.  
  571. /DefineResource {
  572.   2 copy /Generic /Category findresource /DefineResource get exec
  573.   exch pop
  574.   exch //.defaultcsnames exch .knownget {
  575.     1 index .definedefaultcs
  576.     currentglobal not { /.LocalDefaults load 0 true put } if
  577.   } if
  578. } bind
  579.  
  580. /UndefineResource {
  581.   dup /Generic /Category findresource /UndefineResource get exec
  582.   //.defaultcsnames exch .knownget {
  583.     .undefinedefaultcs
  584.     currentglobal not {
  585.     % Recompute .LocalDefaults by scanning.  This is rarely needed.
  586.       /.LocalDefaults load 0 false //.defaultcsnames {
  587.     pop .LocalInstances exch known { pop true exit } if
  588.       } forall put
  589.     } if
  590.   } if
  591. } bind
  592.  
  593. .definecategory            % ColorSpace
  594.  
  595. currentglobal false setglobal
  596. /ColorSpace /Category findresource
  597.   /.LocalDefaults [false] cvx .forceput    % category is global, array is local
  598. setglobal
  599.  
  600. % Define the Encoding category.
  601.  
  602. /Encoding mark
  603.  
  604. /InstanceType /arraytype
  605.  
  606. % Handle already-registered encodings, including lazily loaded encodings
  607. % that aren't loaded yet.
  608.  
  609. /Instances mark
  610.   EncodingDirectory
  611.    { dup length 256 eq { [ exch readonly 0 -1 ] } { pop [null 2 -1] } ifelse
  612.    } forall
  613. .dicttomark
  614.  
  615. /.ResourceFileDict mark
  616.   EncodingDirectory
  617.    { dup length 256 eq { pop pop } { 0 get } ifelse
  618.    } forall
  619. .dicttomark
  620.  
  621. /ResourceFileName
  622.  { .ResourceFileDict 2 index .knownget
  623.     { exch copy exch pop }
  624.     { /Generic /Category findresource /ResourceFileName get exec }
  625.    ifelse
  626.  } bind
  627.  
  628. .definecategory            % Encoding
  629.  
  630. % Make placeholders in level2dict for the redefined Encoding operators,
  631. % so that they will be swapped properly when we switch language levels.
  632.  
  633. /.findencoding /.findencoding load def
  634. /findencoding /findencoding load def
  635. /.defineencoding /.defineencoding load def
  636.  
  637. (END ENCODING) VMDEBUG
  638.  
  639. % Define the Font category.
  640.  
  641. /.fontstatus {        % <fontname> .fontstatus <fontname> <found>
  642.   {        % Create a loop context just so we can exit it early.
  643.         % Check Fontmap.
  644.     Fontmap 1 index .knownget {
  645.       {
  646.     dup type /nametype eq {
  647.       .fontstatus { null exit } if
  648.     } {
  649.       dup type /stringtype eq {
  650.         findlibfile { closefile pop null exit } if pop
  651.       } {
  652.         % Procedure, assume success.
  653.         pop null exit
  654.       } ifelse
  655.     } ifelse
  656.       } forall dup null eq { pop true exit } if
  657.     } if
  658.         % Convert names to strings; give up on other types.
  659.     dup type /nametype eq { .namestring } if
  660.     dup type /stringtype ne { false exit } if
  661.         % Check the resource directory.
  662.     dup .fonttempstring /FontResourceDir getsystemparam .genericrfn
  663.     status {
  664.       pop pop pop pop true exit
  665.     } if
  666.         % Check for a file on the search path with the same name
  667.         % as the font.
  668.     findlibfile { closefile true exit } if
  669.         % Scan a FONTPATH directory and try again.
  670.     .scannextfontdir not { false exit } if
  671.   } loop
  672. } bind def
  673.  
  674. /Font mark
  675.  
  676. /InstanceType /dicttype
  677.  
  678. /DefineResource
  679.     { 2 copy //definefont exch pop
  680.       /Generic /Category findresource /DefineResource get exec
  681.     } bind
  682. /UndefineResource
  683.     { dup //undefinefont
  684.       /Generic /Category findresource /UndefineResource get exec
  685.     } bind
  686. /FindResource
  687.     { dup ResourceStatus
  688.        { pop 1 gt { .loadfont } { .GetInstance pop 0 get } ifelse }
  689.        { .loadfont }
  690.       ifelse
  691.     } bind
  692. /ResourceForAll {
  693.     { .scannextfontdir not { exit } if } loop
  694.     /Generic /Category findresource /ResourceForAll get exec
  695. } bind
  696. /ResourceStatus {
  697.     dup .GetInstance {
  698.       exch pop dup 1 get exch 2 get true
  699.     } {
  700.       .fontstatus { pop 2 -1 true } { pop false } ifelse
  701.     } ifelse
  702. } bind
  703.  
  704. /.loadfont
  705.     { dup vmstatus pop exch pop exch
  706.         % Hack: rebind .currentresourcefile so that all calls of
  707.         % definefont will know these are built-in fonts.
  708.       currentfile {pop //findfont exec} .execasresource  % (findfont is a procedure)
  709.       exch vmstatus pop exch pop exch sub
  710.         % stack: name font vmused
  711.         % findfont has the prerogative of not calling definefont
  712.         % in certain obscure cases of font substitution.
  713.       2 index .GetInstance
  714.        { dup 1 1 put
  715.          2 3 -1 roll put
  716.        }
  717.        { pop
  718.        }
  719.       ifelse exch pop
  720.     } bind
  721.  
  722. /Instances FontDirectory length 2 mul dict
  723.  
  724. .definecategory            % Font
  725.  
  726. % Redefine font "operators".
  727. /.definefontmap
  728.  { /Font /Category findresource /Instances get
  729.    dup 3 index known
  730.     { pop
  731.     }
  732.     { 2 index
  733.         % Make sure we create the array in global VM.
  734.       .currentglobal true .setglobal
  735.       [null 2 -1] exch .setglobal
  736.       .growput
  737.     }
  738.    ifelse
  739.    //.definefontmap exec
  740.  } bind def
  741.  
  742. % Make sure the old definitions are still in systemdict so that
  743. % they will get bound properly.
  744. systemdict begin
  745.   /.origdefinefont /definefont load def
  746.   /.origundefinefont /undefinefont load def
  747.   /.origfindfont /findfont load def
  748. end
  749. /definefont {
  750.   /Font defineresource
  751. } bind odef
  752. /undefinefont {
  753.   /Font undefineresource
  754. } bind odef
  755. % The Red Book requires that findfont be a procedure, not an operator,
  756. % but it still needs to restore the stacks reliably if it fails.
  757. /.findfontop {
  758.   /Font findresource
  759. } bind odef
  760. /findfont {
  761.   .findfontop
  762. } bind def    % Must be a procedure, not an operator
  763.  
  764. % Remove initialization utilities.
  765. currentdict /.definecategory .undef
  766. currentdict /.emptydict .undef
  767.  
  768. end                % level2dict
  769.  
  770. % Convert deferred resources after we finally switch to Level 2.
  771.  
  772. /.fixresources {
  773.     % Encoding resources
  774.   EncodingDirectory
  775.    { dup length 256 eq
  776.       { /Encoding defineresource pop }
  777.       { pop pop }
  778.      ifelse
  779.    } forall
  780.   /.findencoding { /Encoding findresource } bind def
  781.   /findencoding /.findencoding load def        % must be a procedure
  782.   /.defineencoding { /Encoding defineresource pop } bind def
  783.     % ColorRendering resources and ProcSet
  784.   systemdict /ColorRendering .knownget {
  785.     /ColorRendering exch /ProcSet defineresource pop
  786.     systemdict /ColorRendering undef
  787.     /Default currentcolorrendering /ColorRendering defineresource pop
  788.   } if
  789.     % ColorSpace resources
  790.   systemdict /CIEsRGB .knownget {
  791.     /sRGB exch /ColorSpace defineresource pop
  792.     systemdict /CIEsRGB undef
  793.   } if
  794.     % ColorSpaceFamily resources
  795.   colorspacedict { pop dup /ColorSpaceFamily defineresource pop } forall
  796.     % Filter resources
  797.   filterdict { pop dup /Filter defineresource pop } forall
  798.     % FontType and FMapType resources
  799.   buildfontdict { pop dup /FontType defineresource pop } forall
  800.   mark
  801.     buildfontdict 0 known { 2 3 4 5 6 7 8 } if
  802.     buildfontdict 9 known { 9 } if
  803.   counttomark { dup /FMapType defineresource pop } repeat pop
  804.     % FormType resources
  805.   .formtypes { pop dup /FormType defineresource pop } forall
  806.     % HalftoneType resources
  807.   .halftonetypes { pop dup /HalftoneType defineresource pop } forall
  808.     % ColorRenderingType resources
  809.   .colorrenderingtypes {pop dup /ColorRenderingType defineresource pop} forall
  810.     % ImageType resources
  811.   .imagetypes { pop dup /ImageType defineresource pop } forall
  812.     % PatternType resources
  813.   .patterntypes { pop dup /PatternType defineresource pop } forall
  814.     % Make the fixed resource categories immutable.
  815.   /.shadingtypes where {
  816.     pop .shadingtypes { pop dup /ShadingType defineresource pop } forall
  817.   } if
  818.   [ /ColorSpaceFamily /Emulator /Filter /IODevice /ColorRenderingType
  819.     /FMapType /FontType /FormType /HalftoneType /ImageType /PatternType
  820.     /.shadingtypes where { pop /ShadingType } if
  821.   ] {
  822.     /Category findresource
  823.     dup /Instances get readonly pop
  824.     .LocalInstances readonly pop
  825.     readonly pop
  826.   } forall
  827.     % clean up
  828.   systemdict /.fixresources undef
  829. } bind def
  830.