PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/share/ghostscript/Resource/Init
Viewing File: /usr/share/ghostscript/Resource/Init/gs_lev2.ps
% Copyright (C) 2001-2019 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., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, 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 % 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 odef % 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 /exec load 3 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 exec % 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 } executeonly { pop pop } ifelse } executeonly 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 executeonly odef % must be bound and hidden for .forceput /setuserparams { % <dict> setuserparams - {.setuserparams2} stopped {/setuserparams load $error /errorname get signalerror} if } .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 /exec load 3 packedarray cvx } forall .dicttomark //.checksetparams exec % 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 } executeonly { pop pop } ifelse } executeonly forall pop } .bind executeonly 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 dup /CurDisplayList 0 .forceput dup /CurFormCache 0 .forceput dup /CurInputDevice () .forceput dup /CurOutlineCache 0 .forceput dup /CurOutputDevice () .forceput dup /CurPatternCache 0 .forceput dup /CurUPathCache 0 .forceput dup /CurScreenStorage 0 .forceput dup /CurSourceList 0 .forceput dup /DoPrintErrors //false .forceput dup /JobTimeout 0 .forceput dup /LicenseID (LN-001) .forceput % bogus dup /MaxDisplayList 140000 .forceput dup /MaxFormCache 100000 .forceput dup /MaxImageBuffer 524288 .forceput dup /MaxOutlineCache 65000 .forceput dup /MaxPatternCache 100000 .forceput dup /MaxUPathCache 300000 .forceput dup /MaxScreenStorage 84000 .forceput dup /MaxSourceList 25000 .forceput dup /PrinterName product .forceput dup /RamSize 4194304 .forceput /WaitTimeout 40 .forceput % 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 exec} put (%ProcessComment) cvn { /ProcessComment getuserparam dup //null eq { pop pop pop } { exec } ifelse } bind def /ProcessDSCComment //null .definepsuserparam psuserparams /ProcessDSCComment {//.checkprocesscomment exec} 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} stopped {pop /setvmthreshold load $error /errorname get signalerror} {pop} ifelse } 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} stopped {pop /vmreclaim load $error /errorname get signalerror} {pop} ifelse } ifelse } .bind executeonly 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 executeonly 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 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. % convenience function to make a dictionary from an object and a key /.pair2dict { 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 //.pair2dict exec setsystemparams } bind def } if dup /StartupMode known { /dosysstart { /StartupMode getsystemparam 0 ne } bind def /setdosysstart { { 1 } { 0 } ifelse /StartupMode //.pair2dict exec 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 //.pair2dict exec 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 /setduplexmode { /Duplex //.pair2dict exec setpagedevice } bind def /setmargins { exch 2 array astore /Margins //.pair2dict exec setpagedevice } bind def /setpagemargin { 0 2 array astore /PageOffset //.pair2dict exec 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 { count 1 lt { /setresolution /stackunderflow signalerror } if dup type dup /integertype eq exch /realtype eq or not { /setresolution /typecheck signalerror } if dup 2 array astore /HWResolution //.pair2dict exec { setpagedevice } stopped { pop /setresolution $error /errorname get signalerror } if } 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 exec {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 currentdict exch /statusdict exch .forceput % 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 % Special type to install % e-sRGB ICC profile color space /CIEesRGBICC [ /ICCBased mark /N 3 /DataSource (esrgb) /Alternate [/DeviceRGB] /Name (esrgb) .dicttomark ] def % Special type to install % rommRGB ICC profile color space /CIErommRGBICC [ /ICCBased mark /N 3 /DataSource (rommrgb) /Alternate [/DeviceRGB] /Name (rommrgb) .dicttomark ] def % ------ Painting ------ % % 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 } executeonly 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 } executeonly 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 executeonly 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 executeonly 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 executeonly 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 executeonly 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 eq { pop pop }{ % Check that the tint is a number between 0 and 1 dup type dup /integertype eq exch /realtype eq or not { /setcustomcolor /typecheck cvx signalerror } if dup 1 le not { /setcustomcolor /rangecheck cvx signalerror } if dup 0 ge not { /setcustomcolor /rangecheck cvx signalerror } if % The array is supposed to be the result of fundcmykcustomcolor. Our % implementation just pushes all the arguments into the array and that's % what buildcolorspacearray expects. So check that now. % Starting with the first N-1 elemenst which must be numbers where 0 <= x <= 1 1 index 0 1 2 index length 2 sub { 1 index exch get dup type dup /integertype eq exch /realtype eq or not { /setcustomcolor /typecheck cvx signalerror } if dup 1 le not { /setcustomcolor /rangecheck cvx signalerror } if 0 ge not { /setcustomcolor /rangecheck cvx signalerror } if } for % Finally, check the last element of the array, which must be a string. dup length 1 sub get type /stringtype eq not { /setcustomcolor /typecheck cvx signalerror } if exch //buildcolorspacearray exec setcolorspace % Set the Separation color space as current setcolor % Set the tint as the current color } ifelse } bind executeonly 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 % undefine things defined in this file and not referenced elsewhere [ /.checkprocesscomment /.pair2dict /.setcolorrendering1 /.checkparamtype /.checksetparams ] {level2dict exch .forceundef} forall