home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / gs-esp / 8.15 / lib / gs_resmp.ps < prev    next >
Encoding:
Text File  |  2006-07-06  |  21.9 KB  |  523 lines

  1. %    Copyright (C) 2000 artofcode LLC.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: gs_resmp.ps,v 1.10.2.1 2004/10/25 15:19:39 igor Exp $
  14. % A procset to redefine a resource category with a resource map.
  15.  
  16. % Public entries :
  17.  
  18. % Redefine - a procedure for redefining a resource category with a map.
  19. %    Methods for interpreting the resource map to be provided by client 
  20. %    in the argument dictionary.
  21. %
  22. %    Note that the procedure Redefine is idempotential :
  23. %    consequtive calls to it will not replace the category methods,
  24. %    but will merge resource maps. If an interleaving redefinition
  25. %    needs to cancel the idempotentity, it must remove the entry
  26. %    /.IsRedefinedWithMap from the category dictionary.
  27.  
  28. % MakeResourceEnumerator - this procedure is useful for
  29. %    redefining any category. It provides a proper order of instances
  30. %    and proper stacks during resourceforall.
  31.  
  32. % BindWithCurrentdict - a procedure for generating temporary procedures 
  33. %    from templates, binding them with a local dictionary.
  34.  
  35. % execstack_lookup - a procedure for communicating through the execution stack.
  36. %    It allows for a callee to get an information from an indirect caller.
  37.  
  38. % The procedures are designed for exeution witout putting
  39. % the procset instance onto the dictionary stack.
  40.  
  41. languagelevel 2 .setlanguagelevel
  42. currentglobal true setglobal
  43.  
  44. /MappedCategoryRedefiner 10 dict begin % The procset.
  45.  
  46. currentpacking false setpacking
  47.  
  48. /InstanceEnumeratorPattern   %  - InstanceEnumeratorPattern ...
  49. {  
  50.   % This is a pattern for enumeration procedure to be built dynamically,
  51.   % applying BindWithCurrentdict with a temporary dictionary.
  52.   % The following names will be replaced with specific objects
  53.   % during BindWithCurrentdict :
  54.   % en_local_dict - a dictionary for storing the local integer variable 'status'.
  55.   % scr - the scratch string argument of resourceforall;
  56.   % proc - the procedure argument of resourceforall;
  57.   % InstancesStatus - a dictionary that maps resource instance names to their status value;
  58.   % Category - the category to be enumerated.
  59.  
  60.   % When this procedure is called from ResourceForAll, the category is the current dictionary.
  61.   % We remove it from the dictionary stack before performing the enumeration
  62.   % to provide the <proc> to write to the underlying dictionary,
  63.   % and put it back after the enumeration is completed.
  64.   end
  65.   { 
  66.     0 1 2 {
  67.       en_local_dict exch /status exch put
  68.       InstancesStatus {                                            
  69.         en_local_dict /status get eq {
  70.           scr cvs                           % ... (Font)
  71.           proc exec                         %
  72.         } {
  73.           pop
  74.         } ifelse                            % ...
  75.       } forall
  76.     } for                                   % ...
  77.   } stopped
  78.   Category begin
  79.   { stop } if
  80. } bind def
  81.  
  82. % An auxiliary proc for BindWithCurrentdict :
  83. /.BindAux    % <proc> BindAux <proc>
  84. { 0 exec
  85. } bind def
  86.  
  87. setpacking
  88.  
  89. /BindWithCurrentdict     % <proc> BindWithCurrentdict <proc>
  90. {  
  91.   % Make a copy of the given procedure, binding in the values of all names
  92.   % defined in currentdict.
  93.   % Caution1 : this code cannot handle procedures that were already
  94.   %            bound recursively.
  95.   % Caution2 : this code don't bind packedarrays. This was done
  96.   %            intentionally for a termination of the procedure tree.
  97.  
  98.   dup length array copy
  99.   dup length 1 sub -1 0 {                      
  100.     2 copy get                            % {precopy} i {elem}
  101.     dup dup type /arraytype eq exch xcheck and {
  102.                                           % {precopy} i {elem}
  103.       //.BindAux exec                     % {precopy} i {elem_copy}
  104.       2 index 3 1 roll put                % {precopy}
  105.     } {
  106.       dup dup type /nametype eq exch xcheck and {
  107.                                           % {precopy} i {elem}
  108.         currentdict exch .knownget {            
  109.           2 index 3 1 roll put            % {precopy}
  110.         } {                                            
  111.           pop
  112.         } ifelse
  113.       } {
  114.         pop pop
  115.       } ifelse
  116.     } ifelse                              % {precopy}
  117.   } for                                   % {copy}
  118.   cvx
  119. } bind def
  120.  
  121. //.BindAux 0 //BindWithCurrentdict put   % bind the recursive call in 'Bind'.
  122.  
  123. /MakeResourceEnumerator   % <proc> <scr> <InstancesStatus> MakeResourceEnumerator <Enumerator>
  124. {
  125.   % Build the enumeration procedure :
  126.  
  127.   % Since the resourceforall procedure may leave values on the operand stack,
  128.   % we cannot simply store the enumerator's local data on the stack.
  129.   % We also cannot use a static dictionary to store local variables,
  130.   % because of possible recursion in the resourceforall procedure.
  131.   % To work around this, we create a copy of the enumeration procedure and
  132.   % bind it dynamically with a temporary dictionary, which contains
  133.   % local variables for the currently executing instance of resourceforall.
  134.  
  135.   currentdict                    % Category
  136.   6 dict begin % the temporary dictionary
  137.     /Category exch def           %
  138.     /InstancesStatus exch def
  139.     /scr exch def
  140.     /proc exch def
  141.     /en_local_dict currentdict def
  142.     //InstanceEnumeratorPattern //BindWithCurrentdict exec     % Enumerator
  143.     /status 0 def % variable for the current status to enumerate - do not bind with it !
  144.   end
  145.  
  146. } bind def
  147.  
  148. /execstack_lookup     % <object> execstack_lookup <object1>
  149.                       % <object> execstack_lookup null
  150. { % Checks whether execution stack contains a procedure starting with <object>,
  151.   % and retrives the 2nd element of the procedure,
  152.   % or null if the procedure was not found.
  153.   %
  154.   % Since 'execstack' actually renders subarrays of procedures,
  155.   % the pattern for recognition must be like this :
  156.   %
  157.   %   { <object> <object1>
  158.   %     CallSomething
  159.   %   } loop
  160.   %
  161.   % The solution with 'loop' depends on how GS implements cycles,
  162.   % so it must not appear in documents, which are required to be interpreter independent.
  163.   % Any other type of cycles are also acceptable.
  164.   % If no repitition is really needed, just insert 'exit' into its body.
  165.   % If <object> <object1> are not needed for the caller, insert "pop pop" after them.
  166.   % If <object1> is really unuseful, the pattern may be simplified :
  167.   %
  168.   %   { <object> pop
  169.   %     CallSomething
  170.   %     exit
  171.   %   } loop
  172.   %
  173.   % It will retrieve 'pop' or 'null'.
  174.   %
  175.   % Note that 2 topmost execstack elements are the execstack_lookup procedure and its caller.
  176.   % We don't check them.
  177.  
  178.   currentglobal false setglobal                    % <object> bGlobal
  179.   countexecstack array execstack                   % <object> bGlobal [execstack]
  180.   dup null exch                                    % <object> bGlobal [execstack] null [execstack]
  181.   length 3 sub -1 0 {                              % <object> bGlobal [execstack] null i
  182.     2 index exch get                               % <object> bGlobal [execstack] null proc
  183.     dup type dup /packedarraytype eq exch /arraytype eq or {
  184.       dup length 1 gt {                            % <object> bGlobal [execstack] null proc
  185.         dup 0 get                                  % <object> bGlobal [execstack] null proc elem0
  186.         5 index eq {                               % <object> bGlobal [execstack] null proc
  187.           1 get                                    % <object> bGlobal [execstack] null object1
  188.           exch pop exit                            % <object> bGlobal [execstack] object1
  189.         } {
  190.           pop
  191.         } ifelse
  192.       } {
  193.         pop                                        % <object> bGlobal [execstack] false
  194.       } ifelse
  195.     } {
  196.       pop                                          % <object> bGlobal [execstack] false
  197.     } ifelse
  198.   } for                                            % <object> bGlobal [execstack] bResult
  199.   exch pop exch setglobal exch pop                 % bResult
  200. } bind def
  201.  
  202. currentpacking false setpacking
  203. /MethodsToRedefine 5 dict begin
  204.  
  205.     % Procedures in this dictionary really are patterns for new category methods.
  206.     % The following names will be replaced with specific objects during BindWithCurrentdict :
  207.     %   .map - the map dictionary;
  208.     %   DefineResource, ResourceStatus, ResourceFileName, FindResource, ResourceForAll 
  209.     %        - procedures from the original resource category.
  210.  
  211.     /FindResource  % <Name> FindResource <dict>
  212.     { RESMPDEBUG { (resmp FindResource beg ) print dup = } if
  213.       dup ResourceStatus exec {
  214.         pop 2 lt
  215.       } {
  216.         false
  217.       } ifelse                             % bInVirtualMemory
  218.       { FindResource exec
  219.       } {
  220.         dup dup .map exch .knownget {      % /Name /Name <<record>>
  221.           dup dup /RecordVirtualMethods get /IsActive get exec {
  222.             1 index .getvminstance {       % /Name /Name <<record>> holder
  223.               1 get 1 eq
  224.             } {
  225.               true
  226.             } ifelse                       % /Name /Name <<record>> bStatusIs1
  227.             4 1 roll                       % bStatusIs1 /Name /Name <<record>>
  228.             dup /RecordVirtualMethods get /MakeInstance get exec
  229.                                            % bStatusIs1 /Name /Name Instance size
  230.             5 1 roll                       % size bStatusIs1 /Name /Name Instance
  231.             DefineResource exec            % size bStatusIs1 /Name Instance
  232.             % Make ResourceStatus to return correct values for this instance :
  233.             % Hack: we replace status values in the instance holder :
  234.             exch .getvminstance pop        % size bStatusIs1 Instance holder
  235.             dup 5 -1 roll 2 exch put       % bStatusIs1 Instance holder
  236.             3 2 roll {                     % Instance holder
  237.               1 1 put                      % Instance
  238.             } {
  239.               pop
  240.             } ifelse                       % Instance
  241.           } {                              % /Name /Name <<record>>
  242.             pop pop FindResource exec            
  243.           } ifelse
  244.         } {                                % /Name /Name
  245.           pop FindResource exec            
  246.         } ifelse
  247.       } ifelse
  248.       RESMPDEBUG { (resmp FindResource end) = } if
  249.     } bind def
  250.  
  251.     /ResourceStatus   % <Name> ResourceStatus <status> <size> true
  252.                       % <Name> ResourceStatus false
  253.     { RESMPDEBUG { (resmp ResourceStatus beg ) print dup == } if
  254.       dup ResourceStatus exec {            % /Name status size
  255.         1 index 2 lt {
  256.           % In VM - return with it.
  257.           3 2 roll pop true
  258.         } {
  259.           % Not in VM.
  260.           exch pop exch                    % size /Name
  261.           dup .map exch .knownget {        % size /Name <<record>>
  262.             dup dup /RecordVirtualMethods get /IsActive get exec {
  263.               3 2 roll pop                 % /Name <<record>>
  264.               dup /RecordVirtualMethods get /GetSize get exec 2 exch true
  265.             } {                            % size /Name <<record>>
  266.               pop pop 2 exch true
  267.             } ifelse
  268.           } {                              % size /Name
  269.             pop 2 exch true
  270.           } ifelse
  271.         } ifelse
  272.       } {                                  % /Name
  273.         dup .map exch .knownget {          % /Name <<record>>
  274.           dup dup /RecordVirtualMethods get /IsActive get exec {
  275.             dup /RecordVirtualMethods get /GetSize get exec 2 exch true
  276.           } {                              % /Name <<record>>
  277.             pop pop false
  278.           } ifelse
  279.         } {                                % /Name
  280.           pop false
  281.         } ifelse
  282.       } ifelse
  283.       RESMPDEBUG { (resmp ResourceStatus end) = } if
  284.     } bind def
  285.  
  286.     /ResourceFileName  % <Name> <scratch> ResourceFileName <string>
  287.     { RESMPDEBUG { (resmp ResourceFileName beg ) print 1 index = } if
  288.       exch                                                    % (scratch) /Name
  289.       .map 1 index .knownget {                                % (scratch) /Name <<record>>
  290.           RESMPDEBUG { (resmp ResourceFileName : have a map record.) = } if
  291.         dup dup /RecordVirtualMethods get /IsActive get exec {
  292.           RESMPDEBUG { (resmp ResourceFileName : record is active.) = } if
  293.           dup /RecordVirtualMethods get /GetFilePath get exec % (string)
  294.           RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if
  295.         } {                                                   % (scratch) /Name <<record>>
  296.           RESMPDEBUG { (resmp ResourceFileName : record is NOT active.) = } if
  297.           pop exch ResourceFileName exec
  298.           RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if
  299.         } ifelse
  300.       } { 
  301.         RESMPDEBUG { (resmp ResourceFileName : have NO map record.) = } if
  302.         exch ResourceFileName exec
  303.         RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if
  304.       } ifelse
  305.       RESMPDEBUG { (resmp ResourceFileName end) = } if
  306.     } bind def
  307.  
  308.     /ResourceForAll  % <template> <proc> <scratch> ResourceForAll -
  309.     { RESMPDEBUG { (resmp ResourceForAll beg ) print 2 index = } if
  310.       % Create InstancesStatus dictionary :
  311.       20 dict % IS - Instances Status
  312.       4 1 roll                            % <<IS>> (templ) {proc} (sctarch)
  313.                                           % <<IS>> bOrder (templ) {proc} (sctarch)
  314.       % Check if we are under another ResourceForAll :
  315.       /.DisableResourceOrdering //execstack_lookup exec null eq 4 1 roll
  316.  
  317.       % Put underlying resources to the InstancesStatus dictionary :
  318.       currentdict % the category
  319.       begin % ResourceForAll removes it locally.
  320.       2 index
  321.       { cvn                               % <<IS>> bOrder (templ) {proc} (sctarch) /Name
  322.         4 index {
  323.           dup ResourceStatus exec {pop 6 index 3 1 roll put} {pop} ifelse
  324.         } {
  325.           5 index exch 2 put % Don't need the ordering, put '2' as a scratch.
  326.         } ifelse
  327.       }
  328.       2 index ResourceForAll exec         % <<IS>> bOrder (templ) {proc} (sctarch)
  329.       4 3 roll pop                        % <<IS>> (templ) {proc} (sctarch)
  330.       end
  331.  
  332.       % Put .map entries to the InstancesStatus dictionary :
  333.       4 -1 roll begin                     % (templ) {proc} (sctarch)
  334.       .map {                              % (templ) {proc} (sctarch) /Name record
  335.          dup dup /RecordVirtualMethods get /IsActive get exec {
  336.            pop                            % (templ) {proc} (sctarch) /Name
  337.            dup currentdict exch known {
  338.              pop
  339.            } {
  340.              dup 2 index cvs              % (templ) {proc} (sctarch) /Name (Name)
  341.              4 index .stringmatch {       % (templ) {proc} (sctarch) /Name
  342.                2 def % It is not in VM.
  343.              } {
  344.                pop
  345.              } ifelse
  346.            } ifelse
  347.         } {                               % (templ) {proc} (sctarch) /Name record
  348.           pop pop
  349.         } ifelse
  350.       } forall                            % (templ) {proc} (sctarch)
  351.  
  352.       % prepare stacks for the enumeration :
  353.       3 2 roll pop                        % {proc} (sctarch)
  354.       currentdict end                     % {proc} (scratch) <<IS>>
  355.  
  356.       % Make the enumerator and apply it :
  357.       //MakeResourceEnumerator exec exec
  358.       RESMPDEBUG { (resmp ResourceForAll end)= } if
  359.     } bind def
  360.  
  361.     /GetCIDSystemInfoFromMap   % <Name> GetCIDSystemInfoFromMap <Name>
  362.                                % <Name> GetCIDSystemInfoFromMap <dict>
  363.     { RESMPDEBUG { (resmp GetCIDSystemInfoFromMap beg ) print dup = } if
  364.       % This is a special function for communicating with GetCIDSystemInfo in gs_cidcm.ps .
  365.       dup .map exch .knownget {
  366.         RESMPDEBUG { (resmp GetCIDSystemInfoFromMap : have a map record.) = } if
  367.         dup /RecordVirtualMethods get /GetCSI get exec
  368.         dup null ne {
  369.           RESMPDEBUG { (resmp GetCIDSystemInfoFromMap : retrieving a dict.) = } if
  370.           exch
  371.         } if
  372.         pop
  373.       } if
  374.       RESMPDEBUG { (resmp GetCIDSystemInfoFromMap end) = } if
  375.     } bind def
  376.  
  377. currentdict end def
  378. setpacking
  379.  
  380. /Redefine     % <OptionsDict> Redefine -
  381. { % Before calling this proc, the OptionsDict must specify options for
  382.   % the catregory to be redefined :
  383.   % CategoryName - a name of category to redefine;
  384.   % MapFileName - a string for the resource map file name;
  385.   % VerifyMap - a procedure :
  386.   %   <raw_map> VerifyMap -
  387.   %   - checks the map for consistency
  388.   % PreprocessRecord  - a procedure :
  389.   %   <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> true
  390.   %   <map> <Name> <raw_record> PreprocessRecord <map> <Name> <raw_record> false
  391.   %   - converts a map record into a dictionary;
  392.   %   It must add RecordVirtualMethods dictionary to the record :
  393.   %     MakeInstance - a procedure :
  394.   %         <Name> <record> MakeInstance <Name> <Instance> <size>
  395.   %         - converts the record to resource instance;
  396.   %     GetFilePath - a procedure for ResourceFileName :
  397.   %         <scratch> <Name> <record> GetFilePath <filepath>
  398.   %     GetSize - a procedure for ResourceStatus :
  399.   %         <Name> <record> GetSize <size>
  400.   %     GetCSI - a procedure for obtaining CIDSystemInfo dictionary from the record :
  401.   %         <record> GetCSI <CSI>
  402.   %         <record> GetCSI null
  403.   %     IsActive - a procedure for skipping records depending on the current device :
  404.   %         <record> IsActive <bool>
  405.   %     Also it is allowed to contain additional entries for client's needs.
  406.   % The OptionsDict is also used for storing some local variables.
  407.  
  408.   % If a category is being redefined several times with this function,
  409.   % each redefinition must either use an unique map file,
  410.   % or the map file should be scanned by the last redefinition
  411.   % (and must be defined in the last one with /MapFileName).
  412.   % This happens so because we must accumulate all variants of
  413.   % methods before scanning the map. We would like to delay
  414.   % the scanning until all redefinitions are done, but it requires
  415.   % to implement a queue of "refinish" methods and execute it
  416.   % at very end of the prelude.
  417.  
  418.   begin % OptionsDict
  419.   CategoryName /Category findresource /OldCategory exch def
  420.   OldCategory /.IsRedefinedWithMap known {
  421.     % Already redefined with map - don't redefine, but enhance the map.
  422.     OldCategory /NewCategory exch def
  423.   } {
  424.     % Redefine with a new category instance.
  425.     OldCategory dup length dict 
  426.     dup /.PreprocessRecord 4 dict put
  427.     copy /NewCategory exch def
  428.   } ifelse
  429.  
  430.   % Provide the 'or' logic for PreprocessRecord,
  431.   % to allow different record types to be mixed in a single map file.
  432.   % We do this with building a dictionary of PreprocessRecord procedures,
  433.   % which come from different calls to Redefine :
  434.   NewCategory /.PreprocessRecord get dup length % <<pr>> l  
  435.   currentdict /PreprocessRecord get .growput
  436.  
  437.   currentdict /MapFileName known {
  438.     MapFileName .libfile {
  439.       1 dict begin
  440.       /; {} def
  441.       mark exch cvx exec .dicttomark           % <<map>>
  442.       end
  443.       dup VerifyMap                            % <<map>>
  444.     } {
  445.       QUIET not {
  446.         currentdict /IsMapFileOptional .knownget not { false } if not {
  447.           (Warning: the map file ) print dup =string cvs print ( was not found.) =
  448.         } if
  449.       } if
  450.       pop 0 dict                               % <<map>>
  451.     } ifelse
  452.   } {
  453.     currentdict /.map .knownget not { 
  454.       0 dict                                   % <<map>>
  455.     } if
  456.   } ifelse
  457.  
  458.   % Preprocess entries :
  459.   dup NewCategory /.PreprocessRecord get       % <<map>> <<map>> <<pr>>
  460.   3 1 roll {                                   % <<pr>> <<map>> /Name raw_record
  461.     false 3 1 roll                             % <<pr>> <<map>> false /Name raw_record 
  462.     4 index {                                  % <<pr>> <<map>> false /Name raw_record i {pr}
  463.       exch pop                                 % <<pr>> <<map>> false /Name raw_record {pr}
  464.       exec {                                   % <<pr>> <<map>> false /Name record
  465.         3 -1 roll pop true 3 1 roll            % <<pr>> <<map>> true /Name record
  466.         exit
  467.       } if                                     % <<pr>> <<map>> false /Name raw_record
  468.     } forall
  469.     3 2 roll {                                 % <<pr>> <<map>> /Name record
  470.       2 index 3 1 roll put                     % <<pr>> <<map>>
  471.     } {
  472.       exch                                     % <<pr>> <<map>> raw_record /Name
  473.       (Incorrect record ) print =string cvs print ( of the map file ) print MapFileName =string cvs print (.) =
  474.       end % Pops OptionsDict from dstack.
  475.       pop pop pop                              %
  476.       /Redefine cvx /undefinedresource signalerror
  477.     } ifelse
  478.   } forall                                     % <<pr>> <<map>>
  479.   exch pop                                     % <<map>>
  480.  
  481.  
  482.   % Add the map :
  483.   OldCategory /.IsRedefinedWithMap known {     % <<map>>
  484.     % Just add to the old map :
  485.     OldCategory /.map get copy pop             %
  486.   } {                                          % <<map>>
  487.     % Store the map to both the category and OptionsDict :
  488.     dup NewCategory exch /.map exch put
  489.     /.map exch def                             %
  490.   } ifelse
  491.   OldCategory /.IsRedefinedWithMap known not {
  492.     % Copy old methods to OptionsDict :
  493.     [ /DefineResource /ResourceStatus /ResourceFileName 
  494.       /FindResource /ResourceForAll
  495.     ] {
  496.       dup OldCategory exch get def
  497.     } forall
  498.     
  499.     % Build new methods :
  500.     //MethodsToRedefine {
  501.       //BindWithCurrentdict exec NewCategory 3 1 roll put  
  502.     } forall
  503.     CategoryName /CIDFont ne {
  504.       NewCategory /GetCIDSystemInfoFromMap undef
  505.       % This is some ugly, sorry.
  506.     } if
  507.     % Redefine the category :
  508.     NewCategory /.IsRedefinedWithMap true put
  509.     CategoryName NewCategory /Category defineresource pop
  510.   } if
  511.   end % OptionsDict
  512. } bind executeonly def
  513.  
  514. currentdict /PutPreprocessRecord .undef
  515.  
  516. currentdict end
  517. /ProcSet defineresource pop
  518.  
  519. setglobal .setlanguagelevel
  520.