summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps')
-rw-r--r--Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps1198
1 files changed, 1198 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps b/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps
new file mode 100644
index 00000000000..93037388f8f
--- /dev/null
+++ b/Master/tlpkg/tlgs/Resource/Init/gs_lev2.ps
@@ -0,0 +1,1198 @@
+% Copyright (C) 2001-2012 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.
+%
+% Refer to licensing information at http://www.artifex.com or contact
+% Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
+% CA 94903, U.S.A., +1(415)492-9861, for further information.
+%
+
+% Initialization file for Level 2 functions.
+% When this is run, systemdict is still writable,
+% but (almost) everything defined here goes into level2dict.
+
+level2dict begin
+
+% ------ System and user parameters ------ %
+
+% User parameters must obey save/restore, and must also be maintained
+% per-context. We implement the former, and some of the latter, here
+% with PostScript code. NOTE: our implementation assumes that user
+% parameters change only as a result of setuserparams -- that there are
+% no user parameters that are ever changed dynamically by the interpreter
+% (although the interpreter may adjust the value presented to setuserparams)
+%
+% There are two types of user parameters: those which are actually
+% maintained in the interpreter, and those which exist only at the
+% PostScript level. We maintain the current state of both types in
+% a read-only local dictionary named userparams, defined in systemdict.
+% In a multi-context system, each context has its own copy of this
+% dictionary. In addition, there is a constant dictionary named
+% psuserparams where each key is the name of a user parameter that exists
+% only in PostScript and the value is a procedure to check that the value
+% is legal: setuserparams uses this for checking the values.
+% setuserparams updates userparams explicitly, in addition to setting
+% any user parameters in the interpreter; thus we can use userparams
+% to reset those parameters after a restore or a context switch.
+% NOTE: the name userparams is known to the interpreter, and in fact
+% the interpreter creates the userparams dictionary.
+
+% Check parameters that are managed at the PostScript level.
+/.checkparamtype { % <newvalue> <type> .checkparamtype <bool>
+ exch type eq
+} .bind def
+/.checksetparams { % <newdict> <opname> <checkdict>
+ % .checksetparams <newdict>
+ 2 .argindex {
+ % Stack: newdict opname checkdict key newvalue
+ 3 copy 3 1 roll .knownget {
+ exec not {
+ pop pop pop load /typecheck signalerror
+ } if
+ dup type /stringtype eq {
+ dup rcheck not {
+ pop pop pop load /invalidaccess signalerror
+ } if
+ } if
+ } {
+ pop
+ } ifelse pop pop
+ } forall pop pop
+} .bind def % not odef, shouldn't reset stacks
+
+% currentuser/systemparams creates and returns a dictionary in the
+% current VM. The easiest way to make this work is to copy any composite
+% PostScript-level parameters to global VM. Currently we have strings
+% as well as arrays. For arrays, we also need to copy any contents that
+% are in VM. Also copying string parameters insures the contents won't
+% be changed. Also be careful to preserve 'executable' state.
+/.copyparam { % <value> .copyparam <value'>
+ dup type /arraytype eq {
+ .currentglobal //true .setglobal exch
+ dup wcheck exch dup xcheck exch % original attributes
+ dup length array exch dup { % stack: destination_array original_array original_array
+ dup type /arraytype eq {
+ dup 2 index ne { % avoid recursion
+ .copyparam % recurse to handle composite array elements
+ } {
+ % this array self referenced, do it again (yuk!)
+ pop 1 index % get copy of destination array
+ } ifelse
+ } {
+ dup type /stringtype eq {
+ .copyparam
+ } if
+ }
+ ifelse 3 1 roll % keep arrays on top
+ } forall pop astore
+ exch { cvx } if % set executable state
+ exch not { readonly } if % set readonly attribute as original
+ exch .setglobal
+ } if
+ dup type /stringtype eq {
+ dup wcheck exch % save attr for setting readonly
+ .currentglobal //true .setglobal
+ 1 index length string exch .setglobal
+ copy exch not { readonly } if
+ } if
+} .bind def
+
+% Some user parameters are managed entirely at the PostScript level.
+% We take care of that here.
+systemdict begin
+/psuserparams 48 dict def
+/getuserparam { % <name> getuserparam <value>
+ /userparams .systemvar 1 .argindex get exch pop
+} odef
+% Fill in userparams (created by the interpreter) with current values.
+mark .currentuserparams
+counttomark 2 idiv {
+ userparams 3 1 roll put
+} repeat pop
+/.definepsuserparam { % <name> <value> .definepsuserparam -
+ psuserparams 3 copy pop
+ type cvlit /.checkparamtype cvx 2 packedarray cvx put
+ userparams 3 1 roll put
+} .bind def
+end
+/currentuserparams { % - currentuserparams <dict>
+ /userparams .systemvar dup length dict .copydict
+} odef
+% We break out setuserparams into a separate procedure so that setvmxxx
+% can use it without affecting the command in case of an error.
+/.setuserparams2 {
+ % Check that we will be able to set the PostScript-level
+ % user parameters.
+ /setuserparams /psuserparams .systemvar .checksetparams
+ % Set the C-level user params. If this succeeds, we know that
+ % the password check succeeded.
+ dup .setuserparams
+ % Now set the PostScript-level params.
+ % The interpreter may have adjusted the values of some of the
+ % parameters, so we have to read them back.
+ dup {
+ /userparams .systemvar 2 index known {
+ psuserparams 2 index known not {
+ pop dup .getuserparam
+ } if
+ .copyparam
+ % special protection for the security related parameters
+ [ /PermitFileReading /PermitFileWriting /PermitFileControl ]
+ { 2 index eq { % force all strings to readonly but make sure the
+ % array is in the correct VM space (local/global).
+ currentglobal exch dup gcheck setglobal
+ dup length array exch { readonly exch } forall astore
+ exch setglobal
+ } if
+ } forall
+ % protect top level of parameters that we copied
+ dup type dup /arraytype eq exch /stringtype eq or { readonly } if
+ /userparams .systemvar 3 1 roll .forceput % userparams is read-only
+ } {
+ pop pop
+ } ifelse
+ } forall
+ % A context switch might have occurred during the above loop,
+ % causing the interpreter-level parameters to be reset.
+ % Set them again to the new values. From here on, we are safe,
+ % since a context switch will consult userparams.
+ .setuserparams
+} .bind def
+/setuserparams { % <dict> setuserparams -
+ .setuserparams2
+} .bind odef
+% Initialize user parameters managed here.
+/JobName () .definepsuserparam
+
+% Restore must restore the user parameters.
+% (Since userparams is in local VM, save takes care of saving them.)
+/restore { % <save> restore -
+ //restore /userparams .systemvar .setuserparams
+} .bind odef
+
+% The pssystemparams dictionary holds some system parameters that
+% are managed entirely at the PostScript level.
+systemdict begin
+currentdict /pssystemparams known not {
+ /pssystemparams 40 dict readonly def
+} if
+/getsystemparam { % <name> getsystemparam <value>
+ //pssystemparams 1 .argindex .knownget { exch pop } { .getsystemparam } ifelse
+} odef
+end
+/currentsystemparams { % - currentsystemparams <dict>
+ mark .currentsystemparams //pssystemparams { } forall .dicttomark
+} odef
+/setsystemparams { % <dict> setsystemparams -
+ % Check that we will be able to set the PostScript-level
+ % system parameters.
+ dup pop % check # of args
+ /SAFETY .systemvar /safe get {
+ % SAFER mode disallows some changes
+ [ /GenericResourceDir /FontResourceDir /GenericResourcePathSep ] {
+ 2 copy .knownget {
+ exch //pssystemparams exch .knownget {
+ ne { /setsystemparams /invalidaccess signalerror } if
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } forall
+ } if
+ /setsystemparams //pssystemparams mark exch {
+ type cvlit /.checkparamtype cvx 2 packedarray cvx
+ } forall .dicttomark .checksetparams
+ % Set the C-level system params. If this succeeds, we know that
+ % the password check succeeded.
+ dup .setsystemparams
+ % Now set the PostScript-level params. We must copy local strings
+ % into global VM.
+ dup
+ { //pssystemparams 2 index known
+ { % Stack: key newvalue
+ .copyparam
+ % protect top level parameters that we copied
+ dup type dup /arraytype eq exch /stringtype eq or { readonly } if
+ //pssystemparams 3 1 roll .forceput % pssystemparams is read-only
+ }
+ { pop pop
+ }
+ ifelse
+ }
+ forall pop
+} .bind odef
+
+% Initialize the passwords.
+% NOTE: the names StartJobPassword and SystemParamsPassword are known to
+% the interpreter, and must be bound to noaccess strings.
+% The length of these strings must be max_password (iutil2.h) + 1.
+/StartJobPassword 65 string noaccess def
+/SystemParamsPassword 65 string noaccess def
+
+% Redefine cache parameter setting to interact properly with userparams.
+/setcachelimit {
+ { mark /MaxFontItem 2 .argindex .dicttomark setuserparams pop }
+ stopped
+ { /setcachelimit .systemvar $error /errorname get signalerror
+ } if
+} .bind odef
+/setcacheparams {
+ % The MaxFontCache parameter is a system parameter, which we might
+ % not be able to set. Fortunately, this doesn't matter, because
+ % system parameters don't have to be synchronized between this code
+ % and the VM.
+ counttomark 1 add copy setcacheparams
+ currentcacheparams % mark size lower upper
+ 3 -1 roll pop
+ /MinFontCompress 3 1 roll
+ /MaxFontItem exch
+ .dicttomark { setuserparams cleartomark } stopped {
+ /setcacheparams .systemvar $error /errorname get signalerror
+ } if
+} .bind odef
+
+% Add bogus user and system parameters to satisfy badly written PostScript
+% programs that incorrectly assume the existence of all the parameters
+% listed in Appendix C of the Red Book. Note that some of these may become
+% real parameters later: code near the end of gs_init.ps takes care of
+% removing any such parameters from ps{user,system}params.
+
+% psuserparams
+ /MaxFormItem 100000 .definepsuserparam
+ /MaxPatternItem 20000 .definepsuserparam
+ /MaxScreenItem 48000 .definepsuserparam
+ /MaxUPathItem 0 .definepsuserparam
+
+% File Access Permission parameters
+ .currentglobal //true .setglobal
+ /.checkFilePermitparams {
+ type /arraytype eq {
+ currentuserparams /LockFilePermissions get {
+ 5 { pop } repeat /setuserparams /invalidaccess signalerror
+ }{
+ % in addition to validating the value, ensure the value is read/only
+ dup { readonly exch } forall
+ .currentglobal exch dup gcheck .setglobal length array exch .setglobal
+ astore readonly
+ }
+ ifelse
+ } {
+ 5 { pop } repeat /setuserparams /typecheck signalerror
+ }
+ ifelse
+ //true
+ } .bind def
+% Initialize the File Permission access control to wide open
+% These will only be accessed via current/set userparams.
+% Values are a string containing multiple nul terminated path strings
+ /PermitFileReading dup [ (*) ] .definepsuserparam
+ psuserparams exch /.checkFilePermitparams load put
+ /PermitFileWriting dup [ (*) ] .definepsuserparam
+ psuserparams exch /.checkFilePermitparams load put
+ /PermitFileControl dup [ (*) ] .definepsuserparam
+ psuserparams exch /.checkFilePermitparams load put
+ .setglobal
+
+pssystemparams begin
+ /CurDisplayList 0 .forcedef
+ /CurFormCache 0 .forcedef
+ /CurInputDevice () .forcedef
+ /CurOutlineCache 0 .forcedef
+ /CurOutputDevice () .forcedef
+ /CurPatternCache 0 .forcedef
+ /CurUPathCache 0 .forcedef
+ /CurScreenStorage 0 .forcedef
+ /CurSourceList 0 .forcedef
+ /DoPrintErrors //false .forcedef
+ /JobTimeout 0 .forcedef
+ /LicenseID (LN-001) .forcedef % bogus
+ /MaxDisplayList 140000 .forcedef
+ /MaxFormCache 100000 .forcedef
+ /MaxImageBuffer 524288 .forcedef
+ /MaxOutlineCache 65000 .forcedef
+ /MaxPatternCache 100000 .forcedef
+ /MaxUPathCache 300000 .forcedef
+ /MaxScreenStorage 84000 .forcedef
+ /MaxSourceList 25000 .forcedef
+ /PrinterName product .forcedef
+ /RamSize 4194304 .forcedef
+ /WaitTimeout 40 .forcedef
+end
+
+% Define the procedures for handling comment scanning. The names
+% %ProcessComment and %ProcessDSCComment are known to the interpreter.
+% These procedures take the file and comment string and file as operands.
+/.checkprocesscomment {
+ dup //null eq {
+ pop //true
+ } {
+ dup xcheck {
+ type dup /arraytype eq exch /packedarraytype eq or
+ } {
+ pop //false
+ } ifelse
+ } ifelse
+} .bind def
+/ProcessComment //null .definepsuserparam
+psuserparams /ProcessComment {.checkprocesscomment} put
+(%ProcessComment) cvn {
+ /ProcessComment getuserparam
+ dup //null eq { pop pop pop } { exec } ifelse
+} bind def
+/ProcessDSCComment //null .definepsuserparam
+psuserparams /ProcessDSCComment {.checkprocesscomment} put
+/.loadingfont //false def
+(%ProcessDSCComment) cvn {
+ /ProcessDSCComment getuserparam
+ dup //null eq .loadingfont or { pop pop pop } { exec } ifelse
+} bind def
+
+% ------ Miscellaneous ------ %
+
+(<<) cvn % - << -mark-
+ /mark load def
+% (>> is defined primitively.)
+/languagelevel 2 def
+% When running in Level 2 mode, this interpreter is supposed to be
+% compatible with Adobe version 2017.
+/version (2017) readonly def
+
+% If binary tokens are supported by this interpreter,
+% set an appropriate default binary object format.
+/setobjectformat where
+ { pop
+ /RealFormat getsystemparam (IEEE) eq { 1 } { 3 } ifelse
+ /ByteOrder getsystemparam { 1 add } if
+ setobjectformat
+ } if
+
+% Aldus Freehand versions 2.x check for the presence of the
+% setcolor operator, and if it is missing, substitute a procedure.
+% Unfortunately, the procedure takes different parameters from
+% the operator. As a result, files produced by this application
+% cause an error if the setcolor operator is actually defined
+% and 'bind' is ever used. Aldus fixed this bug in Freehand 3.0,
+% but there are a lot of files created by the older versions
+% still floating around. Therefore, at Adobe's suggestion,
+% we implement the following dreadful hack in the 'where' operator:
+% If the key is /setcolor, and
+% there is a dictionary named FreeHandDict, and
+% currentdict is that dictionary,
+% then "where" consults only that dictionary and not any other
+% dictionaries on the dictionary stack.
+.wheredict /setcolor {
+ /FreeHandDict .where {
+ /FreeHandDict get currentdict eq {
+ pop currentdict /setcolor known { currentdict //true } { //false } ifelse
+ } {
+ .where
+ } ifelse
+ } {
+ .where
+ } ifelse
+} bind put
+
+% ------ Virtual memory ------ %
+
+/currentglobal % - currentglobal <bool>
+ /currentshared load def
+/gcheck % <obj> gcheck <bool>
+ /scheck load def
+/setglobal % <bool> setglobal -
+ /setshared load def
+% We can make the global dictionaries very small, because they auto-expand.
+/globaldict currentdict /shareddict .knownget not { 4 dict } if def
+/GlobalFontDirectory SharedFontDirectory def
+
+% VMReclaim and VMThreshold are user parameters.
+/setvmthreshold { % <int> setvmthreshold -
+ mark /VMThreshold 2 .argindex .dicttomark .setuserparams2 pop
+} odef
+/vmreclaim { % <int> vmreclaim -
+ dup 0 gt {
+ dup 2 le 1 index type /integertype eq and {
+ pop % ignore user requests for vmreclaim
+ % (reclaim will still happen controlled by vmthreshold)
+ }
+ { .vmreclaim } % let internal operator handle error conditions
+ ifelse
+ } {
+ % VMReclaim userparam controls enable/disable GC
+ mark /VMReclaim 2 index .dicttomark .setuserparams2 pop
+ } ifelse
+} odef
+-1 setvmthreshold
+
+% ------ IODevices ------ %
+
+/.getdevparams where {
+ pop /currentdevparams { % <iodevice> currentdevparams <dict>
+ .getdevparams .dicttomark
+ } odef
+} if
+/.putdevparams where {
+ pop /setdevparams { % <iodevice> <dict> setdevparams -
+ dup type /dicttype ne { /setdevparams .systemvar /typecheck signalerror } if
+ mark 1 index { } forall counttomark 2 add index
+ .putdevparams pop pop
+ } odef
+} if
+
+% ------ Job control ------ %
+
+serverdict begin
+
+% We could protect the job information better, but we aren't attempting
+% (currently) to protect ourselves against maliciousness.
+
+/.jobsave //null def % top-level save object
+/.jobsavelevel 0 def % save depth of job (0 if .jobsave is null,
+ % 1 otherwise)
+/.adminjob //true def % status of current unencapsulated job
+
+end % serverdict
+
+% Because there may be objects on the e-stack created since the job save,
+% we have to clear the e-stack before doing the end-of-job restore.
+% We do this by executing a 2 .stop, which is caught by the 2 .stopped
+% in .runexec; we leave on the o-stack a procedure to execute aftewards.
+%
+%**************** The definition of startjob is not complete yet, since
+% it doesn't reset stdin/stdout.
+/.startnewjob { % <exit_bool> <password_level>
+ % .startnewjob -
+ serverdict /.jobsave get dup //null eq { pop } { restore } ifelse
+ exch {
+ % Unencapsulated job
+ serverdict /.jobsave //null put
+ serverdict /.jobsavelevel 0 put
+ serverdict /.adminjob 3 -1 roll 1 gt put
+ } {
+ % Encapsulated job
+ pop
+ serverdict /.jobsave save put
+ serverdict /.jobsavelevel 1 put
+ .userdict /quit { stop } .bind put % CET 28-10 requires a procedure
+ } ifelse
+ % Reset the interpreter state.
+ clear cleardictstack
+ initgraphics
+ //false setglobal
+} bind def
+/.startjob { % <exit_bool> <password> <finish_proc>
+ % .startjob <ok_bool>
+ vmstatus pop pop serverdict /.jobsavelevel get eq
+ 2 .argindex .checkpassword 0 gt and {
+ exch .checkpassword exch count 3 roll count 3 sub { pop } repeat
+ cleardictstack
+ % Reset the e-stack back to the 2 .stopped in .runexec,
+ % passing the finish_proc to be executed afterwards.
+ 2 .stop
+ } { % Password check failed
+ pop pop pop //false
+ } ifelse
+} odef
+/startjob { % <exit_bool> <password> startjob <ok_bool>
+ % This is a hack. We really need some way to indicate explicitly
+ % to the interpreter that we are under control of a job server.
+ 1 .argindex type /booleantype ne {
+ /startjob .systemvar /typecheck signalerror
+ } if
+ { .startnewjob //true } .startjob
+} odef
+
+% The procedure to undo the job encapsulation
+/.endjob {
+ clear cleardictstack
+ serverdict /.jobsave get dup //null eq { pop } { restore } ifelse
+ serverdict /.jobsave //null put
+ 2 .vmreclaim % recover local and global VM
+} odef
+
+systemdict begin
+/quit { % - quit -
+ //systemdict begin serverdict /.jobsave get //null eq
+ { end //quit }
+ { /quit .systemvar /invalidaccess /signalerror load end exec }
+ ifelse
+} bind odef
+end
+
+% We would like to define exitserver as a procedure, using the code
+% that the Red Book says is equivalent to it. However, since startjob
+% resets the exec stack, we can't do this, because control would never
+% proceed past the call on startjob if the exitserver is successful.
+% Instead, we need to construct exitserver out of pieces of startjob.
+
+serverdict begin
+
+/exitserver { % <password> exitserver -
+ //true exch { .startnewjob } .startjob not {
+ /exitserver /invalidaccess signalerror
+ } if
+} bind def
+
+end % serverdict
+
+% ------ Compatibility ------ %
+
+% In Level 2 mode, the following replace the definitions that gs_statd.ps
+% installs in statusdict and serverdict.
+% Note that statusdict must be allocated in local VM.
+% We don't bother with many of these yet.
+
+/.dict1 { exch mark 3 1 roll .dicttomark } bind def
+
+currentglobal //false setglobal 25 dict exch setglobal begin
+currentsystemparams
+
+% The following do not depend on the presence of setpagedevice.
+/buildtime 1 index /BuildTime get def
+% Also define /buildtime in systemdict because Adobe does so and some fonts use it as ID
+systemdict /buildtime dup load put
+/byteorder 1 index /ByteOrder get def
+/checkpassword { .checkpassword 0 gt } bind def
+dup /DoStartPage known
+ { /dostartpage { /DoStartPage getsystemparam } bind def
+ /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def
+ } if
+dup /StartupMode known
+ { /dosysstart { /StartupMode getsystemparam 0 ne } bind def
+ /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def
+ } if
+%****** Setting jobname is supposed to set userparams.JobName, too.
+/jobname { /JobName getuserparam } bind def
+/jobtimeout { /JobTimeout getuserparam } bind def
+/ramsize { /RamSize getsystemparam } bind def
+/realformat 1 index /RealFormat get def
+dup /PrinterName known
+ { /setprintername { /PrinterName .dict1 setsystemparams } bind def
+ } if
+/printername
+ { currentsystemparams /PrinterName .knownget not { () } if exch copy
+ } bind def
+currentuserparams /WaitTimeout known
+ { /waittimeout { /WaitTimeout getuserparam } bind def
+ } if
+
+% The following do require setpagedevice.
+/.setpagedevice where { pop } { (%END PAGEDEVICE) .skipeof } ifelse
+/defaulttimeouts
+ { currentsystemparams dup
+ /JobTimeout .knownget not { 0 } if
+ exch /WaitTimeout .knownget not { 0 } if
+ currentpagedevice /ManualFeedTimeout .knownget not { 0 } if
+ } bind def
+/margins
+ { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse
+ } bind def
+/pagemargin
+ { currentpagedevice /PageOffset .knownget { 0 get } { 0 } ifelse
+ } bind def
+/pageparams
+ { currentpagedevice
+ dup /Orientation .knownget { 1 and ORIENT1 { 1 xor } if } { 0 } ifelse exch
+ dup /PageSize get aload pop 3 index 0 ne { exch } if 3 2 roll
+ /PageOffset .knownget { 0 get } { 0 } ifelse 4 -1 roll
+ } bind def
+/setdefaulttimeouts
+ { exch mark /ManualFeedTimeout 3 -1 roll
+ /Policies mark /ManualFeedTimeout 1 .dicttomark
+ .dicttomark setpagedevice
+ /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams
+ } bind def
+/.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def
+/setduplexmode { /Duplex .dict1 setpagedevice } bind def
+/setmargins
+ { exch 2 array astore /Margins .dict1 setpagedevice
+ } bind def
+/setpagemargin { 0 2 array astore /PageOffset .dict1 setpagedevice } bind def
+/setpageparams
+ { mark /PageSize 6 -2 roll
+ 4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore
+ /Orientation 5 -1 roll ORIENT1 { 1 xor } if
+ /PageOffset counttomark 2 add -1 roll 0 2 array astore
+ .dicttomark setpagedevice
+ } bind def
+/setresolution
+ { dup 2 array astore /HWResolution .dict1 setpagedevice
+ } bind def
+%END PAGEDEVICE
+
+% The following are not implemented yet.
+%manualfeed
+%manualfeedtimeout
+%pagecount
+%pagestackorder
+%setpagestackorder
+
+% -------- ICC manager -------- %
+% All color management is going
+% through ICC flow. We need
+% to have the default device
+% spaces gray, RGB and CMYK
+% defined by ICC profiles
+
+//systemdict /ICCProfilesDir .knownget {
+ % Set the directory sepcified by the command line option
+ mark exch /ICCProfilesDir exch .dicttomark .setuserparams2
+} {
+ % First see if the current value is valid so we don't have to guess
+ mark .currentuserparams .dicttomark /ICCProfilesDir get
+ (default_gray.icc) concatstrings {status} .internalstopped
+ {pop //false} if
+ {
+ pop pop pop pop % current value was OK. Just clean up stack
+ } {
+ % Search for valid (iccprofiles) directory as a sibling to (Resource)
+ % and set it as a default if found.
+ LIBPATH {
+ (Resource) search {
+ exch pop exch pop (iccprofiles) concatstrings
+ .file_name_separator concatstrings
+ dup (default_gray.icc) concatstrings status {
+ pop pop pop pop
+ mark exch /ICCProfilesDir exch .dicttomark .setuserparams2
+ exit
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } forall
+ } ifelse % if currentuserparams ICCProfilesDir
+} ifelse % ICCProfilesDir set in systemdict (command line option)
+
+mark % collect dict key value pairs for anything set in systemdict (command line options)
+[ /DefaultRGBProfile /DefaultGrayProfile /DefaultCMYKProfile /DeviceNProfile
+ /NamedProfile /SourceObjectICC /OverrideICC
+]
+{ dup //systemdict exch .knownget not {
+ pop % discard keys not in systemdict
+ } if
+} forall
+.dicttomark .setuserparams2
+
+pop % currentsystemparams
+
+% Flag the current dictionary so it will be swapped when we
+% change language levels. (See zmisc2.c for more information.)
+/statusdict currentdict def
+
+currentdict end
+/statusdict exch .forcedef % statusdict is local, systemdict is global
+
+% The following compatibility operators are in systemdict. They are
+% defined here, rather than in gs_init.ps, because they require the
+% resource machinery.
+
+/devforall { % <proc> <scratch> devforall -
+ exch {
+ 1 index currentdevparams
+ /Type .knownget { /FileSystem eq } { //false } ifelse
+ { exec } { pop pop } ifelse
+ } /exec load 3 packedarray cvx exch
+ (*) 3 1 roll /IODevice resourceforall
+} odef
+/devstatus { % <(%disk*%)> devstatus <searchable> <writable>
+ % <hasNames> <mounted> <removable> <searchOrder>
+ % <freePages> <size> true
+ % <string> devstatus false
+ dup length 5 ge {
+ dup 0 5 getinterval (%disk) eq {
+ dup /IODevice resourcestatus {
+ pop pop dup currentdevparams
+ dup /Searchable get
+ exch dup /Writeable get
+ exch dup /HasNames get
+ exch dup /Mounted get
+ exch dup /Removable get
+ exch dup /SearchOrder get
+ exch dup /Free get
+ exch /LogicalSize get
+ 9 -1 roll pop //true
+ } {
+ pop //false
+ } ifelse
+ } {
+ pop //false
+ } ifelse
+ } {
+ pop //false
+ } ifelse
+} odef
+
+% ------ Color spaces ------ %
+% gs_res.ps uses these entries in colorspacedict
+% to populate the ColorSpaceFamily resource, so we need
+% to add the supported spaces.
+%
+systemdict /colorspacedict get begin
+/CIEBasedA [] def
+/CIEBasedABC [] def
+/DevicePixel [] def
+/Indexed [] def
+/Pattern [] def
+/Separation [] def
+end
+
+% ------ CIE color rendering ------ %
+
+% Define findcolorrendering and a default ColorRendering ProcSet.
+
+/findcolorrendering { % <intentname> findcolorrendering
+ % <crdname> <found>
+ % Adobe interpreters report /findcolorrendering (literal name), not the
+ % operator itself, if an error occurs in findcolorrendering.
+ /findcolorrendering {
+ /ColorRendering /ProcSet findresource
+ 1 .argindex dup type /nametype eq { .namestring } if (.) concatstrings
+ 1 index /GetPageDeviceName get exec dup type /nametype eq { .namestring } if (.) concatstrings
+ 2 index /GetHalftoneName get exec dup type /nametype eq { .namestring } if
+ concatstrings concatstrings cvn % stack: intentname procset crdname
+ dup /ColorRendering resourcestatus {
+ pop pop exch pop exch pop //true
+ } {
+ pop /GetSubstituteCRD get exec //false
+ } ifelse
+ } .errorexec
+} odef
+
+5 dict dup begin
+
+/GetPageDeviceName { % - GetPageDeviceName <name>
+ currentpagedevice dup /PageDeviceName .knownget {
+ exch pop dup //null eq { pop /none } if
+ } {
+ pop /none
+ } ifelse
+} bind def
+
+/GetHalftoneName { % - GetHalftoneName <name>
+ currenthalftone /HalftoneName .knownget not { /none } if
+} bind def
+
+/GetSubstituteCRD { % <intentname> GetSubstituteCRD <crdname>
+ pop /DefaultColorRendering
+} bind def
+
+end
+% The resource machinery hasn't been activated, so just save the ProcSet
+% and let .fixresources finish the installation process.
+/ColorRendering exch def
+
+% Define setcolorrendering.
+
+/.colorrenderingtypes 5 dict def
+
+/setcolorrendering { % <crd> setcolorrendering -
+ dup /ColorRenderingType get
+ dup type /integertype ne {
+ /setcolorrendering .systemvar /typecheck signalerror
+ } if
+ //.colorrenderingtypes exch .knownget {
+ exec
+ } {
+ /setcolorrendering .systemvar /rangecheck signalerror
+ } ifelse
+} odef
+
+/.setcolorrendering1 where { pop } { (%END CRD) .skipeof } ifelse
+
+.colorrenderingtypes 1 {
+ % Adobe ProcSet "Adobe_AGM_Core 2.0 0" places an /Intent key into CRD's
+ dup /Intent .knownget {
+ //.renderingintentdict exch .knownget { .setrenderingintent } if
+ } if
+ dup .buildcolorrendering1 .setcolorrendering1
+} .bind put
+
+% Note: the value 101 in the next line must be the same as the value of
+% GX_DEVICE_CRD1_TYPE in gscrdp.h.
+.colorrenderingtypes 101 {
+ dup .builddevicecolorrendering1 .setdevicecolorrendering1
+} .bind put
+
+% sRGB output CRD, D65 white point
+mark
+/ColorRenderingType 1
+/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] readonly
+
+% Bradford Cone Space
+/MatrixPQR [ 0.8951 -0.7502 0.0389
+ 0.2664 1.7135 -0.0685
+ -0.1614 0.0367 1.0296] readonly
+
+/MatrixLMN [ 3.240449 -0.969265 0.055643
+ -1.537136 1.876011 -0.204026
+ -0.498531 0.041556 1.057229 ] readonly
+
+% Inverse sRGB gamma transform
+/EncodeABC [ { dup 0.00304 le
+ { 12.92321 mul }
+ { 1 2.4 div exp 1.055 mul 0.055 sub }
+ ifelse
+ } bind dup dup
+ ] readonly
+
+/WhitePoint [ 0.9505 1 1.0890 ] readonly % D65
+/BlackPoint [ 0 0 0 ] readonly
+
+% VonKries-like transform in Bradford Cone Space
+ /TransformPQR
+ % The implementations have been moved to C for performance.
+ [ { .TransformPQR_scale_WB0 } bind
+ { .TransformPQR_scale_WB1 } bind
+ { .TransformPQR_scale_WB2 } bind
+ ] readonly
+.dicttomark setcolorrendering
+
+%END CRD
+
+% Initialize a CIEBased color space for sRGB.
+/CIEsRGB [ /CIEBasedABC
+ mark
+ /DecodeLMN [ {
+ dup 0.03928 le { 12.92321 div } { 0.055 add 1.055 div 2.4 exp } ifelse
+ } bind dup dup ] readonly
+ /MatrixLMN [
+ 0.412457 0.212673 0.019334
+ 0.357576 0.715152 0.119192
+ 0.180437 0.072175 0.950301
+ ] readonly
+ /WhitePoint [0.9505 1.0 1.0890] readonly
+ .dicttomark readonly
+] readonly def
+
+% Special type to install
+% sRGB ICC profile color space
+/CIEsRGBICC [ /ICCBased
+ mark
+ /N 3
+ /DataSource (srgb)
+ /Alternate [/DeviceRGB]
+ /Name (srgb)
+ .dicttomark
+] def
+
+% Special type to install
+% sGray ICC profile color space
+/CIEsGRAYICC [ /ICCBased
+ mark
+ /N 1
+ /DataSource (sgray)
+ /Alternate [/DeviceGray]
+ /Name (sgray)
+ .dicttomark
+] def
+
+% ------ Painting ------ %
+
+%% We don't want to do any high level forms stuff if the source
+%% is PDF because :
+%% 1) Transparent forms are handled separately and we don't want to ge confused
+%% 2) PDF forms are too llikely to trip over the limitations in our support
+%% 3) Its highly unusual to find a PDF file which uses forms sensibly.
+%%
+%% So we have a special PDF version of execform which doesn't do high level forms.
+
+/.PDFexecform {
+ % This is a separate operator so that the stacks will be restored
+ % properly if an error occurs.
+ dup /Matrix get concat
+ dup /BBox get aload pop
+ exch 3 index sub exch 2 index sub rectclip
+ dup /PaintProc get
+ 1 index /Implementation known not {
+ 1 index dup /Implementation //null .forceput readonly pop
+ } if
+ exec
+}.bind odef
+
+/PDFexecform {
+ gsave {
+ .PDFexecform
+ } stopped grestore {stop} if
+} odef
+
+% A straightforward definition of execform that doesn't actually
+% do any caching.
+/.execform1 {
+ % This is a separate operator so that the stacks will be restored
+ % properly if an error occurs.
+ %% High level forms need the CTM before the Form Matrix is applied
+ /UNROLLFORMS where {/UNROLLFORMS get}{false}ifelse not
+ {matrix currentmatrix exch} if
+ dup /Matrix get concat
+ dup /BBox get aload pop
+ exch 3 index sub exch 2 index sub rectclip
+ dup /PaintProc get
+ 1 index /Implementation known not {
+ 1 index dup /Implementation //null .forceput readonly pop
+ } if
+ /UNROLLFORMS where {/UNROLLFORMS get}{false}ifelse not
+ %% [CTM] <<Form>> PaintProc .beginform -
+ {
+ %% First,, check to see if we have no /Implementation already defined (see above)
+ 1 index /Implementation get //null eq
+ {
+ %% We don't, so copy the form dictionary
+ 1 index 4 1 roll
+ %% tell devices we're starting a form, run the PaintProc, and then tell the devices we've finished
+ 3 -1 roll 2 index
+ .beginform exec
+
+ %% This is all horrible code to deal with illegal forms which leave junk on the operand stack
+ %% Starting from 1 (not 0, we don't want to look at the loop count) and going up to the
+ %% number of objects on the stack, check each object to see if its the Form dict (it is
+ %% *supposed* to be the top object after executing the PaintProc). I don't currently check to see if
+ %% the PaintProc ate the dict, but if there are extra objects, remove them and tell
+ %% the user.
+ %%
+ count 1 1 3 -1 roll {
+ dup index
+ dup type /dicttype eq {
+ /Implementation known {
+ 2 sub 0 1 3 -1 roll {
+ QUIET not {
+ (\n WARNING - Form PaintProc left operands on the stack after execution.\n This is technically illegal and these have been removed, \n if output is incorrect run again with -dUNROLLFORMS.\n) =
+ } if
+ pop pop
+ } for
+ exit
+ }if
+ } {
+ pop pop
+ }ifelse
+ } for
+
+ .endform
+ %% Ask devices if they have cached the form, and what ID to use if so
+ %% returning -1 means 'no ID'
+ .get_form_id dup -1 eq
+ {pop pop}
+ {
+ %% The form is cached with a specific ID. Make a dictionary (which we'll store in the
+ %% Form dictioanry using the /Implementation key).
+ 1 dict dup /FormID 4 -1 roll put
+ 1 index exch /Implementation exch .forceput readonly pop
+ }
+ ifelse
+ }
+ {
+ %% We have a (non-null) Implementation, get the dictionary and pull the
+ %% FormID key from it, then tell the device to use the stored form with the
+ %% specified key.
+ pop dup /Implementation get /FormID get .repeatform
+ }ifelse
+ }
+ {exec} ifelse
+} .bind odef % must bind .forceput
+
+/.formtypes 5 dict
+ dup 1 /.execform1 load put
+def
+
+/execform { % <form> execform -
+ gsave {
+ dup /FormType get //.formtypes exch get exec
+ } stopped grestore { stop } if
+} odef
+
+/.patterntypes 5 dict
+ dup 1 /.buildpattern1 load put
+def
+
+/makepattern { % <proto_dict> <matrix> makepattern <pattern>
+ dup type /dicttype eq {
+ % "<dict> makepattern" reports /typecheck on Adobe
+ /makepattern .systemvar /typecheck signalerror
+ } if
+ //.patterntypes 2 .argindex /PatternType get .knownget not {
+ /makepattern .systemvar /rangecheck signalerror
+ } if
+ .currentglobal //false .setglobal exch
+ % Stack: proto matrix global buildproc
+ 3 index dup length 1 add dict .copydict
+ % Stack: proto matrix global buildproc newdict
+ 3 index 3 -1 roll exec
+ % Stack: proto matrix global newdict instance
+ % Create an 'Implementation' entry for the pattern dict. The PRLM 3rd says
+ % this about the contents of Implementation: "The type and value of this
+ % entry are implementation-dependent." The CET (page 2 of 18-02f) expects
+ % that this entry be an array and that the second element of the array be a
+ % gstate. We put our pattern instance struct into the first element of the
+ % array.
+ 1 index /Implementation 3 -1 roll
+ .getCPSImode { gstate } { //null } ifelse 2 array astore
+ put % put Implementation into the pattern dict.
+ % Stack: proto matrix global newdict
+ readonly exch .setglobal exch pop exch pop
+} odef
+
+/setpattern { % [<comp1> ...] <pattern> setpattern -
+ { currentcolorspace 0 get /Pattern ne {
+ [ /Pattern currentcolorspace ] setcolorspace
+ } if setcolor
+ } stopped {
+ /setpattern .systemvar $error /errorname get signalerror
+ } if
+} odef
+
+% The following functions emulate the actions of findcmykcustomcolor and
+% setcustomcolor. These functions are described in Adobe's TN 5044. That
+% same document also says "The following "operators" are not defined in the
+% PostScript Language Reference Manual, but should be used as pseudo-operators
+% in your PostScript language output. Separation applications from Adobe
+% Systems and other vendors will redefine these convention operators to
+% separate your documents. Your application should conditionally define
+% procedures with these special names, as shown later in this document."
+%
+% We are providing these functions because we have found files created by
+% "QuarkXPress: pictwpstops filter 1.0" which produce bad shading dictionaries
+% if these operators are not defined.
+
+% Also we add a findrgbcustomcolor that was discovered in Adobe Illustrator
+% AI5 (Adobe Illustrator (R) Version 7.0 Full Prolog) ProcSet that allows
+% us to create Separation colorspace with a /DeviceRGB tint transform.
+
+% Conditionally disable the TN 5044 psuedo-ops if NO_TN5044 specified
+/NO_TN5044 where { pop (%END TN 5044 psuedo-ops) .skipeof } if
+
+% TN 5044 does not define the contents of the array. We are simply putting
+% the values given into an array. This is consistent with what we see when
+% testing with Adobe Distiller 6.0.
+% <cyan> <magenta> <yellow> <black> <key> findcmykcustomcolor <array>
+/findcmykcustomcolor { 5 array astore } bind def
+% The following isn't documented by Adobe, but was found in Adobe Illustrator (R)
+% Version 7.0 Full Prolog
+/findrgbcustomcolor { 4 array astore } bind def
+
+% Build a tint transform function for use by setcustomcolor. This function
+% is for a Separation color space which has either a DeviceCMYK base color space
+% (i.e. 1 input and 4 outputs) or a DeviceRGB colorspace (1 in, 3 out).
+% The input to buildcustomtinttransform is the array created by findcmykcustomcolor
+% and the length of the array is used to determine the alternate colorspace.
+% The resulting function for CMYK is:
+% { dup cyan mul exch dup magenta mul exch dup yellow mul exch black mul }
+% Where cyan, magenta, yellow, and black are values from the array.
+% For RGB, since the resulting function is:
+% { dup red mul exch dup green mul exch blue mul }
+/buildcustomtinttransform % <array> buildcustomtinttransform <function>
+{
+ dup length 5 eq {
+ % CMYK
+ [ /dup load 2 index 0 get /mul load
+ /exch load /dup load 6 index 1 get /mul load
+ /exch load /dup load 10 index 2 get /mul load
+ /exch load 13 index 3 get /mul load
+ ]
+ } {
+ % RGB is assumed
+ [ /dup load 2 index 0 get /mul load
+ /exch load /dup load 6 index 1 get /mul load
+ /exch load 9 index 2 get /mul load
+ ]
+ } ifelse
+ cvx bind exch pop % Make executable and remove the input array
+} bind def
+
+% Construct the colorspace array to be used by setcolorspace from the array
+% result of either findcmykcustomcolor or findrgbcustomcolor.
+/buildcolorspacearray % <array> buildcustomtinttransform <colorspace_array>
+{ % as with buildcustomtinttransform, the length of the array is used to
+ % determine the alternate colorspace
+ dup length 5 eq {
+ % Start building Separation colorspace with CMYK alternate
+ [ /Separation 2 index 4 get % Get separation name from array's key
+ /DeviceCMYK
+ 4 index //buildcustomtinttransform exec % build the tint transform function
+ ]
+ } {
+ [ /Separation 2 index 3 get % Get separation name from array's key
+ /DeviceRGB
+ 4 index //buildcustomtinttransform exec % build the tint transform function
+ ]
+ } ifelse
+ exch pop % remove the input array
+} bind def
+
+% Set a custom color based upon a tint and array which describes the custom
+% color. See findcmykcustomcolor. First we create and then set a Separation
+% colorspace. Then we set the specified color.
+% Note that older Adobe ProcSets apparently allow for 'null' as the tint
+% for some reason, so an alternate operational mode is tolerated:
+% null setcustomcolor -
+/setcustomcolor % <array> <tint> setcustomcolor -
+{ dup //null ne {
+ exch //buildcolorspacearray exec
+ setcolorspace % Set the Separation color space as current
+ setcolor % Set the tint as the current color
+ }
+ { pop pop } % 'null' as the tint is ignored. pop tint and array
+ ifelse
+} bind def
+
+% This proc is supposed to implement a version of overprinting. TN 5044 says
+% that this proc is not used by any shipping host-based application. We have
+% only found it being used in a proc set in files by Canvas from Deneba Systems.
+% Even their proc set does not actually do any overprinting. However their
+% files crash if this is not defined. Thus we have a copy of this proc but
+% we are simply checking for inputs being -1 and if so then we set the value
+% to 0.
+/setcmykoverprint {
+ 4 { dup -1 eq { pop 0 } if 4 1 roll } repeat setcmykcolor
+} bind def
+
+/separation_all [/Separation /All /DeviceCMYK { dup dup dup } bind ] readonly def
+
+% Collect the arguments into the image dictionary
+% <width> <height> <bits/sample> <matrix> <proc> args2dict <dict>
+/args2dict {
+ 10 dict begin
+ {1 0} 1
+ { /ImageType /Decode /DataSource /ImageMatrix /BitsPerComponent /Height /Width
+ } { exch def } forall
+ currentdict end
+} bind def
+
+% Prints (1-gray) on all separations.
+% <gray> setseparationgray -
+/setseparationgray {
+ //separation_all setcolorspace
+ 1 exch sub setcolor
+} bind def
+
+% Renders an image whose sample values specify the amount of the custom color.
+% <width> <height> <bits/sample> <matrix> <proc> <array> customcolorimage -
+/customcolorimage {
+ gsave
+ //buildcolorspacearray exec setcolorspace
+ //args2dict exec image
+ grestore
+} bind def
+
+% Renders an image on all process and custom color plates.
+% <width> <height> <bits/sample> <matrix> <proc>
+/separationimage {
+ gsave
+ //separation_all setcolorspace
+ //args2dict exec image
+ grestore
+} bind def
+
+{ /buildcustomtinttransform /buildcolorspacearray /separation_all /args2dict }
+{ currentdict exch undef } forall
+
+%END TN 5044 psuedo-ops
+
+end % level2dict