summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps')
-rw-r--r--Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps4088
1 files changed, 4088 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps
new file mode 100644
index 00000000000..88da2de7485
--- /dev/null
+++ b/Master/tlpkg/tlgs/Resource/Init/pdf_draw.ps
@@ -0,0 +1,4088 @@
+% Copyright (C) 2001-2012 Artifex Software, Inc.
+% All Rights Reserved.
+%
+% This software is provided AS-IS with no warranty, either express or
+% implied.
+%
+% This software is distributed under license and may not be copied,
+% modified or distributed except as expressly authorized under the terms
+% of the license contained in the file LICENSE in this distribution.
+%
+% Refer to licensing information at http://www.artifex.com or contact
+% Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
+% CA 94903, U.S.A., +1(415)492-9861, for further information.
+%
+
+% 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
+
+/SetGroupExtGStateDict
+<<
+ /AlphaIsShape //AIS
+ /FillConstantAlpha //ca
+ % We don't have to worry about the enumeration order, even
+ % with the color/space settings, since we only store, not
+ % not set them.
+ /FillColor //sc1
+ /FillColorSpace { /FillColorSpace gput } bind
+ /FillOverprint //op
+ /SoftMask //SMask
+ /StrokeConstantAlpha //CA
+ /StrokeColor //SC1
+ /StrokeColorSpace { /StrokeColorSpace gput } bind
+ /StrokeOverprint //OP
+ /TextSpacing //Tc
+ % We can't use //Tz as we've stored the value we actually use,
+ % not value * 100 (see /Tz in pdf_ops.ps)
+ /TextHScaling { /TextHScaling gput } bind
+ /Leading //TD
+ /TextFont { /TextFont gput} bind
+ /TextLineMatrix { /TextLineMatrix gput } bind
+ /TextMatrix { /TextMatrix gput } bind
+ /TextRise { /TextRise gput } bind
+ /TextRenderingMode { /TextRenderingMode gput } bind
+ /WordSpacing //Tw
+>> 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 { (%Function: ) 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
+ /Coords {
+ aload
+ 5 1 roll
+ 4 { % Bug 694542
+ dup type dup /integertype ne exch /realtype ne and {
+ ( **** Error: replacing malformed number ') pdfformaterror pdfstring cvs pdfformaterror
+ (' with 0.\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ 0
+ } if
+ 4 1 roll
+ } repeat
+ 5 -1 roll
+ astore
+ } bind
+ /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
+ /Extend {
+ mark exch {oforce} forall ]
+ } 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 {
+ %% Horrible hacky fix, see /DoImage later in ths file for more information
+ %%
+ dup /ColorSpace known {
+ dup /ColorSpace get dup type /arraytype eq {
+ exch dup length dict copy exch
+ dup length array copy /ColorSpace exch 2 index 3 1 roll put
+ } {pop} ifelse
+ } if
+
+ 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
+ } bind
+ /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
+ } bind
+ /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
+ } bind
+ /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub } bind
+ /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub } bind
+ /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub } bind
+ /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub } bind
+ /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub } bind
+ /Line { exch pop abs neg } bind
+ /LineX { pop } bind
+ /LineY { exch pop } bind
+ /Square { abs exch abs 2 copy lt { exch } if pop neg } bind
+ /Cross { abs exch abs 2 copy gt { exch } if pop neg } bind
+ /Rhomboid { abs exch abs 0.9 mul add 2 div } bind
+ /DoubleDot { 2 {360 mul sin 2 div exch } repeat add } bind
+ /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg } bind
+ /SimpleDot { dup mul exch dup mul add 1 exch sub } bind
+ /InvertedSimpleDot { dup mul exch dup mul add 1 sub } bind
+ /CosineDot { 180 mul cos exch 180 mul cos add 2 div } bind
+ /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add } bind
+ /InvertedDouble {
+ exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
+ } bind
+.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
+
+/.resolveht6 {
+ %% resolvestream will reposition PDFfile. If we are in the middle
+ %% of reading a content stream from PDFfile when we execute this,
+ %% then reading the next buffer will read from the wrong place. We
+ %% must save and restore the position of PDFfile. See the definition
+ %% of resolvestream. Bug #695886
+ PDFfile fileposition exch
+ mark exch { oforce } forall .dicttomark
+ dup dup //false resolvestream /ReusableStreamDecode filter
+ /Thresholds exch put
+ dup /TransferFunction .knownget {
+ resolveidfnproc
+ 1 index exch /TransferFunction exch put
+ } if
+ exch PDFfile exch setfileposition
+} bdef
+
+/htrdict mark
+ 1 //.resolveht1
+ 5 //.resolveht5
+ 6 //.resolveht6
+ 10 //.resolveht6
+ 16 //.resolveht6
+.dicttomark readonly def
+
+currentdict /.resolveht1 undef
+currentdict /.resolveht5 undef
+currentdict /.resolveht6 undef
+
+/resolvehalftone { % <dict> resolvehalftone <halftone>
+ dup /HalftoneType oget
+ dup //htrdict exch .knownget {
+ exch pop exec
+ } {
+ =string cvs
+ ( **** Error: Incorrect halftone type ) exch concatstrings
+ (. Using defailt.\n) concatstrings pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ gsave .setdefaulthalftone currenthalftone grestore
+ } 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
+ % And if we ha\ve done a gsave inside a text block, we need to update
+ % that matrix instead.
+ currentdict /qTextSaveMatrix .knownget {
+ //cmmatrix exch dup concatmatrix pop
+ } if
+ } bdef
+
+ /i { 1 .min setflat } bdef
+ /J { setlinecap } bind 0 get def
+ /d { setdash } bind 0 get def
+ /j { setlinejoin } bind 0 get def
+ /w { setlinewidth } bind 0 get 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 }
+
+ % Some functions used to implement phases of HT and HTP
+ /sethalftones {
+ dup /Default eq {
+ pop .setdefaulthalftone
+ } {
+ resolvehalftone sethalftone
+ } ifelse
+ } bdef
+ /sethalftonephases {
+ /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
+ } bdef
+
+ /HT {
+ dup sethalftones .swapcolors sethalftones .swapcolors
+ % 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.
+ dup sethalftonephases .swapcolors sethalftonephases .swapcolors
+ }
+ % PDF 1.3
+ % The font is an indirect reference, not a resource name
+ /Font { aload pop exch oforce resourcefont exch 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} PDFSTOPONERROR { exec //false } { stopped } ifelse
+ {
+ pop (\n **** Error in SMask during ExtGState. Ignoring the mask, output may be incorrect.\n)
+ pdfformaterror
+ } if
+ }
+ /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 type /dicttype eq
+ {
+ dup /G knownogetdict
+ {pop}
+ {
+ ( **** Error: Ignoring invalid transparency SMask group\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ % replace the invalid SMask object
+ pop /None
+ } ifelse
+ } if
+
+ dup /None eq 1 index //null eq or PDFusingtransparency not or {
+ pop //null
+ SoftMask //null ne {
+ % get rid of the current SMask (Bug 695471)
+ false % colorspace not set
+ << /Subtype /None >> % Special type for this purpose
+ 0 0 0 0 % fake BBox
+ .begintransparencymaskgroup
+ } if
+ exit
+ } if
+ % 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
+ 1 index /G oget /Group knownoget not {
+ ( **** Error: Ignoring a transparency group XObject without /Group attribute.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ cleartomark //null exit
+ } if
+ gsave //nodict begin
+ /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 oforce_array
+ 1 index /Matrix knownoget {
+ oforce_array .bbox_transform 4 array astore
+ } if
+ /BBox exch 4 2 roll
+ % Because we don't execute the group form stream until we find
+ % out whether we're actually going to draw through it, we need
+ % to save the current gstate with the other parameters, so
+ % we can subsequently execute it in the correct graphics state.
+ % We need to concatenate the Matrix in this gstate as per the PDF
+ % spec 7.5.4 (p. 552 in the PDF 1.7 Ref) (bug 694455).
+ gsave
+ dup /Matrix knownoget {
+ matrix currentmatrix matrix concatmatrix setmatrix
+ } if
+ /GroupGState gstate currentgstate 6 2 roll
+ grestore
+ /GroupMat matrix currentmatrix 8 2 roll
+ /GroupExtGState 1 dict
+ //SetGroupExtGStateDict
+ {
+ exch dup where
+ {
+ exch get 2 index 3 1 roll put
+ }
+ {
+ pop pop
+ } ifelse
+ } forall
+ 10 2 roll
+ /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
+ pop
+ .dicttomark
+ exit
+ } loop
+ 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 resources.
+/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
+ //nodict begin
+ matrix currentmatrix 4 1 roll
+ mark currentcolor counttomark dup 4 add exch roll pop
+ currentcolorspace 4 1 roll .getuseciecolor 4 1 roll
+ currentuserparams /OverrideICC get 4 1 roll
+ mark /OverrideICC true .dicttomark setuserparams
+
+ % We can't simply set the group's gstate here because
+ % we can't use gsave/grestore. So we actually set it
+ % in .execgroup. But the matrix needs set here for
+ % .begintransparencymaskgroup to correctly work.
+ % It might seem we should also set the colorspace
+ % in case the group doesn't have one, *but* empirical
+ % suggests that is not the case - fts_26_2600.pdf and
+ % fts_26_2603.pdf render incorrectly if we set the
+ % colrospace
+ 1 index /GroupMat .knownget { setmatrix } if
+
+ 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
+ dup 4 1 roll /BBox get aload pop .begintransparencymaskgroup
+ exch dup /Resources knownoget { oforce } { 2 dict } ifelse
+ 3 -1 roll dup /GroupGState .knownget { 2 index /GroupGState 3 -1 roll put} if
+ /GroupExtGState .knownget { 1 index /GroupExtGState 3 -1 roll put} if
+ exch //false resolvestream
+ 1 index exch .execgroup
+ % We have to remove these in case the Form XObject is subsequently used as
+ % a form rather than a group - they remain in the paramdict for the SMask
+ % so this will all still work if the SMask is re-evaluated.
+ dup /GroupGState undef
+ /GroupExtGState undef
+ .endtransparencymask
+ PDFfile exch setfileposition
+ mark exch /OverrideICC exch .dicttomark setuserparams
+ .setuseciecolor setcolorspace setcolor
+ setmatrix
+ end % restore colorspace, color and ExtGState (end)
+ /SoftMask where pop /SoftMask //true put % special setting to tell us it has been rendered
+} bdef
+
+% Paint a Form+Group XObject, either for a transparency mask or for a Do.
+/.execgroup { % <resdict> <stream> .execgroup -
+ pdfemptycount 3 1 roll
+ /pdfemptycount count 3 sub store
+ gsave //nodict begin
+
+ % We have to set the gstate correctly for lazy evaluation of a softmask group.
+ % we also must preserve the color(space) as setup in .execmaskgroup.
+ % This stuff must be done here, as .execmaskgroup can't use gsave/grestore to
+ % manipulate the gstates, due to the requirements of .begintransparencymaskgroup.
+ % We also must set the ExtGState values.
+ % It may seem redundant to do the color(space) twice (once here and once in
+ % .execmaskgroup) but we have to set it in .execmaskgroup for the background
+ % color and set it here once in the correct gstate.
+ mark currentcolor currentcolorspace counttomark 2 add index dup
+ /GroupGState .knownget { setgstate } if
+ /GroupExtGState .knownget { { exch exec } forall } if
+ setcolorspace setcolor pop
+ newpath //null SMask
+ 1 .setopacityalpha 1 .setshapealpha
+ 1 CA 1 ca
+ /Compatible .setblendmode
+ % Execute the body of the Form, similar to DoForm.
+ pdfopdict .pdfruncontext
+ end grestore
+ /pdfemptycount exch store
+} bdef
+
+/.beginformgroup { % groupdict bbox .beginformgroup -
+ exch mark exch % bbox mark groupdict
+ dup /CS knownoget { resolvecolorspace dup setgcolorspace /CS exch 3 2 roll} 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
+ .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} stopped {pop} if 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 9 dict begin
+ /DeviceGray { pop 1 } bdef
+ /DeviceRGB { pop 3 } bdef
+ /DeviceCMYK { pop 4 } bdef
+ /CIEBasedA //DeviceGray def
+ /CIEBasedABC //DeviceRGB def
+ /CalGray //DeviceGray def
+ /CalRGB //DeviceRGB def
+ /Lab //DeviceRGB def
+ /ICCBased { 1 oget /N oget } bdef
+ /Separation //DeviceGray def
+ /DeviceN { 1 oget length } bdef
+ /Indexed //DeviceGray def
+currentdict end readonly def
+
+% <colorspace> csncomp <n>
+/csncomp {
+ dup dup type /arraytype eq { 0 oget } if
+ //csncompdict exch get exec
+} bdef
+
+currentdict /csncompdict undef
+
+/ICCBased-resolve {
+ PDFfile fileposition exch
+ dup dup 1 oget
+ mark exch { oforce } forall .dicttomark
+ dup dup //true resolvestream
+ /ReusableStreamDecode filter /DataSource exch put
+
+ % Check that the number of components (/N) defined in the ICCBased
+ % dictionry matches the actual profile. Bug #696120
+ dup /N get
+ 1 index
+ %% If we get an error reading the profile, just assume that /N is correct
+ %% If its genuinely faulty we will use an alternate based on /N.
+ {.numicc_components} stopped {pop dup} if
+ dup 3 -1 roll ne {
+ %% /N and the actual number of components don't match. Ensure
+ %% that we have a valid number of components from the ICC
+ %% profile. Certain kinds of profile can't determine the numebr of components
+ %% and in ths case we must not override the /N value.
+ dup 0 gt {
+ ( **** Error: ICCbased space /N value does not match the ICC profile.\n) pdfformaterror
+ ( Using the number of channels from the profile.\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ 1 index dup /N get /OrigN exch put
+ 1 index exch /N exch put
+ }{
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+
+ 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
+} bdef
+
+/csrdict 13 dict begin
+ /DeviceGray { } bdef
+ /DeviceRGB { } bdef
+ /DeviceCMYK { } bdef
+
+ /CalGray { 1 oget [ exch /CalGray exch ] } bdef
+ /CalRGB { 1 oget [ exch /CalRGB exch ] } bdef
+ /Lab { 1 oget [ exch /Lab exch ] } bdef
+
+ /CalCMYK {
+ pop /DeviceCMYK % not defined by Adobe
+ } bdef
+
+ /ICCBased {
+ dup 1 get type /dicttype ne { % don't resolve more than once
+ ICCBased-resolve
+ } 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
+
+ %% Make sure the ink name is not an indirect object....
+ 3 -1 roll oforce 3 1 roll
+
+ 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
+ %% Resolve 'hival' in case it is an indirect reference. This is kind of
+ %% dumb, it just makes the file bigger, but it *is* legal.
+ 3 1 roll oforce 3 -1 roll
+
+ 1 index -1 eq {
+ exch pop 255 exch
+ ( **** Error: Highest color index given as -1. Assuming this actually means 255.\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ 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 % Stack: /Indexed csp comp table
+ 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
+ dup /Filter oknown not { % For Bug691941.pdf and similar lossage
+ dup /Length knownoget not { 0 } if
+ } {
+ 0
+ } ifelse
+ % Stack: filepos /Indexed basespace hival lookup Length
+ 2 index 1 add
+ % Stack: filepos /Indexed basespace hival lookup Length len
+ 4 index csncomp mul .max string
+ % Stack: filepos /Indexed basespace hival lookup (...)
+ exch //true resolvestream
+ 1 index readstring not {
+ % The string is padded with 0s
+ ( **** Error: Short look-up table in the Indexed color space was padded with 0's.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ pop
+ % Stack: filepos /Indexed basespace hival (...)
+ PDFfile 6 -1 roll setfileposition
+ } if
+ 4 array astore
+ % Stack: [filepos /Indexed basespace hival (...)]
+ % 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
+ ( **** Error: The name /Indexed cannot be abbreviated to /I in the color space\n)
+ pdfformaterror
+ ( Output may be incorrect.\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> <true> | <false>
+ dup type /nametype ne {
+ (\n **** Error: CS/cs (setcolorspace) operand not a name: ) pdfformaterror
+ dup stderrfile dup 3 -1 roll write==only flushfile
+ ( ****\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ dup type /arraytype eq { % Adobe InDesign + PDF Library has array
+ resolvecolorspace
+ } if //true
+ } {
+ dup Page /ColorSpace rget {
+ exch pop resolvecolorspace //true
+ } {
+ //csnames 1 index known {
+ //true
+ } {
+ ( **** Error: Undefined space resource: /)
+ exch .namestring concatstrings (\n) concatstrings pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ //false
+ } ifelse
+ } ifelse
+ } ifelse
+} bdef
+
+/resolvecolorspace { % <cspace> resolvecolorspace <cspace'>
+ dup type /dicttype eq {
+ dup /N known {
+ ( **** ICCBased color space is a bare stream dictionary\n) pdfformatwarning
+ [ /ICCBased 3 -1 roll ] ICCBased-resolve exec
+ //false
+ } {
+ dup /ColorSpace knownoget {
+ ( **** Error: unrecognised color space <</ColorSpace /Device...>>\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ exch pop //true
+ } {
+ //true
+ } ifelse
+ } ifelse
+ } {
+ //true
+ } ifelse {
+ 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 not { /DeviceRGB } if % Arbitrary
+ } {
+ csset exch pop
+ } ifelse
+ } ifelse
+ } if
+} 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
+
+%% Bug #696017 When we begin a text block, we switch to a special set of marking operations
+%% for paths, these ops don't use the current CTM, but the 'SavedTextMatrix', in order to
+%% correctly position marks which are illegally present inside a text block. But, if we are
+%% executing a PaintProc (eg for a pattern) we *don't* want to do that or the pattern will be wrong.
+%% So we moved the .pdfpaintproc to .actual_pdfpaintproc, and redefined .pdfpaintproc to test
+%% the current value of /m. We always switch to the regular marking operations, but if the definition
+%% of /m at the start of the PaintProc was a special text version, then we switch back to that after we
+%% finished running the PaintProc.
+
+/.actual_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 mark
+
+ /pdfemptycount count 3 sub def 5 3 roll
+ %
+ % Stack: ... <old emptycount> <dictcount> mark <patdict> <resdict>
+ % |
+ % New empty count points here -----------+
+
+ exch //false resolvestream pdfopdict .pdfruncontext
+ cleartomark
+
+ //false
+ { countdictstack
+ 2 index le { exit } if
+ currentdict /n known not or
+ Q
+ } loop {
+ ( **** Error: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ pop
+
+ % 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
+
+/.pdfpaintproc {
+ %% Get the /m from pdfopdict (must be present)
+ %% and check its a packedarray
+ pdfopdict /m get dup type /packedarraytype eq {
+ %% get the initial element of the packedarray
+ %% and check its a name
+ 0 get dup type /nametype eq {
+ %% If the name is inside_text_m then we are in a text block
+ /inside_text_m eq
+ }{
+ pop false
+ } ifelse
+ }{
+ pop false
+ } ifelse
+ %% rearrange the operands, move the boolean to the back
+ 3 1 roll
+ %% Uncopnditionally use the normal marking ops
+ switch_to_normal_marking_ops
+ .actual_pdfpaintproc
+ %% If we were in a text block, restore the text marking ops.
+ {
+ switch_to_text_marking_ops
+ } if
+}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 /BBox 2 copy knownoget { normrect put } { pop pop } ifelse
+ dup /.pattern_uses_transparency 1 index patternusestransparency put
+ PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Pattern: ) print dup === flush } if } if
+} bdef
+
+/ignore_color_op ( **** Error: Ignoring a color operation in a cached context.\n Output may be incorrect.\n) readonly def
+
+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 } if
+ } ifelse
+ } bdef
+
+ /sc { .incachedevice {
+ .pdfcount { pop } repeat //ignore_color_op pdfformaterror
+ } {
+ scresolve { sc*_and_set } { sc1_and_set } 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 } if
+ } ifelse
+ } bdef
+
+ /ri { .incachedevice {
+ pop //ignore_color_op pdfformaterror
+ } {
+ ri
+ } ifelse
+ } bdef
+
+ /SC { .incachedevice {
+ .pdfcount { pop } repeat //ignore_color_op pdfformaterror
+ } {
+ scresolve { SC*_and_set } { SC1_and_set } ifelse
+ } ifelse
+ } bdef
+
+ /SCN /SC load def
+end
+
+currentdict /ignore_color_op undef
+
+% ---------------- Paths ---------------- %
+
+drawopdict begin
+ % Path construction
+ /m { { moveto } stopped { count pdfemptycount sub 2 .min { pop } repeat 0 0 moveto } if } bdef
+ /l { { lineto } stopped { count pdfemptycount sub 2 .min { pop } repeat } if } bdef
+ /c { { curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bdef
+
+ /v { count pdfemptycount sub 4 ge {
+ { currentpoint 6 2 roll curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if
+ } {
+ count pdfemptycount sub { pop } repeat
+ } ifelse
+ } bdef
+ /y { { 2 copy curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bdef
+
+ /re {
+ 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto
+ closepath
+ } bdef
+
+ /h { closepath } bind 0 get 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_save 1 array def
+ /sh_group << /Subtype /Group /Isolated //true >> readonly def
+
+ /do_shade {
+ 0 .setoverprintmode
+ { dup /.shading .knownget {
+ exch pop
+ } {
+ .buildshading
+ } ifelse
+ .shfill
+ } stopped {
+ pop
+ ( **** Error: Ignoring invalid smooth shading object, output may be incorrect.\n)
+ pdfformaterror
+ } if
+ } bdef
+
+ /sh {
+ OFFlevels length 0 eq {
+ setfillstate resolvesh
+ //sh_save 0 save put
+ PDFusingtransparency {
+ SoftMask //null ne {
+ //sh_group
+ 1 index /BBox knownoget {
+ { oforce } forall
+ } {
+ gsave clippath pathbbox grestore
+ } ifelse
+ .begintransparencygroup
+ } if
+ dup checkOPtrans exch 1 index {
+ % We need to push a non-isolated, non-knockout transparency group and
+ % perform the operation in CompatibleOverprint mode, then end the
+ % transparency group. Do the begintransparencygroup step here.
+ mark /Subtype /Group /Isolated //false .dicttomark
+ 1 index /BBox knownoget {
+ { oforce } forall
+ } {
+ gsave clippath pathbbox grestore
+ } ifelse
+ .begintransparencygroup
+ exch .currentblendmode exch .currentopacityalpha exch 4 -1 roll % save current values
+ /CompatibleOverprint .setblendmode 1 .setopacityalpha
+ } if
+ //do_shade exec
+ {
+ .endtransparencygroup .setopacityalpha .setblendmode % end the CompatibleOverprint group
+ } if
+ SoftMask //null ne {
+ .endtransparencygroup
+ } if
+ } {
+ //do_shade exec
+ } ifelse
+ //sh_save 0 get restore
+ } {
+ pop
+ } ifelse
+ } bdef
+ currentdict dup /sh_save undef /sh_group undef
+end
+
+% ---------------- XObjects ---------------- %
+
+/xobjectprocs mark % <dict> -proc- -
+ /Image { DoImage }
+ /Form { DoForm }
+ /PS { DoPS }
+.dicttomark readonly def
+
+% 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
+ /CalGray { pop //01_1 } bind
+ /CalRGB { pop //01_3 } bind
+ /Lab { 1 get /Range knownoget not { [-100 100 -100 100] } 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
+
+/jp2_csp_dict mark
+ 12 { /DeviceCMYK } % CMYK
+ 14 { [ /Lab << /WhitePoint [ 0.9505 1 1.0890 ] readonly >> ] } % LAB, WhitePoint == D65
+ 16 { /sRGBICC /ColorSpace findresource } bind
+ 17 { /sGrayICC /ColorSpace findresource } bind
+ 18 3 index % YCC is converted to RGB
+% 19 % CIEJab not supportec by PDF 1.7
+% 20 % e-sRGB
+% 21 % ROMMRGB
+% 24 % e-sYCC
+.dicttomark readonly def
+
+% Process jp2 blocks (aka boxes). All procedures have the signature
+% <file> <length> -> ... <file> <flush_length>
+/jp2_tag_dict 10 dict begin
+
+ /jp2h { % descend into a sub-stream, don't return.
+ () /SubFileDecode filter 0
+ } bdef
+
+ /ihdr {
+ 14 sub % file len-14
+ 1 index (1234567890abcd) readstring pop % file len-14 (14)
+ /JPXComponents 1 index 8 getu16 % file len-14 (14) /JPXComponents NC
+ def % file len-14 (14)
+ 10 get
+ %% If the BPC is 255 then each component has variable depth
+ %% we can't handle this, but JasPer is known to produce
+ %% images whcih declare this, but are actually all equal, we cater
+ %% for that in the bpcc box below.
+ dup 16#FF eq not {
+ 16#7F and 1 add
+ dup 12 eq { pop 16 } if
+ /BitsPerComponent exch def % file len-14
+ } {pop} ifelse
+ } bdef
+
+ %% if the ihdr has a BPC of 255 then we get a bpcc box which
+ %% gives the bpc for each component individually. We cannot
+ %% actually deal with differing component depths, but it
+ %% seems JasPer produces images with this box where all the
+ %% component depths are in fact the same.
+ /bpcc {
+ JPXComponents sub
+ 1 index JPXComponents string readstring pop
+ dup 0 get /BitsPerComponent exch def
+ 1 1 JPXComponents 1 sub {
+ 1 index exch get BitsPerComponent eq not {
+ ( **** Error: JPX image colour channels do not all have the same colour depth\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ } for
+
+ pop
+ /BitsPerComponent BitsPerComponent 1 add def
+ } bdef
+
+ /colr {
+ currentdict /ColorSpace known not {
+ 3 sub
+ 1 index (123) readstring pop % file len-3 (3)
+ 0 get dup 1 eq {
+ pop 4 sub % file len-7
+ 1 index (1234) readstring pop % file len-16 (4)
+ 0 getu32 % file len-16 enum
+ //jp2_csp_dict exch .knownget {
+ exec /ColorSpace exch def % file len-7
+ } {
+ ( **** Error: Unknown enumerated color space in JPX stream.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ } {
+ dup 2 eq exch 3 eq or {
+ 1 index exch () /SubFileDecode filter /ReusableStreamDecode filter
+ /JPXICC exch def
+ 0 % file 0
+ } {
+ ( **** Error: Unknown color space method in JPX stream.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ } ifelse
+ } if
+ } bdef
+
+ % Palette colors are decoded by the library.
+ /pclr {
+ 4 sub
+ 1 index (1234) readstring pop
+ 3 get 16#7F and 1 add
+ /BitsPerComponent exch def
+ } bdef
+
+ /cdef {
+ pop
+ dup (12) readstring pop
+ 0 getu16 {
+ dup (123456) readstring pop
+ 2 getu16
+ dup 3 lt {
+ { /JPXColors /JPXOpacity /JPXPremult } exch get
+ currentdict 1 index .knownget { 1 add } { 1 } ifelse def
+ } {
+ pop
+ } ifelse
+ } repeat
+ 0
+ } bdef
+
+currentdict end 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 //== exec % f (TBox) LBox-8..16
+ } if
+
+ //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
+currentdict /jp2_csp_dict .undef
+
+% Add a key-value pair to the last /DecodeParms dictionary
+% Copy the objects to avoid spoiling shared ones.
+% <resdict> <key> <value> -> <resdict>
+/add-to-last-param {
+ 2 index /DecodeParms knownoget {
+ dup {} eq {
+ pop //false
+ } {
+ //true
+ } ifelse
+ } {
+ //false
+ } ifelse {
+ dup type /arraytype eq {
+ [ exch { oforce } forall
+ dup //null eq { pop 1 dict } if
+ ]
+ dup dup length 1 sub get % <resdict> <key> <value> [] <<>>
+ } {
+ dup length 1 add dict copy dup % <resdict> <key> <value> <<>> <<>>
+ } ifelse
+ 4 2 roll put % <resdict> obj
+ } {
+ % <resdict> <key> <value>
+ mark 3 1 roll .dicttomark % <resdict> obj
+ 1 index /Filter knownoget {
+ dup type /arraytype eq {
+ length array % <resdict> obj [...]
+ dup dup length 1 sub % <resdict> obj [...] [...] len-1
+ 4 -1 roll put % <resdict> [... obj]
+ } {
+ pop
+ } ifelse
+ } if
+ } ifelse
+ 1 index exch
+ /DecodeParms exch put % <resdict>
+} bdef
+
+/last-ditch-bpc-csp {
+ currentdict /BitsPerComponent oknown not {
+ ( **** Error: image has no /BitsPerComponent key; assuming 8 bit.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ /BitsPerComponent 8 def
+ } if
+
+ currentdict /ColorSpace knownoget not {
+ dup /ColorSpace knownoget not {
+ ( **** Error: image has no /ColorSpace key; assuming /DeviceRGB.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ /DeviceRGB
+ } if
+ } if
+ resolvecolorspace
+
+ %% This section is to deal with the horrible pair of files in Bug #696690 and Bug #696120
+ %% These files have ICCBased spaces where the value of /N and the number of components
+ %% in the profile differ. In addition the profile in Bug #696690 is invalid. In the
+ %% case of Bug #696690 the /N value is correct, and the profile is wrong, in the case
+ %% of Bug #696120 the /N value is incorrect and the profile is correct.
+ %% We 'suspect' that Acrobat uses the fact that Bug #696120 is a pure image to detect
+ %% that the /N is incorrect, we can't be sure whether it uses the profile or just uses
+ %% the /N to decide on a device space. What we now do is; If the /N and device profile
+ %% number of components don't match, we assume the device profile is correct and patch
+ %% /N to be the same as the profile (see /ICCBased-resolve), but we save the original
+ %% value of /N in /OrigN. In setcolor, if the space is a genuine ICCBased space
+ %% (not a replacement for a device profile) we call set_dev_color which will actually
+ %% exercise the profile. If that fails we return an error. Here we run setcolor in a
+ %% stopped context, and if it fails we check to see if there is a /OrigN (ths occurs
+ %% only if the /N was different to the number of components in the profile). If there
+ %% is a /OrigN then prefer that to the profile, otherwise they agreed, so just use
+ %% /N and select a device space. If we can't select a device space with the correct
+ %% number of components, give up and throw an error. See also 'Cdict' in pdf_ops.ps.
+ dup type /arraytype eq {
+ dup 0 get /ICCBased eq {
+ gsave
+ dup setcolorspace dup 1 get /N get
+ 1 sub mark exch 0 1 3 -1 roll
+ {pop 0} for
+ {setcolor} stopped
+ grestore
+ {
+ cleartomark
+ 1 get
+ dup /OrigN .knownget {exch pop}{/N get} ifelse
+ [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch
+ {get} stopped
+ {
+ ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print
+ /setcolorspace cvx /undefined signalerror
+ }
+ {
+ dup //null eq {
+ ( **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print
+ /setcolorspace cvx /undefined signalerror
+ }{
+ ICCProfileNError not {
+ ( **** Warning : Error setting an ICCBased colour space, using /N to set an alternate device space.\n) print
+ ( Output may be incorrect.\n) print
+ } if
+ } ifelse
+ }ifelse
+ /ICCProfileNError true def
+ }{cleartomark}ifelse
+ } if
+ } if
+ /ColorSpace exch def
+} bdef
+
+/get-smask-in-data { % <dict> -> <int>
+ /SMaskInData knownoget {
+ dup dup 1 ne exch 2 ne and {
+ pop 0
+ } if
+ } {
+ 0
+ } ifelse
+} bdef
+
+/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 { cvi 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
+
+ %% If the image has a rendering intent, get its numeric equivalent
+ %% from renderingintentdict, and save it in the dictionary we pass
+ %% on to render images.
+ dup /Intent knownoget {
+ //.renderingintentdict exch .knownget { /Intent exch def } if
+ } if
+
+ 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 /Filter knownoget {
+ dup type /arraytype eq {
+ dup length
+ dup 0 gt {
+ 1 sub get oforce
+ } {
+ pop
+ } ifelse
+ } if
+ /JPXDecode eq
+ } {
+ //false
+ } ifelse {
+ % /JPXDecode tricks
+
+ % Previously we only ran the code to extract the Color Space and Bits Per Component
+ % from the JOX stream if the image dict had either BPC or ColorSpace undefined.
+ % However, while this is correct for the ColorSpace, its *not* correct for the BPC.
+ % According to the spec we should ignore any BPC in the image dicitonary and
+ % always use the BPC from the JPX stream.
+ % Now the code in get_jp2_csp always overwrites the ColorSpace (in the image resource dict)
+ % which technically is fine, because the image dictionary entry must be either not present or the
+ % same as the JPX stream. However, this doesn't work, so instead we just save the existing
+ % color space (if any). Then after extracting the color space and BPC from the JPX stream
+ % we put back the saved color space, but only if there was one previously.
+ dup /ColorSpace oknown {
+ dup dup /ColorSpace get /ImageDictColorSpace exch put
+ } if
+ dup /IDFlag known {
+ ( **** Warning: PDF spec bans inline JPX images.\n) pdfformatwarning
+ % 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 /DecodeParms knownoget {
+ dup type /arraytype eq {
+ dup length 1 gt {
+ dup length 1 sub 0 exch getinterval
+ 1 index exch /DecodeParms exch put
+ } {
+ pop
+ dup /DecodeParms undef
+ } ifelse
+ } {
+ pop
+ dup /DecodeParms undef
+ } ifelse
+ } if
+ } {
+ pop
+ dup /Filter undef
+ dup /DecodeParms undef
+ } ifelse
+ } {
+ pop
+ dup /Filter undef
+ dup /DecodeParms undef
+ } ifelse
+
+ //false resolvestream get_jp2_csp
+
+ currentdict /ColorSpace oknown not {
+ currentdict /JPXICC .knownget {
+ [ /ICCBased mark
+ /DataSource 5 -1 roll
+ /N currentdict /JPXColors .knownget not {
+ currentdict /JPXComponents get
+ } if
+ .dicttomark
+ ] /ColorSpace exch def
+ } if
+ } if
+
+ { /JPXICC /JPXColors /JPXComponents /JPXOpacity /JPXPremult } {
+ currentdict exch undef
+ } forall
+
+ } ifelse
+
+ % If we had a Color Space in the image dictionary before we read the JPX
+ % stream, put it back now. We mujst do this before last-ditch-bpc-csp
+ % because that resolves any indirect references to the color space.
+ dup /ImageDictColorSpace known {
+ dup /ImageDictColorSpace get currentdict /ColorSpace 3 -1 roll put
+ } if
+
+ //last-ditch-bpc-csp exec
+
+ dup /ColorSpace oknown {
+ % Propagate known color space to the filter
+ /ColorSpace currentdict /ColorSpace get //add-to-last-param exec
+ } if
+
+ /Decode 2 copy knownoget not {
+ ColorSpace //defaultdecodedict
+ ColorSpace dup type /arraytype eq { 0 get } if get exec
+ } if def
+
+ dup get-smask-in-data dup 0 ne {
+ PDFusingtransparency {
+ currentdict dup length dict copy begin
+ {/Mask/SMask/SMaskInData/Name} { currentdict exch undef } forall
+ 2 eq {
+ /Matte [ Decode length 2 idiv { 0 } repeat ] def
+ } if
+ /Decode //01_1 def
+ /ColorSpace /DeviceGray def
+ {/File /FilePosition /Filter /Length /DecodeParms /FFilter /FDecodeParms } {
+ 2 copy knownoget {
+ def
+ } {
+ pop
+ } ifelse
+ } forall
+ currentdict /Alpha //true //add-to-last-param exec pop
+ /SMask currentdict end def
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } { % not JPX image
+ //last-ditch-bpc-csp exec
+ /Decode 2 copy knownoget not {
+ ColorSpace //defaultdecodedict
+ ColorSpace dup type /arraytype eq { 0 get } if get exec
+ } if def
+
+ } ifelse % fi JPX tricks
+
+ % Add a /Height key containing the image height to the DecodeParms
+ % for any Filters we will apply. If there are no DecodeParms for any
+ % filter, create one and add a /Height key. This is to solve the problem
+ % in Bug #695116 where a JPEG image has a bad height, which is later
+ % fixed up using a DNL marker. By placing the image height from the
+ % PDF in the DeoceParms we cna use it in the DCTDecode filter to
+ % work around this.
+ dup /Filter knownoget { % <<stream dict>> /name or [array]
+ dup type /arraytype eq {
+ % <<stream dict>> [array of names]
+ length % <<stream dict>> number of filters
+ 1 index /DecodeParms knownoget {
+ exch pop % drop length of Filter array, the DecodeParams has 1 entry per filter
+ % <<stream dict>> [array of decodeparams]
+ } {
+ % No deocde params, we must make an array of them
+ % <<stream dict>> number of filters
+ array % <<stream dict>> []
+ dup % <<stream dict>> [] []
+ 2 index /DecodeParms exch % <<stream dict>> [] [] /DecodeParms <<stream dict>>
+ 3 1 roll % <<stream dict>> <<stream dict>> [] /DecodeParms
+ exch put % <<stream dict>> []
+ } ifelse
+ dup length 1 sub % <<stream dict>> [] arraylength-1
+ 0 1 3 -1 roll % <<stream dict>> [] 0 1 arraylength-1
+ { % <<stream dict>> [] loopcount
+ 1 index % <<stream dict>> [] loopcount []
+ 2 copy % <<stream dict>> [] loopcount [] loopcount []
+ exch
+ get % <<stream dict>> [] loopcount [] <<>> or -null-
+ dup null eq {
+ pop exch % <<stream dict>> [] [] loopcount
+ <</Height
+ 5 index /Height oget % <<stream dict>> [] [] loopcount << /Height Height
+ round cvi
+ >>
+ put % <<stream dict>> []
+ }{ %
+ oforce_recursive % resolve any indirect references
+ dup type /dicttype eq {
+ % <<stream dict>> [] loopcount [] <<>>
+ /Height % <<stream dict>> [] loopcount [] <<>> /Height
+ 5 index /Height oget % <<stream dict>> [] loopcount [] <<>> /Height Height
+ round
+ cvi
+ put pop pop % <<stream dict>> []
+ }{
+ %% bogus entry, throw it away and create a new one
+ pop exch % <<stream dict>> [] loopcount []
+ <</Height
+ 5 index /Height oget % <<stream dict>> [] [] loopcount << /Height Height
+ round cvi
+ >>
+ put % <<stream dict>> []
+ } ifelse
+ }ifelse
+ } for
+ pop % <<stream dict>>
+ }{
+ pop % <<stream dict>>
+ dup /DecodeParms knownoget {
+ oforce_recursive % resolve any indirect references
+ dup type /dicttype eq {
+ % <<stream dict>> <<decode parms dict>>
+ /Height 2 index % <<stream dict>> <<decode parms dict>> /Height <<stream dict>>
+ /Height oget % <<stream dict>> <<decode parms dict>> /Height ImageHeight
+ round cvi
+ put % <<stream dict>>
+ }{
+ %% bogus entry, throw it away and create a new one
+ pop % <<image dict>> <<stream dict>> []
+ <</Height % <<stream dict>> <<image dict>> << /Height
+ 2 index /Height oget % <<stream dict>> <<image dict>> << /Height Height
+ round cvi
+ >>
+ 1 index exch /DecodeParms exch put % <<stream dict> <<image dict>>
+ } ifelse
+ }{
+ dup % <<stream dict>> <<stream dict>>
+ /DecodeParms <</Height % <<stream dict>> <<stream dict>> /DecodeParms << /Height
+ 3 index % <<stream dict>> <<stream dict>> /DecodeParms << /Height <<stream dict>>
+ /Height oget
+ round cvi
+ >> % <<stream dict>> <<stream dict>> /DecodeParms << /Height ImageHeight>>
+ put % <<stream dict>>
+ }ifelse
+ }ifelse
+ } if
+
+ % 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
+
+currentdict /add-to-last-param undef
+currentdict /last-ditch-bpc-csp undef
+
+/DoImage {
+ %% Bug #696439. This is incredibly icky. When we find indirect obects we resolve them
+ %% and store the resolved object in the containing object. This means that we retain
+ %% the image dicionary here until the end of job. Potentially wasteful. Even worse though
+ %% is the case where the image has a ColorSpace which is not an indirect object, but *is*
+ %% an ICCBased colour space. In ths case we end up resolving the colour space and storing it
+ %% here. Unfortunately, we use a ReusableStreamDecode filter on the ICC profile, which means
+ %% we end up retaining the memory for that too. ICC profiles can be large, and if there are a
+ %% lot of places where they get used, we can exhaust memory.
+ %% Here we check if the ColorSpace is an array object, if it is we *copy* the image dictionary
+ %% and use the copy instead. The copy is (eventually) discarded so we don't retain the ICC profile
+ %% and don't exhaust memory. Note that we have to copy the actual colour space array too, copying
+ %% the dictionary just copies the opriginal array as well.
+ %%
+ dup /ColorSpace known {
+ dup /ColorSpace get dup type /arraytype eq {
+ exch dup length dict copy exch
+ dup length array copy /ColorSpace exch 2 index 3 1 roll put
+ } {pop} ifelse
+ } if
+
+ checkaltimage dup length 6 add dict % <<image>> <<>>
+ 1 index /SMask knownoget { % <<image>> <<>> <<sm>>
+ dup 3 index ne { % <<image>> <<>> <<sm>> <<sm>>
+ 1 index exch /SMask exch put
+ } {
+ pop
+ ( **** Error: ignoring recursive /SMask attribute.\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ } 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 {
+ oforce_array
+ //false 1 index {
+ type /integertype ne or
+ } forall {
+ (\n **** Error: Some elements of Mask array are not integers.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ [ exch { 0.5 add cvi } forall ] % following AR4, 5, 6 implementation
+ } if
+ } if
+ % Check elements of array are within 0::(2**BitsPerComponent)-1
+ % This is a PostScript error, but AR tries to fix the Mask.
+ 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 {
+ ( **** Error: Some elements of Mask array are out of range.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+
+ ColorSpace dup type /arraytype eq { 0 oget } if /Indexed eq
+ BitsPerComponent 1 eq and {
+ % AR9 treats Indexed 1 bpc images specially. Bug 692852.
+ dup 0 oget
+ dup 0 lt exch 1 BitsPerComponent bitshift ge or {
+ % First component is invalid - AR9 ignores the mask
+ pop //null
+ } {
+ % Second component is invalid; AR9 replaces it with 1.
+ [ exch 0 oget 1 ]
+ } ifelse
+ } {
+ % AR5, AR9 do this for most cases. Bug 690786.
+ [ exch { 1 BitsPerComponent bitshift 1 sub and } forall ]
+ } ifelse
+ } if
+ dup //null ne {
+ /MaskColor exch def
+ } {
+ pop
+ /ImageType 1 def
+ } ifelse
+ } {
+ % 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} stopped {pop} if 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>
+ /PreserveSMask /GetDeviceParam .special_op {
+ exch pop
+ }{
+ //false
+ }ifelse
+ {
+ pop % pdfwrite will process SMask directly during 'doimage'
+ } {
+ .begintransparencymaskimage
+ PDFfile fileposition exch
+ gsave //nodict begin
+ //null /SoftMask gput
+ 1 .setopacityalpha 1 .setshapealpha
+ 1 CA 1 ca
+ /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/gdevpdft.c
+ >> 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
+ } {
+ 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 handler
+% for images with a soft mask.
+//systemdict /NEW_IMAGE3X .knownget not { //false } if {
+ /doimagesmask { % <imagemask> doimagesmask -
+ doimage
+ } bdef
+} if
+
+/doimage { % <imagemask> doimage -
+ % imagedict is currentdict, gets popped from dstack
+ //null checkOPtrans {
+ % We need to push a non-isolated, non-knockout transparency group and
+ % perform the operation in CompatibleOverprint mode, then end the
+ % transparency group. Do the begintransparencygroup step here.
+ mark /Subtype /Group /Isolated //false .dicttomark 0 0 1 1 .begintransparencygroup
+ OPsavedict dup /saveBM .currentblendmode put /saveOA .currentopacityalpha put % save current values
+ /CompatibleOverprint .setblendmode 1 .setopacityalpha
+ } if
+
+ %% save the current rendering intent
+ .currentrenderintent exch
+
+ %% Check the image dictionary to see if there is a /Intent
+ currentdict /Intent known {
+ %% and set the current rendering intent to match if so
+ Intent .setrenderingintent
+ } if
+
+ DataSource exch
+ currentdict /SMask known PDFusingtransparency and {
+ /PreserveSMask /GetDeviceParam .special_op {
+ pop pop
+ currentdict /SMask oget
+ makesoftmaskimage
+ } if
+ } if
+ currentdict /Mask knownoget {
+ makemaskimage
+ } if
+ % Stack: datasource imagemask
+ { currentdict end setfillstate { imagemask } }
+ { ColorSpace setgcolorspace currentdict end setfillblend { image } }
+ ifelse
+ PDFSTOPONERROR { exec //false } { stopped } ifelse {
+ dup type /dicttype eq { pop } if % Sometimes image fails to restore the stack
+ $error /errorname get dup /ioerror eq {
+ pop (\n **** Error: File has insufficient data for an image.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } {
+ (\n **** Error: File encountered ')
+ exch 40 string cvs concatstrings
+ (' error while processing an image.\n) concatstrings
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ } if
+ % Close the input stream, unless it is PDFfile or
+ % PDFsource.
+ dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
+
+ %% restore the rendering intent
+ .setrenderingintent
+
+ .currentblendmode /CompatibleOverprint eq {
+ .endtransparencygroup
+ OPsavedict dup /saveOA get .setopacityalpha /saveBM get .setblendmode
+ } if
+} bdef
+
+/.paintform { % <formdict> <resdict> <stream> .paintform -
+ 1 index /FormResDict gput % For broken forms that inherit resources from the context.
+ 3 -1 roll dup /Group known PDFusingtransparency and {
+ .paintgroupform
+ } {
+ pop pdfopdict .pdfruncontext
+ } ifelse
+} bdef
+
+/IncrementAppearanceNumber {
+ pdfdict /AppearanceNumber .knownget {
+ 1 add pdfdict /AppearanceNumber 3 -1 roll .forceput
+ }{
+ pdfdict /AppearanceNumber 0 .forceput
+ } ifelse
+}bdef
+
+/MakeAppearanceName {
+ pdfdict /AppearanceNumber get
+ 10 string cvs
+ dup length 10 add string dup 0 (\{FormName) putinterval
+ dup 3 -1 roll
+ 9 exch putinterval
+ dup dup length 1 sub (\}) putinterval
+} bdef
+
+/MakeNewAppearanceName {
+ IncrementAppearanceNumber
+ MakeAppearanceName
+}bdef
+
+/DoAppearance {
+%% Might need to rethink this. The problem is that if the page has a CropBox, we apply
+%% that as an initial clip. When we run the form, we don't apply the /Rect from the
+%% annotation, which means that the form could be out of the clip, which results in
+%% content going missing. Resetting the clip prevents this.
+ gsave initclip
+ MakeNewAppearanceName
+ .pdfFormName
+ pdfdict /.PreservePDFForm known {pdfdict /.PreservePDFForm get} {//false}ifelse exch
+ pdfdict /.PreservePDFForm true .forceput
+ DoForm
+ pdfdict /.PreservePDFForm 3 -1 roll .forceput
+ grestore
+} bdef
+
+/DoForm {
+ %% save the current value, if its true we will set it to false later, in order
+ %% to prevent us preserving Forms which are used *from* an annotation /Appearance.
+ pdfdict /.PreservePDFForm known {pdfdict /.PreservePDFForm get} {//false}ifelse exch
+
+ %% We may alter the Default* colour spaces, if the Resources
+ %% ColorSpace entry contains one of them. But we don't want that
+ %% to become the new default, we want to revert to any existing
+ %% definition, or the Device space. The Default* spaces are defined
+ %% as ColorSpace resources, so the only way to handle them is to
+ %% save and restore round the definitions
+ 3 dict dup begin
+ /saved_DG /DefaultGray /ColorSpace findresource def
+ /saved_DRGB /DefaultRGB /ColorSpace findresource def
+ /saved_DCMYK /DefaultCMYK /ColorSpace findresource def
+ end
+ exch
+
+ % 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 }
+ {
+ 0 1 Matrix length 1 sub
+ {
+ dup Matrix exch get type dup
+ /integertype eq exch
+ /realtype eq or not
+ {
+ (\n **** Error: Invalid element in /Form XObject matrix.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ Matrix exch 0.00 put
+ }
+ { pop }
+ ifelse
+ } for
+ } ifelse
+ currentdict /BBox known not {
+ (\n **** Error: Required entry /BBox not present in Form.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ /BBox [0 1 0 1]
+ } if
+ currentdict end { oforce } forall
+ >>
+ dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
+
+ %% Ugly hackery for Default* colour spaces in forms
+ %%
+ dup /ColorSpace knownoget {
+ oforce {
+ //false 3 1 roll
+ exch dup /DefaultGray eq
+ {
+ pop exec resolvecolorspace dup csncomp 1 eq {
+ dup type /nametype eq { 1 array astore } if
+ /DefaultGray exch /ColorSpace defineresource pop
+ pop //true
+ }{
+ pop
+ ( **** Error: ignoring invalid /DefaultGray color space.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ }{
+ dup /DefaultRGB eq {
+ pop exec resolvecolorspace dup csncomp 3 eq {
+ dup type /nametype eq { 1 array astore } if
+ /DefaultRGB exch /ColorSpace defineresource pop
+ pop //true
+ }{
+ pop
+ ( **** Error: ignoring invalid /DefaultRGB color space in Form Resources.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ }{
+ /DefaultCMYK eq {
+ exec resolvecolorspace dup csncomp 4 eq {
+ dup type /nametype eq { 1 array astore } if
+ /DefaultCMYK exch /ColorSpace defineresource pop
+ pop //true
+ }{
+ pop
+ ( **** Error: ignoring invalid /DefaultCMYK color space in Form Resources.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ }{
+ pop
+ } ifelse
+ } ifelse
+ }ifelse
+ { % if using color space substitution, "transition" the current color space
+ currentcolorspace dup length 1 eq { % always an array
+ 0 get
+ dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK eq or {
+ /Pattern setcolorspace setcolorspace
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } if
+ } forall
+ } if
+
+ 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 4 sub store
+
+ pdfdict /.PreservePDFForm known {pdfdict /.PreservePDFForm get}{//false} ifelse
+ {
+ %% We must *not* preserve any subsidiary forms (curently at least) as PDF
+ %% form preservation doesn't really work. This is used just for Annotation
+ %% Appearances currently, and if they should happen to use a form, we do not
+ %% want to preserve it.
+ pdfdict /.PreservePDFForm false .forceput
+ /q cvx /execform cvx 5 -2 roll
+ }{
+ /q cvx /PDFexecform cvx 5 -2 roll
+ } ifelse
+
+ 4 .execn
+ % Restore pdfemptycount
+ 0
+ { countdictstack
+ 2 index le { exit } if
+ currentdict /n known not { 1 add } if
+ countdictstack
+ Q
+ countdictstack eq {end} if
+ } loop
+ 1 gt {
+ ( **** Error: Form stream has unbalanced q/Q operators \(too many q's\)\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ pop
+ /pdfemptycount exch store
+
+ %% Put back pre-existing Default* ColorSpace definitions.
+ dup type /dicttype eq {
+ begin
+ saved_DG /DefaultGray exch /ColorSpace defineresource pop
+ saved_DRGB /DefaultRGB exch /ColorSpace defineresource pop
+ saved_DCMYK /DefaultCMYK exch /ColorSpace defineresource pop
+ end
+ } if
+ pdfdict /.PreservePDFForm 3 -1 roll .forceput
+} 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
+
+/ocg_pocs 4 dict begin
+ /AllOn {
+ //true exch {
+ oforce dup type /dicttype eq {
+ /OFF known not and
+ } {
+ pop
+ } ifelse
+ } forall
+ } bdef
+ /AnyOn {
+ //false exch {
+ oforce dup type /dicttype eq {
+ /OFF known not or
+ } {
+ pop
+ } ifelse
+ } forall
+ } bdef
+ /AnyOff {
+ //AllOn exec not
+ } bdef
+ /AllOff {
+ //AnyOn exec not
+ } bdef
+currentdict end readonly def
+
+% Check whether OCG or OCMD is visible
+% <dict> oc-is-visible <bool>
+/ocg-is-visible {
+ dup /Type knownoget {
+ /OCMD eq {
+ dup /OCGs knownoget not { {} } if % OC OCGs
+ dup type /dicttype eq { 1 array astore } if
+ //true 1 index { //null eq and } forall {
+ pop pop //true % all nulls => show
+ } {
+ exch /P knownoget not { /AnyOn } if % OCGs P
+ //ocg_pocs exch get exec % bool
+ } ifelse
+ } {
+ /OFF known not % OFF is inserted by process_trailer_attrs
+ } ifelse
+ } {
+ /OFF known not % OFF is inserted by process_trailer_attrs
+ } ifelse
+} bdef
+
+drawopdict begin
+ /Do { % /Name
+ %% Bug 695897 This file has nested text blocks and also a Do image inside
+ %% a text block. Here we attempt to detect and recover from this by setting the
+ %% CTM to the matrix we saved before the text block. NB we update the 'TextSaveMatrix'
+ %% or 'qTextSaveMatrix' whenever a 'cm' is issued, even if we are in a text block, so
+ %% these matrices 'ought' to be correct.
+ %% Of course, the file is badly broken, but 'Acrobat can open it....'
+ currentdict /TextSaveMatrix known {
+ gsave
+ ( **** Error: Executing Do inside a text block, attempting to recover\n) pdfformaterror
+ currentdict /TextSaveMatrix get setmatrix
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ currentdict /qTextSaveMatrix known {
+ gsave
+ ( **** Error: Executing Do inside a text block, attempting to recover\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ currentdict /qTextSaveMatrix get setmatrix
+ } if
+ setfillblend
+ PDFfile fileposition exch % pos /Name
+ dup Page /XObject rget {
+ exch pop % pos obj
+ OFFlevels length 0 eq {
+ dup /OC knownoget { ocg-is-visible } { //true } ifelse
+ } {
+ //false
+ } ifelse {
+ dup /Subtype oget //xobjectprocs exch get % pos obj {proc}
+ % Don't leave extra objects on the stack while executing
+ % the definition of the form.
+ 3 -1 roll % obj {proc} pos
+ 2 .execn % pos
+ } {
+ pop % pos
+ } ifelse
+ } {
+ % This should cause an error, but Acrobat Reader can
+ % continue, so we do too.
+ ( **** Error: Undefined XObject resource: )
+ exch =string cvs concatstrings (\n) concatstrings
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ PDFfile exch setfileposition
+ } bdef
+end
+
+currentdict /xobjectprocs .undef
+currentdict /ocg_pocs .undef
+
+% ---------------- 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 {
+ gsave
+ %% Bug 696547, related to Bug 695897 (see /Do above) This file has an inline image inside
+ %% a text block. Here we attempt to detect and recover from this by setting the
+ %% CTM to the matrix we saved before the text block. NB we update the 'TextSaveMatrix'
+ %% or 'qTextSaveMatrix' whenever a 'cm' is issued, even if we are in a text block, so
+ %% these matrices 'ought' to be correct.
+ %% Of course, the file is badly broken, but 'Acrobat can open it....'
+ currentdict /TextSaveMatrix known {
+ ( **** Error: Executing ID inside a text block, attempting to recover\n) pdfformaterror
+ currentdict /TextSaveMatrix get setmatrix
+ ( Output may be incorrect.\n) pdfformaterror
+ } if
+ currentdict /qTextSaveMatrix known {
+ ( **** Error: Executing ID inside a text block, attempting to recover\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ currentdict /qTextSaveMatrix get setmatrix
+ } if
+
+ 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
+ OFFlevels length 0 eq {
+ doimage
+ } {
+ pop Width
+ currentdict /ImageMask knownoget dup { and } if not {
+ ColorSpace oforce csncomp mul
+ BitsPerComponent mul
+ } if
+ 7 add 8 idiv Height mul
+ DataSource exch () /SubFileDecode filter flushfile
+ end
+ } ifelse
+ % 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
+ grestore
+ } bdef
+end
+
+currentdict /is_space_dict undef
+
+% ================================ 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 { TJ } def
+
+ /Tform { Tform } def % Text formatting and painting for AcroForm
+ % without appearance streams.
+end
+
+% ======================= Invalid operators ============================ %
+
+drawopdict begin
+ /QBT {
+ Q BT
+ ( **** Error: invalid operator QBT processed as Q BT .\n)
+ pdfformaterror % Bug 690089
+ ( Output may be incorrect.\n) pdfformaterror
+ } def
+
+ /. {
+ 0.
+ ( **** Error: invalid operator . processed as number 0. .\n)
+ pdfformaterror % Bug 690730
+ ( Output may be incorrect.\n) pdfformaterror
+ } def
+end
+
+% ============================== Annotations ============================== %
+
+% Create links from separate widget annotations to the parent field nodes.
+% Surprisingly, separate widget annotations don't have a link to the parent
+% from which they inherit some data.
+/link_widget_annots { % <<parent>> <<kid>> -> <<parent>> <<kid>>
+ dup /Kids knownoget {
+ { oforce
+ dup type /dicttype eq {
+ link_widget_annots
+ } if
+ pop
+ } forall
+ } if
+ dup /Parent oknown not {
+ 2 copy exch /ParentField exch put
+ } if
+} bdef
+
+% Get and normalize an annotation's rectangle.
+/annotrect { % <annot> annotrect <x> <y> <w> <h>
+ /Rect oget oforce_recursive aload pop
+ exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if
+ exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if
+} bdef
+
+% Set an annotation color.
+% If the /C array is empty we don't want to draw the annotation
+%
+/annotsetcolor { % <annot> annotsetcolor bool
+ /C knownoget {
+ dup length 4 eq {
+ aload pop setcmykcolor true
+ }{
+ dup length 3 eq {
+ aload pop setrgbcolor true
+ }{
+ dup length 1 eq {
+ aload pop setgray true
+ } {
+ dup length 0 eq {
+ pop
+ false
+ }{
+ ( **** Error: invalid color specified for annotation /C entry)
+ pdfformaterror false
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ } ifelse
+ } ifelse
+ } ifelse
+ }
+ { 0 setgray true} 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
+ } {
+ 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 {
+ ( **** Error: Invalids annotation border object, border has not been drawn.\n)
+ pdfformaterror
+ ( Output may be incorrect.\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 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
+ 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
+%
+% AR8 and AR9 print 3D annotations even if Print flag is off. Bug 691486.
+%
+/annotvisible { % <annot> annotvisible <visible>
+ dup /Subtype knownoget { /3D eq } { //false } ifelse % 3D annot
+ exch /F knownoget not { 0 } if % Get flag value
+ dup 2 and 0 eq {
+ /Printed load {
+ 4 and 4 eq or % Printed or 3D
+ } {
+ 32 and 0 eq exch pop % not NoView
+ } ifelse
+ } {
+ pop pop //false % Hidden
+ } ifelse
+} bdef
+
+/set_bc_color <<
+ 1 { 0 get oforce setgray } bind
+ 3 { { oforce } forall setrgbcolor } bind
+ 4 { { oforce } forall setcmykcolor } bind
+>> readonly def
+
+% Get an inherited attribute from a node through /Parent and /ParentField
+% links. The latter is set at start-up to access parents of annotations and
+% defaults at AcroForm.
+/fget % <field> <key> fget <value> -true-
+ { % <field> <key> fget -false-
+ {
+ 2 copy knownoget {
+ exch pop exch pop //true exit
+ } {
+ exch
+ dup /Parent knownoget {
+ exch pop exch
+ } {
+ /ParentField knownoget {
+ exch
+ } {
+ pop //false exit
+ } ifelse
+ } ifelse
+ } ifelse
+ } loop
+ } bind def
+
+% <annot> foo <annot>
+/make_tx_da {
+ 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 roll sub abs exch ] def
+ /Resources 1 index /DR fget not { 0 dict } if def
+ /File 1 index /V fget not { () } if length
+ 2 index /DA fget not { () } if length add
+ 500 add 65535 .min string dup 3 1 roll def
+ /NullEncode filter % <annot> file
+
+ dup (BT ) writestring
+ 1 index /DA fget not {
+ 1 index /V fget {
+ <FEFF> anchorsearch{
+ pop pop /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont
+ }{
+ pop /Helvetica findfont 12 scalefont setfont
+ } ifelse
+ } if
+ ()
+ }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 2 index /MaxLen fget not { 0 } if write=
+ dup 2 index /V fget not { () } if write==
+ dup 2 index /Ff fget not { 0 } if write=
+ dup 2 index /Q fget not { 0 } if write=
+ dup (Tform ET) write=
+ dup .fileposition /Length exch def
+ /File File 0 Length getinterval def
+ closefile % <annot>
+ end
+} bdef
+
+/can-regenerate-ap { % <annot> -> <bool>
+ //false exch
+ NeedAppearances {
+ dup /FT fget {
+ /Tx eq {
+ dup /V oknown {
+ pop not 1
+ } if
+ } if
+ } if
+ } if
+ pop
+} bdef
+
+/drawwidget { % <scalefactor_x> <scalefactor_y> <annot> drawwidget -
+
+%% This code checks to see if we can geenrate an appearance stream for the
+%% given widget, and if we can it ignores the given Appearance stream, so that
+%% we generate one instead. This seems wrong to me, if we've been given an
+%% appearance stream we should use it, no synthesize something else. Several
+%% files in our regression test suite render 'incorrectly' when compared to
+%% Acrobat with this removed, clearly Acrobat always ignores appearances. However
+%% several other files are rendered better when we *don't* ignore the Appearance
+%% So on balance I'm choosing to honour the appearance.
+%%
+% dup /UpdatedAP known not {
+% dup can-regenerate-ap {
+% dup /AP undef
+% } 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
+ } 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 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
+ } {
+ % 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
+ {
+ 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
+ } {
+ 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
+
+ dup can-regenerate-ap {
+ make_tx_da
+ dup /UpdatedAP //true put
+ 3 copy drawwidget
+ } if
+ } ifelse
+ pop pop pop
+} bdef
+
+currentdict /set_bc_color undef
+
+% 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
+ 2 index /AP knownoget {
+ /N knownogetdict { % <<Annot>> x y <<N>>
+ dup 4 index /AS knownoget {
+ knownoget {
+ exch pop
+ } if
+ } {
+ pop
+ } ifelse
+ 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 {
+ ( **** Error: /BBox has zero width or height, which is not allowed.\n)
+ pdfformaterror
+ ( Output may be incorrect.\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
+ 3 -1 roll pop
+ } {
+ ( **** Error: /Annot dict is missing required /Rect entry.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ pop 1 1
+ } ifelse
+} bdef
+
+% Draw an annotation.
+/drawannottypes 20 dict begin
+
+ % x0 y0 x1 y1 x2 y2 x3 y3 -> x0 y0 x1-x0 y1-y0 x2-x0 y2-y0
+ /quadpoints2basis {
+ 8 { oforce 8 1 roll } repeat
+
+ % The text is oriented with respect to the vertex with the smallest
+ % y value (or the leftmost of those, if there are two such vertices)
+ % (x0, y0) and the next vertex in a counterclockwise direction
+ % (x1, y1), regardless of whether these are the first two points in
+ % the QuadPoints array.
+
+ 2 {
+ 2 index 1 index eq {
+ 3 index 2 index gt {
+ 4 2 roll
+ } if
+ } {
+ 2 index 1 index gt {
+ 4 2 roll
+ } if
+ } ifelse
+ 8 4 roll
+ } repeat
+ 6 index 3 index gt {
+ 8 4 roll
+ } if
+
+ % ^
+ % |
+ % * (x2,y2) * (x3,y3)
+ % |
+ % |
+ % *------------*->
+ % (x0,y0) (x1,y1)
+
+ pop pop % x0 y0 x1 y1 x2 y2
+ 4 index sub exch % x0 y0 x1 y1 y2-y0 x2
+ 5 index sub exch % x0 y0 x1 y1 x2-x0 y2-y0
+ 4 2 roll
+ 4 index sub exch % x0 y0 x2-x0 y2-y0 y1-y0 x1
+ 5 index sub exch % x0 y0 x2-x0 y2-y0 x1-x0 y1-y0
+ 4 2 roll % x0 y0 x1-x0 y1-y0 x2-x0 y2-y0
+ } bdef
+
+ /Link { % <annot> -> <false>
+ 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
+ } bdef
+
+ /Ink { % <annot> -> <annot> <true>
+ % <annot> -> <false>
+ dup /AP oknown {
+ //true
+ } {
+ 1 setlinewidth
+ 1 setlinecap
+ 1 setlinejoin
+ dup annotsetcolor {
+ dup calc_annot_scale
+ 2 copy mul 0 ne
+ {
+ 3 index annotrect pop pop translate
+ scale
+ /InkList knownoget {
+ { oforce
+ mark exch { oforce } forall
+ .pdfinkpath
+ stroke
+ } forall
+ } if
+ }
+ {
+ pop pop
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }
+ ifelse
+ } if
+ //false
+ } ifelse
+ } bdef
+
+ /Underline {
+ dup /AP oknown {
+ //true
+ } {
+ 0 setlinecap
+ dup annotsetcolor {
+ dup calc_annot_scale
+ 2 copy mul 0 ne
+ {
+ scale
+ /QuadPoints knownoget {
+ aload length 8 idiv {
+ //quadpoints2basis exec
+
+ % Acrobat draws the line at 1/7 of the box width from the bottom
+ % of the box and 1/16 thick of the box width. /Rect is ignored.
+
+ 2 copy dup mul exch dup mul add sqrt 16 div setlinewidth
+ 7 div 4 index add exch % x0 y0 x1-x0 y1-y0 (y2-y0)/7+y0 x2-x0
+ 7 div 5 index add exch % x0 y0 x1-x0 y1-y0 (x2-x0)/7+x0 (y2-y0)/7+y0
+ 2 copy moveto
+ 2 index add exch
+ 3 index add exch lineto % x0 y0 x1-x0 y1-y0
+ pop pop pop pop
+ stroke
+ } repeat
+ } if
+ }
+ {
+ pop pop
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }
+ ifelse
+ } if
+ //false
+ } ifelse
+ } bdef
+
+ /StrikeOut {
+ dup /AP oknown {
+ //true
+ } {
+ 0 setlinecap
+ dup annotsetcolor {
+ dup calc_annot_scale
+ 2 copy mul 0 ne
+ {
+ scale
+ /QuadPoints knownoget {
+ aload length 8 idiv {
+ //quadpoints2basis exec
+
+ % Acrobat draws the line at 3/7 of the box width from the bottom
+ % of the box and 1/16 thick of the box width. /Rect is ignored.
+
+ 2 copy dup mul exch dup mul add sqrt 16 div setlinewidth
+ 0.4285714 mul 4 index add exch % x0 y0 x1-x0 y1-y0 (y2-y0)*3/7+y0 x2-x0
+ 0.4285714 mul 5 index add exch % x0 y0 x1-x0 y1-y0 (x2-x0)*3/7+x0 (y2-y0)*3/7+y0
+ 2 copy moveto
+ 2 index add exch
+ 3 index add exch lineto % x0 y0 x1-x0 y1-y0
+ pop pop pop pop
+ stroke
+ } repeat
+ } if
+ }
+ {
+ pop pop
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }
+ ifelse
+ } if
+ //false
+ } ifelse
+ } bdef
+
+ % Connect 2 points with an arc that has max distance from the line
+ % segment to the ark equal 1/4 of the radius.
+ /highlight-arc { % x1 y1 x0 y0 -> -
+ 4 2 roll % x0 y0 x1 y1
+ dup 3 index add 2 div % x0 y0 x1 y1 (y1+y0)/2
+ 2 index 5 index sub .9375 mul sub % x0 y0 x1 y1 (y1+y0)/2-15/16*dx=yc
+ 4 index 3 index add 2 div % x0 y0 x1 y1 yc (x0+x1)/2
+ 2 index 5 index sub .9375 mul add % x0 y0 x1 y1 yc xc
+ exch % x0 y0 x1 y1 xc yc
+ dup 3 index exch sub % x0 y0 x1 y1 xc yc y1-yc
+ 4 index 3 index sub % x0 y0 x1 y1 xc yc y1-yc x1-xc
+ dup dup mul 2 index dup mul add sqrt %x0 y0 x1 y1 xc yc y1-yc x1-xc r
+ 3 1 roll atan % x0 y0 x1 y1 xc yc r a1
+ 6 index 3 index sub % x0 y0 x1 y1 xc yc r a1 y0-yc
+ 8 index 5 index sub % x0 y0 x1 y1 xc yc r a1 y0-yc x0-xc
+ atan % x0 y0 x1 y1 xc yc r a1 a2
+ exch arcn % x0 y0 x1 y1
+ pop pop pop pop
+ } bind def
+
+ /emptydict 0 dict readonly def
+
+ /Highlight {
+ 0 setlinecap
+ dup annotsetcolor {
+ /QuadPoints knownoget {
+ aload length 8 idiv {
+ 6 -2 roll
+ 2 copy moveto
+ //highlight-arc exec
+ 2 copy lineto
+ //highlight-arc exec
+ closepath
+ } repeat
+ PDFusingtransparency {
+ //emptydict
+ pathbbox 2 index add exch 3 index add exch .begintransparencygroup
+ /Multiply .setblendmode
+ fill
+ .endtransparencygroup
+ } { % for -dNOTRANSPARENCY
+ stroke newpath
+ } ifelse
+ } if
+ } if
+ //false
+ } bdef
+ currentdict /emptydict undef
+ currentdict /highlight-arc undef
+
+ /Squiggly {
+ dup /AP oknown {
+ //true
+ } {
+ dup annotsetcolor {
+ dup calc_annot_scale
+ 2 copy mul 0 ne
+ {
+ scale
+ /QuadPoints knownoget {
+ aload length 8 idiv {
+ gsave
+ 8 copy moveto lineto
+ 4 2 roll lineto lineto closepath clip newpath
+ //quadpoints2basis exec
+ 6 -2 roll translate % adjust for x0 y0 % x1-x0 y1-y0 x2-x0 y2-y0
+ 1 index 56 div 1 index 56 div translate % zigzag box is 1/56 up
+ 1 index 72 div 1 index 72 div translate % the line in the box is 1/72 up
+ 2 copy dup mul exch dup mul add sqrt % x1-x0 y1-y0 x2-x0 y2-y0 |p2|
+ 4 index dup mul 4 index dup mul add sqrt % x1-x0 y1-y0 x2-x0 y2-y0 |p2| |p1|
+ dup 0 gt 2 index 0 gt and {
+ div % x1-x0 y1-y0 x2-x0 y2-y0 |p2|/|p1|=p12
+ dup 1 exch div 4 mul 1 add cvi exch 6 2 roll % cnt p12 x1-x0 y1-y0 x2-x0 y2-y0
+ 4 2 roll % cnt p12 x2-x0 y2-y0 x1-x0 y1-y0
+ 4 index mul exch 4 index mul exch % cnt p12 x2-x0 y2-y0 (x1-x0)*p12 (y1-y0)*p12
+ 4 2 roll 0 0 6 array astore concat % cnt p12
+ 1 40 div 1 72 div scale
+ pop % cnt
+ 0 0 moveto
+ 1 setlinecap
+ 1 setlinejoin
+ 1 setlinewidth
+ {
+ 5 10 lineto
+ 10 0 lineto
+ 10 0 translate
+ } repeat
+ stroke
+ } {
+ 6 { pop } repeat
+ } ifelse
+ grestore
+ } repeat
+ } if
+ }
+ {
+ pop pop
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }
+ ifelse
+ } if
+ //false
+ } ifelse
+ } bdef
+
+ /Text {
+ dup /AP oknown {
+ //true
+ } {
+ dup calc_annot_scale
+ 2 copy mul 0 ne
+ {
+ scale
+ annotrect 4 2 roll translate
+ exch pop
+
+ % Draw a page icon
+ 0.5 exch 18.5 sub translate
+ 1 setlinewidth
+ 0.75 setgray
+ 0.5 -1 moveto 10 -1 lineto 15 4 lineto 15 17.5 lineto stroke
+
+ 0 0 moveto
+ 9 0 lineto
+ 14 5 lineto
+ 14 18 lineto
+ 0 18 lineto closepath
+ gsave .5 setgray fill grestore 0 setgray stroke
+
+ 3 8 moveto 7.5 8 lineto
+ 3 11 moveto 10 11 lineto
+ 3 14 moveto 10 14 lineto
+ 9 0 moveto 9 5 lineto 14 5 lineto
+ stroke
+ }
+ {
+ pop pop
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }
+ ifelse
+ //false
+ } ifelse
+ } bdef
+
+ /FreeText {
+ dup /AP knownoget {
+ %% Check minimal entriy in /AP dictionary
+ /N known not {
+ //true
+ }{
+ //false
+ }ifelse
+ } {
+ //true
+ }ifelse
+ %% We either have no appearance, or its invalid, make one up.
+ {
+ gsave
+
+ dup annotrect (rectclip from freetext annotation) == flush rectclip
+
+ dup /CA knownoget {
+ .setopacityalpha
+ } if
+
+ dup /ca knownoget {
+ .setopacityalpha
+ } if
+
+ dup /C knownoget {
+ dup length 4 eq {
+ aload pop setcmykcolor true
+ }{
+ dup length 3 eq {
+ aload pop setrgbcolor true
+ }{
+ dup length 1 eq {
+ aload pop setgray true
+ } {
+ dup length 0 eq {
+ pop
+ false
+ }{
+ ( **** Error: invalid color specified for FreeText annotation /C entry)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ false
+ } ifelse
+ } ifelse
+ } ifelse
+ } ifelse
+ }{
+ 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
+ } 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}
+ /r {aload pop setrgbcolor} % Can't find this actually defined anywhere, but Acrobat seems to honour it :-(
+ /rg {setrgbcolor}
+ /RG {setrgbcolor}
+ /G {setgray}
+ /g {setgray}
+ /k {setcmykcolor}
+ /K {setcmykcolor}
+ >> def
+ dup /DA knownoget {
+ length string /tempstr exch def
+ dup /DA get tempstr copy pop
+ {
+ %% This is kind of ugly, we use token to process the string
+ %% and process each token separately.
+ tempstr
+ token {
+ exch /tempstr exch def
+ %% If the token is a name
+ %%
+ dup type /nametype eq {
+ %% Is it a name we want to take actionon
+ dup DA_Action_Dict exch known {
+ DA_Action_Dict exch get exec
+ }{
+ %% Its not a name we know, is it executable
+ dup xcheck {exec} if
+ } ifelse
+ }{
+ %% Not a name, just make it executable and execute it
+ cvx exec
+ }ifelse
+ }{
+ exit
+ }ifelse
+ } loop
+ } {
+ 0 setgray
+ /Helvetica findfont 12 scalefont setfont
+ }ifelse
+ %% draw the border, if we don't have a border style dictionary, draw a default one.
+ 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
+ }ifelse
+
+ %% 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
+
+ %% Get the Contents string, if we don't have one, we're done
+ %%
+ 2 index /Contents knownoget {
+ %% Check for UTF16-BE, we probably don't work properly with this yet.
+ %%
+ dup 0 get 254 eq 1 index 1 get 255 eq and
+ {
+ /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont
+ dup length 2 div 1 sub 0 1 3 -1 roll {
+ %% llx urx (string) index
+ 1 index exch 2 mul 2 getinterval %% llx urx (string) (substring)
+ dup stringwidth pop currentpoint pop add 3 index gt {
+ currentpoint exch pop 4 index exch 12 sub moveto
+ } if
+ show
+ } for
+ pop
+ }
+ {
+ %% Heuristic to determine the height (ascender to descender) of the text
+ %% for when we move down a line.
+ gsave
+ /..TextHeight (Hy) false charpath pathbbox exch pop exch sub exch pop def
+ grestore
+ %% 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.
+ %%
+ dup length 1 sub 0 1 3 -1 roll {
+ %% llx urx (string) index
+ 1 index exch get %% llx urx (string) int
+ dup 10 eq 1 index 13 eq or {
+ pop
+ currentpoint exch pop 3 index exch ..TextHeight sub moveto
+ } {
+ 1 string dup 0 4 -1 roll
+ put dup %% llx urx (string) (int) (int)
+ stringwidth pop currentpoint pop add 3 index gt {
+ currentpoint exch pop 4 index exch ..TextHeight sub moveto
+ } if
+ show
+ } ifelse
+ } for
+ pop
+ }ifelse
+ } if
+ pop pop
+ //false
+ grestore
+ }
+ {
+ //true
+ } ifelse
+ } bdef
+
+ /frame {
+ { 255 div } forall setrgbcolor
+ -95 -25 translate
+ 2 190 atan rotate
+ {
+ 6 0 moveto
+ 190 0 190 6 6 arct
+ 190 47 184 47 6 arct
+ 0 47 0 41 6 arct
+ 0 0 6 0 6 arct
+ closepath
+
+ 10 4 moveto
+ 185 4 185 9 5 arct
+ 185 43 180 43 5 arct
+ 5 43 5 38 5 arct
+ 5 4 9 4 5 arct
+ closepath
+ eofill
+ }
+ gsave 1 -1 translate 0.75 setgray dup exec grestore
+ exec
+ } bdef
+
+ % (text) y h -> -
+ /text {
+ /Times-Bold findfont exch scalefont setfont % (text) y
+ gsave
+ 0 0 moveto
+ 1 index //false charpath flattenpath pathbbox
+ pop exch pop sub 2 div
+ grestore
+ 95 add exch moveto
+ gsave 1 -1 rmoveto 0.75 setgray dup show grestore
+ show
+ } bdef
+
+ /red <ef4023> readonly def
+ /green <3fae49> readonly def
+ /blue <0072bc> readonly def
+
+ /stamp_dict 14 dict begin
+ /Approved {
+ //green //frame exec
+ (APPROVED) 13 30 //text exec
+ } bdef
+ /AsIs {
+ //red //frame exec
+ (AS IS) 13 30 //text exec
+ } bdef
+ /Confidential {
+ //red //frame exec
+ (CONFIDENTIAL) 17 20 //text exec
+ } bdef
+ /Departmental {
+ //blue //frame exec
+ (DEPARTMENTAL) 17 20 //text exec
+ } bdef
+ /Draft {
+ //red //frame exec
+ (DRAFT) 13 30 //text exec
+ } bdef
+ /Experimental {
+ //blue //frame exec
+ (EXPERIMENTAL) 17 20 //text exec
+ } bdef
+ /Expired {
+ //red //frame exec
+ (EXPIRED) 13 30 //text exec
+ } bdef
+ /Final {
+ //red //frame exec
+ (FINAL) 13 30 //text exec
+ } bdef
+ /ForComment {
+ //green //frame exec
+ (FOR COMMENT) 17 20 //text exec
+ } bdef
+ /ForPublicRelease {
+ //green //frame exec
+ (FOR PUBLIC) 26 18 //text exec
+ (RELEASE) 8.5 18 //text exec
+ } bdef
+ /NotApproved {
+ //red //frame exec
+ (NOT APPROVED) 17 20 //text exec
+ } bdef
+ /NotForPublicRelease {
+ //red //frame exec
+ (NOT FOR) 26 18 //text exec
+ (PUBLIC RELEASE) 8.5 18 //text exec
+ } bdef
+ /Sold {
+ //blue //frame exec
+ (SOLD) 13 30 //text exec
+ } bdef
+ /TopSecret {
+ //red //frame exec
+ (TOP SECRET) 14 26 //text exec
+ } bdef
+ currentdict end readonly def
+
+ {/text/frame/red/green/blue} {currentdict exch undef} forall
+
+ /Stamp {
+ dup /AP oknown {
+ //true
+ } {
+ dup calc_annot_scale
+ 2 copy mul 0 ne
+ {
+ scale
+ % translate to the center of Rect
+ dup annotrect
+ 4 2 roll % dx dy x0 y0
+ 2 index 2 div add exch
+ 3 index 2 div add exch translate % dx dy
+
+ 50 div exch 190 div .min dup scale
+
+ /Name knownoget not { /Draft } if
+ //stamp_dict 1 index known not { exch pop /Draft exch } if
+ //stamp_dict exch get exec
+ }
+ {
+ pop pop
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }
+ ifelse
+ //false
+ } ifelse
+ } bdef
+
+ currentdict /quadpoints2basis undef
+currentdict end readonly def
+
+/drawannot { % <annot> drawannot -
+ dup annotvisible {
+ gsave
+ dup dup /Subtype knownoget {
+ //drawannottypes exch .knownget { exec } { //true } ifelse
+ {
+ dup calc_annot_scale 2 copy mul 0 ne
+ {
+ 3 -1 roll drawwidget
+ }
+ {
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }ifelse % Draw rejected annots as widgets
+ } if % type known
+ } {
+ pop
+ ( **** Error: Ignoring /Annot dict without required /Subtype entry.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ grestore
+ } if pop % annotvisible
+} bdef
+currentdict /drawannottypes undef
+
+% Draw an annotation.
+
+/loadannot {
+ dup /AP .knownget { % <<Annot dict>> <<Appearance dictionary>> true | false
+ oforce
+
+ dup { % <<Annot dict>> <<Appearance dict>> /Key <</Key dict>>
+ oforce % <<Annot dict>> <<Appearance dict>> /Key <<resolved /Key dict>>
+
+ %%
+ %% Check to see if the apperance key has a simple stream or a dictionary of states
+ %%
+ dup /Subtype known % <<Annot dict>> <<Appearance dict>> /Key <<resolved /Key dict>> bool
+ {
+ %% Simple appearance stream
+ DoAppearance % <<Annot dict>> <<Appearance dict>> /Key
+ 2 index % <<Annot dict>> <<Appearance dict>> /Key <<Annot dict>>
+ /AP << % <<Annot dict>> <<Appearance dict>> /Key <<Annot dict>> /AP <<
+ 4 -1 roll MakeAppearanceName cvx cvn >> put % <<Annot dict>> <<Appearance dict>>
+ } {
+ %% dictionary of states <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>>
+ dup % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>>
+ { % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey <<State dictionary>>
+ oforce % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey <<resolved State dictionary>>
+ DoAppearance % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey
+ 1 index exch % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> /StateKey
+ MakeAppearanceName cvx cvn % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> /StateKey {}
+ put % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>>
+ } forall
+ put % <<Annot dict>> <<Appearance dict>> /Key
+ dup
+ }ifelse
+ } forall
+ pop % <<Annot dict>>
+ } if
+
+ %% Parent (or /P) references will be incorrect. Remove them
+ %% for now as they are optional.
+ dup /Popup known {dup /Popup undef} if
+ dup /IRT known {dup /IRT undef} if
+ dup /RT known {dup /RT undef} if
+ dup /P known {dup /P undef} if
+ dup /Parent known {dup /Parent undef} if
+
+ %% Resolve any indirect references. May need further work :-(
+ {
+ %% We know /AP doesn't need processing, we handled that above...
+ 1 index /AP eq not {
+ dup {oforce} stopped not {exch pop} if
+ dup type /dicttype eq{
+ dup
+ {
+ dup {oforce} stopped not {exch pop} if
+ 2 index 3 1 roll put
+ } forall
+ } if
+ dup type /arraytype eq {
+ 0 1 2 index length 1 sub{
+ dup 2 index exch get dup {oforce} stopped not {exch pop} if
+ 2 index 3 1 roll put
+ } for
+ } if
+ } if
+ } forall
+} bdef
+
+
+/ApplyCTMToQuadPoints {
+ %% Nasty hackery here really. We need to undo the HWResolution scaling which
+ %% is done by pdfwrite. Default is 720 dpi, so 0.1. We also need to make
+ %% sure that any translation of the page (because its been rotated for example)
+ %% is also modified by the requisite amount. SO we ned to calculate a matrix
+ %% which does the scaling and concatenate it with the current matrix.
+ %% Do this inside a gsave/grestore pair to avoid side effects!
+
+ gsave
+ currentpagedevice /HWResolution get
+ aload pop exch 72 exch div exch 72 exch div
+ matrix 3 1 roll 2 index 3 3 -1 roll put
+ 1 index 0 3 -1 roll put
+ matrix currentmatrix exch matrix concatmatrix
+ setmatrix
+
+ oforce
+
+ %% QuadPoints are given as 'n' sequences of 8 numbers.
+
+ mark exch aload counttomark 1 roll
+ counttomark 1 sub 2 div cvi {
+ transform
+ counttomark 1 sub 2 roll
+ } repeat
+ counttomark -1 roll astore
+
+ exch pop % the mark
+
+ grestore
+} bdef
+
+/preserveannottypes 20 dict begin
+
+/Circle {mark exch loadannot /ANN pdfmark false} bdef
+/FileAttachment {mark exch loadannot /ANN pdfmark false} bdef
+/FreeText {mark exch loadannot /ANN pdfmark false} bdef
+
+/Highlight {
+ mark exch
+ dup /QuadPoints .knownget {
+ 1 index /QuadPoints 3 -1 roll
+ ApplyCTMToQuadPoints
+ put
+ } if
+ loadannot /ANN pdfmark false
+} bdef
+
+/Ink {mark exch loadannot /ANN pdfmark false} bdef
+
+/Line {
+ mark exch dup /L .knownget {
+ aload 5 1 roll transform 4 -2 roll transform 4 2 roll
+ 5 -1 roll astore
+ 1 index /L 3 -1 roll put
+ } if
+ loadannot /ANN pdfmark false
+} bdef
+
+/Link {mark exch {drawannot} PDFSTOPONERROR {exec}{stopped {(Error: Ignoring invalid annotation, output may be incorrect.\n) pdfformaterror} if} ifelse cleartomark false} bdef
+
+/Movie {mark exch loadannot /ANN pdfmark false} bdef
+/Popup {mark exch loadannot /ANN pdfmark false} bdef
+/Sound {mark exch loadannot /ANN pdfmark false} bdef
+/Square {mark exch loadannot /ANN pdfmark false} bdef
+/Stamp {mark exch loadannot /ANN pdfmark false} bdef
+
+/StrikeOut {
+ mark exch
+ dup /QuadPoints .knownget {
+ 1 index /QuadPoints 3 -1 roll
+ ApplyCTMToQuadPoints
+ put
+ } if
+ loadannot /ANN pdfmark false
+} bdef
+
+/Squiggly {
+ mark exch
+ dup /QuadPoints .knownget {
+ 1 index /QuadPoints 3 -1 roll
+ ApplyCTMToQuadPoints
+ put
+ } if
+ loadannot /ANN pdfmark false
+} bdef
+
+/Text {mark exch loadannot /ANN pdfmark false} bdef
+/TrapNet {mark exch loadannot /ANN pdfmark false} bdef
+
+/Underline {
+ mark exch
+ dup /QuadPoints .knownget {
+ 1 index /QuadPoints 3 -1 roll
+ ApplyCTMToQuadPoints
+ put
+ } if
+ loadannot /ANN pdfmark false
+} bdef
+
+%% Widget annotations are only used with AcroForms, and since we don't preserve AcroForms
+%% we don't want to preserve widget annotations either, because the consumer of the new
+%% PDF won't know what values they should take. So we draw widget annotations instead. If we
+%% ever preserve AcroForms then we should alter this to preserve Widgets as well.
+%% simply chane "drawannot" to "mark exch loadannot /ANN pdfmark"
+/Widget {mark exch {drawannot} PDFSTOPONERROR {exec}{stopped {(Error: Ignoring invalid annotation, output may be incorrect.\n) pdfformaterror} if} ifelse cleartomark false} bdef
+
+currentdict end readonly def
+
+/preserveannot { % <annot> preserveannot -
+ dup annotvisible {
+ gsave
+ dup dup /Subtype knownoget {
+ //preserveannottypes exch .knownget { exec } { //true } ifelse
+ {
+ dup calc_annot_scale 2 copy mul 0 ne
+ {
+ 3 -1 roll drawwidget
+ }
+ {
+ ( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ }ifelse % Draw rejected annots as widgets
+ } if % type known
+ } {
+ pop
+ ( **** Error: Ignoring /Annot dict without required /Subtype entry.\n)
+ pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ grestore
+ } if pop % annotvisible
+} bdef
+
+currentdict /preserveannottypes 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
+ } {
+ %% If we don't have a NeedApperances, treat as true, because Acrobat
+ %% always regenerates Appearances anyway.
+ 2 index /NeedAppearances knownoget not { //true } 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 roll sub abs exch ] def
+ /Resources 3 index /DR pget not { 0 dict } if def
+ /File 1000 string dup 3 1 roll def
+ /Length 1000 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 {
+ 3 index /DV pget not { () } if write==
+ } if
+ 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) //== exec
+} bdef
+
+/Sig {
+ (Sig is not yet implemened ) //== exec
+} 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 have 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 annotations.
+
+/draw_form_field { % <field> draw_form_field -
+ dup /Kids knownoget { % field []
+ dup length 0 gt {
+ dup 0 oget /Parent knownoget { % field [] kid
+ pop % mon-terminal field % field []
+ exch pop % []
+ { oforce draw_form_field } forall
+ } {
+ pop draw_terminal_field % separate annots % -
+ } ifelse
+ } {
+ ( **** Error: Ignoring empty /Kids array in Form field.\n) pdfformaterror
+ ( Output may be incorrect.\n) pdfformaterror
+ } ifelse
+ } {
+ draw_terminal_field % merged annotation % -
+ } ifelse
+} bdef
+
+/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 % pdfdict
+end % GS_PDF_ProcSet
+.setglobal