% Copyright (C) 1994, 1995, 1997 Aladdin Enterprises. All rights reserved. % % This file is part of Aladdin Ghostscript. % % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author % or distributor accepts any responsibility for the consequences of using it, % or for whether it serves any particular purpose or works at all, unless he % or she says so in writing. Refer to the Aladdin Ghostscript Free Public % License (the "License") for full details. % % Every copy of Aladdin Ghostscript must include a copy of the License, % normally in a plain ASCII text file named PUBLIC. The License grants you % the right to copy, modify and redistribute Aladdin Ghostscript, but only % under certain conditions described in the License. Among other things, the % License requires that the copyright notice and this notice be preserved on % all copies. % pdf_draw.ps % PDF drawing operations (graphics, text, and images). % We don't handle the following PDF elements yet (identified by % page number in the reference manual): % style strings (63-64), except in a few known fonts % font descriptor resources (71-75), except for MissingWidth % text clipping modes (104) % What do these mean?? % We handle the following PDF 1.2 constructs: % gs operator (but not functions) /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal true .setglobal /pdfdict where { pop } { /pdfdict 100 dict def } ifelse GS_PDF_ProcSet begin pdfdict begin % For simplicity, we use a single interpretation dictionary for all % PDF graphics operations, even though this is too liberal. /drawopdict 100 dict def % ================================ Graphics ================================ % % ---------------- Functions ---------------- % /resolvefunction { % resolvefunction % Don't lose our place in PDFfile. PDFfile fileposition exch dup true resolvestream % The stream isn't positionable, so read all the data now. % Note that we only support FunctionType 0. % Stack: filepos fndict stream 1 index /Range get length 2 idiv 2 index /BitsPerSample get mul 2 index /Size get { mul } forall 7 add 8 idiv string 1 index exch readstring pop exch closefile % Stack: filepos fndict data exch dup length 1 add dict .copydict dup /DataSource 4 -1 roll put .buildfunction exch PDFfile exch setfileposition } bdef % ---------------- Graphics state management ---------------- % drawopdict begin % Graphics state stack /q { q } def /Q { Q } def % Graphics state setting /cm { cm } def /i { i } def /J { J } def /d { d } def /j { j } def /w { w } def /M { M } def /gs { gs } def end /gsparamdict mark /Type { pop } /SA { /setstrokeadjust 1 # } /OP { /setoverprint 1 # } /BG { dup /Identity eq { pop { } /setblackgeneration 1 # } { %****** DUMMY ****** pop } ifelse } /UCR { dup /Identity eq { pop { } /setundercolorremoval 1 # } { %****** DUMMY ****** pop } ifelse } /TR { dup /Identity eq { pop { } /settransfer 1 # } { %****** DUMMY ****** pop } ifelse } /HT { dup /Default eq { pop /.setdefaultscreen 0 # } { %****** DUMMY ****** pop } ifelse } /HTP { oget aload pop /sethalftonephase 2 # } .dicttomark readonly def /gs % gs - { Page /ExtGState rget { { oforce exch gsparamdict exch .knownget { exec } { pop } ifelse } forall } if } bdef % ---------------- Color setting ---------------- % /csncompdict mark /DeviceGray 1 /CalGray 1 /DeviceRGB 3 /CalRGB 3 /Lab 3 /DeviceCMYK 4 /CalCMYK 4 /Separation 1 .dicttomark readonly def /csrdict mark /DeviceGray { /DefaultGray Page /ColorSpace rget { exch pop } if } /CalGray { } /DeviceRGB { /DefaultRGB Page /ColorSpace rget { exch pop } if } /CalRGB { } /Lab { } /DeviceCMYK { } /CalCMYK { } /Indexed %****** SHOULD RESOLVE BASE SPACE ***** { dup 3 oget dup type /stringtype eq { pop } { % The color lookup table is a stream. % Get its contents. Don't lose our place in PDFfile. PDFfile fileposition 3 1 roll true resolvestream 1 index 2 get 1 add csncompdict 3 index 1 get dup type /arraytype eq { 0 get } if get mul string readstring pop % Stack: cspace filepos table 1 index 3 3 -1 roll put exch PDFfile exch setfileposition } ifelse } /Pattern { dup type /nametype ne { dup length 1 ge { 1 get resolvecolorspace /Pattern exch 2 array astore } if } if } /Separation %****** SHOULD RESOLVE ALTERNATIVE SPACE ****** { % Resolve the tintTransform function. dup 3 oget resolvefunction 1 index 3 3 -1 roll put } .dicttomark readonly def /csgray % csgray - { /DeviceGray resolvecolorspace dup /DeviceGray eq { pop } { exch 3 -1 roll } ifelse pop cvx exec } bdef /csrgb % csrgb - { /DeviceRGB resolvecolorspace dup /DeviceRGB eq { pop } { exch 3 -1 roll } ifelse pop cvx exec } bdef /cscmyk % cscmyk - { pop cvx exec } bdef /csresolve % csresolve { dup Page /ColorSpace rget { exch pop resolvecolorspace } { /undefined cvx signalerror } ifelse } bdef /resolvecolorspace { % resolvecolorspace dup dup type /arraytype eq { 0 get } if //csrdict exch .knownget { exec dup type /nametype ne { dup length 1 eq { 0 get } if } if } { csresolve } ifelse } bdef /cset % ... [- ] cset - { % We can't really make sc[n] and SC[N] work, because % the color space information isn't available at % conversion time; so we hack it by assuming that % all the operands on the stack are used, and that % if the top operand is a name, it's a Pattern resource. 1 index type /nametype eq { exch Page /Pattern rget { resolvepattern } { null } ifelse exch } if count 1 sub get exec } bdef /resolvepattern % resolvepattern { % Don't do the resolvestream now: just capture the data % from the file if necessary. dup length dict copy dup /FilePosition .knownget { 1 index /File get dup fileposition 3 1 roll % Stack: dict savepos pos file dup 3 -1 roll setfileposition dup 3 index /Length get string readstring pop % Stack: dict savepos file string 3 1 roll exch setfileposition 1 index /File 3 -1 roll put dup /FilePosition undef } if dup /PaintProc { false resolvestream pdfopdict .pdfrun } put } bdef drawopdict begin /g { /g { cs sc1 } csgray } bdef /rg { /rg { cs sc3 } csrgb } bdef /k { /k { cs sc4 } cscmyk } bdef /cs { csresolve cs } bdef /sc { { null sc1 sc2 sc3 sc4 sc5 } cset } bdef /scn /sc load def /G { /G { CS SC1 } csgray } bdef /RG { /RG { CS SC3 } csrgb } bdef /K { /K { CS SC4 } cscmyk } bdef /CS { csresolve CS } bdef /SC { { null SC1 SC2 SC3 SC4 SC5 } cset } bdef /SCN /SC load def end % ---------------- Paths ---------------- % drawopdict begin % Path construction /m { m } def /l { l } def /c { c } def /v { v } def /y { y } def /re { re } def /h { h } def % Path painting and clipping /n { n } def /S { S } def /s { s } def /f { f } def /f* { f* } def /B { B } def /b { b } def /B* { B* } def /b* { b* } def /W { W } def /W* { W* } def end % ---------------- XObjects ---------------- % /xobjectprocs mark % -proc- - /Image { DoImage } /Form { DoForm } .dicttomark readonly def /defaultdecodedict mark /DeviceGray [0 1] readonly /CalGray 1 index /DeviceRGB [0 1 0 1 0 1] readonly /CalRGB 1 index /Lab { 0 100 2 index 1 get /Range .knownget not { {-100 100 -100 100} } if aload pop 6 array astore readonly } bind /DeviceCMYK [0 1 0 1 0 1 0 1] readonly /CalCMYK 1 index /Separation [0 1] readonly .dicttomark readonly def /DoImage { dup length dict 1 index /ColorSpace knownoget { resolvecolorspace dup type /arraytype eq { dup length 1 eq { 0 get } if } if exch begin /ColorSpace exch def } { begin } ifelse /ImageType 1 def % Always define ImageMask appropriately. dup /ImageMask knownoget dup { and } if /ImageMask exch def /Width 2 copy oget def /Height 2 copy oget def /BitsPerComponent 2 copy oget def /Decode 2 copy knownoget not { % Decode is required for the PostScript image operators. ImageMask { [0 1] } { ColorSpace dup type /arraytype eq { 0 get } if dup /Indexed eq { pop [ 0 1 BitsPerComponent bitshift 1 sub ] } { defaultdecodedict exch get exec } ifelse } ifelse } if def /Interpolate 2 copy knownoget { def } { pop } ifelse /ImageMatrix Width 0 0 Height neg 0 Height 6 array astore def % Define DataSource as the width of the row buffer, % which is what is needed if we're writing PostScript. /DataSource Width BitsPerComponent mul ImageMask not { Decode length 2 idiv mul } if 7 add 8 idiv def % Even though we're going to read data, % pass false to resolvestream so that % it doesn't try to use Length (which may not be present). false resolvestream /Is_stream exch store currentdict end ID } bdef % Redefine Is, which constructs the data source for the image, % to retrieve the stream. (pdf_2ps.ps redefines Is to copy the data too.) userdict /Is_stream null put /Is % Is { Is_stream } bdef /DoForm { dup [ /pop load 2 index { false resolvestream pdfopdict .pdfrun } aload pop ] cvx /PaintProc exch put execform } bdef drawopdict begin /Do { PDFfile fileposition exch dup Page /XObject rget not { /undefined cvx signalerror } if exch pop dup /Subtype get xobjectprocs exch get exec PDFfile exch setfileposition } bdef end % ---------------- In-line images ---------------- % % Undo the abbreviations in an in-line image dictionary. % Note that these can appear as keys, values, or members of array values. % /I is ambiguous; we check specially for it below. /unabbrevdict mark % Top-level dictionary keys /BPC /BitsPerComponent /CS /ColorSpace /D /Decode /DP /DecodeParms /F /Filter /H /Height /IM /ImageMask /W /Width % Values /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CC /CalCMYK /CCF /CCITTFaxDecode /CG /CalGray /CR /CalRGB /DCT /DCTDecode /CMYK /DeviceCMYK /G /DeviceGray /RGB /DeviceRGB /I /Indexed /LZW /LZWDecode /RL /RunLengthDecode .dicttomark readonly def /unabbrev % unabbrev { dup type /nametype eq { unabbrevdict 1 index .knownget { exch pop } if } { dup type /arraytype eq { dup 0 1 2 index length 1 sub { 2 copy get unabbrev put dup } for pop } if } ifelse } bdef drawopdict begin /BI { mark } bdef /ID { counttomark { counttomark 1 roll dup /I eq { pop /Interpolate } { unabbrev } ifelse } repeat /File PDFsource .dicttomark DoImage PDFsource token pop /EI ne { /ID cvx /syntaxerror signalerror } if } bdef end % ================================ Text ================================ % drawopdict begin % Text control /BT { BT } def /ET { ET } def /Tc { Tc } def /TL { TL } def /Tr { Tr } def /Ts { Ts } def /Tw { Tw } def /Tz { Tz } def % Text positioning /Td { Td } def /TD { TD } def /Tm { Tm } def /T* { T* } def % Text painting /Tj { Tj } def /' { ' } def /" { " } def /TJ { mark exch aload pop TJ } def end end % pdfdict end % GS_PDF_ProcSet .setglobal .