220 lines
7.7 KiB
PostScript
220 lines
7.7 KiB
PostScript
% 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
|