home *** CD-ROM | disk | FTP | other *** search
/ jppd.dyndns.org / jppd.dyndns.org.tar / jppd.dyndns.org / QUERYPRO / Impressora_PDF / converter.exe / GPLGS / gs_resmp.ps < prev    next >
Text File  |  2003-02-19  |  22KB  |  505 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 2003/02/18 19:57:16 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.     { dup ResourceStatus exec {
  213.         pop 2 lt
  214.       } {
  215.         false
  216.       } ifelse                             % bInVirtualMemory
  217.       { FindResource exec
  218.       } {
  219.         dup dup .map exch .knownget {      % /Name /Name <<record>>
  220.           dup dup /RecordVirtualMethods get /IsActive get exec {
  221.             1 index .getvminstance {       % /Name /Name <<record>> holder
  222.               1 get 1 eq
  223.             } {
  224.               true
  225.             } ifelse                       % /Name /Name <<record>> bStatusIs1
  226.             4 1 roll                       % bStatusIs1 /Name /Name <<record>>
  227.             dup /RecordVirtualMethods get /MakeInstance get exec
  228.                                            % bStatusIs1 /Name /Name Instance size
  229.             5 1 roll                       % size bStatusIs1 /Name /Name Instance
  230.             DefineResource exec            % size bStatusIs1 /Name Instance
  231.             % Make ResourceStatus to return correct values for this instance :
  232.             % Hack: we replace status values in the instance holder :
  233.             exch .getvminstance pop        % size bStatusIs1 Instance holder
  234.             dup 5 -1 roll 2 exch put       % bStatusIs1 Instance holder
  235.             3 2 roll {                     % Instance holder
  236.               1 1 put                      % Instance
  237.             } {
  238.               pop
  239.             } ifelse                       % Instance
  240.           } {                              % /Name /Name <<record>>
  241.             pop pop FindResource exec            
  242.           } ifelse
  243.         } {                                % /Name /Name
  244.           pop FindResource exec            
  245.         } ifelse
  246.       } ifelse
  247.     } bind def
  248.  
  249.     /ResourceStatus   % <Name> ResourceStatus <status> <size> true
  250.                       % <Name> ResourceStatus false
  251.     { dup ResourceStatus exec {            % /Name status size
  252.         1 index 2 lt {
  253.           % In VM - return with it.
  254.           3 2 roll pop true
  255.         } {
  256.           % Not in VM.
  257.           exch pop exch                    % size /Name
  258.           dup .map exch .knownget {        % size /Name <<record>>
  259.             dup dup /RecordVirtualMethods get /IsActive get exec {
  260.               3 2 roll pop                 % /Name <<record>>
  261.               dup /RecordVirtualMethods get /GetSize get exec 2 exch true
  262.             } {                            % size /Name <<record>>
  263.               pop pop 2 exch true
  264.             } ifelse
  265.           } {                              % size /Name
  266.             pop 2 exch true
  267.           } ifelse
  268.         } ifelse
  269.       } {                                  % /Name
  270.         dup .map exch .knownget {          % /Name <<record>>
  271.           dup dup /RecordVirtualMethods get /IsActive get exec {
  272.             dup /RecordVirtualMethods get /GetSize get exec 2 exch true
  273.           } {                              % /Name <<record>>
  274.             pop pop false
  275.           } ifelse
  276.         } {                                % /Name
  277.           pop false
  278.         } ifelse
  279.       } ifelse
  280.     } bind def
  281.  
  282.     /ResourceFileName  % <Name> <scratch> ResourceFileName <string>
  283.     { exch                                                    % (scratch) /Name
  284.       .map 1 index .knownget {                                % (scratch) /Name <<record>>
  285.         dup dup /RecordVirtualMethods get /IsActive get exec {
  286.           dup /RecordVirtualMethods get /GetFilePath get exec % (string)
  287.         } {                                                   % (scratch) /Name <<record>>
  288.           pop exch ResourceFileName exec
  289.         } ifelse
  290.       } { 
  291.         exch ResourceFileName exec
  292.       } ifelse
  293.     } bind def
  294.  
  295.     /ResourceForAll  % <template> <proc> <scratch> ResourceForAll -
  296.     { % Create InstancesStatus dictionary :
  297.       20 dict % IS - Instances Status
  298.       4 1 roll                            % <<IS>> (templ) {proc} (sctarch)
  299.                                           % <<IS>> bOrder (templ) {proc} (sctarch)
  300.       % Check if we are under another ResourceForAll :
  301.       /.DisableResourceOrdering //execstack_lookup exec null eq 4 1 roll
  302.  
  303.       % Put underlying resources to the InstancesStatus dictionary :
  304.       currentdict % the category
  305.       begin % ResourceForAll removes it locally.
  306.       2 index
  307.       { cvn                               % <<IS>> bOrder (templ) {proc} (sctarch) /Name
  308.         4 index {
  309.           dup ResourceStatus exec {pop 6 index 3 1 roll put} {pop} ifelse
  310.         } {
  311.           5 index exch 2 put % Don't need the ordering, put '2' as a scratch.
  312.         } ifelse
  313.       }
  314.       2 index ResourceForAll exec         % <<IS>> bOrder (templ) {proc} (sctarch)
  315.       4 3 roll pop                        % <<IS>> (templ) {proc} (sctarch)
  316.       end
  317.  
  318.       % Put .map entries to the InstancesStatus dictionary :
  319.       4 -1 roll begin                     % (templ) {proc} (sctarch)
  320.       .map {                              % (templ) {proc} (sctarch) /Name record
  321.          dup dup /RecordVirtualMethods get /IsActive get exec {
  322.            pop                            % (templ) {proc} (sctarch) /Name
  323.            dup currentdict exch known {
  324.              pop
  325.            } {
  326.              dup 2 index cvs              % (templ) {proc} (sctarch) /Name (Name)
  327.              4 index .stringmatch {       % (templ) {proc} (sctarch) /Name
  328.                2 def % It is not in VM.
  329.              } {
  330.                pop
  331.              } ifelse
  332.            } ifelse
  333.         } {                               % (templ) {proc} (sctarch) /Name record
  334.           pop pop
  335.         } ifelse
  336.       } forall                            % (templ) {proc} (sctarch)
  337.  
  338.       % prepare stacks for the enumeration :
  339.       3 2 roll pop                        % {proc} (sctarch)
  340.       currentdict end                     % {proc} (scratch) <<IS>>
  341.  
  342.       % Make the enumerator and apply it :
  343.       //MakeResourceEnumerator exec exec
  344.  
  345.     } bind def
  346.  
  347.     /GetCIDSystemInfoFromMap   % <Name> GetCIDSystemInfoFromMap <Name>
  348.                                % <Name> GetCIDSystemInfoFromMap <dict>
  349.     { % This is a special function for communicating with GetCIDSystemInfo in gs_cidcm.ps .
  350.       dup .map exch .knownget {
  351.         dup /RecordVirtualMethods get /GetCSI get exec
  352.         dup null ne {
  353.           exch
  354.         } if
  355.         pop
  356.       } if
  357.     } bind def
  358.  
  359. currentdict end def
  360. setpacking
  361.  
  362. /Redefine     % <OptionsDict> Redefine -
  363. { % Before calling this proc, the OptionsDict must specify options for
  364.   % the catregory to be redefined :
  365.   % CategoryName - a name of category to redefine;
  366.   % MapFileName - a string for the resource map file name;
  367.   % VerifyMap - a procedure :
  368.   %   <raw_map> VerifyMap -
  369.   %   - checks the map for consistency
  370.   % PreprocessRecord  - a procedure :
  371.   %   <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> true
  372.   %   <map> <Name> <raw_record> PreprocessRecord <map> <Name> <raw_record> false
  373.   %   - converts a map record into a dictionary;
  374.   %   It must add RecordVirtualMethods dictionary to the record :
  375.   %     MakeInstance - a procedure :
  376.   %         <Name> <record> MakeInstance <Name> <Instance> <size>
  377.   %         - converts the record to resource instance;
  378.   %     GetFilePath - a procedure for ResourceFileName :
  379.   %         <scratch> <Name> <record> GetFilePath <filepath>
  380.   %     GetSize - a procedure for ResourceStatus :
  381.   %         <Name> <record> GetSize <size>
  382.   %     GetCSI - a procedure for obtaining CIDSystemInfo dictionary from the record :
  383.   %         <record> GetCSI <CSI>
  384.   %         <record> GetCSI null
  385.   %     IsActive - a procedure for skipping records depending on the current device :
  386.   %         <record> IsActive <bool>
  387.   %     Also it is allowed to contain additional entries for client's needs.
  388.   % The OptionsDict is also used for storing some local variables.
  389.  
  390.   % If a category is being redefined several times with this function,
  391.   % each redefinition must either use an unique map file,
  392.   % or the map file should be scanned by the last redefinition
  393.   % (and must be defined in the last one with /MapFileName).
  394.   % This happens so because we must accumulate all variants of
  395.   % methods before scanning the map. We would like to delay
  396.   % the scanning until all redefinitions are done, but it requires
  397.   % to implement a queue of "refinish" methods and execute it
  398.   % at very end of the prelude.
  399.  
  400.   begin % OptionsDict
  401.   CategoryName /Category findresource /OldCategory exch def
  402.   OldCategory /.IsRedefinedWithMap known {
  403.     % Already redefined with map - don't redefine, but enhance the map.
  404.     OldCategory /NewCategory exch def
  405.   } {
  406.     % Redefine with a new category instance.
  407.     OldCategory dup length dict 
  408.     dup /.PreprocessRecord 4 dict put
  409.     copy /NewCategory exch def
  410.   } ifelse
  411.  
  412.   % Provide the 'or' logic for PreprocessRecord,
  413.   % to allow different record types to be mixed in a single map file.
  414.   % We do this with building a dictionary of PreprocessRecord procedures,
  415.   % which come from different calls to Redefine :
  416.   NewCategory /.PreprocessRecord get dup length % <<pr>> l  
  417.   currentdict /PreprocessRecord get .growput
  418.  
  419.   currentdict /MapFileName known {
  420.     MapFileName .libfile {
  421.       1 dict begin
  422.       /; {} def
  423.       mark exch cvx exec .dicttomark           % <<map>>
  424.       end
  425.       dup VerifyMap                            % <<map>>
  426.     } {
  427.       QUIET not {
  428.         currentdict /IsMapFileOptional .knownget not { false } if not {
  429.           (Warning: the map file ) print dup =string cvs print ( was not found.) =
  430.         } if
  431.       } if
  432.       pop 0 dict                               % <<map>>
  433.     } ifelse
  434.   } {
  435.     currentdict /.map .knownget not { 
  436.       0 dict                                   % <<map>>
  437.     } if
  438.   } ifelse
  439.  
  440.   % Preprocess entries :
  441.   dup NewCategory /.PreprocessRecord get       % <<map>> <<map>> <<pr>>
  442.   3 1 roll {                                   % <<pr>> <<map>> /Name raw_record
  443.     false 3 1 roll                             % <<pr>> <<map>> false /Name raw_record 
  444.     4 index {                                  % <<pr>> <<map>> false /Name raw_record i {pr}
  445.       exch pop                                 % <<pr>> <<map>> false /Name raw_record {pr}
  446.       exec {                                   % <<pr>> <<map>> false /Name record
  447.         3 -1 roll pop true 3 1 roll            % <<pr>> <<map>> true /Name record
  448.         exit
  449.       } if                                     % <<pr>> <<map>> false /Name raw_record
  450.     } forall
  451.     3 2 roll {                                 % <<pr>> <<map>> /Name record
  452.       2 index 3 1 roll put                     % <<pr>> <<map>>
  453.     } {
  454.       exch                                     % <<pr>> <<map>> raw_record /Name
  455.       (Incorrect record ) print =string cvs print ( of the map file ) print MapFileName =string cvs print (.) =
  456.       end % Pops OptionsDict from dstack.
  457.       pop pop pop                              %
  458.       /Redefine cvx /undefinedresource signalerror
  459.     } ifelse
  460.   } forall                                     % <<pr>> <<map>>
  461.   exch pop                                     % <<map>>
  462.  
  463.  
  464.   % Add the map :
  465.   OldCategory /.IsRedefinedWithMap known {     % <<map>>
  466.     % Just add to the old map :
  467.     OldCategory /.map get copy pop             %
  468.   } {                                          % <<map>>
  469.     % Store the map to both the category and OptionsDict :
  470.     dup NewCategory exch /.map exch put
  471.     /.map exch def                             %
  472.   } ifelse
  473.   OldCategory /.IsRedefinedWithMap known not {
  474.     % Copy old methods to OptionsDict :
  475.     [ /DefineResource /ResourceStatus /ResourceFileName 
  476.       /FindResource /ResourceForAll
  477.     ] {
  478.       dup OldCategory exch get def
  479.     } forall
  480.     
  481.     % Build new methods :
  482.     //MethodsToRedefine {
  483.       //BindWithCurrentdict exec NewCategory 3 1 roll put  
  484.     } forall
  485.     CategoryName /CIDFont ne {
  486.       NewCategory /GetCIDSystemInfoFromMap undef
  487.       % This is some ugly, sorry.
  488.     } if
  489.     % Redefine the category :
  490.     NewCategory /.IsRedefinedWithMap true put
  491.     CategoryName NewCategory /Category defineresource pop
  492.   } if
  493.   end % OptionsDict
  494. } bind executeonly def
  495.  
  496. currentdict /PutPreprocessRecord .undef
  497.  
  498. currentdict end
  499. /ProcSet defineresource pop
  500.  
  501. setglobal .setlanguagelevel
  502.