% Copyright (C) 2000 Artifex Software, Inc. All rights reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% For more information about licensing, please refer to
% http://www.ghostscript.com/licensing/. For information on
% commercial licensing, go to http://www.artifex.com/licensing/ or
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
% $Id: gs_resmp.ps 8954 2008-08-08 04:22:38Z ray $
% A procset to redefine a resource category with a resource map.
% Public entries :
% Redefine - a procedure for redefining a resource category with a map.
% Methods for interpreting the resource map to be provided by client
% in the argument dictionary.
%
% Note that the procedure Redefine is idempotential :
% consequtive calls to it will not replace the category methods,
% but will merge resource maps. If an interleaving redefinition
% needs to cancel the idempotentity, it must remove the entry
% /.IsRedefinedWithMap from the category dictionary.
% MakeResourceEnumerator - this procedure is useful for
% redefining any category. It provides a proper order of instances
% and proper stacks during resourceforall.
% BindWithCurrentdict - a procedure for generating temporary procedures
% from templates, binding them with a local dictionary.
% execstack_lookup - a procedure for communicating through the execution stack.
% It allows for a callee to get an information from an indirect caller.
% The procedures are designed for exeution witout putting
% the procset instance onto the dictionary stack.
languagelevel 2 .setlanguagelevel
currentglobal true setglobal
/MappedCategoryRedefiner 10 dict begin % The procset.
currentpacking false setpacking
/InstanceEnumeratorPattern % - InstanceEnumeratorPattern ...
{
% This is a pattern for enumeration procedure to be built dynamically,
% applying BindWithCurrentdict with a temporary dictionary.
% The following names will be replaced with specific objects
% during BindWithCurrentdict :
% en_local_dict - a dictionary for storing the local integer variable 'status'.
% scr - the scratch string argument of resourceforall;
% proc - the procedure argument of resourceforall;
% InstancesStatus - a dictionary that maps resource instance names to their status value;
% Category - the category to be enumerated.
% When this procedure is called from ResourceForAll, the category is the current dictionary.
% We remove it from the dictionary stack before performing the enumeration
% to provide the to write to the underlying dictionary,
% and put it back after the enumeration is completed.
end
{
0 1 2 {
en_local_dict exch /status exch put
InstancesStatus {
en_local_dict /status get eq {
scr cvs % ... (Font)
proc exec %
} {
pop
} ifelse % ...
} forall
} for % ...
} stopped
Category begin
{ stop } if
} bind def
% An auxiliary proc for BindWithCurrentdict :
/.BindAux % BindAux
{ 0 exec
} bind def
setpacking
/BindWithCurrentdict % BindWithCurrentdict
{
% Make a copy of the given procedure, binding in the values of all names
% defined in currentdict.
% Caution1 : this code cannot handle procedures that were already
% bound recursively.
% Caution2 : this code don't bind packedarrays. This was done
% intentionally for a termination of the procedure tree.
dup length array copy
dup length 1 sub -1 0 {
2 copy get % {precopy} i {elem}
dup dup type /arraytype eq exch xcheck and {
% {precopy} i {elem}
//.BindAux exec % {precopy} i {elem_copy}
2 index 3 1 roll put % {precopy}
} {
dup dup type /nametype eq exch xcheck and {
% {precopy} i {elem}
currentdict exch .knownget {
2 index 3 1 roll put % {precopy}
} {
pop
} ifelse
} {
pop pop
} ifelse
} ifelse % {precopy}
} for % {copy}
cvx
} bind def
//.BindAux 0 //BindWithCurrentdict put % bind the recursive call in 'Bind'.
/MakeResourceEnumerator % MakeResourceEnumerator
{
% Build the enumeration procedure :
% Since the resourceforall procedure may leave values on the operand stack,
% we cannot simply store the enumerator's local data on the stack.
% We also cannot use a static dictionary to store local variables,
% because of possible recursion in the resourceforall procedure.
% To work around this, we create a copy of the enumeration procedure and
% bind it dynamically with a temporary dictionary, which contains
% local variables for the currently executing instance of resourceforall.
% Always place the enumerator in local VM,
% because its elements may be in local VM.
currentglobal 4 1 roll
false setglobal
currentdict % Category
6 dict begin % the temporary dictionary
/Category exch def
/InstancesStatus exch def
/scr exch def
/proc exch def
/en_local_dict currentdict def
//InstanceEnumeratorPattern //BindWithCurrentdict exec % Enumerator
/status 0 def % variable for the current status to enumerate - do not bind with it !
end
exch setglobal
} bind def
/execstack_lookup %