diff options
Diffstat (limited to 'Resource/Init/pdf_draw.ps')
-rw-r--r-- | Resource/Init/pdf_draw.ps | 855 |
1 files changed, 632 insertions, 223 deletions
diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps index a359a9c1..1deb0526 100644 --- a/Resource/Init/pdf_draw.ps +++ b/Resource/Init/pdf_draw.ps @@ -419,14 +419,43 @@ end % Some functions used to implement phases of HT and HTP /sethalftones { + % As is so often the case, if we get an error we need to clean up the stack, but we can't + % use mark/cleartomark, because the action which caused the error may have left a mark + % on the stack. So we need to define our own mark. On an error we'll clean up the stack + % until we reach this unique key on the stack + /SethalftonesMark exch + dup /Default eq { - pop .setdefaulthalftone - } { - resolvehalftone sethalftone + pop .setdefaulthalftone pop + } + { + {resolvehalftone} stopped + { + (\n **** Error resolving halftone. Ignoring the halftone, output may be incorrect.\n) + pdfformaterror + % Clean up the stack by checking every entry until we find our unique key + {/SethalftonesMark eq {exit} if} loop + } + { + {sethalftone} stopped + { + (\n **** Error setting halftone. Ignoring the halftone, output may be incorrect.\n) + pdfformaterror + % Clean up the stack by checking every entry until we find our unique key + {/SethalftonesMark eq {exit} if} loop + } + { + pop + }ifelse + }ifelse } ifelse } bind executeonly def /sethalftonephases { - aload pop -1 2 index 2 index .setscreenphase pop pop + {aload pop -1 2 index 2 index .setscreenphase pop pop} stopped + { + (\n **** Error setting halftone phase. Ignoring the phase, output may be incorrect.\n) + pdfformaterror + } if } bind executeonly def /HT { @@ -549,9 +578,25 @@ end cleartomark //null exit } if gsave //nodict begin - /CS knownoget { + dup /CS knownoget { + exch pop resolvecolorspace dup setgcolorspace csput - } if + } + { + % Group attributes dictionaries are supposed to contain a /CS + % entry, but Acrobat apparently also handles a /ColorSpace.... + /ColorSpace knownoget { + ( **** Error: A transparency group XObject has a /ColorSpace instead of /CS attribute.\n) + pdfformaterror + resolvecolorspace dup setgcolorspace csput + } + { + ( **** Error: Ignoring a transparency group XObject without /CS attribute.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + cleartomark //null exit + }ifelse + } ifelse aload pop setcolor [ currentgray ] end grestore /GrayBackground exch 3 2 roll @@ -643,9 +688,19 @@ def 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 + % Group attributes dictionaries are supposed to contain a /CS + % entry, but Acrobat apparently also handles a /ColorSpace.... + dup /Group oget /ColorSpace knownoget { + ( **** Error: A transparency group attribute dictionary has a /ColorSpace instead of /CS attribute.\n) + pdfformaterror + 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 } ifelse 3 -1 roll dup dup 4 1 roll /BBox get aload pop .begintransparencymaskgroup @@ -1066,6 +1121,8 @@ currentdict end readonly def //true } ifelse { dup dup type /arraytype eq { 0 get } if + dup type /packedarraytype eq {exch pop exec dup} if + //csrdict exch .knownget { exec dup type /nametype ne { dup length 1 eq { 0 get } if } if } { @@ -1423,8 +1480,12 @@ drawopdict begin } { clippath } ifelse - //null setup_trans + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + 4 array astore grestore + //null + setup_trans //do_shade exec teardown_trans } { @@ -2210,21 +2271,15 @@ currentdict /last-ditch-bpc-csp undef } bind executeonly def /doimagesmask { % <imagemask> doimagesmask - - PDFusingtransparency { - currentdict /SMask knownoget + PDFusingtransparency not + /PreserveSMask /GetDeviceParam .special_op { exch pop } { //false } ifelse + or { + % not using transparency OR the device supports SMask (e.g. pdfwrite) + doimage } { - //false - } ifelse - { % We are doing transparency and SMask is present in the image - % stack: <imagemask> <SMask> - /PreserveSMask /GetDeviceParam .special_op { - exch pop - }{ - //false - }ifelse - { - pop % pdfwrite will process SMask directly during 'doimage' - } { + currentdict /SMask knownoget { + % We are doing transparency and SMask is present in the image + % stack: <imagemask> <SMask> .begintransparencymaskimage PDFfile fileposition exch gsave //nodict begin @@ -2236,34 +2291,44 @@ currentdict /last-ditch-bpc-csp undef 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/gdevpdft.c - % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask - % entry if we get here, so we don't need to check its existence. Just pull it out and see if - % the SMask has a Matte entry. If it does, get the ColorSpace from the parent image and - % put a /CS key with that colour space in the Group that we manufacture. Bug #700686 - % We also need to actually set the current colour space to be the same as the group - % code only picks up the current colour space, not the space from the dictionary. - currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if - >> 0 0 1 1 .begintransparencygroup - doimage - .endtransparencygroup - % tell the compositor we're done with the SMask. - % Note that any SMask in the ExtGState should be reapplied - % by the next call to setfill(stroke)state AND this relies - % on our lazy evaulation of SMask groups - //false << /Subtype /None >> 0 0 0 0 .begintransparencymaskgroup - } { - .currentSMask //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 + << /Subtype /Group /Isolated //true + /.image_with_SMask //true + % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c + % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask + % entry if we get here, so we don't need to check its existence. Just pull it out and see if + % the SMask has a Matte entry. If it does, get the ColorSpace from the parent image and + % put a /CS key with that colour space in the Group that we manufacture. Bug #700686 + % We also need to actually set the current colour space to be the same as the group + % code only picks up the current colour space, not the space from the dictionary. + currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if + >> 0 0 1 1 + .begintransparencygroup + .currentstrokeconstantalpha .currentfillconstantalpha .currentshapealpha .currentopacityalpha 5 -1 roll + 1 .setfillconstantalpha 1 .setstrokeconstantalpha + 1 .setopacityalpha 1 .setshapealpha doimage + .setopacityalpha .setshapealpha .setfillconstantalpha .setstrokeconstantalpha .endtransparencygroup - } - { doimage } - ifelse + % tell the compositor we're done with the SMask. + % Note that any SMask in the ExtGState should be reapplied + % by the next call to setfill(stroke)state AND this relies + % on our lazy evaulation of SMask groups + //false << /Subtype /None >> 0 0 0 0 .begintransparencymaskgroup + } { + % We don't have an SMask in the image but there might be an SMask in the ExtGState + .currentSMask //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 + .currentstrokeconstantalpha .currentfillconstantalpha .currentshapealpha .currentopacityalpha 5 -1 roll + 1 .setopacityalpha 1 .setshapealpha + doimage + .setopacityalpha .setshapealpha .setfillconstantalpha .setstrokeconstantalpha + .endtransparencygroup + } { + doimage + } ifelse + } ifelse } ifelse } bind executeonly def @@ -2315,6 +2380,9 @@ currentdict /last-ditch-bpc-csp undef /doimage { % <imagemask> doimage - % imagedict is currentdict, gets popped from dstack + %% We must save the colour space, in case it gets changed. I did try doing this + %% at a higher level (/Do) but that caused numerous problems with pdfwrite. + currentcolorspace exch %% save the current rendering intent .currentrenderintent exch @@ -2336,7 +2404,12 @@ currentdict /last-ditch-bpc-csp undef makemaskimage } if % Stack: datasource imagemask - gsave 1 1 moveto 0 0 lineto /image setup_trans grestore + gsave 1 1 moveto 0 0 lineto + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + 4 array astore grestore + /image + setup_trans { currentdict end setfillstate //true ValidateDecode { imagemask } } { ColorSpace setgcolorspace currentdict end setfillblend //false ValidateDecode { image } } ifelse @@ -2361,6 +2434,13 @@ currentdict /last-ditch-bpc-csp undef %% restore the rendering intent .setrenderingintent + %% and restore the colour space. We need to do this in a stopped context because + %% if we are rendering a glyph, the cache device will throw an error if we try + %% to change colour space (even when the new space is the same as the old space) + %% We can't tell if we are rendering a bitmap for a glyph, and its hard to compare + %% colour spaces, so just ignore errors for now. + {setcolorspace} stopped {pop} if + teardown_trans } bind executeonly def @@ -3043,7 +3123,7 @@ end } ifelse } ifelse } - { 0 setgray //true} ifelse + { //false } ifelse } bind executeonly def % Draw the border. Currently, we ignore requests for beveling, and we @@ -3051,17 +3131,20 @@ end /strokeborder { % <annot> <width> <dash> strokeborder - 1 index 0 ne { % do not draw if border width is 0 gsave - 2 index annotsetcolor - { +% 2 index annotsetcolor +% { 0 setdash dup setlinewidth - exch annotrect + exch dup annotrect + 5 -1 roll /RD knownoget { + applyRD + } if 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 +% } { +% pop pop pop +% } ifelse } { pop pop pop }ifelse @@ -3094,12 +3177,16 @@ end % Scaling due to -dPDFFitPage is not undone, to keep the correct border width % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not - //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFitPage + //systemdict /PDFFitPage known not and + % Don't apply USerUnit if we are passing it to the device + /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and + { % UserUnit is ignored if -dPDFFitPage 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 + } if + 3 -1 roll pop strokeborder } { dup 2 get exch dup length 3 gt { 3 get } { pop {} } ifelse @@ -3138,23 +3225,39 @@ end % Scaling due to -dPDFFitPage is not undone, to keep the correct border width % compared to the size of the surrounding marks. //systemdict /NoUserUnit .knownget not { //false } if not - //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFitPage + //systemdict /PDFFitPage known not and + % Don't apply USerUnit if we are passing it to the device + /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and + { % UserUnit is ignored if -dPDFFitPage Page /UserUnit knownoget { div } if } if {} 2 index /S knownoget { /D eq { 2 index /D knownoget not { {3} } if exch pop } if } if 3 index /CA knownoget {.setopacityalpha} if - 3 -1 roll pop 2 index annotsetcolor {0 setdash setlinewidth stroke} if + 3 -1 roll pop +% 2 index annotsetcolor { + 0 setdash setlinewidth stroke +% } if } { dup 2 get - exch dup length 3 gt { 3 get } { pop {} } ifelse - 3 index /CA knownoget {.setopacityalpha} if - 2 index annotsetcolor {0 setdash setlinewidth stroke} if + % If element 3 of the /Border array is 0, then don't draw the border + dup 0 ne { + exch dup length 3 gt { 3 get } { pop {} } ifelse + 3 index /CA knownoget {.setopacityalpha} if +% 2 index annotsetcolor { + 0 setdash setlinewidth stroke +% } if + }{ + pop pop + } ifelse } ifelse } { 3 index /CA knownoget {.setopacityalpha} if - 1 {} 2 index annotsetcolor {0 setdash setlinewidth stroke} if + 1 {} +% 2 index annotsetcolor { + 0 setdash setlinewidth stroke +% } if } ifelse pop grestore @@ -3241,12 +3344,24 @@ end 1 index /DA fget not { 1 index /V fget { <EFBBBF> anchorsearch { - pop /Helvetica findfont 12 scalefont setfont + pop /Helvetica findfont + 12 scalefont setfont } { <FEFF> anchorsearch { pop pop /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont } { - pop /Helvetica findfont 12 scalefont setfont + pop /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 12 scalefont setfont }ifelse }ifelse } if @@ -3318,109 +3433,151 @@ end % } if % } if - dup /AP knownoget { - dup /N known not { - ( **** Error: Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror + % Acrobat doesn't draw Widget annotations unles they have both /FT + % (which is defined as required) and /T keys present. Annoyingly + % these can either be inherited from the Form Definition Field + % dictionary (via the AcroForm tree) or present directly in the + % annotation, so we need to check the annotation to make sure its + % a Widget, then follow any /Parent key up to the root node + % extracting and storing any FT or T keys as we go (we only care if + % these are present, their value is immaterial). If after all that + % both keys are not present, then we don't draw the annotation. + + dup /Subtype get /Widget eq { + dup /FT known 1 index /T known and not { + dup + { + dup /FT knownoget { + /FT exch 3 index 3 1 roll put + } if + dup /T knownoget { + /T exch 3 index 3 1 roll put + } if + /Parent knownoget not { + exit + } if + } loop } if - //false - [/N /R /D] { - % stack: scalex scaley annot appearance false key - 2 index exch knownogetdict { - exch not exit + dup /FT known 1 index /T known and { + //true + } { + ( **** Warning: A Widget annotation dictionary lacks either the FT or T key.\n) + pdfformaterror + ( Acrobat ignores such annotations, annotation will not be rendered.\n) + pdfformaterror + ( Output may not be as expected.\n) pdfformaterror + //false + } ifelse + } { + //true + }ifelse + + { + dup /AP knownoget { + dup /N known not { + ( **** Error: Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror } if - } forall - % stack: scalex scaley annot appearance value true - % stack: scalex scaley annot appearance false - dup { - pop exch pop + //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 knownoget { type /integertype eq } { //false } ifelse - 1 index /File knownoget { type /filetype eq or } if { - % 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 + dup /Length knownoget { type /integertype eq } { //false } ifelse + 1 index /File knownoget { type /filetype eq or } if { + % If this is a form then simply use it + //true } { - % Stack: annot Ndict AS - % Get the specified appearance. If no appearance, then - % display nothing - set stack = false. - knownoget + 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 - } { - exch pop % discard useless AP dictionary - } ifelse % Stack: scalex scaley annot appearance true % Stack: scalex scaley annot false - { - dup type /dicttype eq { + { + dup type /dicttype eq { % 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 - } { - ( **** Error: Annotation's appearance is not a dictionary.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - } ifelse - } if - } { - dup /MK knownoget { % mk - dup /BG knownoget { % mk bg - dup length % mk bg len - //set_bc_color exch .knownget { - gsave - exec - 3 index 3 index scale - 1 index annotrect rectfill - grestore + 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 } { - pop + ( **** Error: Annotation's appearance is not a dictionary.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror } ifelse } if - dup /BC knownoget { - dup length - //set_bc_color exch .knownget { - gsave - exec - 1 setlinewidth - 3 index 3 index scale - 1 index annotrect rectstroke - grestore - } { - pop - } ifelse + } { + dup /MK knownoget { % mk + dup /BG knownoget { % mk bg + dup length % mk bg len + //set_bc_color exch .knownget { + gsave + exec + 3 index 3 index scale + 1 index annotrect rectfill + grestore + } { + pop + } ifelse + } if + dup /BC knownoget { + dup length + //set_bc_color exch .knownget { + gsave + exec + 1 setlinewidth + 3 index 3 index scale + 1 index annotrect rectstroke + grestore + } { + pop + } ifelse + } if + pop } if - pop - } if - dup can-regenerate-ap { - make_tx_da - dup /UpdatedAP //true put - 3 copy drawwidget - } if - } ifelse + dup can-regenerate-ap { + make_tx_da + dup /UpdatedAP //true put + 3 copy drawwidget + } if + } ifelse + } if pop pop pop } bind executeonly def + currentdict /set_bc_color undef % For annotation object we have to determine the size of the output rectangle @@ -3471,6 +3628,23 @@ currentdict /set_bc_color undef } ifelse } bind executeonly def +/applyRD { + % x y w h [l t r b] + dup 0 get % x y w h [] l + 6 -1 roll add + 5 1 roll %x+l y w h [] + dup 1 get %x+l y w h [] b + 5 -1 roll add %x+l w h [] b+y + 4 1 roll %x+l y+b w h [] + aload pop %x+l y+b w h l t r b + exch %x+l y+b w h l t b r + 4 -1 roll add %x+l y+b w h t b r+l + 3 1 roll add %x+l y+b w h r+l t+b + 3 -1 roll exch sub %x+l y+b w r+l h-(t+b) + 3 1 roll sub %x+l y+b h-(t+b) w-(r+l) + exch +} bind executeonly def + % Draw an annotation. /drawannottypes 20 dict begin @@ -3569,16 +3743,30 @@ currentdict /set_bc_color undef { gsave dup /ca knownoget {.setopacityalpha} if - dup annotrect rectfill + dup annotrect + 5 index /RD knownoget { + applyRD + } if + rectfill grestore dup /CA knownoget {.setopacityalpha} if - drawborder + dup annotsetcolor { + drawborder + } if //false }{ - pop + dup annotrect + 5 index /RD knownoget { + applyRD + } if + drawopdict /re get exec + dup annotsetcolor { + strokeborderpath + } if } ifelse //endannottransparency exec grestore + //false }ifelse } bind executeonly def @@ -3608,11 +3796,17 @@ currentdict /set_bc_color undef } { gsave //startannottransparency exec - dup annotrect 4 2 roll exch 3 index 2 div add exch 2 index 2 div add + dup annotrect + 5 index /RD knownoget { + applyRD + } if + 4 2 roll exch 3 index 2 div add exch 2 index 2 div add translate //drawellipse exec dup fillborderpath - strokeborderpath + dup annotsetcolor { + strokeborderpath + } if //endannottransparency exec grestore //false @@ -3661,8 +3855,14 @@ currentdict /set_bc_color undef fill grestore dup /CA knownoget {.setopacityalpha} if - strokeborderpath - } if + dup annotsetcolor { + strokeborderpath + } if + } { + dup annotsetcolor { + strokeborderpath + } if + } ifelse //endannottransparency exec //false grestore @@ -3795,7 +3995,7 @@ currentdict /set_bc_color undef fillborderpath grestore } bind executeonly def - /None {} bind executeonly def + /None {pop} bind executeonly def /Butt { dup /BS knownoget { @@ -3880,36 +4080,50 @@ currentdict /set_bc_color undef } { gsave //startannottransparency exec - dup /L knownoget { - 1 index /LE knownoget { - gsave - 1 index aload pop % x1 y1 x2 y2 - 3 -1 roll sub % x1 x2 dy - 3 1 roll exch sub % dy dx - 2 copy translate - atan - rotate - dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec - grestore - gsave - 1 index aload pop % x1 y1 x2 y2 - 3 -1 roll sub % x1 x2 dy - 3 1 roll exch sub % dy dx - 2 copy translate - atan 180 add - rotate - 1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec - grestore - }if - aload pop 4 2 roll - moveto lineto - strokeborderpath - }{ - ( **** Error: Invalid L array for Line, annotation has not been drawn.\n) - pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - pop - } ifelse + dup annotsetcolor { + dup /L knownoget { + 1 index /LE knownoget { % <annot> [x1 y1 x2 y2] [LE1 LE2] + gsave + 1 index aload pop % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 y1 x2 y2 + 3 -1 roll sub % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 x2 dy + 3 1 roll exch sub % <annot> [x1 y1 x2 y2] [LE1 LE2] dy dx + 3 index aload pop 4 2 roll pop pop + translate + 0 0 moveto + atan % <annot> [x1 y1 x2 y2] [LE1 LE2] + rotate + dup 1 get % <annot> [x1 y1 x2 y2] [LE1 LE2] LE1 + dup //LineEnd_dict exch known not + { + pop /None + } if + //LineEnd_dict exch % <annot> [x1 y1 x2 y2] [LE1 LE2] <dict> LE1 + get % <annot> [x1 y1 x2 y2] [LE1 LE2] {} + 3 index exch % <annot> [x1 y1 x2 y2] [LE1 LE2] <annot> {} + exec + grestore + gsave + 1 index aload pop % x1 y1 x2 y2 + 3 -1 roll sub % x1 x2 dy + 3 1 roll exch sub % dy dx + 3 index aload pop pop pop + translate + 0 0 moveto + atan 180 add + rotate + 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec + grestore + }if + aload pop 4 2 roll + moveto lineto + strokeborderpath + }{ + ( **** Error: Invalid L array for Line, annotation has not been drawn.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop + } ifelse + } if //endannottransparency exec //false grestore @@ -3977,14 +4191,16 @@ currentdict /set_bc_color undef /Link { % <annot> -> <false> //startannottransparency exec - dup drawborder dup calc_annot_scale - 2 copy mul 0 ne - {3 -1 roll drawwidget //false} - { - pop pop - ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror - ( Output may be incorrect.\n) pdfformaterror - }ifelse + dup annotsetcolor { + dup drawborder dup calc_annot_scale + 2 copy mul 0 ne + {3 -1 roll drawwidget //false} + { + pop pop + ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + }ifelse + } if //endannottransparency exec } bind executeonly def @@ -3998,7 +4214,8 @@ currentdict /set_bc_color undef 1 setlinewidth 1 setlinecap 1 setlinejoin - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4047,7 +4264,8 @@ currentdict /set_bc_color undef //true } { 0 setlinecap - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4087,7 +4305,8 @@ currentdict /set_bc_color undef //true } { 0 setlinecap - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4149,7 +4368,8 @@ currentdict /set_bc_color undef //true } { 0 setlinecap - dup annotsetcolor { + dup annotsetcolor + { /QuadPoints knownoget { aload length 8 idiv { 6 -2 roll @@ -4161,7 +4381,9 @@ currentdict /set_bc_color undef } repeat PDFusingtransparency { //emptydict - pathbbox 2 index add exch 3 index add exch .begintransparencygroup + % If we get an error, just emit an empty box + { pathbbox } stopped { 0 0 0 0 } if + 2 index add exch 3 index add exch .begintransparencygroup /Multiply .setblendmode fill .endtransparencygroup @@ -4182,7 +4404,8 @@ currentdict /set_bc_color undef //true } { //startannottransparency exec - dup annotsetcolor { + dup annotsetcolor + { dup calc_annot_scale 2 copy mul 0 ne { @@ -4323,18 +4546,37 @@ currentdict /set_bc_color undef }{ //false } ifelse - {dup annotrect - %% Somewhat horrifyingly, rectfill maps directly to the device fill_rectangle - %% method, which bypasses transparency (!!) So we construct the rectangle, - %% and fill it, manually instead.... - gsave 4 2 roll moveto 1 index 0 rlineto - 0 exch rlineto neg 0 rlineto closepath fill grestore + { + dup annotrect + 5 index /RD knownoget { + applyRD + } if + rectfill } if %% get and process the default appearance string, if we don't have one, use a default /DA_Action_Dict << - /Tf {exch dup /Helv eq {pop /Helvetica findfont exch scalefont setfont}{findfont exch scalefont setfont}ifelse} + /Tf + { + exch dup /Helv eq + { + pop /Helvetica dup findfont + } + {dup findfont}ifelse + + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + definefont + exch scalefont setfont + } /r {aload pop setrgbcolor} % Can't find this actually defined anywhere, but Acrobat seems to honour it :-( /rg {setrgbcolor} /RG {setrgbcolor} @@ -4380,27 +4622,108 @@ currentdict /set_bc_color undef {cleartomark pop} ifelse } { 0 setgray - /Helvetica findfont 12 scalefont setfont + /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 12 scalefont setfont }ifelse %% draw the border, if we don't have a border style dictionary, draw a default one. - dup /BS knownoget { + dup /BS knownoget + { pop dup drawborder }{ newpath 0 setgray 1 setlinewidth - dup annotrect 4 -1 roll 1 add 4 -1 roll 1 add 4 -1 roll 2 sub 4 -1 roll 2 sub - 4 2 roll moveto - currentpoint exch 3 index add exch lineto - currentpoint 2 index add lineto - exch currentpoint 3 1 roll exch sub exch lineto - currentpoint 3 -1 roll sub lineto stroke + dup annotrect + 5 index /RD knownoget { + applyRD + 4 -1 roll 4 -1 roll 4 -1 roll 4 -1 roll + 4 2 roll + } { + 4 -1 roll 1 add 4 -1 roll 1 add 4 -1 roll 2 sub 4 -1 roll 2 sub + 4 2 roll + }ifelse + moveto + currentpoint exch 3 index add exch + lineto + currentpoint 2 index add + lineto + exch currentpoint 3 1 roll exch sub exch + lineto + currentpoint 3 -1 roll sub + lineto stroke }ifelse + gsave % in case we rotate the contents %% Start the current point at the top left of the annotation Rect %% - dup annotrect 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub - 3 -1 roll add 2 index exch moveto 1 index add + dup /Rotate knownoget + % x y w h - x' w' x' y' + { + dup 90 eq { + pop + dup annotrect + 5 index /RD knownoget { + applyRD + } if + exch pop 3 -1 roll 2 index + moveto 90 rotate + 1 index add + } { + dup 180 eq { + pop + dup annotrect + 5 index /RD knownoget { + applyRD + } if + pop 3 -1 roll 1 index add -1 mul exch 1 index -1 mul 4 -1 roll + moveto 180 rotate + 1 index add + }{ + 270 eq { + dup annotrect + 5 index /RD knownoget { + applyRD + } if + dup 4 -1 roll add 3 -1 roll 3 index add exch + moveto 270 rotate + exch pop currentpoint + pop dup 3 -1 roll add + }{ + dup annotrect + 5 index /RD knownoget { + applyRD + 3 -1 roll add 2 index exch + moveto 1 index add + }{ + 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub + 3 -1 roll add 2 index exch + moveto 1 index add + } ifelse + } ifelse + } ifelse + } ifelse + }{ + dup annotrect + 5 index /RD knownoget { + applyRD + 3 -1 roll add 2 index exch + moveto 1 index add + }{ + 4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub + 3 -1 roll add 2 index exch + moveto 1 index add + } ifelse + } ifelse %% Get the Contents string, if we don't have one, we're done %% @@ -4439,7 +4762,6 @@ currentdict /set_bc_color undef %% and use it immediatley to start the text one line down %% currentpoint ..TextHeight sub moveto - %% Now we process each character code in the string. If we find %% a /r/ or /n then we drop a line. If the character would end up %% outside the Annot Rect, then we drop a line before showing it. @@ -4453,7 +4775,8 @@ currentdict /set_bc_color undef } { 1 string dup 0 4 -1 roll put dup %% llx urx (string) (int) (int) - stringwidth pop currentpoint pop add 3 index gt { + stringwidth pop currentpoint pop add 3 index + gt { currentpoint exch pop 4 index exch ..TextHeight sub moveto } if show @@ -4470,6 +4793,34 @@ currentdict /set_bc_color undef } ifelse } if pop pop + + grestore % in case the contents were rotated + dup /CL knownoget { + dup length 6 eq { + dup aload pop pop pop + } { + dup length 4 eq { + dup aload pop + } { + pop 0 + } ifelse + } ifelse + 4 2 roll + exch 4 -1 roll sub + 3 1 roll exch sub + atan exch + aload pop moveto lineto lineto + currentpoint +% stroke +% 0 1 0 setrgbcolor + moveto currentpoint translate 0 0 moveto + 360 exch sub rotate + currentpoint + -5 -8 rlineto + moveto + 5 -8 rlineto + stroke + } if //endannottransparency exec //false grestore @@ -4505,7 +4856,18 @@ currentdict /set_bc_color undef PDFusingtransparency { .begintransparencytextgroup } if - /Times-Bold findfont exch scalefont setfont % (text) y + /Times-Bold findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Times-Bold-PDFDocEncoding def + currentdict + end + /Times-Bold-PDFDocEncoding exch definefont + exch scalefont setfont % (text) y gsave 0 0 moveto 1 index //false charpath flattenpath pathbbox @@ -4668,7 +5030,18 @@ currentdict /set_bc_color undef .begintransparencytextgroup } if 0 setgray - /Helvetica findfont 9 scalefont setfont + /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 9 scalefont setfont 2 index aload pop 3 1 roll pop pop 30 sub exch 5 add exch moveto show PDFusingtransparency { @@ -4687,7 +5060,18 @@ currentdict /set_bc_color undef .begintransparencytextgroup } if 0 setgray - /Helvetica findfont 9 scalefont setfont + /Helvetica findfont + % re-encode the font to PDFDocEncoding + dup length dict begin + { + 1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse + } forall + /Encoding /PDFDocEncoding /Encoding findresource def + /FontName /Helvetica-PDFDocEncoding def + currentdict + end + /Helvetica-PDFDocEncoding exch definefont + 9 scalefont setfont dup stringwidth pop 2 index aload pop pop exch pop exch sub exch sub 2 div 2 index aload pop 3 1 roll pop pop 11 sub 3 1 roll add exch moveto @@ -4748,6 +5132,25 @@ currentdict end readonly def ifelse } bind executeonly def +/.PDFPreserveAnnotType? +{ + //false exch + /PreserveAnnotTypes where + { + /PreserveAnnotTypes get + { + dup /* eq exch 2 index eq or + { + pop //true exch + exit + } if + } forall + pop + } + {pop pop //true} + ifelse +} bind executeonly def + /drawannot { % <annot> drawannot - dup annotvisible { gsave @@ -5050,7 +5453,7 @@ currentdict end readonly def gsave dup dup /Subtype knownoget { - dup //.PDFDrawAnnotType? exec + dup //.PDFPreserveAnnotType? exec { //preserveannottypes exch .knownget { exec } { //true } ifelse { @@ -5068,7 +5471,13 @@ currentdict end readonly def }ifelse } if } - {pop} ifelse + { + % Not preserving this type of annotation + % discard teh Subtype + pop + % copy the Annot dictionary and try drawing it instead + dup drawannot + } ifelse % type known } { pop |