% Copyright (C) 1997, 2000 Aladdin Enterprises. 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_dps.ps,v 1.8 2002/11/14 17:24:00 raph Exp $% Initialization file for Display PostScript functions.% ------ Contexts ------ %% To create a context with private local VM, we use the .localfork% operator to actually create the context, the new VM, and an empty% userdict, and then we call the .initlocaldicts procedure to make% local copies of the initial contents of the dictionaries in local VM.% savedlocaldicts in systemdict is a global read-only dictionary whose% elements are global read-only copies of these initial contents;% we just copy its elements into local VM and install them in systemdict.% userdict and internaldict require special handling.% Switching between contexts with different local VMs requires% changing the bindings in systemdict that reference local objects.% For this purpose, each userdict has an entry called localdicts% which holds the local copies of the elements of savedlocaldicts,% plus internaldict. The context switching code in the interpreter% effectively copies this dictionary into systemdict.% NOTE: the name localdicts is known to the interpreter.% Switching between contexts also requires resetting the user parameters.% The interpreter records the value of userparams (a local dictionary% referenced from systemdict) for each context, and uses it for this.% See gs_lev2.ps for more details.% NOTE: the name userparams is known to the interpreter.% Save copies of local dictionaries at the end of system initialization.% Also save the initial gstate./.savelocalstate { .currentglobal true .setglobal //systemdict /savedlocaldicts mark //systemdict { dup gcheck { pop pop } { dup type /dicttype eq { % Save a copy of this dictionary in global VM. dup maxlength dict .copydict readonly } { pop pop } ifelse } ifelse } forall .dicttomark readonly put % Create localdicts for the current context. false .setglobal userdict /localdicts mark savedlocaldicts { pop dup load } forall /internaldict dup load .dicttomark readonly put % Save a copy of the initial gstate. true .setglobal //systemdict /savedinitialgstate gstate readonly put .setglobal} .bind def% Initialize local dictionaries and gstate when creating a new context.% Note that until this completes, we are in the anomalous situation of% having systemdict point to dictionaries that are in a non-current% local VM. Because of this, we turn off garbage collection temporarily./.copylocal { % <name> <dict> .copylocal <name> <dict'> % Copy a dictionary to the current (local) VM, % and make it read-only if its current definition is. dup maxlength dict .copydict 1 index load wcheck not { readonly } if} .bind def% When this is called, the dictionary stack is in its initial state,% and there is (anomalously) only one gstate on the gstate stack./.initlocaldicts { % - .initlocaldicts - -2 vmreclaim .currentglobal //systemdict begin false .setglobal % Since localdicts doesn't exist yet, references from % systemdict to local objects won't get restored if % a context switch happens in this code. Therefore, % until localdicts is defined, we have to keep all our % state on the operand stack. % Acquire userdict. %****** WRONG IF NON-STANDARD INITIAL DSTACK ****** countdictstack array dictstack { dup gcheck not { exit } if pop } forall % Create localdicts with a local copy of each dictionary, % except for userdict and userparams, which just need % to be filled in. mark savedlocaldicts { 1 index /userdict eq { % Stack: userdict mark ... /userdict inituserdict counttomark 1 add index .copydict } { 1 index /userparams eq { % Stack: userdict mark ... /userparams inituserparams userparams .copydict } { .copylocal } ifelse } ifelse } forall /internaldict dup .makeinternaldict .makeoperator .dicttomark readonly /localdicts exch put % localdicts is now defined in userdict. % Copy the definitions into systemdict. localdicts { .forcedef } forall % Set the user parameters. userparams readonly .setuserparams % Establish the initial gstate(s). /savedinitialgstate .systemvar setgstate gsave % Wrap up. end .setglobal} odef% Check whether an object is a procedure./.proccheck { % <obj> .proccheck <bool> dup xcheck exch type dup /arraytype eq exch /packedarraytype eq or and} bind def% Create a context with private local VM.% The .localfork operator does all the work, but we must ensure that% .initlocaldicts gets called when the new context starts up./localfork { % <mark> <obj1> ... <objN> <proc> % <stdin|null> <stdout|null> % localfork <context> .currentglobal true .setglobal 3 index dup .proccheck not { pop .setglobal /localfork cvx /typecheck signalerror } if {exec .initlocaldicts} aload pop 3 1 roll 3 packedarray cvx 4 1 roll 5 -1 roll pop .setglobal .localfork} odef% Fork a context that shares VM. The .fork operator creates an empty% userparams dictionary for the context, but we still need to initialize% this dictionary when the new context starts up./.postfork { % - .postfork - % Initialize the user parameters. savedlocaldicts /userparams get userparams .copydict readonly pop} odef/fork { % <mark> <obj1> ... <objN> <proc> fork <context> .currentglobal false .setglobal 1 index dup .proccheck not { pop .setglobal /fork cvx /typecheck signalerror } if {exec .postfork} aload pop 3 1 roll 3 packedarray cvx 3 1 roll exch pop .setglobal .fork} odef% ------ Halftone phase ------ %/sethalftonephase { % <x> <y> sethalftonephase - -1 2 index 2 index .setscreenphase pop pop} odef/currenthalftonephase { % - currenthalftonephase <x> <y> 0 .currentscreenphase} odef% ------ Device-source images ------ */.imagetypes 2 /.image2 load put% ------ Device information ------ %/.deviceinfodict mark /Colors null /GrayValues null /RedValues null /GreenValues null /BlueValues null /ColorValues null.dicttomark readonly def/deviceinfo { % - deviceinfo <dict> currentdevice //.deviceinfodict .getdeviceparams .dicttomark dup begin /ColorValues .knownget { 0 le { currentdict /ColorValues undef } { % hack around devices that incorrect set GrayValues Colors 3 eq { 1 } { GrayValues } ifelse RedValues mul GreenValues mul BlueValues mul ColorValues ne { currentdict /GrayValues undef currentdict /RedValues undef currentdict /GreenValues undef currentdict /BlueValues undef } if } ifelse } if currentdict end readonly} odef% The current implementation allocates a 2-element array each time.% Perhaps we should change this to 2 separate parameters for X and Y?/.wtdict mark /wtranslation null.dicttomark readonly def/wtranslation { % - wtranslation <x> <y> currentdevice //.wtdict .getdeviceparams exch pop exch pop aload pop} odefcurrentdict /.wtdict .undef% ------ View clipping ------ %/rectviewclip { % <x> <y> <width> <height> rectviewclip - % <numarray|numstring> rectviewclip - newpath .rectappend viewclip} odef
% Copyright (C) 1997, 2000 Aladdin Enterprises. 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_dps.ps,v 1.8 2002/11/14 17:24:00 raph Exp $
% Initialization file for Display PostScript functions.
% ------ Contexts ------ %
% To create a context with private local VM, we use the .localfork
% operator to actually create the context, the new VM, and an empty
% userdict, and then we call the .initlocaldicts procedure to make
% local copies of the initial contents of the dictionaries in local VM.
% savedlocaldicts in systemdict is a global read-only dictionary whose
% elements are global read-only copies of these initial contents;
% we just copy its elements into local VM and install them in systemdict.
% userdict and internaldict require special handling.
% Switching between contexts with different local VMs requires
% changing the bindings in systemdict that reference local objects.
% For this purpose, each userdict has an entry called localdicts
% which holds the local copies of the elements of savedlocaldicts,
% plus internaldict. The context switching code in the interpreter
% effectively copies this dictionary into systemdict.
% NOTE: the name localdicts is known to the interpreter.
% Switching between contexts also requires resetting the user parameters.
% The interpreter records the value of userparams (a local dictionary
% referenced from systemdict) for each context, and uses it for this.
% See gs_lev2.ps for more details.
% NOTE: the name userparams is known to the interpreter.
% Save copies of local dictionaries at the end of system initialization.
% Also save the initial gstate.
/.savelocalstate {
.currentglobal true .setglobal
//systemdict /savedlocaldicts mark //systemdict {
dup gcheck {
pop pop
} {
dup type /dicttype eq {
% Save a copy of this dictionary in global VM.
dup maxlength dict .copydict readonly
} {
pop pop
} ifelse
} ifelse
} forall .dicttomark readonly put
% Create localdicts for the current context.
false .setglobal
userdict /localdicts mark savedlocaldicts {
pop dup load
} forall /internaldict dup load
.dicttomark readonly put
% Save a copy of the initial gstate.
true .setglobal
//systemdict /savedinitialgstate gstate readonly put
.setglobal
} .bind def
% Initialize local dictionaries and gstate when creating a new context.
% Note that until this completes, we are in the anomalous situation of
% having systemdict point to dictionaries that are in a non-current
% local VM. Because of this, we turn off garbage collection temporarily.
/.copylocal { % <name> <dict> .copylocal <name> <dict'>
% Copy a dictionary to the current (local) VM,
% and make it read-only if its current definition is.
dup maxlength dict .copydict
1 index load wcheck not { readonly } if
} .bind def
% When this is called, the dictionary stack is in its initial state,
% and there is (anomalously) only one gstate on the gstate stack.
/.initlocaldicts { % - .initlocaldicts -
-2 vmreclaim
.currentglobal //systemdict begin
false .setglobal
% Since localdicts doesn't exist yet, references from
% systemdict to local objects won't get restored if
% a context switch happens in this code. Therefore,
% until localdicts is defined, we have to keep all our
% state on the operand stack.
% Acquire userdict.
%****** WRONG IF NON-STANDARD INITIAL DSTACK ******
countdictstack array dictstack
{ dup gcheck not { exit } if pop } forall
% Create localdicts with a local copy of each dictionary,
% except for userdict and userparams, which just need
% to be filled in.
mark savedlocaldicts {
1 index /userdict eq {
% Stack: userdict mark ... /userdict inituserdict
counttomark 1 add index .copydict
} {
1 index /userparams eq {
% Stack: userdict mark ... /userparams inituserparams
userparams .copydict
} {
.copylocal
} ifelse
} ifelse
} forall /internaldict dup .makeinternaldict .makeoperator
.dicttomark readonly /localdicts exch put
% localdicts is now defined in userdict.
% Copy the definitions into systemdict.
localdicts { .forcedef } forall
% Set the user parameters.
userparams readonly .setuserparams
% Establish the initial gstate(s).
/savedinitialgstate .systemvar setgstate gsave
% Wrap up.
end .setglobal
} odef
% Check whether an object is a procedure.
/.proccheck { % <obj> .proccheck <bool>
dup xcheck
exch type dup /arraytype eq exch /packedarraytype eq or and
} bind def
% Create a context with private local VM.
% The .localfork operator does all the work, but we must ensure that
% .initlocaldicts gets called when the new context starts up.
/localfork { % <mark> <obj1> ... <objN> <proc>
% <stdin|null> <stdout|null>
% localfork <context>
.currentglobal true .setglobal 3 index
dup .proccheck not {
pop .setglobal /localfork cvx /typecheck signalerror
} if
{exec .initlocaldicts} aload pop
3 1 roll 3 packedarray cvx
4 1 roll 5 -1 roll pop .setglobal .localfork
} odef
% Fork a context that shares VM. The .fork operator creates an empty
% userparams dictionary for the context, but we still need to initialize
% this dictionary when the new context starts up.
/.postfork { % - .postfork -
% Initialize the user parameters.
savedlocaldicts /userparams get userparams .copydict readonly pop
} odef
/fork { % <mark> <obj1> ... <objN> <proc> fork <context>
.currentglobal false .setglobal 1 index
dup .proccheck not {
pop .setglobal /fork cvx /typecheck signalerror
} if
{exec .postfork} aload pop
3 1 roll 3 packedarray cvx
3 1 roll exch pop .setglobal .fork
} odef
% ------ Halftone phase ------ %
/sethalftonephase { % <x> <y> sethalftonephase -
-1 2 index 2 index .setscreenphase pop pop
} odef
/currenthalftonephase { % - currenthalftonephase <x> <y>
0 .currentscreenphase
} odef
% ------ Device-source images ------ */
.imagetypes 2 /.image2 load put
% ------ Device information ------ %
/.deviceinfodict mark
/Colors null /GrayValues null /RedValues null /GreenValues null
/BlueValues null /ColorValues null
.dicttomark readonly def
/deviceinfo { % - deviceinfo <dict>
currentdevice //.deviceinfodict .getdeviceparams .dicttomark
dup begin
/ColorValues .knownget {
0 le
{ currentdict /ColorValues undef }
{
% hack around devices that incorrect set GrayValues
Colors 3 eq { 1 } { GrayValues } ifelse
RedValues mul GreenValues mul BlueValues mul ColorValues ne
{ currentdict /GrayValues undef
currentdict /RedValues undef
currentdict /GreenValues undef
currentdict /BlueValues undef
} if
}
ifelse
} if
currentdict end readonly
} odef
% The current implementation allocates a 2-element array each time.
% Perhaps we should change this to 2 separate parameters for X and Y?
/.wtdict mark
/wtranslation null
.dicttomark readonly def
/wtranslation { % - wtranslation <x> <y>
currentdevice //.wtdict .getdeviceparams exch pop exch pop aload pop
} odef
currentdict /.wtdict .undef
% ------ View clipping ------ %
/rectviewclip { % <x> <y> <width> <height> rectviewclip -
% <numarray|numstring> rectviewclip -
newpath .rectappend viewclip
} odef