[ SEA-GHOST MINI SHELL]
% Copyright (C) 2001-2018 Artifex Software, Inc.
% All Rights Reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
% CA 94945, U.S.A., +1(415)492-9861, for further information.
%
% pdf_draw.ps
% PDF drawing operations (graphics, text, and images).
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
/GS_PDF_ProcSet load begin
pdfdict begin
% For simplicity, we use a single interpretation dictionary for all
% PDF graphics operations, even though this is too liberal.
/drawopdict 100 dict def
% ================================ Graphics ================================ %
% ---------------- Functions ---------------- %
% Note that resolvefunction converts a PDF Function to a PostScript Function;
% resolve*fnproc converts a PDF function to a PostScript procedure.
% We need to process all required and optional parameters to resolve any
% use of indirect references.
/fnrdict mark
0 { .resolvefn0 }
2 { .resolvefn2 }
3 { .resolvefn3 }
4 { .resolvefn4 }
.dicttomark readonly def
/.resolvefn0 {
dup length 1 add dict .copydict % make room for DataSource
% now resolve any indirect references
dup /Size 2 copy knownoget { put } { pop pop } ifelse
dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse
dup /Order 2 copy knownoget { put } { pop pop } ifelse
dup /Encode 2 copy knownoget { put } { pop pop } ifelse
dup /Decode 2 copy knownoget { put } { pop pop } ifelse
% Don't lose our place in PDFfile.
PDFfile fileposition exch
dup //true resolvestream
% The stream isn't positionable, so read all the data now.
% Stack: filepos fndict stream
1 index /Range get length 2 idiv 2 index /BitsPerSample get mul
2 index /Size get { mul } forall
7 add 8 idiv
dup 65535 le {
string 1 index exch readstring pop
} {
1 index exch () /SubFileDecode filter /ReusableStreamDecode filter
} ifelse
exch closefile
% Stack: filepos fndict data
exch dup /DataSource 4 -1 roll put
exch PDFfile exch setfileposition
} bind executeonly def
/.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
} bind executeonly def
/.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
} bind executeonly def
/.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
} bind executeonly def
/.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
} bind executeonly def
/resolvefunction { % <fndict> resolvefunction <function>
.resolvefn
PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Function: ) print dup === flush } if } if
} bind executeonly def
/resolvefnproc { % <fndict> resolvefnproc <proc>
resolvefunction .buildfunction
} bind executeonly def
/resolveidfnproc { % <fndict> resolveidfnproc <proc>
dup /Identity eq { pop { } } { resolvefnproc } ifelse
} bind executeonly def
/resolvedefaultfnproc { % <fndict> <default> resolved'fnproc <proc>
1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
} bind executeonly def
%% A BBox where width or height (or both) is 0 should still paint one pixel
%% See the ISO 32000-2:2017 spec, section 8.7.4.3, p228 'BBox' and 8.7.3.1
/FixPatternBBox
{
dup aload pop
3 index 2 index sub 0 eq {
3 index 0.000001 add 3 -1 roll pop exch
} if
2 index 1 index sub 0 eq {
2 index 0.000001 add exch pop
}if
5 -1 roll astore
}bind executeonly def
% ---------------- 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 executeonly
/BBox {
dup dup dup aload pop normrect_elems
5 -1 roll astore
FixPatternBBox
} bind executeonly
/ColorSpace {
resolvecolorspace
} bind executeonly
/Function {
dup type /dicttype eq {
resolvefunction
} {
[ exch { oforce resolvefunction } forall ]
} ifelse
} bind executeonly
/Extend {
mark exch {oforce} forall ]
} bind executeonly
.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
} bind executeonly def
/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
} bind executeonly def
% ---------------- 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 executeonly
/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 executeonly
/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 executeonly
/EllipseA { dup mul .9 mul exch dup mul add 1 exch sub } bind executeonly
/InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub } bind executeonly
/EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub } bind executeonly
/EllipseC { dup mul .9 mul exch dup mul add 1 exch sub } bind executeonly
/InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub } bind executeonly
/Line { exch pop abs neg } bind executeonly
/LineX { pop } bind executeonly
/LineY { exch pop } bind executeonly
/Square { abs exch abs 2 copy lt { exch } if pop neg } bind executeonly
/Cross { abs exch abs 2 copy gt { exch } if pop neg } bind executeonly
/Rhomboid { abs exch abs 0.9 mul add 2 div } bind executeonly
/DoubleDot { 2 {360 mul sin 2 div exch } repeat add } bind executeonly
/InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg } bind executeonly
/SimpleDot { dup mul exch dup mul add 1 exch sub } bind executeonly
/InvertedSimpleDot { dup mul exch dup mul add 1 sub } bind executeonly
/CosineDot { 180 mul cos exch 180 mul cos add 2 div } bind executeonly
/Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add } bind executeonly
/InvertedDouble {
exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
} bind executeonly
.dicttomark readonly def
/.resolveht1 {
mark exch {
oforce
1 index /SpotFunction eq {
dup type /arraytype eq {
%% check all the names in the array in turn, stop when we find
%% the first one we recognise.
{
//spotfunctions exch .knownget {
exit
} if
} forall
dup type /nametype eq {
%% If we didn't find any that we recognise, then use
%% the default halftone's spot function
.setdefaulthalftone currenthalftone dup /SpotFunction .knownget {
exch pop
}{
/GraySpotFunction .knownget not {
//spotfunctions /Round get
} if
}ifelse
} if
}{
dup type /nametype eq
{ //spotfunctions exch get } { resolvefnproc }
ifelse
} ifelse
} {
1 index /TransferFunction eq {
resolveidfnproc
} if
} ifelse
} forall .dicttomark
} bind executeonly def
/.resolveht5 {
mark exch {
oforce dup type /dicttype eq { resolvehalftone } if
} forall .dicttomark
} bind executeonly def
/.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
} bind executeonly def
/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
} bind executeonly def
% ---------------- Graphics state management ---------------- %
/cmmatrix matrix def
drawopdict begin
% Graphics state stack
/q { q } executeonly def
/Q { Q } executeonly 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
} bind executeonly def
/i { 1 .min setflat } bind executeonly def
/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 } bind executeonly def
/gs { gs } executeonly def
end
% Each entry in this dictionary is
% <gsres> <value> -proc- <gsres>
/gsbg {
/BGDefault load resolvedefaultfnproc setblackgeneration
} bind executeonly def
/gsucr {
/UCRDefault load resolvedefaultfnproc setundercolorremoval
} bind executeonly def
/gstr {
dup type /arraytype eq {
{ oforce /TRDefault load resolvedefaultfnproc } forall
setcolortransfer
} {
/TRDefault load resolvedefaultfnproc settransfer
} ifelse
} bind executeonly def
/gsparamdict mark
/SA { setstrokeadjust } executeonly
/OP { 1 index /op known not { dup op } if OP } executeonly
% 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 } executeonly
/UCR { 1 index /UCR2 known { pop } { gsucr } ifelse } executeonly
/TR { 1 index /TR2 known { pop } { gstr } ifelse } executeonly
% Some functions used to implement phases of HT and HTP
/sethalftones {
dup /Default eq {
pop .setdefaulthalftone
} {
resolvehalftone sethalftone
} ifelse
} bind executeonly def
/sethalftonephases {
/sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
} bind executeonly def
/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
} executeonly
/HTP {
% HTP may be present even if this isn't a DPS interpreter.
dup sethalftonephases .swapcolors sethalftonephases .swapcolors
} executeonly
% PDF 1.3
% The font is an indirect reference, not a resource name
/Font { aload pop exch oforce resourcefont exch Tf }
/LW { setlinewidth } executeonly
/LC { setlinecap } executeonly
/LJ { setlinejoin } executeonly
/ML { 1 .max setmiterlimit } executeonly
/D { aload pop setdash } executeonly
/RI { ri } executeonly
/op { op } executeonly
/OPM { OPM } executeonly
/BG2 { gsbg } executeonly
/UCR2 { gsucr } executeonly
/TR2 { gstr } executeonly
/FL { 1 .min setflat } executeonly
/SM {
% SM may be present even if this is only a Level 2 interpreter.
/setsmoothness where { pop setsmoothness } { pop } ifelse
} executeonly
% PDF 1.4
% All of these require the "transparency" feature in the interpreter.
/ca { ca } executeonly
/CA { CA } executeonly
/SMask {
{gssmask} PDFSTOPONERROR { exec //false } { stopped } ifelse
{
pop (\n **** Error in SMask during ExtGState. Ignoring the mask, output may be incorrect.\n)
pdfformaterror
} if
} executeonly
/AIS { AIS } executeonly
/BM { BM } executeonly
/TK { TK } executeonly
/UseBlackPtComp { UseBlackPtComp } executeonly
/HTO {
% PDF 2.0, supposed to be 'similar' to halftone phase but using a different
% co-ordiate system. Treat the same for now and fix if anyone ever complains.
aload pop transform cvi exch cvi exch 2 array astore
dup sethalftonephases .swapcolors sethalftonephases .swapcolors
} executeonly
.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
} {
//pdfdict /.gs_warning_issued known not {
(\n **** Error 'gs' ignored -- ExtGState missing from Resources.\n)
pdfformaterror
( Output may be incorrect.\n) pdfformaterror
//pdfdict /.gs_warning_issued //true .forceput
PDFSTOPONERROR { /gs /undefined signalerror } if
} executeonly if
} executeonly
ifelse
} bind executeonly def
% ------ 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
.currentSMask //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
% 10 2 roll
/.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
pop
.dicttomark
exit
} loop
SMask
} bind executeonly def
% 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 executeonly
/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 /GroupGState .knownget { 1 index /GroupGState 3 -1 roll put} if
exch //false resolvestream
1 index exch
%% Get the current colour space and colour values (as an array), we need to pass these to .execgroup
%% as well, so that it can restore them, in case the colour space gets changed by transparency
%% graphics state stuff.
mark currentcolor counttomark array astore exch pop
currentcolorspace 4 2 roll
.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.
/GroupGState undef
.endtransparencymask
PDFfile exch setfileposition
mark exch /OverrideICC exch .dicttomark setuserparams
.setuseciecolor setcolorspace setcolor
setmatrix
end % restore colorspace, color and ExtGState (end)
.currentSMask /Processed //true put % special setting to tell us it has been rendered
} bind executeonly def
% Paint a Form+Group XObject, either for a transparency mask or for a Do.
/.execgroup { % [colour values] <colour space> <resdict> <stream> .execgroup -
pdfemptycount 3 1 roll
/pdfemptycount count 5 sub store
gsave //nodict begin
% We have to set the gstate correctly for lazy evaluation of a softmask group.
% we also must restore the color(space) as setup in .execmaskgroup or paintformgroup.
% 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.
1 index
/GroupGState .knownget { setgstate } if
newpath //null SMask
1 .setopacityalpha 1 .setshapealpha
1 CA 1 ca
/Compatible .setblendmode
% Execute the body of the Form, similar to DoForm.
pdfopdict
%% Restore the colour space (passed in on the stack) and current colour
%%
6 -2 roll
setcolorspace
aload pop setcolor
.pdfruncontext
end grestore
/pdfemptycount exch store
} bind executeonly def
/.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
} bind executeonly def
% .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 -
%% Pass the current color space, and an array with the current color vales
%% as arguments to .execgroup
mark currentcolor counttomark array astore exch pop
currentcolorspace 5 2 roll
dup /Group oget exch /BBox oget
% Stack: resdict stream groupdict bbox
.beginformgroup
.execgroup
.endtransparencygroup
} bind executeonly def
% 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
.currentalphaisshape
{ /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
/ColorSpace DataDict /ColorSpace get def
} bind executeonly def
% ---------------- 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 } bind executeonly def
/DeviceRGB { pop 3 } bind executeonly def
/DeviceCMYK { pop 4 } bind executeonly def
/CIEBasedA //DeviceGray def
/CIEBasedABC //DeviceRGB def
/CalGray //DeviceGray def
/CalRGB //DeviceRGB def
/Lab //DeviceRGB def
/ICCBased { 1 oget /N oget } bind executeonly def
/Separation //DeviceGray def
/DeviceN { 1 oget length } bind executeonly def
/Indexed //DeviceGray def
currentdict end readonly def
% <colorspace> csncomp <n>
/csncomp {
dup dup type /arraytype eq { 0 oget } if
//csncompdict exch get exec
} bind executeonly def
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
} bind executeonly def
/csrdict 13 dict begin
/DeviceGray { } bind executeonly def
/DeviceRGB { } bind executeonly def
/DeviceCMYK { } bind executeonly def
/CalGray { 1 oget [ exch /CalGray exch ] } bind executeonly def
/CalRGB { 1 oget [ exch /CalRGB exch ] } bind executeonly def
/Lab { 1 oget [ exch /Lab exch ] } bind executeonly def
/CalCMYK {
pop /DeviceCMYK % not defined by Adobe
} bind executeonly def
/ICCBased {
dup 1 get type /dicttype ne { % don't resolve more than once
ICCBased-resolve
} if
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
/Pattern {
dup type /nametype ne {
dup length 1 gt {
1 oget resolvecolorspace
/Pattern exch 2 array astore
} if
} if
} bind executeonly def
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
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
%% 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.
% Not true since moving the ExtGState parameters into the gstate.
% //null sc1 //null SC1
} ifelse
% Save old values on opstack, set pdfemptycount to new value.
pdfemptycount countdictstack mark
%% We can't simply 'def' into the dictionary saved by 'q' above, we need to
%% call gput to copy it and store inside it. Stupid or what....
/pdfemptycount count 3 sub gput 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
currentdict /n known currentdict /self known or{
Q
}{
(\n **** Error: File has unbalanced q/Q operators \(too many Q's\)\n Output may be incorrect.\n)
//pdfdict /.Qqwarning_issued .knownget
{
{
pop
}
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
} executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
end
} executeonly ifelse
} executeonly loop
{
(\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n)
//pdfdict /.Qqwarning_issued .knownget
{
{
pop
}
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
} executeonly
{
currentglobal //pdfdict gcheck .setglobal
//pdfdict /.Qqwarning_issued //true .forceput
.setglobal
pdfformaterror
} executeonly ifelse
} executeonly 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
} bind executeonly odef
/.pdfpaintproc {
%% Get the /m from pdfopdict (must be present)
%% and check its a packedarray
pdfopdict /m get dup type /packedarraytype eq {
%% The non-text version of /m is executeonly, so if we can't read it, its not a text block.
dup rcheck {
%% 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
}{
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
}bind executeonly odef
/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 FixPatternBBox 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
} bind executeonly def
/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
} bind executeonly def
/rg { .incachedevice {
pop pop pop //ignore_color_op pdfformaterror
} {
/DeviceRGB cssubst { cs sc* } { rg } ifelse
} ifelse
} bind executeonly def
/k { .incachedevice {
pop pop pop pop //ignore_color_op pdfformaterror
} {
k
} ifelse
} bind executeonly def
/cs { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
csresolve { cs } if
} ifelse
} bind executeonly def
/sc { .incachedevice {
.pdfcount { pop } repeat //ignore_color_op pdfformaterror
} {
scresolve 1 index //null eq {
pop pop
//ignore_color_op pdfformaterror
} {
{ sc*_and_set } { sc1_and_set } ifelse
} ifelse
} ifelse
} bind executeonly def
/scn /sc load def
/G { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
/DeviceGray cssubst { CS SC1 } { G } ifelse
} ifelse
} bind executeonly def
/RG { .incachedevice {
pop pop pop //ignore_color_op pdfformaterror
} {
/DeviceRGB cssubst { CS SC* } { RG } ifelse
} ifelse
} bind executeonly def
/K { .incachedevice {
pop pop pop pop //ignore_color_op pdfformaterror
} {
K
} ifelse
} bind executeonly def
/CS { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
csresolve { CS } if
} ifelse
} bind executeonly def
/ri { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
ri
} ifelse
} bind executeonly def
/SC { .incachedevice {
.pdfcount { pop } repeat //ignore_color_op pdfformaterror
} {
scresolve 1 index //null eq {
pop pop
//ignore_color_op pdfformaterror
}{
{ SC*_and_set } { SC1_and_set } ifelse
}ifelse
} ifelse
} bind executeonly def
/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 } bind executeonly def
/l { { lineto } stopped { count pdfemptycount sub 2 .min { pop } repeat } if } bind executeonly def
/c { { curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def
/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
} bind executeonly def
/y { { 2 copy curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def
/re {
4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto
closepath
} bind executeonly def
/h { closepath } bind 0 get def
% Path painting and clipping
/n { n } executeonly def
/S { S } executeonly def
/s { s } executeonly def
/f { f } executeonly def
/f* { f* } executeonly def
/B { B } executeonly def
/b { b } executeonly def
/B* { B* } executeonly def
/b* { b* } executeonly def
/W { W } executeonly def
/W* { W* } executeonly def
/sh_save 1 array def
/sh_group << /Subtype /Group /Isolated //true >> readonly def
/do_shade {
0 .setoverprintmode
{ dup /.shading .knownget {
exch pop
} {
.buildshading_and_shfill
} ifelse
} stopped {
pop
( **** Error: Ignoring invalid smooth shading object, output may be incorrect.\n)
pdfformaterror
} if
} bind executeonly def
/sh {
OFFlevels length 0 eq {
setfillstate resolvesh
//sh_save 0 save put
PDFusingtransparency {
.currentSMask //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
.currentSMask //null ne {
.endtransparencygroup
} if
} {
//do_shade exec
} ifelse
//sh_save 0 get restore
} {
pop
} ifelse
} bind executeonly def
currentdict dup /sh_save undef /sh_group undef
end
% ---------------- XObjects ---------------- %
/xobjectprocs mark % <dict> -proc- -
/Image { DoImage } executeonly
/Form { DoForm } executeonly
/PS { DoPS } executeonly
.dicttomark readonly def
% Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
% color space names.
/defaultdecodedict mark
/DeviceGray { pop //01_1 } bind executeonly
/DeviceRGB { pop //01_3 } bind executeonly
/DeviceCMYK { pop //01_4 } bind executeonly
/CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind executeonly
/CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind executeonly
/CalGray { pop //01_1 } bind executeonly
/CalRGB { pop //01_3 } bind executeonly
/Lab { 1 get /Range knownoget not { [-100 100 -100 100] } {aload pop 0 100 6 2 roll 6 array astore}ifelse } bind executeonly
/ICCBased {
1 oget dup /Range knownoget {
exch pop
}{
/N get [ exch {0 1} repeat ] readonly
} ifelse
} bind executeonly
/Separation { pop //01_1 } bind executeonly
/DeviceN {
1 oget length [ exch {0 1} repeat ] readonly
} bind executeonly
/Indexed {
pop [ 0 1 BitsPerComponent bitshift 1 sub ]
} bind executeonly
.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
} bind executeonly def
% <string> <index> getu16 <integer>
/getu16 {
2 copy get 8 bitshift 3 1 roll 1 add get add
} bind executeonly def
% <string> <index> getu32 <integer>
/getu32 {
2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
} bind executeonly 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 executeonly
17 { /sGrayICC /ColorSpace findresource } bind executeonly
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
} bind executeonly def
/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
} bind executeonly def
%% 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
} bind executeonly def
/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
} bind executeonly def
% 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
} bind executeonly def
/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
} bind executeonly def
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 executeonly 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>
} bind executeonly def
/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
} bind executeonly def
/get-smask-in-data { % <dict> -> <int>
/SMaskInData knownoget {
dup dup 1 ne exch 2 ne and {
pop 0
} if
} {
0
} ifelse
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
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
} bind executeonly def
/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 see also 697919 and 689717.
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
} {
ColorSpace dup type /arraytype eq { 0 oget } if /DeviceGray eq
BitsPerComponent 1 eq and {
%% For DeviceGray, try clamping the values to 0 and 1 respectively
dup 0 oget
dup 0 lt exch 1 gt or {
dup 0 oget
dup 0 lt {
pop dup 0 0 put
}{
dup 0 1 put
} ifelse
} if
dup 1 oget
dup 0 lt exch 1 gt or {
dup 1 oget
dup 0 lt {
pop dup 0 0 put
}{
dup 0 1 put
} ifelse
} if
}{
% AR5, AR9 do this for most cases. Bug 690786.
[ exch { 1 BitsPerComponent bitshift 1 sub and } forall ]
} ifelse
} ifelse
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
} bind executeonly def
/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 .setSMask
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
} {
.currentSMask //null ne {
% the image doesn't have an SMask, but the ExtGState does, force a group.
<< /Subtype /Group /Isolated //true >> 0 0 1 1 .begintransparencygroup
doimage
.endtransparencygroup
}
{ doimage }
ifelse
} ifelse
} bind executeonly def
% 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
} bind executeonly def
} if
/ValidateDecode { % <<image dict>> -imagemask- ValidateDecode <<image dict>>
exch
dup /Decode .knownget {
dup length % -imagemask- <<image dict>> [Decode] length
4 -1 roll % <<image dict>> [Decode] length -imagemask-
{
1 % ImageMask Decode arrays must be [0 1] or [1 0]
}
{
mark currentcolor counttomark % <<image dict>> [Decode] length [ ... component_count
dup 2 add 1 roll % <<image dict>> [Decode] length component_count [ ....
cleartomark % <<image dict>> [Decode] length component_count
} ifelse
2 mul dup % <<image dict>> [Decode] length comp_count*2 comp_count*2
3 1 roll % <<image dict>> [Decode] comp_count*2 length comp_count*2
eq { % <<image dict>> length of Decode matches colour space requirement
pop pop % <<image dict>> remove [Decode] and comp_count*2
}{ % <<image dict>> Decode array incorrect
dup 2 index length % <<image dict>> [Decode] comp_count*2 comp_count*2 length
exch sub 0 gt { % Decode is too long
(\n **** Warning: Decode array for an image is too long\n) pdfformatwarning
( Output may be incorrect.\n) pdfformatwarning
0 exch % <<image dict>> [Decode] 0 comp_count*2
getinterval % <<image dict>> [subarray of Decode]
1 index exch /Decode exch % <<image dict>> <<image dict>> /Decode [subarray]
put % <<image dict>>
}{
% Decode is too short, Acrobat throws errors on this
(\n **** ERROR: Decode array for an image is too short\n) pdfformaterror
( Output may be incorrect.\n) pdfformaterror
pop pop % remove [Decode] and comp_count*2
} ifelse
} ifelse
} {
exch pop
}ifelse
}bind executeonly def
/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 true ValidateDecode { imagemask } }
{ ColorSpace setgcolorspace currentdict end setfillblend false ValidateDecode { 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
} bind executeonly def
/.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
} bind executeonly def
/IncrementAppearanceNumber {
//pdfdict /AppearanceNumber .knownget {
1 add //pdfdict /AppearanceNumber 3 -1 roll .forceput
} executeonly
{
//pdfdict /AppearanceNumber 0 .forceput
} executeonly ifelse
}bind executeonly odef
/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
} bind executeonly def
/MakeNewAppearanceName {
IncrementAppearanceNumber
MakeAppearanceName
}bind executeonly def
/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
} bind executeonly odef
/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
} executeonly
{
/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
} bind executeonly odef
/_dops_save 1 array def
/DoPS {
DOPS
{
//_dops_save 0 save put
//true resolvestream cvx exec
//_dops_save 0 get restore
}
{ pop }
ifelse
} bind executeonly def
currentdict /_dops_save undef
/ocg_pocs 4 dict begin
/AllOn {
//true exch {
oforce dup type /dicttype eq {
/OFF known not and
} {
pop
} ifelse
} forall
} bind executeonly def
/AnyOn {
//false exch {
oforce dup type /dicttype eq {
/OFF known not or
} {
pop
} ifelse
} forall
} bind executeonly def
/AnyOff {
//AllOn exec not
} bind executeonly def
/AllOff {
//AnyOn exec not
} bind executeonly def
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
} {
dup /OFF known not % OFF is inserted by process_trailer_attrs
{
%% /OC is not in the OCProperties /OFF array, so we need to
%% test its usage. We may eventually have to add a /ON to the dictionary
%% if the OCProperties /ON array defines the /OC, I think that should override
% the Usage, but I don't have an example to test.
/Usage .knownget {
oforce
/Printed where {
/Printed get
} {
//false
}ifelse
{
%% We are behaving as a printer, check the Print state
/Print .knownget {
/PrintState .knownget {
oforce
/OFF eq {
//false
}{
//true
} ifelse
}{
//true
} ifelse
}{
%% If we don't know, assume its visible
//true
} ifelse
}{
%% We are behaving as a viewer, check the View state
/View .knownget {
oforce
/ViewState .knownget {
/OFF eq {
//false
}{
//true
} ifelse
}{
//true
} ifelse
}{
%% If we don't know, assume its visible
//true
} ifelse
} ifelse
}{
%% If we don't know, assume its visible
//true
} ifelse
}{
pop //false
}ifelse
} ifelse
} {
/OFF known not % OFF is inserted by process_trailer_attrs
} ifelse
} bind executeonly def
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
% Bug #698226, Acrobat signals an error for recursive XObjects in a PDF file
% but continues. This is true even if the XObject is not a simple self-reference
% (eg /Fm1 -> /Fm2 -> /Fm3 -> /Fm1).
% Normally when dealing with recursion we would put a dictionary on the stack, store the
% object numbers encoutnered in it, and check each new object number to see if we've
% already seen it. This doesn't work well for XObjects, because the operand stack can be
% in any state when we run a Do. So we make a new dictionary in pdfdict to hold the
% object numbers.
% We also don't usually know the object number of a Form, we just get given its name
% so we need a new routine to return the object number. This is because the parent XObject
% might reference teh object by one name, while the child references it by another, we
% can't permit clashes.
%
% Start by getting the object number for a Form XObject
dup Page /XObject obj_get dup 0 eq not {
% Now get the recording dictionary and see if that object number has been seen
//pdfdict /Recursive_XObject_D get 1 index known {
( **** Error: Recursive XObject detected, ignoring ") print 1 index 256 string cvs print (", object number ) print 256 string cvs print (\n) print
( Output may be incorrect.\n) pdfformaterror
//false
}{
% We haven't seen it yet, so record it.
//pdfdict /Recursive_XObject_D get 1 index null put
3 1 roll
//true
}ifelse
}
{
% I don't think this should be possible, but just in case
( **** Error: Unable to determine object number for ) print exch 256 string cvs print ( so ignoring it) print
( Output may be incorrect.\n) pdfformaterror
//false
} ifelse
% If we could get the object number, and we haven't already seen it, then execute it.
{
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
//pdfdict /Recursive_XObject_D get exch undef
}{
% Otherwise ignore it and tidy up the stacks
pop pop
} ifelse
} bind executeonly def
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
} bind executeonly def
/is_space_dict << 0 0 9 9 10 10 12 12 13 13 32 32 >> readonly def
drawopdict begin
/BI { mark } bind executeonly def
/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
} bind executeonly def
end
currentdict /is_space_dict undef
% ================================ Text ================================ %
drawopdict begin
% Text control
/BT { BT } executeonly def
/ET { ET } executeonly def
/Tc { Tc } executeonly def
/TL { TL } executeonly def
/Tr { Tr } executeonly def
/Ts { Ts } executeonly def
/Tw { Tw } executeonly def
/Tz { Tz } executeonly def
% Text positioning
/Td { Td } executeonly def
/TD { TD } executeonly def
/Tm { Tm } executeonly def
/T* { T* } executeonly def
% Text painting
/Tj { Tj } executeonly def
/' { ' } executeonly def
/" { " } executeonly def
/TJ { TJ } executeonly def
/Tform { Tform } executeonly 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
} executeonly def
/. {
0.
( **** Error: invalid operator . processed as number 0. .\n)
pdfformaterror % Bug 690730
( Output may be incorrect.\n) pdfformaterror
} executeonly 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
} bind executeonly def
% 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
} bind executeonly def
% 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
} bind executeonly def
% Set an annotation color.
% If the /C array is empty we don't want to draw the annotation
%
/annotsetinteriorcolor { % <annot> annotsetcolor bool
/IC 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
} bind executeonly def
% 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
} bind executeonly def
% 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: Invalid 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
} bind executeonly def
% stroke the path of an annotation border.
/strokeborderpath { % <annot> strokeborderpath -
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: Invalid 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 index /CA knownoget {.setopacityalpha} if
3 -1 roll pop 2 index annotsetcolor {0 setdash setlinewidth stroke} if
} {
dup 2 get
exch dup length 3 gt { 3 get } { pop {} } ifelse
3 index /CA knownoget {.setopacityalpha} if
2 index annotsetcolor {0 setdash setlinewidth stroke} if
} ifelse
} {
3 index /CA knownoget {.setopacityalpha} if
1 {} 2 index annotsetcolor {0 setdash setlinewidth stroke} if
} ifelse
pop
grestore
} bind executeonly def
/fillborderpath { % <annot> fillborderpath -
gsave
dup /ca knownoget {.setopacityalpha} if
annotsetinteriorcolor
{fill} if
grestore
}bind executeonly def
%
% 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
} bind executeonly def
/set_bc_color <<
1 { 0 get oforce setgray } bind executeonly
3 { { oforce } forall setrgbcolor } bind executeonly
4 { { oforce } forall setcmykcolor } bind executeonly
>> 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 executeonly 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 {
<EFBBBF> anchorsearch {
pop /Helvetica findfont 12 scalefont setfont
} {
<FEFF> anchorsearch {
pop pop /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont
} {
pop /Helvetica findfont 12 scalefont setfont
}ifelse
}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
} bind executeonly def
/can-regenerate-ap { % <annot> -> <bool>
//false exch
NeedAppearances {
dup /FT fget {
dup /Tx eq {
pop
dup /V oknown {
pop not 1
} if
} {
/Ch eq {
dup /V oknown {
pop not 1
} if
} if
} ifelse
} if
} if
pop
} bind executeonly def
/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
} bind executeonly def
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
} bind executeonly def
% Draw an annotation.
/drawannottypes 20 dict begin
/startannottransparency {
PDFusingtransparency {
dup /BM known {
dup /BM get
<< exch /BM exch >>
} {
<< >>
}ifelse
%% We should be able to use the Rect to create the group, but it seems
%% Acrobat ignores this, or at least doesn't clip the annotation to it :-(
% 1 index /Rect known {
% 1 index annotrect exch % llx lly h w
% 3 index add exch % x y urx h
% 2 index add
% }{
clippath pathbbox newpath
% } ifelse
.begintransparencygroup
} if
}bind executeonly def
/endannottransparency {
PDFusingtransparency {
.endtransparencygroup
} if
}bind executeonly def
% 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
} bind executeonly def
/Square {
dup /AP oknown {
//true
}{
gsave
//startannottransparency exec
dup
annotsetinteriorcolor
{
gsave
dup /ca knownoget {.setopacityalpha} if
dup annotrect rectfill
grestore
dup /CA knownoget {.setopacityalpha} if
drawborder
//false
}{
pop
} ifelse
//endannottransparency exec
grestore
}ifelse
} bind executeonly def
%% Width Height drawellipse -
/drawellipse {
%% Don Lancaster's code for drawing an ellipse
0.55228475 0.00045 sub % improved magic value
3 1 roll % magic width height
2 div exch 2 div % magic y-radius x-radius
dup 3 index mul % magic y-radius x-radius x-magic
2 index % magic y-radius x-radius x-magic y-radius
5 -1 roll mul % magic y-radius x-radius x-magic y-magic
2 index neg 0 moveto % xrad neg 0 moveto
2 index neg 1 index 3 index neg 6 index 0 8 index curveto % xrad neg ymag xmag neg yrad 0 yrad curveto
1 index 4 index 4 index 3 index 1 index 0 curveto % xmag yrad xrad ymag xrad 0 curveto
2 index 1 index neg 3 index 6 index neg 0 1 index curveto % xrad ymag neg xmag yrad neg 0 yrad neg curveto
% Stack: yrad xrad xmag ymag
exch neg 4 1 roll 3 -1 roll neg 3 1 roll exch neg exch
neg 1 index 0 curveto % xmag neg yrad neg xrad neg ymag neg 0 curveto
}bind executeonly def
/Circle {
dup /AP oknown {
//true
}{
gsave
//startannottransparency exec
dup annotrect 4 2 roll exch 3 index 2 div add exch 2 index 2 div add
translate //drawellipse exec
dup
fillborderpath
strokeborderpath
//endannottransparency exec
grestore
//false
} ifelse
} bind executeonly def
/Polygon {
dup /AP oknown {
//true
}{
gsave
//startannottransparency exec
dup /Vertices knownoget {
dup length 2 div 1 sub cvi 0 1 3 -1 roll
{
2 mul dup
2 index exch 2 getinterval aload pop
3 -1 roll 0 eq {
moveto
}{
lineto
} ifelse
}
for
pop
closepath
//true
} {
( **** Error: Invalid Vertices for Polygon, annotation has not been drawn.\n)
pdfformaterror
( Output may be incorrect.\n) pdfformaterror
//false
} ifelse
1 index annotsetinteriorcolor {
//true
}{
//false
}ifelse
and
{
gsave
dup /ca knownoget {.setopacityalpha} if
fill
grestore
dup /CA knownoget {.setopacityalpha} if
strokeborderpath
} if
//endannottransparency exec
//false
grestore
} ifelse
} bind executeonly def
/LineEnd_dict 10 dict begin
%% Stack contains <annot>
%% CTM rotated so line segment is vertical, translated so line endpoint at 0,0
/Square {
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
dup 2.5 mul
gsave
dup neg 1 index neg exch moveto
dup neg 1 index lineto
dup 1 index exch lineto
dup neg lineto
closepath
1 index /CA knownoget {.setopacityalpha} if
1 index fillborderpath
grestore
3 mul
dup neg 1 index neg exch moveto
dup neg 1 index lineto
dup 1 index exch lineto
dup neg lineto
closepath
strokeborderpath
} bind executeonly def
/Circle {
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
dup
gsave
2.5 mul dup
0 moveto
0 0 3 -1 roll 0 360 arc
1 index /CA knownoget {.setopacityalpha} if
1 index fillborderpath
grestore
3 mul dup
0 moveto
0 0 3 -1 roll 0 360 arc
strokeborderpath
} bind executeonly def
/Diamond {
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
dup 2.5 mul
gsave
dup neg 0 exch moveto
dup neg 0 lineto
dup 0 exch lineto
0 lineto
closepath
1 index /CA knownoget {.setopacityalpha} if
1 index fillborderpath
grestore
3 mul
dup neg 0 exch moveto
dup neg 0 lineto
dup 0 exch lineto
0 lineto
closepath
strokeborderpath
} bind executeonly def
/OpenArrow {
dup
gsave
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
0 setlinejoin
dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
dup 6 mul neg exch 4 mul lineto
strokeborderpath
grestore
} bind executeonly def
/ClosedArrow {
dup
gsave
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
dup
gsave
0 setlinejoin
dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
dup 6 mul neg exch 4 mul lineto closepath
1 index strokeborderpath
grestore
dup 1.3 mul neg 0 translate
dup 2 div sub
dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto
dup 8.4 mul neg exch 5.9 mul lineto closepath
dup /CA knownoget {.setopacityalpha} if
fillborderpath
grestore
} bind executeonly def
/None {} bind executeonly def
/Butt {
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
3 mul dup neg 0 exch moveto 0 exch lineto
strokeborderpath
} bind executeonly def
/ROpenArrow {
gsave
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
180 rotate
0 setlinejoin
dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
dup 6 mul neg exch 4 mul lineto
strokeborderpath
grestore
} bind executeonly def
/RClosedArrow {
gsave
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
180 rotate
dup
gsave
0 setlinejoin
dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
dup 6 mul neg exch 4 mul lineto closepath
1 index strokeborderpath
grestore
dup 1.3 mul neg 0 translate
dup 2 div sub
dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto
dup 8.4 mul neg exch 5.9 mul lineto closepath
dup /CA knownoget {.setopacityalpha} if
fillborderpath
grestore
} bind executeonly def
/Slash {
gsave
dup
/BS knownoget {
/W knownoget {
}{
1
}ifelse
}{
1
}ifelse
330 rotate
3 mul dup neg 0 exch moveto 0 exch lineto
strokeborderpath
grestore
} bind executeonly def
currentdict end readonly def
/Line {
dup /AP oknown {
//true
} {
gsave
//startannottransparency exec
dup /L knownoget {
1 index /LE knownoget {
gsave
1 index aload pop % x1 y1 x2 y2
3 -1 roll sub % x1 x2 dy
3 1 roll exch sub % dy dx
2 copy translate
atan
rotate
dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
grestore
gsave
1 index aload pop % x1 y1 x2 y2
3 -1 roll sub % x1 x2 dy
3 1 roll exch sub % dy dx
2 copy translate
atan 180 add
rotate
1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
grestore
}if
aload pop 4 2 roll
moveto lineto
strokeborderpath
}{
( **** Error: Invalid L array for Line, annotation has not been drawn.\n)
pdfformaterror
( Output may be incorrect.\n) pdfformaterror
pop
} ifelse
//endannottransparency exec
//false
grestore
} ifelse
} bind executeonly def
/PolyLine {
dup /AP oknown {
//true
}{
gsave
//startannottransparency exec
dup /Vertices knownoget {
1 index /LE knownoget {
gsave
1 index 0 4 getinterval aload pop
4 2 roll
2 copy translate 4 2 roll
3 -1 roll sub % x1 x2 dy
3 1 roll exch sub % dy dx
atan
rotate
dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
grestore
gsave
1 index dup length 4 sub 4 getinterval aload pop
2 copy translate
3 -1 roll sub % x1 x2 dy
3 1 roll exch sub % dy dx
atan
rotate
1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
grestore
} if
dup length 2 div 1 sub cvi 0 1 3 -1 roll
{
2 mul dup
2 index exch 2 getinterval aload pop
3 -1 roll 0 eq {
moveto
}{
lineto
} ifelse
}
for
pop
//true
} {
( **** Error: Invalid Vertices for Polygon, annotation has not been drawn.\n)
pdfformaterror
( Output may be incorrect.\n) pdfformaterror
//false
} ifelse
{
strokeborderpath
} if
//endannottransparency exec
//false
grestore
} ifelse
} bind executeonly def
/Link { % <annot> -> <false>
//startannottransparency exec
dup drawborder dup calc_annot_scale
2 copy mul 0 ne
{3 -1 roll drawwidget //false}
{
pop pop
( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
( Output may be incorrect.\n) pdfformaterror
}ifelse
//endannottransparency exec
} bind executeonly def
/Ink { % <annot> -> <annot> <true>
% <annot> -> <false>
dup /AP oknown {
//true
} {
//startannottransparency exec
1 setlinewidth
1 setlinecap
1 setlinejoin
dup annotsetcolor {
dup calc_annot_scale
2 copy mul 0 ne
{
scale
dup /InkList knownoget {
{ oforce
mark exch { oforce } forall
.pdfinkpath
stroke
} forall
pop
} {
/Path knownoget {
oforce
dup length 1 sub 0 1 3 -1 roll {
dup 0 eq {
1 index exch get aload pop moveto
} {
1 index exch get dup length 2 eq {
aload pop lineto
}{
aload pop curveto
} ifelse
}ifelse
} for
pop dup
strokeborderpath
} if
}ifelse
}
{
pop pop
( **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
( Output may be incorrect.\n) pdfformaterror
}
ifelse
} if
//endannottransparency exec
//false
} ifelse
} bind executeonly def
/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
} bind executeonly def
/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
} bind executeonly def
% 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 executeonly def
/emptydict 0 dict readonly def
/Highlight {
% technically we should apply an appearance stream if we have one, but if we do
% some test files don't match Acrobat. PDF 2.0 says appearance streams are mandatory,
% and take precedence over generatig new ones, so we may need to revisit this.
% dup /AP oknown {
% //true
% }{
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
% } ifelse
} bind executeonly def
currentdict /emptydict undef
currentdict /highlight-arc undef
/Squiggly {
dup /AP oknown {
//true
} {
//startannottransparency exec
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
//endannottransparency exec
//false
} ifelse
} bind executeonly def
/Text {
dup /AP oknown {
//true
} {
//startannottransparency exec
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
//endannottransparency exec
//false
} ifelse
} bind executeonly def
/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
//startannottransparency exec
dup annotrect 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 {
PDFusingtransparency {
.begintransparencytextgroup
} if
%% 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
PDFusingtransparency {
.endtransparencytextgroup
} if
} if
pop pop
//endannottransparency exec
//false
grestore
}
{
//true
} ifelse
} bind executeonly def
/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
} bind executeonly def
% (text) y h -> -
/text {
PDFusingtransparency {
.begintransparencytextgroup
} if
/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
PDFusingtransparency {
.endtransparencytextgroup
} if
} bind executeonly def
/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
} bind executeonly def
/AsIs {
//red //frame exec
(AS IS) 13 30 //text exec
} bind executeonly def
/Confidential {
//red //frame exec
(CONFIDENTIAL) 17 20 //text exec
} bind executeonly def
/Departmental {
//blue //frame exec
(DEPARTMENTAL) 17 20 //text exec
} bind executeonly def
/Draft {
//red //frame exec
(DRAFT) 13 30 //text exec
} bind executeonly def
/Experimental {
//blue //frame exec
(EXPERIMENTAL) 17 20 //text exec
} bind executeonly def
/Expired {
//red //frame exec
(EXPIRED) 13 30 //text exec
} bind executeonly def
/Final {
//red //frame exec
(FINAL) 13 30 //text exec
} bind executeonly def
/ForComment {
//green //frame exec
(FOR COMMENT) 17 20 //text exec
} bind executeonly def
/ForPublicRelease {
//green //frame exec
(FOR PUBLIC) 26 18 //text exec
(RELEASE) 8.5 18 //text exec
} bind executeonly def
/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
} bind executeonly def
/Sold {
//blue //frame exec
(SOLD) 13 30 //text exec
} bind executeonly def
/TopSecret {
//red //frame exec
(TOP SECRET) 14 26 //text exec
} bind executeonly def
currentdict end readonly def
{/text/frame/red/green/blue} {currentdict exch undef} forall
/Stamp {
dup /AP oknown {
//true
} {
//startannottransparency exec
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 0.0 eq {pop 1.0} if 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
//endannottransparency exec
//false
} ifelse
} bind executeonly def
/Popup {
dup /Open oknown {
dup /Open get {
dup /AP oknown {
//true
}{
gsave
//startannottransparency exec
newpath
0.05 setlinewidth
dup /Parent .knownget {
oforce
} {
dup /P .knownget {
oforce
} {
dup
} ifelse
} ifelse
/C .knownget {
aload pop
}{
1 1 0
}ifelse
setrgbcolor
dup /Rect get
dup aload pop
2 index sub
exch 3 index sub exch
4 copy
gsave 1 setgray rectfill grestore
gsave 0 setgray rectstroke grestore
1 index /Parent .knownget {
oforce
}{
1 index /P .knownget {
oforce
}{
1 index
} ifelse
}ifelse
dup
/Contents .knownget {
gsave
PDFusingtransparency {
.begintransparencytextgroup
} if
0 setgray
/Helvetica findfont 9 scalefont setfont
2 index aload pop 3 1 roll pop pop 30 sub exch 5 add exch
moveto show
PDFusingtransparency {
.endtransparencytextgroup
} if
grestore
} if
exch
dup aload pop 3 -1 roll pop exch 2 index sub -15
4 copy rectfill
0 setgray rectstroke
exch
/T .knownget {
gsave
PDFusingtransparency {
.begintransparencytextgroup
} if
0 setgray
/Helvetica findfont 9 scalefont setfont
dup stringwidth pop
2 index aload pop pop exch pop exch sub
exch sub 2 div 2 index aload pop 3 1 roll pop pop 11 sub 3 1 roll add exch moveto
show
PDFusingtransparency {
.endtransparencytextgroup
} if
grestore
} if
grestore
//endannottransparency exec
//false
} ifelse
} {
pop //false
}ifelse
} {
pop //false
}ifelse
} bind executeonly def
/Redact {
%% Redact annotations are part of a process, a Redact annotation is only present
%% until the content is removed, before that the content should be present and
%% I beleive we should print it. So take no action for Redact annotations if they
%% have no appearance.
dup /AP oknown {
//true
} {
//false
} ifelse
} bind executeonly def
currentdict /startannottransparency undef
currentdict /endannottransparency undef
currentdict /quadpoints2basis undef
currentdict /drawellipse undef
currentdict end readonly def
/.PDFDrawAnnotType?
{
//false exch
/ShowAnnotTypes where
{
/ShowAnnotTypes get
{
dup /* eq exch 2 index eq or
{
pop //true exch
exit
} if
} forall
pop
}
{pop pop //true}
ifelse
} bind executeonly def
/drawannot { % <annot> drawannot -
dup annotvisible {
gsave
dup dup /Subtype knownoget {
dup //.PDFDrawAnnotType? exec
{
//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
}ifelse
} {
pop
( **** Error: Ignoring /Annot dict without required /Subtype entry.\n)
pdfformaterror
( Output may be incorrect.\n) pdfformaterror
} ifelse
grestore
} if pop % annotvisible
} bind executeonly def
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
Removepdfobj#
} 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
} bind executeonly def
/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
} bind executeonly def
/preserveannottypes 20 dict begin
/Circle {mark exch loadannot /ANN pdfmark false} bind executeonly def
/FileAttachment {mark exch loadannot /ANN pdfmark false} bind executeonly def
/FreeText {mark exch loadannot /ANN pdfmark false} bind executeonly def
/Highlight {
mark exch
dup /QuadPoints .knownget {
1 index /QuadPoints 3 -1 roll
ApplyCTMToQuadPoints
put
} if
loadannot /ANN pdfmark false
} bind executeonly def
/Ink {mark exch loadannot /ANN pdfmark false} bind executeonly def
/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
} bind executeonly def
/Link {
/NO_PDFMARK_DESTS where {pop NO_PDFMARK_DESTS not}{true}ifelse
{
mark exch
dup /BS knownoget { << exch { oforce } forall >> /BS exch 3 -1 roll } if
dup /F knownoget { /F exch 3 -1 roll } if
dup /C knownoget { /Color exch 3 -1 roll } if
dup /Rect knownoget { /Rect exch 3 -1 roll } if
dup /Border knownoget {
dup type /arraytype eq {
dup length 3 lt
} {
//true
} ifelse {
pop [ 0 0 0 ] % Following AR5 use invisible border.
} if
/Border exch 3 -1 roll
} if
dup /A knownoget {
dup /URI known {
/A mark 3 2 roll % <<>> /A [ <<action>>
{ oforce } forall
.dicttomark
3 2 roll
} {
dup /S knownoget {
%% Because we process GoTo Destinations into absolute references in the PDF file
%% we need to resolve the /D or /Dest. However, we must *not* do this for
%% GoToR Destinations because (obviously) those are in a different file and
%% we cannot resolve them into absolute references. We don't need to anyway
%% because that file must already have a named destination.
dup /GoTo eq {
pop
dup /D knownoget {
exch pop exch dup length dict copy dup /Dest 4 -1 roll put
} if
}{
dup /GoToR eq {
pop /A mark % <<..action dict..>> /A [
3 2 roll % /A [ <<..action dict..>>
{ oforce } forall
.dicttomark
3 2 roll
}{
dup /Launch eq {
pop /A mark % <<..action dict..>> /A [
3 2 roll % /A [ <<..action dict..>>
{ oforce } forall
.dicttomark
3 2 roll
}{
/Named eq {
/N knownoget {
namedactions exch .knownget {
exec {
pop
( **** Warning: Ignoring a named action pointing out of the document page range.\n)
pdfformatwarning
} {
/Page exch 3 -1 roll
} ifelse
} if
} if
} if
}ifelse
} ifelse
} ifelse
} if
} ifelse
} if
{ linkdest } stopped {
cleartomark
( **** Warning: Link annotation points out of the document page range.\n)
pdfformatwarning
} {
pop
{
%% Need to remove any '/.gs.pdfobj# key/value pairs from any dictionaries
counttomark array astore dup length 1 sub 0 1 3 -1 roll {
dup 2 index exch get Removepdfobj# 2 index 3 1 roll put
} for aload pop
/LNK pdfmark
} stopped {cleartomark} if
} ifelse
}{pop} ifelse
false
} bind executeonly def
/Movie {mark exch loadannot /ANN pdfmark false} bind executeonly def
/Popup {mark exch loadannot /ANN pdfmark false} bind executeonly def
/Sound {mark exch loadannot /ANN pdfmark false} bind executeonly def
/Square {mark exch loadannot /ANN pdfmark false} bind executeonly def
/Stamp {mark exch loadannot /ANN pdfmark false} bind executeonly def
/StrikeOut {
mark exch
dup /QuadPoints .knownget {
1 index /QuadPoints 3 -1 roll
ApplyCTMToQuadPoints
put
} if
loadannot /ANN pdfmark false
} bind executeonly def
/Squiggly {
mark exch
dup /QuadPoints .knownget {
1 index /QuadPoints 3 -1 roll
ApplyCTMToQuadPoints
put
} if
loadannot /ANN pdfmark false
} bind executeonly def
/Text {mark exch loadannot /ANN pdfmark false} bind executeonly def
/TrapNet {mark exch loadannot /ANN pdfmark false} bind executeonly def
/Underline {
mark exch
dup /QuadPoints .knownget {
1 index /QuadPoints 3 -1 roll
ApplyCTMToQuadPoints
put
} if
loadannot /ANN pdfmark false
} bind executeonly def
%% 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} bind executeonly def
currentdict end readonly def
/preserveannot { % <annot> preserveannot -
dup /.gs.pdfobj# known {
dup /.gs.pdfobj# undef
} if
dup annotvisible {
gsave
dup dup /Subtype knownoget {
dup //.PDFDrawAnnotType? exec
{
//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
}
{pop} ifelse
% type known
} {
pop
( **** Error: Ignoring /Annot dict without required /Subtype entry.\n)
pdfformaterror
( Output may be incorrect.\n) pdfformaterror
} ifelse
grestore
} if pop % annotvisible
} bind executeonly def
currentdict /preserveannottypes undef
currentdict /.PDFDrawAnnotType? 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
} bind executeonly def
% 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
} bind executeonly def
/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
} if write==
dup 3 index /Ff pget not { 0 } if write=
dup 3 index /Q pget not { 0 } if write=
dup (Tform ET) write=
end
closefile % <acroform> <field> <annot>
dup 1 1 3 -1 roll drawwidget
} if
} ifelse
} bind executeonly def
/Ch {
dup /AP known 3 index /NeedAppearances knownoget not { //true } if not and {
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
} if write==
dup 3 index /Ff pget not { 0 } if write=
dup 3 index /Q pget not { 0 } if write=
dup (Tform ET) write=
end
closefile % <acroform> <field> <annot>
dup 1 1 3 -1 roll drawwidget
} if
} ifelse
} bind executeonly def
/Sig {
(Sig is not yet implemened ) //== exec
} bind executeonly def
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
} bind executeonly def
% 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
} bind executeonly def
/draw_acro_form { % <form> draw_acro_form -
dup /Fields knownoget {
{ oforce draw_form_field } forall
} if
pop
} bind executeonly def
currentdict /draw_terminal_field_dict undef
end % pdfdict
end % GS_PDF_ProcSet
.setglobal
SEA-GHOST - SHELL CODING BY SEA-GHOST