219 lines · 7.7 KB · Text
RawDownload
%    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