Está en la página 1de 4

% % % % % % % % % % % % % %

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 8954 2008-08-08 04:22:38Z ray $ % Initialization file for Display PostScript functions. % ------ Errors ------ % % These errors are only defined in DPS. { /invalidcontext /invalidid } { .registererror } forall % ------ 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 .systemvar /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 .systemvar /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 { newpath .rectappend viewclip } odef % <x> <y> <width> <height> rectviewclip % <numarray|numstring> rectviewclip -

También podría gustarte