You are on page 1of 34

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

Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861.

% $Id: pdf_draw.ps 9850 2009-07-09 00:28:02Z alexcher $ % pdf_draw.ps % PDF drawing operations (graphics, text, and images). /.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 ---------------- % % % % % Note that resolvefunction converts a PDF Function to a PostScript Function; resolve*fnproc converts a PDF function to a PostScript procedure. We need to process all required and optional parameters to resolve any use of indirect references.

/fnrdict mark 0 { .resolvefn0 } 2 { .resolvefn2 } 3 { .resolvefn3 } 4 { .resolvefn4 } .dicttomark readonly def /.resolvefn0 { dup length 1 add dict .copydict % make room for DataSource % now resolve any indirect references dup /Size 2 copy knownoget { put } { pop pop } ifelse dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse dup /Order 2 copy knownoget { put } { pop pop } ifelse dup /Encode 2 copy knownoget { put } { pop pop } ifelse dup /Decode 2 copy knownoget { put } { pop pop } ifelse % Don't lose our place in PDFfile. PDFfile fileposition exch dup //true resolvestream % The stream isn't positionable, so read all the data now. % 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 dup 65535 le { string 1 index exch readstring pop } { 1 index exch () /SubFileDecode filter /ReusableStreamDecode filter } ifelse exch closefile % Stack: filepos fndict data exch dup /DataSource 4 -1 roll put exch PDFfile exch setfileposition } bdef /.resolvefn2 { dup length dict .copydict dup /C0 2 copy knownoget { put } { pop pop } ifelse dup /C1 2 copy knownoget { put } { pop pop } ifelse dup /N 2 copy knownoget { put } { pop pop } ifelse } bdef /.resolvefn3 { dup length dict .copydict dup /Bounds 2 copy knownoget { put } { pop pop } ifelse dup /Encode 2 copy knownoget { put } { pop pop } ifelse dup /Functions 2 copy oget mark exch dup { oforce .resolvefn } forall counttomark -1 roll astore exch pop put } bdef /.resolvefn4 { PDFfile fileposition exch % filepos fndict dup true resolvestream % filepos fndict stream exch dup length dict copy % filepos stream fndict2 dup /Function undef % filepos stream fndict2 exch dup token not { () /rangecheck cvx signalerror } if exch token { /rangecheck cvx signalerror } if % Use .bind to avoid idiom recognition. .bind 1 index /Function 3 -1 roll put exch PDFfile exch setfileposition } bdef /.resolvefn { % <fndict> .resolvefn <fndict'> dup length dict .copydict dup /Domain 2 copy knownoget { put } { pop pop } ifelse dup /Range 2 copy knownoget { put } { pop pop } ifelse dup /FunctionType oget //fnrdict exch get exec } bdef /resolvefunction { % <fndict> resolvefunction <function> .resolvefn PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Functi on: ) print dup === flush } if } if } bdef

/resolvefnproc { % <fndict> resolvefnproc <proc> resolvefunction .buildfunction } bdef /resolveidfnproc { % <fndict> resolveidfnproc <proc> dup /Identity eq { pop { } } { resolvefnproc } ifelse } bdef /resolvedefaultfnproc { % <fndict> <default> resolved'fnproc <proc> 1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse } bdef % ---------------- Shadings ---------------- % /shrdict mark /BBox { dup dup dup aload pop normrect_elems 5 -1 roll astore } bind /ColorSpace { resolvecolorspace } bind /Function { dup type /dicttype eq { resolvefunction } { [ exch { oforce resolvefunction } forall ] } ifelse } bind .dicttomark readonly def /resolveshading { % <shadingstream> resolveshading <shading> dup /.shading_dict .knownget { exch pop dup /ShadingType get 4 ge { dup /DataSource get 0 setfileposition } if } { dup PDFfile fileposition exch mark exch { oforce //shrdict 2 index .knownget { exec } if } forall .dicttomark dup /ShadingType get 4 ge { dup dup true resolvestream % Make a reusable stream so that the shading doesn't % reposition PDFfile at unexpected times. /ReusableStreamDecode filter /DataSource exch put } if exch PDFfile exch setfileposition dup 3 1 roll /.shading_dict exch put } ifelse } bdef /resolvesh { % <shname> resolvesh <shading> % <shname> resolvesh <null> Page /Shading rget { resolveshading } { null }ifelse

} bdef % ---------------- Halftones ---------------- % /spotfunctions mark /Round { abs exch abs 2 copy add 1 le { dup mul exch dup mul add 1 exch sub } { 1 sub dup mul exch 1 sub dup mul add 1 sub } ifelse } /Diamond { abs exch abs 2 copy add .75 le { dup mul exch dup mul add 1 exch sub } { 2 copy add 1.23 le { .85 mul add 1 exch sub } { 1 sub dup mul exch 1 sub dup mul add 1 sub } ifelse } ifelse } /Ellipse { abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt { pop dup mul exch .75 div dup mul add 4 div 1 exch sub } { dup 1 gt { pop 1 exch sub dup mul exch 1 exch sub .75 div dup mul add 4 div 1 sub } { .5 exch sub exch pop exch pop } ifelse } ifelse } /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub } /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub } /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub } /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub } /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub } /Line { exch pop abs neg } /LineX { pop } /LineY { exch pop } /Square { abs exch abs 2 copy lt { exch } if pop neg } /Cross { abs exch abs 2 copy gt { exch } if pop neg } /Rhomboid { abs exch abs 0.9 mul add 2 div } /DoubleDot { 2 {360 mul sin 2 div exch } repeat add } /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg } /SimpleDot { dup mul exch dup mul add 1 exch sub } /InvertedSimpleDot { dup mul exch dup mul add 1 sub } /CosineDot { 180 mul cos exch 180 mul cos add 2 div } /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add } /InvertedDouble { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg } .dicttomark readonly def /htrdict mark 1 { .resolveht1 } 5 { .resolveht5 }

% We don't support types 6, 10, or 16 yet. .dicttomark readonly def /.resolveht1 { mark exch { oforce 1 index /SpotFunction eq { dup type /nametype eq { //spotfunctions exch get } { resolvefnproc } ifelse } { 1 index /TransferFunction eq { resolveidfnproc } if } ifelse } forall .dicttomark } bdef /.resolveht5 { mark exch { oforce dup type /dicttype eq { resolvehalftone } if } forall .dicttomark } bdef /resolvehalftone { % <dict> resolvehalftone <halftone> dup /HalftoneType get dup //htrdict exch .knownget { exch pop exec } { (\n\n **** Unsupported HalftoneType ) pdfformaterror =string cvs pdfformaterror (. ***\n\n) pdfformaterror /resolvehalftone cvx /unregistered signalerror } ifelse } bdef % ---------------- Graphics state management ---------------- % /cmmatrix matrix def drawopdict begin % Graphics state stack /q { q } def /Q { Q } def % Graphics state setting /cm { //cmmatrix astore .getpath exch concat newpath { exec } forall % If inside a BT/ET block, we need to update the TextSaveMatrix currentdict /TextSaveMatrix .knownget { //cmmatrix exch dup concatmatrix pop } if } bdef /i { 1 .min setflat } bdef /J /setlinecap load def /d /setdash load def /j /setlinejoin load def /w /setlinewidth load def /M { 1 .max setmiterlimit } bdef /gs { gs } def

end % Each entry in this dictionary is % <gsres> <value> -proc- <gsres> /gsbg { /BGDefault load resolvedefaultfnproc setblackgeneration } bdef /gsucr { /UCRDefault load resolvedefaultfnproc setundercolorremoval } bdef /gstr { dup type /arraytype eq { { oforce /TRDefault load resolvedefaultfnproc } forall setcolortransfer } { /TRDefault load resolvedefaultfnproc settransfer } ifelse } bdef /gsparamdict mark /SA { setstrokeadjust } /OP { 1 index /op known not { dup op } if OP } % The PDF 1.3 specification says that the name /Default is only % recognized for {BG,UCR,TR}2. However, PDF 1.3 files produced % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default % with the older keys, so we have to implement this. /BG { 1 index /BG2 known { pop } { gsbg } ifelse } /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse } /TR { 1 index /TR2 known { pop } { gstr } ifelse } /HT { dup /Default eq { pop .setdefaulthalftone } { %****** DOESN'T IMPLEMENT THE STREAM CASE YET ****** resolvehalftone sethalftone } ifelse % the transfer function may dependent on the halftone, so make sure % it is set if included in the graphic state (otherwise this is % subject to order of a dictionary forall, which is unpredictable) dup /TR2 .knownget { dup /Default eq { oforce gsparamdict /TR2 get exec } { pop } ifelse } { dup /TR .knownget { /dup /Default eq { oforce gsparamdict /TR get exec } { pop } ifelse } if } ifelse } /HTP { % HTP may be present even if this isn't a DPS interpreter. /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse } % PDF 1.3 /Font { aload pop Tf } /LW { setlinewidth } /LC { setlinecap } /LJ { setlinejoin } /ML { 1 .max setmiterlimit } /D { aload pop setdash } /RI { ri } /op { op } /OPM { OPM }

/BG2 { gsbg } /UCR2 { gsucr } /TR2 { gstr } /FL { 1 .min setflat } /SM { % SM may be present even if this is only a Level 2 interpreter. /setsmoothness where { pop setsmoothness } { pop } ifelse } % PDF 1.4 % All of these require the "transparency" feature in the interpreter. /ca { ca } /CA { CA } /SMask { gssmask } /AIS { AIS } /BM { BM } /TK { TK } .dicttomark readonly def /gs { % <gsres> gs Page /ExtGState rget { % We keep the dictionary on the stack during the forall so that % keys that interact with each other have access to it. dup { oforce exch gsparamdict exch .knownget { exec } { pop } ifelse } forall pop } if } bdef % ------ Transparency support ------ % /gssmask { dup /None eq 1 index //null eq or PDFusingtransparency not or { pop null } { % Preprocess the SMask value into a parameter dictionary for % .begintransparencymaskgroup, with added /BBox and /Draw keys. mark exch % Stack: mark smaskdict dup /S oget /Subtype exch 3 2 roll % Stack: mark ... smaskdict dup /BC knownoget { dup /Background exch 4 2 roll gsave //nodict begin 1 index /G oget /Group oget /CS knownoget { resolvecolorspace dup setgcolorspace csput } if aload pop setcolor [ currentgray ] end grestore /GrayBackground exch 3 2 roll } if dup /TR knownoget { dup /Identity eq { pop } { resolvefnproc /TransferFunction exch 3 2 roll } ifelse } if dup /G oget dup /BBox oget /BBox exch 4 2 roll /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll pop .dicttomark } ifelse SMask } bdef

% Functions specific to the Device* colorspaces to force the switch to % the Device* colorspace so that the SMask will not get a CIEBased* colorspace % in the case when UseCIEColor changes the Device* colorspace to something else. % Also see the logic in pdf_main.ps:pdfopen that similarly defines these resourc es. /forceDefaultCS << { currentcolorspace setcolorspace % this will switch to Device colorspace } bind /DeviceGray exch /DeviceRGB 1 index /DeviceCMYK 1 index >> def % This procedure is called to actually render the soft mask. /.execmaskgroup { % <masknum> <paramdict> <formdict> .execmaskgroup % Save our place in PDFfile. Do not use gsave-grestore when creating % a soft mask with .begintransparencygroup because high level devices % need to modify the graphic state by storing the soft mask ID. % Save the ExtGState (//nodict begin) BEFORE changing the colorspace mark currentcolor counttomark dup 4 add exch roll pop currentcolorspace 4 1 roll .getuseciecolor 4 1 roll //nodict begin PDFfile fileposition 4 1 roll % We have to select the group's color space so that the % background color will be interpreted correctly. % [save/restore]DefaultCS make sure that the SMask logic sees % the Device* spaces, not CIEBased* that UseCIEColor may have % established. false .setuseciecolor % SMask gets processed without UseCIEColor dup /Group oget /CS knownoget { resolvecolorspace dup setgcolorspace csput //true % use currentcolorspace } { % inheriting the colorspace -- make sure Device* spaces are not CIEBased forceDefaultCS currentcolorspace 0 get .knownget { exec } if //false % no defined colorspace } ifelse 3 -1 roll dup /BBox get aload pop .begintransparencymaskgroup { dup /Resources knownoget { oforce } { 0 dict } ifelse exch false resolvestream .execgroup .endtransparencymask } stopped { .discardtransparencymask stop } if PDFfile exch setfileposition .setuseciecolor setcolorspace setcolor end % restore colorspace, color and ExtGState (end) } bdef % Paint a Form+Group XObject, either for a transparency mask or for a Do. /.execgroup { % <resdict> <stream> .execgroup gsave //nodict begin newpath null SMask 1 .setopacityalpha 1 .setshapealpha /Compatible .setblendmode % Execute the body of the Form, similar to DoForm. pdfopdict .pdfruncontext end grestore } bdef

/.beginformgroup { % groupdict bbox .beginformgroup exch mark exch % bbox mark groupdict dup /CS knownoget { resolvecolorspace setgcolorspace } if dup /I knownoget { /Isolated exch 3 2 roll } if dup /K knownoget { /Knockout exch 3 2 roll } if pop .dicttomark % Stack: bbox paramdict exch aload pop .begintransparencygroup } bdef % .paintgroupform implements the Form PaintProc in the case where the % Form XObject dictionary includes a Group key. See .paintform below. /.paintgroupform { % <resdict> <stream> <formdict> .paintgroupform dup /Group oget exch /BBox oget % Stack: resdict stream groupdict bbox .beginformgroup { .execgroup } stopped { .discardtransparencygroup stop } if .endtransparencygroup } bdef % Make an ImageType 103 (soft-masked) image. /makesoftmaskimage { % <datasource> <imagemask> <SMask> makesoftmaskimage % <datasource> <imagemask>, updates currentdict = % imagedict % See the ImageType 3 case of makemaskimage below. % SMask is a stream, another Image XObject. % Stack: datasource imagemask(false) smaskstreamdict PDFfile fileposition exch dup /Matte knownoget { /Matte exch def } if dup length dict makeimagedict pop % In order to prevent the two data sources from being % aliased, we need to make at least one a reusable stream. % We pick the mask, since it's smaller (in case we need to % read all its data now). % Stack: datasource imagemask(false) savedpos % maskdict is currentdict /DataSource DataSource mark /Intent 1 /AsyncRead true .dicttomark .reusablestreamdecode def PDFfile exch setfileposition currentdict end currentdict end 5 dict begin /ImageType 103 def /DataDict exch def dup /InterleaveType 3 put DataDict /Matte knownoget { /Matte exch def } if AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def /ColorSpace DataDict /ColorSpace get def } bdef % ---------------- Color setting ---------------- % /01_1 [0 1] readonly def

/01_3 [0 1 0 1 0 1] readonly def /01_4 [0 1 0 1 0 1 0 1] readonly def % The keys here are resolved (PostScript, not PDF) color space names. /csncompdict 8 dict begin /DeviceGray { pop 1 } bdef /DeviceRGB { pop 3 } bdef /DeviceCMYK { pop 4 } bdef /CIEBasedA { pop 1 } bdef /CIEBasedABC { pop 3 } bdef /ICCBased { 1 oget /N oget } bdef /Separation { pop 1 } bdef /DeviceN { 1 oget length } bdef currentdict end readonly def /csrdict 13 dict begin /DeviceGray { } bdef /DeviceRGB { } bdef /DeviceCMYK { } bdef /CalGray { 1 oget 6 dict begin dup /Gamma knownoget { /exp load 2 packedarray cvx /DecodeA exch def } if dup /BlackPoint knownoget { /BlackPoint exch def } if dup /WhitePoint knownoget { dup /WhitePoint exch def dup /MatrixA exch def /RangeLMN [ 3 2 roll { 0 exch } forall ] def } if /PDFColorSpace exch def [ /CIEBasedA currentdict end ] } bdef /CalRGB { 1 oget 6 dict begin dup /Gamma knownoget { [ exch { /exp load 2 packedarray cvx } forall ] /DecodeABC exch def } if dup /Matrix knownoget { /MatrixABC exch def } if dup /BlackPoint knownoget { /BlackPoint exch def } if dup /WhitePoint knownoget { /WhitePoint exch def } if /PDFColorSpace exch def [ /CIEBasedABC currentdict end ] } bdef /CalCMYK { pop /DeviceCMYK } bdef % not defined by Adobe

/Lab { 1 oget 6 dict begin dup /Range knownoget not { [-100 100 -100 100] } if [0 100 null null null null] dup 2 4 -1 roll putinterval /RangeABC exch def /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def /MatrixABC [1 1 1 1 0 0 0 0 -1] def dup /BlackPoint knownoget { /BlackPoint exch def } if dup /WhitePoint knownoget { /WhitePoint exch def } { ( **** Warning: Lab colorspace is missing WhitePoint.\n)

pdfformaterror /WhitePoint [0.9505 1 1.089] def } ifelse % scaling function g() for DecodeLMN construction { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } /DecodeLMN [ % Store white point implicitly inside procedures. [ 3 index aload pop WhitePoint 0 get /mul .systemvar ] cvx bind [ 4 index aload pop WhitePoint 1 get /mul .systemvar ] cvx bind [ 5 index aload pop WhitePoint 2 get /mul .systemvar ] cvx bind ] def pop /PDFColorSpace exch def [ /CIEBasedABC currentdict end ] } bdef /ICCBased { dup 1 get type /dicttype ne { % don't resolve more than once PDFfile fileposition exch dup dup 1 oget mark exch { oforce } forall .dicttomark dup dup true resolvestream /ReusableStreamDecode filter /DataSource exch put 1 exch put exch PDFfile exch setfileposition % Resolve alternate color space dup 1 get % Get colorspace dictionary dup /Alternate .knownget % Check for alternate color space { oforce resolvecolorspace /Alternate exch put } % resolve and replace { pop } % remove colorspace dictionary ifelse } if } bdef /Separation { aload pop exch oforce resolvecolorspace % Contrary to PDF manuals up to v.1.5, Acrobat Distiller 3.01 % can use /Identity name here instead of a function. exch oforce resolveidfnproc 4 array astore } bdef /DeviceN { [ exch aload pop ] % Copy into a new array dup dup 1 oget % Resolve Names array [ exch { oforce } forall ] % resolve each of the names 1 exch put dup dup 2 oget resolvecolorspace 2 exch put dup dup 3 oget resolvefnproc 3 exch put dup length 4 gt { % Check for attributes dict dup dup 4 oget % devn_array devn_array attr_dict dup /Colorants knownoget % Check for Colorants Dict { % Create a new attribute dict with only a Colorants dict entry. % Resolve all of the Colorant dict entries. This is needed % to prevent a conflict if we attempt to resolve the tint % transform functions of the Colorant color spaces multiple % times. exch pop % Remove old attributes dict << exch % Start new attributes dict % Build new Colorants dict with resolved entries

<< exch { oforce resolvecolorspace } forall >> /Colorants exch >> % Finish new attributes dict } if 4 exch put % Put resolved or new attributes dict } if } bdef /Indexed { aload pop 3 -1 roll oforce resolvecolorspace % Stack: /Indexed hival lookup basespace % If the underlying space is a Lab space, we must scale % the output of the lookup table as part of DecodeABC. dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq { dup 1 get /DecodeLMN known { 1 get dup length dict copy begin /DecodeABC [ 0 2 4 { RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load RangeABC 3 index get /add load DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx } for ] def /RangeABC //01_3 def currentdict end /CIEBasedABC exch 2 array astore } if } if 3 1 roll oforce dup type /stringtype ne { % The color lookup table is a stream. % Get its contents. Don't lose our place in PDFfile. % Stack: /Indexed basespace hival lookup PDFfile fileposition 5 1 roll true resolvestream % Stack: filepos /Indexed basespace hival lookupstream 1 index 1 add % Stack: filepos /Indexed basespace hival lookupstream len 3 index dup dup type /arraytype eq { 0 get } if //csncompdict exch get exec mul string dup 3 1 roll readstring pop % the string is padded with 0s length 1 index length lt { ( **** Warning: Short look-up table in the Indexed color space was p added with 0's.\n) pdfformaterror } if % Stack: filepos /Indexed basespace hival table table' 5 -1 roll PDFfile exch setfileposition } if 4 array astore % Replace the PDFColorSpace with the Indexed space if needed. dup 1 get dup type /arraytype eq { dup length 2 ge { dup 1 get type /dicttype eq { dup 1 get /PDFColorSpace known { dup 1 get /PDFColorSpace 3 index put } if } if } if } if pop } bdef /I { % Bug 689815

( **** Warning: The name /Indexed cannot be abbreviated to /I in the color space\n) pdfformaterror dup 0 /Indexed put //Indexed exec } bdef /Pattern { dup type /nametype ne { dup length 1 gt { 1 oget resolvecolorspace /Pattern exch 2 array astore } if } if } bdef currentdict end readonly def /cssubst { % <csname> cssubst <cspace'> true % <csname> cssubst false

dup resolvecolorspace dup 1 index ne { exch pop true } { pop pop false } ifelse } bdef /csnames mark /DeviceGray dup /DeviceRGB dup /DeviceCMYK dup /Pattern dup .dicttomark readonly def /csresolve { % <csresourcename> csresolve <cspace> dup type /nametype ne { (\n **** Warning: CS/cs (setcolorspace) operand not a name: ) pdfformaterr or dup stderrfile dup 3 -1 roll write==only flushfile ( ****\n) pdfformaterror dup type /arraytype eq { % Adobe InDesign + PDF Library has array resolvecolorspace } if } { dup Page /ColorSpace rget { exch pop resolvecolorspace } { //csnames 1 index known not { /undefined cvx signalerror } if } ifelse } ifelse } bdef /resolvecolorspace { % <cspace> resolvecolorspace <cspace'> dup dup type /arraytype eq { 0 get } if //csrdict exch .knownget { exec dup type /nametype ne { dup length 1 eq { 0 get } if } if } { dup type /nametype eq { csresolve } { csset exch pop } ifelse } ifelse } bdef /scresolve { % % % % % % <c0> ... scresolve <multi> 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.

dup type /nametype eq { Page /Pattern rget { resolvepattern } { null } ifelse } if dup type /dicttype eq { % Check the PaintType, if any (shading patterns don't % have one). dup /PaintType knownoget { 2 eq } { false } ifelse } { .pdfcount 1 gt } ifelse } bdef /.pdfpaintproc { % <patdict> <resdict> .pdfpaintproc PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Begin PaintProc) print dup === flush } if } if PDFfile fileposition 3 1 roll q 1 index /PaintType oget 1 eq { % For colored patterns, set default fill and stroke colors. 0 g 0 G } { % For uncolored patterns, we have to unbind the current % color and color space before running the PaintProc. //null sc1 //null SC1 } ifelse % Save old values on opstack, set pdfemptycount to new value. pdfemptycount countdictstack /pdfemptycount count 3 sub def 4 2 roll % % Stack: ... <old emptycount> <dictcount> <patdict> <resdict> % | % New empty count points here -----+ exch //false resolvestream pdfopdict .pdfruncontext countdictstack exch sub dup 0 gt { ( **** Warning: Pattern stream has unbalanced q/Q operators \(too many q' s\)\n) pdfformaterror { Q } repeat } { pop } ifelse % restore pdfemptycount /pdfemptycount exch def Q PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if PDFfile exch setfileposition } bdef /resolvepattern { % <patternstreamdict> resolvepattern <patterndict> % 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 knownoget { dup 65535 le { dup 0 eq { pop pop () } { string readstring pop } ifelse } { () /SubFileDecode filter /ReusableStreamDecode filter } ifelse } { 0 (endstream) /SubFileDecode filter /ReusableStreamDecode filter } ifelse % Stack: dict savepos file string 3 1 roll exch setfileposition 1 index /File 3 -1 roll put dup /FilePosition undef } if dup /Shading knownoget { resolveshading 1 index /Shading 3 -1 roll put } if dup /PaintProc [ % Bind the resource dictionary into the PaintProc. 2 index /Resources knownoget { oforce } { 0 dict } ifelse /.pdfpaintproc cvx ] cvx put dup /.pattern_uses_transparency 1 index patternusestransparency put PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Patter n: ) print dup === flush } if } if } bdef /ignore_color_op ( xt.\n) readonly def **** Warning: Ignoring a color operation in a cached conte

drawopdict begin /g { .incachedevice { % Bug 689302 pop //ignore_color_op pdfformaterror } { /DeviceGray cssubst { cs sc1 } { g } ifelse } ifelse } bdef /rg { .incachedevice { pop pop pop //ignore_color_op pdfformaterror } { /DeviceRGB cssubst { cs sc* } { rg } ifelse } ifelse } bdef /k { .incachedevice { pop pop pop pop //ignore_color_op pdfformaterror } { k } ifelse } bdef /cs { .incachedevice { pop //ignore_color_op pdfformaterror

} { csresolve cs } ifelse } bdef /sc { .incachedevice { .pdfcount { pop } repeat //ignore_color_op pdfformaterror } { scresolve { sc* } { sc1 } ifelse } ifelse } bdef /scn /sc load def /G { .incachedevice { pop //ignore_color_op pdfformaterror } { /DeviceGray cssubst { CS SC1 } { G } ifelse } ifelse } bdef /RG { .incachedevice { pop pop pop //ignore_color_op pdfformaterror } { /DeviceRGB cssubst { CS SC* } { RG } ifelse } ifelse } bdef /K { .incachedevice { pop pop pop pop //ignore_color_op pdfformaterror } { K } ifelse } bdef /CS { .incachedevice { pop //ignore_color_op pdfformaterror } { csresolve CS } ifelse } bdef /ri { .incachedevice { pop //ignore_color_op pdfformaterror } { ri } ifelse } bdef /SC { .incachedevice { .pdfcount { pop } repeat //ignore_color_op pdfformaterror } { scresolve { SC* } { SC1 } ifelse } ifelse } bdef /SCN /SC load def end currentdict /ignore_color_op undef

% ---------------- Paths ---------------- % drawopdict begin % Path construction /m /moveto load def /l /lineto load def /c /curveto load def /v { currentpoint 6 2 roll curveto } def /y { 2 copy curveto } def /re { 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto closepath } def /h /closepath load 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 /sh { setfillstate resolvesh gsave 0 .setoverprintmode dup /.shading .knownget { exch pop } { dup .buildshading dup 3 1 roll /.shading exch put } ifelse .shfill grestore } def end % ---------------- XObjects ---------------- % /xobjectprocs mark /Image { DoImage } /Form { DoForm } /PS { DoPS } .dicttomark readonly def % <dict> -proc- -

% Note that the keys in defaultdecodedict are resolved (PostScript, not PDF) % color space names. /defaultdecodedict mark /DeviceGray { pop //01_1 } bind /DeviceRGB { pop //01_3 } bind /DeviceCMYK { pop //01_4 } bind /CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind /CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind /ICCBased { 1 oget dup /Range knownoget { exch pop

}{ /N get [ exch {0 1} repeat ] readonly } ifelse } bind /Separation { pop //01_1 } bind /DeviceN { 1 oget length [ exch {0 1} repeat ] readonly } bind /Indexed { pop [ 0 1 BitsPerComponent bitshift 1 sub ] } bind .dicttomark readonly def /checkaltimage { % <resdict> checkaltimage <resdict[']> Printed { dup /Alternates knownoget { { dup /DefaultForPrinting knownoget { { /Image oget exch pop exit } { pop } ifelse } { pop } ifelse } forall } if } if } bdef % <string> <index> getu16 <integer> /getu16 { 2 copy get 8 bitshift 3 1 roll 1 add get add } bind def % <string> <index> getu32 <integer> /getu32 { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add } bind def % Process jp2 blocks (aka boxes). All procedures have the signature % <file> <length> -> ... <file> <flush_length> /jp2_tag_dict << /jp2h { % descend into a sub-stream, never return. () /SubFileDecode filter 0 } bind /ihdr { 14 sub % file len-14 1 index 14 string readstring pop % file len-14 (14) /Components 1 index 8 getu16 % file len-14 (14) /Components NC def % file len-14 (14) 10 get 16#7F and 1 add /BitsPerComponent exch def % file len-14 } bind /colr { 3 sub 1 index 3 string readstring pop % file len-3 (3) 0 get 1 eq {

4 sub % file len-7 1 index 4 string readstring pop % file len-16 (4) 0 getu32 % file len-16 enum dup 16 eq { % Don't set device-independent color space now % to avoid raster differences pop /ColorSpace /DeviceRGB % /sRGB def % file len-7 } { 17 eq { % See above. /ColorSpace /DeviceGray % /sGray def % file len-7 } if } ifelse } { string 1 index exch readstring pop % file () /ColorSpace exch % file /ColorSpace () % ICC ColorSpace is not yet implemented pop pop % 0 % file 0 } ifelse } bind >> readonly def % Parse jp2 file format to get color space and image depth info. % <file> get_jp2_csp /get_jp2_csp { { dup (01234567) readstring pop % f (LBoxTBox) dup length 8 lt { pop exit } if dup 4 4 getinterval exch % f (TBox) (LBoxTBox) 0 getu32 % f (TBox) LBox dup 0 eq { pop pop exit % cannot happen } { dup 1 eq { pop 1 index (01234567) readstring pop 4 getu32 % f (TBox) LBox 16 sub } { 8 sub } ifelse } ifelse % f (TBox) LBox-8..16 PDFDEBUG { 2 copy 2 packedarray == } if % f (TBox) LBox-8..16

//jp2_tag_dict 3 -1 roll .knownget { exec } if % f flush dup 0 ne { 1 index exch % f f flush () /SubFileDecode filter flushfile % skip unwanted blocks

} { pop } ifelse } loop pop } bind def currentdict /jp2_tag_dict .undef /makeimagedict { % <resdict> <newdict> makeimagedict <imagemask> % On return, newdict' is currentdict

begin /Width 2 copy oget def /Height 2 copy oget def % Handle missing BitsPerComponent later. /BitsPerComponent 2 copy knownoget { def } { pop } ifelse /Interpolate 2 copy knownoget { def } { pop } ifelse makeimagekeys } bdef /makeimagekeys { % <resdict> makeimagekeys <imagemask> % newdict is currentdict % Assumes Width, Height, BPC, Interpolate already copied. /ImageType 1 def /ImageMatrix Width 0 0 % Handle 0-height images specially. Height dup 0 eq { pop 1 } if neg 0 1 index neg 6 array astore def dup /ImageMask knownoget dup { and } if { % Image mask % Decode is required for the PostScript image operators. % AI8 writes bogus decode array [0 1 0 0 0 0 0 0] /Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def % BitsPerComponent is optional for masks. /BitsPerComponent 2 copy known { pop } { 1 def } ifelse % 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 /DataSource exch def //true } { % Opaque image dup /ColorSpace oknown 1 index /BitsPerComponent oknown and not { dup /Filter knownoget { dup type /arraytype eq { dup length dup 0 gt { 1 sub get oforce } { pop } ifelse } if /JPXDecode eq { % JPXDecode filters can omit the /ColorSpace and /BitsPerComponent % keys, in which case the interpreter must retrieve this information % from inside the compressed stream. Here we substitute the most % likely values as a work-around. dup /IDFlag known { ( **** Warning: PDF spec bans inline JPX images.\n) pdfformaterror % Inline stream is not positionable. Cannot get ColorSpace.

} { % Drop the last filter (JPXDecode) from the pipeline dup dup length dict copy dup /Filter oget dup type /arraytype eq { dup length 1 gt { dup length 1 sub 0 exch getinterval 1 index exch /Filter exch put dup /Params knownoget { dup type /arraytype eq { dup length 1 gt { dup length 1 sub 0 exch getinterval 1 index exch /Params exch put } { pop dup /Params undef } ifelse } { pop dup /Params undef } ifelse } if } { pop dup /Filter undef dup /Params undef } ifelse } { pop dup /Filter undef dup /Params undef } ifelse //false resolvestream get_jp2_csp } ifelse } if } if currentdict /BitsPerComponent oknown not { ( **** Warning: image has no /BitsPerComponent key; assuming 8 bit.\n) pdfformaterror /BitsPerComponent 8 def } if } if currentdict /ColorSpace knownoget not { dup /ColorSpace knownoget not { ( **** Warning: image has no /ColorSpace key; assuming /DeviceRGB.\n) pdfformaterror /DeviceRGB } if } if resolvecolorspace /ColorSpace exch def % Decode is required for the PostScript image operators. /Decode 2 copy knownoget not { ColorSpace //defaultdecodedict ColorSpace dup type /arraytype eq { 0 get } if get exec } if 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 /DataSource exch def //false } ifelse } bdef /DoImage { checkaltimage dup length 6 add dict 1 index /SMask knownoget { 1 index exch /SMask exch put } if 1 index /Mask knownoget { 1 index exch /Mask exch put } if makeimagedict doimagesmask } bdef /makemaskimage { % <datasource> <imagemask> <Mask> makemaskimage % <datasource> <imagemask>, updates currentdict = % imagedict dup type /arraytype eq { /ImageType 4 def % Check that every element of the Mask is an integer. //false 1 index { type /integertype ne or } forall { (\n **** Warning: Some elements of Mask array are not integers.\n) pdfformaterror [ exch { 0.5 add cvi } forall ] % following AR4, 5, 6 implementation } if % Check elements of array are within 0::(2**BitsPerComponent)-1 % This is a PostScript error, but AR ignores Mask in that case 1 BitsPerComponent bitshift 1 sub //false 2 index { % stack: max_value result_bool value dup 0 lt exch 3 index gt or or } forall exch pop { (\n **** Warning: Some elements of Mask array are out of range.\n) pdfformaterror [ exch { 0 .max 1 BitsPerComponent bitshift 1 sub .min } forall ] } if /MaskColor exch def } { % Mask is a stream, another Image XObject. % Stack: datasource imagemask(false) maskstreamdict PDFfile fileposition exch dup length dict makeimagedict pop % In order to prevent the two data sources from being % aliased, we need to make at least one a reusable stream. % We pick the mask, since it's smaller (in case we need to % read all its data now). % Stack: datasource imagemask(false) savedpos % maskdict is currentdict /DataSource DataSource mark /Intent 1 /AsyncRead true .dicttomark .reusablestreamdecode def PDFfile exch setfileposition currentdict end currentdict end 5 dict begin /ImageType 3 def /InterleaveType 3 def /DataDict exch def /MaskDict exch def /ColorSpace DataDict /ColorSpace get def

} ifelse } bdef /doimagesmask { % <imagemask> doimagesmask PDFusingtransparency { currentdict /SMask knownoget } { false } ifelse { % We are doing transparency and SMask is present in the image % stack: <imagemask> <SMask> currentdevice .devicename /pdfwrite eq { pop % pdfwrite will process SMask directly during 'doimage' } { .begintransparencymaskimage PDFfile fileposition exch gsave //nodict begin null /SoftMask gput 1 .setopacityalpha 1 .setshapealpha /Compatible .setblendmode DoImage end grestore PDFfile exch setfileposition 0 .endtransparencymask } ifelse << /Subtype /Group /Isolated true /.image_with_SMask true % pdfwrite needs : see gs/src/ztrans.c, gs/src/gde vpdft.c >> 0 0 1 1 .begintransparencygroup doimage .endtransparencygroup } { SoftMask //null ne { % the image doesn't have an SMask, but the ExtGState does, force a group. << /Subtype /Group /Isolated true >> 0 0 1 1 .begintransparencygroup doimage .endtransparencygroup } { doimage } ifelse } ifelse } bdef % For development needs we define a special option for running with a new handle r % for images with a soft mask. //systemdict /NEW_IMAGE3X .knownget not { //false } if { /doimagesmask { % <imagemask> doimagesmask doimage } bdef } if /is_big_mask { % - is_big_mask <bool> 1 0 dtransform dup mul exch dup mul sqrt add 0 1 dtransform dup mul exch dup mul sqrt add mul currentdevice getdeviceprops .dicttomark /BufferSpace .knownget not { 4000000 % hack: Can't get the real default value from C source. } if 2 % arbitrary div gt

} bind def % For development needs we define a special option for running with a new handle r % for images with a soft mask. //systemdict /NEW_IMAGE3X .knownget not { //false } if { /is_big_mask { % - is_big_mask <bool> //false } bdef } if /doimage { % <imagemask> doimage % imagedict is currentdict, gets popped from dstack DataSource exch PDFusingtransparency currentdevice .devicename /pdfwrite ne { % This is a temporary workaround for the bug 689080, % which is done under a rush of 8.63 release. % The purpose is to disable a conversion of an image with soft mask % into a Type 103 image, which currently allocates a full mask buffer % before writing clist. % With this workaround the Matte color is not working (ignored). is_big_mask not } { true % pdfwrite doesn't need the workaround explained above, % and cannot work with it. } ifelse and { currentdict /SMask knownoget } { false } ifelse { makesoftmaskimage } { currentdict /Mask knownoget { makemaskimage } if } ifelse % Stack: datasource imagemask { currentdict end setfillstate { imagemask } } { ColorSpace setgcolorspace currentdict end setfillblend { image } } ifelse stopped { dup type /dicttype eq { pop } if % Sometimes image fails to restore the stac

k $error /errorname get dup /ioerror eq { pop (\n **** Warning: File has insufficient data for an image.\n) pdfformaterror } { (\n **** Warning: File encountered ') exch 40 string cvs concatstrings (' error while processing an image.\n) concatstrings pdfformaterror } ifelse } if % Close the input stream, unless it is PDFfile or % PDFsource. dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse } bdef

/.paintform { % <formdict> <resdict> <stream> .paintform 3 -1 roll dup /Group known PDFusingtransparency and { .paintgroupform } { pop pdfopdict .pdfruncontext } ifelse } bdef /DoForm { % Adobe 2nd edition of the PDF 1.3 spec makes /FormType % and /Matrix keys optional. Cope with the missing keys. begin << currentdict /FormType known not { /FormType 1 } if currentdict /Matrix known not { /Matrix { 1 0 0 1 0 0 } cvlit } if currentdict end { oforce } forall >> dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse 3 index false /resolvestream cvx /.paintform cvx ] cvx /PaintProc exch put % Adjust pdfemptycount since we have an extra dictionary on the stack pdfemptycount countdictstack 3 -1 roll /pdfemptycount count 1 sub store q execform % gsave / grestore around the Form % Restore pdfemptycount countdictstack exch sub dup 1 gt { ( **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's \)\n) pdfformaterror } if { Q } repeat /pdfemptycount exch store } bdef /_dops_save 1 array def /DoPS { DOPS { //_dops_save 0 save put true resolvestream cvx exec //_dops_save 0 get restore } { pop } ifelse } bdef currentdict /_dops_save undef drawopdict begin /Do { setfillblend PDFfile fileposition exch dup Page /XObject rget { exch pop dup /Subtype get xobjectprocs exch get % Don't leave extra objects on the stack while executing % the definition of the form. 3 -1 roll 2 .execn } {

% This should cause an error, but Acrobat Reader can % continue, so we do too. ( **** Undefined XObject resource: ) exch =string cvs concatstrings (\n) concatstrings pdfformaterror } ifelse PDFfile exch setfileposition } bdef end % ---------------- In-line images ---------------- % % Undo the abbreviations in an in-line image dictionary. % Note that we must look inside array values. % /I is context-dependent. /unabbrevkeydict mark /BPC /BitsPerComponent /CS /ColorSpace /D /Decode /DP /DecodeParms /F /Filter /H /Height /I /Interpolate /IM /ImageMask /W /Width .dicttomark readonly def /unabbrevvaluedict mark /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CC /CalCMYK /CCF /CCITTFaxDecode /CG /CalGray /CR /CalRGB /DCT /DCTDecode /CMYK /DeviceCMYK /Fl /FlateDecode /G /DeviceGray /RGB /DeviceRGB /I /Indexed /LZW /LZWDecode /RL /RunLengthDecode .dicttomark readonly def /unabbrevtypedict mark /nametype { //unabbrevvaluedict 1 index .knownget { exch pop } if } /arraytype { dup 0 1 2 index length 1 sub { 2 copy get unabbrevvalue put dup } for pop } .dicttomark readonly def /unabbrevvalue { % <obj> unabbrevvalue <obj'> oforce //unabbrevtypedict 1 index type .knownget { exec } if } bdef /is_space_dict << 0 0 9 9 10 10 12 12 13 13 32 32 >> readonly def drawopdict begin /BI { mark } bdef /ID { counttomark 2 idiv dup 7 add dict begin { exch //unabbrevkeydict 1 index .knownget { exch pop } if exch unabbrevvalue def } repeat pop /IDFlag true def % flag for stream processing. /File PDFsource def currentdict makeimagekeys doimage % The Adobe documentation says that the data following ID % consists of "lines", and some PDF files (specifically, some files % produced by PCL2PDF from Visual Software) contain garbage bytes % between the last byte of valid data and an EOL. % Some files (PDFOUT v3.8d by GenText) have EI immediately following % the stream. Some have no EOL and garbage bytes. % Sometimes (bug 690300) CCITTDecode filter consumes 'E' in 'EI'. % Therefore, we search for <start>I<sp|end> or <start|sp>EI<sp|end>

PDFsource read not { /ID cvx /syntaxerror signalerror } if dup 73 eq { pop 10 69 73 % Seed to: <sp>EI } { 10 10 3 -1 roll % Seed to: <sp><sp><any> } ifelse { PDFsource read not dup { 10 exch } if //is_space_dict 2 index known 3 index 73 eq and 4 index 69 eq and //is_space_dict 6 index known and { pop pop pop pop pop exit } { { pop pop pop /ID cvx /syntaxerror signalerror } { 4 -1 roll pop } ifelse } ifelse } loop } bdef end currentdict /is_space_dict undef % ================================ Text ================================ % drawopdict begin % Text control /BT /ET /Tc /TL /Tr /Ts /Tw /Tz /Td /TD /Tm /T* { { { { { { { { { { { { BT ET Tc TL Tr Ts Tw Tz Td TD Tm T* } } } } } } } } } } } } def def def def def def def def % Text positioning def def def def % Text painting /Tj { Tj /' { ' } /" { " } /TJ { TJ } def def def } def

/Tform { Tform } def % Text formatting and painting for AcroForm % without appearance streams. /QBT { Q BT ( **** Warning: invalid operator QBT processed as Q BT .\n) pdfformaterror % Bug 690089 } def end % ============================== Annotations ============================== %

% Get and normalize an /annotrect { /Rect oget aload pop exch 3 index sub dup exch 2 index sub dup } bdef

annotation's rectangle. % <annot> annotrect <x> <y> <w> <h> 0 lt { dup 5 -1 roll add 4 1 roll neg } if 0 lt { dup 4 -1 roll add 3 1 roll neg } if

% Set an annotation color. /annotsetcolor { % <annot> annotsetcolor /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse } bdef % Draw the border. Currently, we ignore requests for beveling, and we % don't round the corners of rectangles. /strokeborder { % <annot> <width> <dash> strokeborder 1 index 0 ne { % do not draw if border width is 0 gsave 2 index annotsetcolor 0 setdash dup setlinewidth exch annotrect 2 { 4 index sub 4 1 roll } repeat 2 { 4 index 0.5 mul add 4 1 roll } repeat rectstroke pop grestore } { pop pop pop } ifelse } bdef % Draw an annotation border. /drawborder { % <annot> drawborder gsave dup /BS known 1 index /Border known or { dup /BS knownoget { dup type /dicttype ne % <annot> <border> <bad?> } { dup /Border oget dup type /arraytype eq { dup length 3 lt } { //true } ifelse % <annot> [border] <bad?> } ifelse { ( **** Warning: Wrong annotation border object, no border is drawn.\n) pdfformaterror pop { 0 0 0 } } if dup type /dicttype eq { dup /W knownoget not { 1 } if % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is % expressed in points (an absolute unit), so compensate here for any % scaling of the PostScript user space done due to /UserUnit. % Scaling due to -dPDFFitPage is not undone, to keep the correct border wi dth % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFi

tPage Page /UserUnit knownoget { div } if } if {} 2 index /S knownoget { /D eq { 2 index /D knownoget not { {3} } if exch pop } if } if 3 -1 roll pop strokeborder } { dup 2 get exch dup length 3 gt { 3 get } { pop {} } ifelse strokeborder } ifelse } { 1 {} strokeborder } ifelse grestore } bdef % % The PDF annotation F (flags) integer is bit encoded. % Bit 1 (LSB) Invisible: 1 --> Do not display if no handler. % Note: We have no handlers but we ignore this bit. % Bit 2 Hidden: 1 --> Do not display. We will not display if this bit is set . % Bit 3 Print: 1 --> Display if printing. We will display if this bit set % (and not hidden) and Printed is true % Bit 4 NoZoom: 1 --> Do not zoom annotation even if image is zoomed. % Bit 5 NoRotate: 1 --> Do not rotate annotation even if image is rotated. % Bit 6 NoView: 0 --> Display if this is a 'viewer'. We will display % if this bit is not set (and not hidden) and Printed is false % Bit 7 Read Only - 1 --> No interaction. We ignore this bit % /annotvisible { % <annot> annotvisible <visible> /F knownoget not { 0 } if % Get flag value dup 2 and 0 eq % Check hidden flag exch dup 4 and 0 ne Printed and % Check print flag exch 32 and 0 eq Printed not and % Check noview flag or % Combine print and view and % Combine with 'hidden' flag test } bdef /drawwidget { % <scalefactor_x> <scalefactor_y> <annot> drawwi dget dup /AP knownoget { dup /N known not { ( **** Appearance dictionary (AP) lacks the mandatory normal (N) appeara nce.\n) pdfformaterror } if //false [/N /R /D] { % stack: scalex scaley annot appearance false key 2 index exch knownogetdict { exch not exit } if } forall % stack: scalex scaley annot appearance value true % stack: scalex scaley annot appearance false dup { pop exch pop % Acrobat Distiller produces files in which this Form

% XObject lacks Type and Subtype keys. This is illegal, % but Acrobat Reader accepts it. The only way we can % tell whether this is a Form or a set of sub-appearances % is by testing for the stream Length or File key. % If the stream lacks Length key, try File key. dup /Length known 1 index /File known or { % If this is a form then simply use it //true } { 1 index /AS knownoget not { % If we do not have AS then use any appearance { exch pop oforce exit } forall //true } { % Stack: annot Ndict AS % Get the specified appearance. If no appearance, then % display nothing - set stack = false. knownoget } ifelse } ifelse } { exch pop % discard useless AP dictionary } ifelse % Stack: scalex scaley annot appearance true % Stack: scalex scaley annot false { % Draw appearance % Initialize graphic following "7.4.4 Appearance Streams" q graphicsbeginpage textbeginpage 1 index annotrect pop pop translate 3 index 3 index scale % Apply scale factors dup /BBox knownoget { 1 index /Matrix knownoget not { {1 0 0 1 0 0} } if .bbox_transform pop pop % Compensate for non-zero origin of BBox neg exch neg exch translate } if DoForm Q } if } { dup /FT knownoget { /Tx eq { % Stack: scalex scaley annot dup /DA known 1 index /V known and { dup /DA oget q graphicsbeginpage textbeginpage 1 index annotrect pop pop translate 3 index 3 index scale % Apply scale factors cvx exec dup /V oget 0 0 moveto dup false charpath pathbbox newpath 3 -1 roll sub abs 3 1 roll sub abs 3 index annotrect 4 2 roll pop pop 6 index mul exch 6 index mul % stack: scale annot V vsize hsize vrect hrect % Calculate horizontal justification first % horizontal can be left (Q=0), center (Q=1), or right (Q=2) justifica tion 3 -1 roll % stack: scalex scaley annot V vsize vrect hrect hsize

5 index /Q knownoget not { 0 } if % default 0 == left dup 0 eq { pop pop pop 0 % left justified } { 1 eq { 2 div exch 2 div exch sub % centered } { sub % right justified (hrect - hsize) } ifelse } ifelse % stack: scalex scaley annot V vsize vrect hoffset % Center the text vertically in the rect (Acrobat Reader seems to do t his) 3 1 roll 2 div exch 2 div sub abs % stack: scalex scaley annot V hoffset voffset moveto show Q } if } if } if } ifelse pop pop pop } bdef % For annotation object we have to determine the size of the output rectangle % and the size of the BBox for the form XObject. From these we calculate % a scale factors for drawing it. /calc_annot_scale { % <annot> calc_annot_scale <x_scale> <y_scale> dup /Rect knownoget { pop dup annotrect 4 2 roll pop pop % get width height size in user space 3 -1 roll /AP knownoget { /N knownogetdict { dup /Matrix knownoget not { {1 0 0 1 0 0} } if exch /BBox knownoget { % x y {matrix} [box] exch .bbox_transform % x y x0 y0 x1 y1 3 -1 roll sub % x y x0 x1 y1-y0 3 1 roll exch sub % x y y1-y0 x1-x0 2 copy mul 0 eq { ( **** Warning: /BBox has zero width or height, which is not allow ed.\n) pdfformaterror pop pop pop pop 1 1 % zero size -- revert to unity scaling } { 3 1 roll div % x x1-x0 y/(y1-y0) 3 1 roll div % y/(y1-y0) x/(x1-x0) exch % x/(x1-x0) y/(y1-y0) } ifelse } { pop pop pop 1 1 % default to unity scaling } ifelse % if we have /BBox } { pop pop 1 1 } ifelse % if we have /N } { pop pop 1 1 } ifelse % if we have /AP } { ( **** Warning: /Annot dict is missing required /Rect entry.\n) pdfformaterror pop 1 1

} ifelse } bdef /drawlink { % <annot> drawlink dup drawborder dup calc_annot_scale 3 -1 roll drawwidget } bdef % Draw an annotation. /drawannottypes mark /Link { drawlink } bind .dicttomark readonly def /drawannot { % <annot> drawannot dup annotvisible { gsave dup dup /Subtype knownoget { //drawannottypes exch .knownget { exec } { dup calc_annot_scale 3 -1 roll drawwidget % Use drawwidget for eve rything else } ifelse % type known } { pop ( **** Warning: /Annot dict without required /Subtype entry is ignored.\ n) pdfformaterror } ifelse grestore } if pop % annotvisible } bdef currentdict /drawannottypes undef % ============================ AcroForm fields ============================ % % Get an attribure of the 0th annotation of a node /annot_oget { % <annot> /Name annot_oget <value> 1 index /Kids knownoget { 0 oget exch oget exch pop } { oget } ifelse } bdef % All procedures have the signature: % <acroform> <field> <annot|field> foo <acroform> <field> <annot|field> /draw_terminal_field_dict 4 dict begin /Btn { 1 index /Tf pget not { 0 } if dup 16#20000 and 0 ne { pop % Push button dup /AP known { 1 1 2 index drawwidget } { (Push button without appearance stream is not yet implemented) = } ifelse } { 16#10000 and 0 ne { % Radio button dup /AP known {

1 index /Kids oget { 1 1 3 -1 roll drawwidget } forall } { (Radio button without appearance stream is not yet implemented) = } ifelse } { % Checkbox dup /AP known { dup 1 1 3 -1 roll drawwidget } { (CkeckBox without appearance stream is not yet implemented) = } ifelse } ifelse } ifelse } bdef /Tx { dup /AP known { dup 1 1 3 -1 roll drawwidget } { 2 index /NeedAppearances knownoget not { //false } if { dup /AP << /N 10 dict dup cvx begin >> put /Subtype /Form def /BBox [ 0 0 4 index /Rect oget { oforce } forall 3 -1 roll sub abs 3 1 ro ll sub abs exch ] def /Resources 3 index /DR pget not { 0 dict } if def /File 1000 string dup 3 1 roll def /Length 0 def % <acroform> <field> <annot> (string) /NullEncode filter % <acroform> <field> <annot> file dup (BT ) writestring 2 index /DA pget not { () } if [ exch { token { dup /Tf eq { 2 index 0 eq { /BBox load 3 get 0.75 mul % empirical constant 4 -1 roll pop 3 1 roll } if } if exch } { exit } ifelse } loop ] { 1 index exch write== } forall dup 3 index /MaxLen pget not { 0 } if write= dup 3 index /V pget not { () } if write== dup 3 index /Ff pget not { 0 } if write= dup 3 index /Q pget not { 0 } if write= dup (Tform ET) write= end closefile % <acroform> <field> <annot> dup 1 1 3 -1 roll drawwidget } if } ifelse

} bdef /Ch { (Ch is not yet implemened) == } bdef /Sig { (Sig is not yet implemened ) == } bdef currentdict end def /draw_terminal_field { % <field> draw_terminal_field dup /Kids knownoget { 0 oget } { dup } ifelse dup /P knownoget { /Page load eq { //draw_terminal_field_dict 2 index /FT pget not { 0 } if .knownget { exec } if } if } if pop pop } bdef % We distinguish 4 types of nodes on the form field tree: % - non-terminal field - has a kid that refers to the parent (or anywhere else) % - terminal field with separate widget annotations - has a kid that doesn't ha ve a parent % - terminal field with a merged widget annotation - has no kids % - widget annotation - has /Subtype and /Rect % % The recursive enumeration of the form fields doesn't descend into widget annot ations. /draw_form_field { % <field> draw_form_field dup /Kids knownoget { % dup 0 oget /Parent knownoget { % pop % mon-terminal field % exch pop % { oforce draw_form_field } forall } { pop draw_terminal_field % separate annots } ifelse } { draw_terminal_field % merged annotation % } ifelse } bdef field [] field [] kid field [] [] % -

/draw_acro_form { % <form> draw_acro_form dup /Fields knownoget { { oforce draw_form_field } forall } if pop } bdef currentdict /draw_terminal_field_dict undef end end .setglobal % pdfdict % GS_PDF_ProcSet

You might also like