summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/lib/pdf_draw.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlgs/lib/pdf_draw.ps')
-rw-r--r--Master/tlpkg/tlgs/lib/pdf_draw.ps1604
1 files changed, 1604 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/lib/pdf_draw.ps b/Master/tlpkg/tlgs/lib/pdf_draw.ps
new file mode 100644
index 00000000000..68789c37de9
--- /dev/null
+++ b/Master/tlpkg/tlgs/lib/pdf_draw.ps
@@ -0,0 +1,1604 @@
+% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
+%
+% This software is provided AS-IS with no warranty, either express or
+% implied.
+%
+% This software is distributed under license and may not be copied,
+% modified or distributed except as expressly authorized under the terms
+% of the license contained in the file LICENSE in this distribution.
+%
+% For more information about licensing, please refer to
+% http://www.ghostscript.com/licensing/. For information on
+% commercial licensing, go to http://www.artifex.com/licensing/ or
+% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
+
+% $Id: pdf_draw.ps 8061 2007-06-19 02:39:15Z alexcher $
+% pdf_draw.ps
+% PDF drawing operations (graphics, text, and images).
+
+/.setlanguagelevel where { pop 2 .setlanguagelevel } if
+.currentglobal true .setglobal
+/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
+GS_PDF_ProcSet begin
+pdfdict begin
+
+% For simplicity, we use a single interpretation dictionary for all
+% PDF graphics operations, even though this is too liberal.
+/drawopdict 100 dict def
+
+% ================================ Graphics ================================ %
+
+% ---------------- Functions ---------------- %
+
+% Note that resolvefunction converts a PDF Function to a PostScript Function;
+% resolve*fnproc converts a PDF function to a PostScript procedure.
+% We need to process all required and optional parameters to resolve any
+% use of indirect references.
+
+/fnrdict mark
+ 0 { .resolvefn0 }
+ 2 { .resolvefn2 }
+ 3 { .resolvefn3 }
+ 4 { .resolvefn4 }
+.dicttomark readonly def
+
+/.resolvefn0 {
+ dup length 1 add dict .copydict % make room for DataSource
+ % now resolve any indirect references
+ dup /Size 2 copy knownoget { put } { pop pop } ifelse
+ dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse
+ dup /Order 2 copy knownoget { put } { pop pop } ifelse
+ dup /Encode 2 copy knownoget { put } { pop pop } ifelse
+ dup /Decode 2 copy knownoget { put } { pop pop } ifelse
+
+ % Don't lose our place in PDFfile.
+ PDFfile fileposition exch
+ dup true resolvestream
+ % The stream isn't positionable, so read all the data now.
+ % Stack: filepos fndict stream
+ 1 index /Range get length 2 idiv 2 index /BitsPerSample get mul
+ 2 index /Size get { mul } forall
+ 7 add 8 idiv string
+ 1 index exch readstring pop exch closefile
+ % Stack: filepos fndict data
+ exch dup /DataSource 4 -1 roll put
+ exch PDFfile exch setfileposition
+} bdef
+
+/.resolvefn2 {
+ dup length dict .copydict
+ dup /C0 2 copy knownoget { put } { pop pop } ifelse
+ dup /C1 2 copy knownoget { put } { pop pop } ifelse
+ dup /N 2 copy knownoget { put } { pop pop } ifelse
+} bdef
+
+/.resolvefn3 {
+ dup length dict .copydict
+ dup /Bounds 2 copy knownoget { put } { pop pop } ifelse
+ dup /Encode 2 copy knownoget { put } { pop pop } ifelse
+ dup /Functions 2 copy oget mark exch dup {
+ oforce .resolvefn
+ } forall
+ counttomark -1 roll astore exch pop put
+} bdef
+
+/.resolvefn4 {
+ PDFfile fileposition exch % filepos fndict
+ dup true resolvestream % filepos fndict stream
+ exch dup length dict copy % filepos stream fndict2
+ dup /Function undef % filepos stream fndict2
+ exch dup token not {
+ () /rangecheck cvx signalerror
+ } if
+ exch token {
+ /rangecheck cvx signalerror
+ } if
+ % Use .bind to avoid idiom recognition.
+ .bind
+ 1 index /Function 3 -1 roll put
+ exch PDFfile exch setfileposition
+} bdef
+
+/.resolvefn { % <fndict> .resolvefn <fndict'>
+ dup length dict .copydict
+ dup /Domain 2 copy knownoget { put } { pop pop } ifelse
+ dup /Range 2 copy knownoget { put } { pop pop } ifelse
+ dup /FunctionType oget //fnrdict exch get exec
+} bdef
+
+/resolvefunction { % <fndict> resolvefunction <function>
+ .resolvefn
+ PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Function: ) print dup === flush } if } if
+} bdef
+
+/resolvefnproc { % <fndict> resolvefnproc <proc>
+ resolvefunction .buildfunction
+} bdef
+
+/resolveidfnproc { % <fndict> resolveidfnproc <proc>
+ dup /Identity eq { pop { } } { resolvefnproc } ifelse
+} bdef
+
+/resolvedefaultfnproc { % <fndict> <default> resolved'fnproc <proc>
+ 1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
+} bdef
+
+% ---------------- Shadings ---------------- %
+
+/shrdict mark
+ /BBox {
+ dup dup dup aload pop normrect_elems
+ 5 -1 roll astore
+ } bind
+ /ColorSpace {
+ resolvecolorspace
+ } bind
+ /Function {
+ dup type /dicttype eq {
+ resolvefunction
+ } {
+ [ exch { oforce resolvefunction } forall ]
+ } ifelse
+ } bind
+.dicttomark readonly def
+
+/resolveshading { % <shadingstream> resolveshading <shading>
+ dup /.shading_dict .knownget {
+ exch pop
+ dup /ShadingType get 4 ge {
+ dup /DataSource get 0 setfileposition
+ } if
+ } {
+ dup
+ PDFfile fileposition exch
+ mark exch {
+ oforce //shrdict 2 index .knownget { exec } if
+ } forall .dicttomark
+ dup /ShadingType get 4 ge {
+ dup dup true resolvestream
+ % Make a reusable stream so that the shading doesn't
+ % reposition PDFfile at unexpected times.
+ /ReusableStreamDecode filter /DataSource exch put
+ } if
+ exch PDFfile exch setfileposition
+ dup 3 1 roll /.shading_dict exch put
+ } ifelse
+} bdef
+/resolvesh { % <shname> resolvesh <shading>
+ % <shname> resolvesh <null>
+ Page /Shading rget {
+ resolveshading
+ } {
+ null
+ }ifelse
+} bdef
+
+% ---------------- Halftones ---------------- %
+
+/spotfunctions mark
+ /Round {
+ abs exch abs 2 copy add 1 le {
+ dup mul exch dup mul add 1 exch sub
+ } {
+ 1 sub dup mul exch 1 sub dup mul add 1 sub
+ } ifelse
+ }
+ /Diamond {
+ abs exch abs 2 copy add .75 le {
+ dup mul exch dup mul add 1 exch sub
+ } {
+ 2 copy add 1.23 le {
+ .85 mul add 1 exch sub
+ } {
+ 1 sub dup mul exch 1 sub dup mul add 1 sub
+ } ifelse
+ } ifelse
+ }
+ /Ellipse {
+ abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
+ pop dup mul exch .75 div dup mul add 4 div 1 exch sub
+ } {
+ dup 1 gt {
+ pop 1 exch sub dup mul exch 1 exch sub
+ .75 div dup mul add 4 div 1 sub
+ } {
+ .5 exch sub exch pop exch pop
+ } ifelse
+ } ifelse
+ }
+ /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
+ /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
+ /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
+ /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
+ /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
+ /Line { exch pop abs neg }
+ /LineX { pop }
+ /LineY { exch pop }
+ /Square { abs exch abs 2 copy lt { exch } if pop neg }
+ /Cross { abs exch abs 2 copy gt { exch } if pop neg }
+ /Rhomboid { abs exch abs 0.9 mul add 2 div }
+ /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
+ /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
+ /SimpleDot { dup mul exch dup mul add 1 exch sub }
+ /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
+ /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
+ /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
+ /InvertedDouble {
+ exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
+ }
+.dicttomark readonly def
+
+/htrdict mark
+ 1 { .resolveht1 }
+ 5 { .resolveht5 }
+ % We don't support types 6, 10, or 16 yet.
+.dicttomark readonly def
+
+/.resolveht1 {
+ mark exch {
+ oforce
+ 1 index /SpotFunction eq {
+ dup type /nametype eq
+ { //spotfunctions exch get } { resolvefnproc }
+ ifelse
+ } {
+ 1 index /TransferFunction eq {
+ resolveidfnproc
+ } if
+ } ifelse
+ } forall .dicttomark
+} bdef
+
+/.resolveht5 {
+ mark exch {
+ oforce dup type /dicttype eq { resolvehalftone } if
+ } forall .dicttomark
+} bdef
+
+/resolvehalftone { % <dict> resolvehalftone <halftone>
+ dup /HalftoneType get
+ dup //htrdict exch .knownget {
+ exch pop exec
+ } {
+ (\n\n **** Unsupported HalftoneType ) pdfformaterror
+ =string cvs pdfformaterror (. ***\n\n) pdfformaterror
+ /resolvehalftone cvx /unregistered signalerror
+ } ifelse
+} bdef
+
+% ---------------- Graphics state management ---------------- %
+
+/cmmatrix matrix def
+drawopdict begin
+ % Graphics state stack
+ /q { q } def
+ /Q { Q } def
+ % Graphics state setting
+ /cm { //cmmatrix astore
+ .getpath
+ exch concat
+ newpath { exec } forall
+ % If inside a BT/ET block, we need to update the TextSaveMatrix
+ currentdict /TextSaveMatrix .knownget {
+ //cmmatrix exch dup concatmatrix pop
+ } if
+ } bdef
+
+ /i { 1 .min setflat } bdef
+ /J /setlinecap load def
+ /d /setdash load def
+ /j /setlinejoin load def
+ /w /setlinewidth load def
+ /M { 1 .max setmiterlimit } bdef
+ /gs { gs } def
+end
+
+% Each entry in this dictionary is
+% <gsres> <value> -proc- <gsres>
+/gsbg {
+ /BGDefault load resolvedefaultfnproc setblackgeneration
+} bdef
+/gsucr {
+ /UCRDefault load resolvedefaultfnproc setundercolorremoval
+} bdef
+/gstr {
+ dup type /arraytype eq {
+ { oforce /TRDefault load resolvedefaultfnproc } forall
+ setcolortransfer
+ } {
+ /TRDefault load resolvedefaultfnproc settransfer
+ } ifelse
+} bdef
+/gsparamdict mark
+ /SA { setstrokeadjust }
+ /OP { 1 index /op known not { dup op } if OP }
+ % The PDF 1.3 specification says that the name /Default is only
+ % recognized for {BG,UCR,TR}2. However, PDF 1.3 files produced
+ % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default
+ % with the older keys, so we have to implement this.
+ /BG { 1 index /BG2 known { pop } { gsbg } ifelse }
+ /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse }
+ /TR { 1 index /TR2 known { pop } { gstr } ifelse }
+ /HT {
+ dup /Default eq {
+ pop .setdefaulthalftone
+ } {
+ %****** DOESN'T IMPLEMENT THE STREAM CASE YET ******
+ resolvehalftone sethalftone
+ } ifelse
+ % the transfer function may dependent on the halftone, so make sure
+ % it is set if included in the graphic state (otherwise this is
+ % subject to order of a dictionary forall, which is unpredictable)
+ dup /TR2 .knownget {
+ dup /Default eq { oforce gsparamdict /TR2 get exec } { pop } ifelse
+ } {
+ dup /TR .knownget {
+ /dup /Default eq { oforce gsparamdict /TR get exec } { pop } ifelse
+ } if
+ } ifelse
+ }
+ /HTP {
+ % HTP may be present even if this isn't a DPS interpreter.
+ /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
+ }
+ % PDF 1.3
+ /Font { aload pop Tf }
+ /LW { setlinewidth }
+ /LC { setlinecap }
+ /LJ { setlinejoin }
+ /ML { 1 .max setmiterlimit }
+ /D { aload pop setdash }
+ /RI { ri }
+ /op { op }
+ /OPM { OPM }
+ /BG2 { gsbg }
+ /UCR2 { gsucr }
+ /TR2 { gstr }
+ /FL { 1 .min setflat }
+ /SM {
+ % SM may be present even if this is only a Level 2 interpreter.
+ /setsmoothness where { pop setsmoothness } { pop } ifelse
+ }
+ % PDF 1.4
+ % All of these require the "transparency" feature in the interpreter.
+ /ca { ca }
+ /CA { CA }
+ /SMask { gssmask }
+ /AIS { AIS }
+ /BM { BM }
+ /TK { TK }
+.dicttomark readonly def
+/gs { % <gsres> gs -
+ Page /ExtGState rget {
+ % We keep the dictionary on the stack during the forall so that
+ % keys that interact with each other have access to it.
+ dup {
+ oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
+ } forall pop
+ } if
+} bdef
+
+% ------ Transparency support ------ %
+
+/gssmask {
+ dup /None eq PDFusingtransparency not or {
+ pop null
+ } {
+ % Preprocess the SMask value into a parameter dictionary for
+ % .begintransparencymaskgroup, with added /BBox and /Draw keys.
+ mark exch % Stack: mark smaskdict
+ dup /S oget /Subtype exch 3 2 roll
+ % Stack: mark ... smaskdict
+ dup /BC knownoget {
+ dup /Background exch 4 2 roll
+ gsave
+ 1 index /G oget /Group oget /CS knownoget {
+ csresolve dup setgcolorspace csput
+ } if
+ aload pop setcolor [ currentgray ]
+ grestore
+ /GrayBackground exch 3 2 roll
+ } if
+ dup /TR knownoget {
+ resolveidfnproc /TransferFunction exch 3 2 roll
+ } if
+ dup /G oget dup /BBox oget /BBox exch 4 2 roll
+ /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
+ pop .dicttomark
+ } ifelse SMask
+} bdef
+
+% This procedure is called to actually render the soft mask.
+/.execmaskgroup { % <masknum> <paramdict> <formdict> .execmaskgroup -
+ % Save our place in PDFfile, and do a gsave to avoid resetting
+ % the color space.
+ currentcolorspace 4 1 roll
+ PDFfile fileposition 4 1 roll
+ % We have to select the group's color space so that the
+ % background color will be interpreted correctly.
+ dup /Group oget /CS knownoget { csresolve dup setgcolorspace csput } if
+ exch dup /BBox get aload pop .begintransparencymaskgroup {
+ dup /Resources knownoget { oforce } { 0 dict } ifelse
+ exch false resolvestream
+ .execgroup .endtransparencymask
+ } stopped {
+ .discardtransparencymask stop
+ } if
+ PDFfile exch setfileposition
+ setcolorspace
+} bdef
+% Paint a Form+Group XObject, either for a transparency mask or for a Do.
+/.execgroup { % <resdict> <stream> .execgroup -
+ gsave //nodict begin
+ null SMask
+ 1 .setopacityalpha 1 .setshapealpha
+ 0 .inittransparencymask 1 .inittransparencymask
+ /Compatible .setblendmode
+ % Execute the body of the Form, similar to DoForm.
+ pdfopdict .pdfruncontext
+ end grestore
+} bdef
+
+/.beginformgroup { % groupdict bbox .beginformgroup -
+ exch mark exch % bbox mark groupdict
+ dup /CS knownoget { csresolve setgcolorspace } if
+ dup /I knownoget { /Isolated exch 3 2 roll } if
+ dup /K knownoget { /Knockout exch 3 2 roll } if
+ pop .dicttomark
+ % Stack: bbox paramdict
+ exch aload pop
+ .begintransparencygroup
+} bdef
+
+% .paintgroupform implements the Form PaintProc in the case where the
+% Form XObject dictionary includes a Group key. See .paintform below.
+/.paintgroupform { % <resdict> <stream> <formdict> .paintgroupform -
+ dup /Group oget exch /BBox oget
+ % Stack: resdict stream groupdict bbox
+ .beginformgroup {
+ .execgroup
+ } stopped {
+ .discardtransparencygroup stop
+ } if .endtransparencygroup
+} bdef
+
+% Make an ImageType 103 (soft-masked) image.
+/makesoftmaskimage { % <datasource> <imagemask> <SMask> makesoftmaskimage
+ % <datasource> <imagemask>, updates currentdict =
+ % imagedict
+ % See the ImageType 3 case of makemaskimage below.
+ % SMask is a stream, another Image XObject.
+ % Stack: datasource imagemask(false) smaskstreamdict
+ PDFfile fileposition exch
+ dup /Matte knownoget { /Matte exch def } if
+ dup length dict makeimagedict pop
+ % In order to prevent the two data sources from being
+ % aliased, we need to make at least one a reusable stream.
+ % We pick the mask, since it's smaller (in case we need to
+ % read all its data now).
+ % Stack: datasource imagemask(false) savedpos
+ % maskdict is currentdict
+ /DataSource DataSource mark
+ /Intent 1
+ /AsyncRead true
+ .dicttomark .reusablestreamdecode def
+ PDFfile exch setfileposition
+ currentdict end currentdict end
+ 5 dict begin
+ /ImageType 103 def
+ /DataDict exch def
+ dup /InterleaveType 3 put
+ DataDict /Matte knownoget {
+ /Matte exch def
+ } if
+ AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
+ /ColorSpace DataDict /ColorSpace get def
+} bdef
+
+% ---------------- Color setting ---------------- %
+
+/01_1 [0 1] readonly def
+/01_3 [0 1 0 1 0 1] readonly def
+/01_4 [0 1 0 1 0 1 0 1] readonly def
+
+% The keys here are resolved (PostScript, not PDF) color space names.
+/csncompdict mark
+ /DeviceGray { pop 1 }
+ /DeviceRGB { pop 3 }
+ /DeviceCMYK { pop 4 }
+ /CIEBasedA { pop 1 }
+ /CIEBasedABC { pop 3 }
+ /ICCBased { 1 oget /N oget }
+ /Separation { pop 1 }
+ /DeviceN { 1 oget length }
+.dicttomark readonly def
+
+/csrdict mark
+ /DeviceGray { }
+ /DeviceRGB { }
+ /DeviceCMYK { }
+ /CalGray {
+ 1 oget 6 dict begin
+ dup /Gamma knownoget {
+ /exp load 2 packedarray cvx /DecodeA exch def
+ } if
+ dup /BlackPoint knownoget { /BlackPoint exch def } if
+ dup /WhitePoint knownoget {
+ dup /WhitePoint exch def
+ dup /MatrixA exch def
+ /RangeLMN [ 3 2 roll { 0 exch } forall ] def
+ } if
+ /PDFColorSpace exch def [ /CIEBasedA currentdict end ]
+ }
+ /CalRGB {
+ 1 oget 6 dict begin
+ dup /Gamma knownoget {
+ [ exch { /exp load 2 packedarray cvx } forall
+ ] /DecodeABC exch def
+ } if
+ dup /Matrix knownoget { /MatrixABC exch def } if
+ dup /BlackPoint knownoget { /BlackPoint exch def } if
+ dup /WhitePoint knownoget { /WhitePoint exch def } if
+ /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
+ }
+ /CalCMYK {
+ pop /DeviceCMYK % not defined by Adobe
+ }
+ /Lab {
+ 1 oget 6 dict begin
+ dup /Range knownoget not { [-100 100 -100 100] } if
+ [0 100 null null null null] dup 2 4 -1 roll putinterval
+ /RangeABC exch def
+ /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
+ /MatrixABC [1 1 1 1 0 0 0 0 -1] def
+ dup /BlackPoint knownoget { /BlackPoint exch def } if
+ dup /WhitePoint knownoget { /WhitePoint exch def } {
+ ( **** Warning: Lab colorspace is missing WhitePoint.\n)
+ pdfformaterror
+ /WhitePoint [0.9505 1 1.089] def
+ } ifelse
+ % scaling function g() for DecodeLMN construction
+ { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
+ /DecodeLMN [
+ % Store white point implicitly inside procedures.
+ [ 3 index aload pop WhitePoint 0 get /mul .systemvar ] cvx bind
+ [ 4 index aload pop WhitePoint 1 get /mul .systemvar ] cvx bind
+ [ 5 index aload pop WhitePoint 2 get /mul .systemvar ] cvx bind
+ ] def pop
+ /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
+ }
+ /ICCBased {
+ dup 1 get type /dicttype ne { % don't resolve more than once
+ PDFfile fileposition exch
+ dup dup 1 oget
+ mark exch { oforce } forall .dicttomark
+ dup dup true resolvestream
+ /ReusableStreamDecode filter /DataSource exch put
+ 1 exch put
+ exch PDFfile exch setfileposition
+ % Resolve alternate color space
+ dup 1 get % Get colorspace dictionary
+ dup /Alternate .knownget % Check for alternate color space
+ { oforce resolvecolorspace /Alternate exch put } % resolve and replace
+ { pop } % remove colorspace dictionary
+ ifelse
+ } if
+ } bind
+ /Separation {
+ aload pop exch oforce resolvecolorspace
+ % Contrary to PDF manuals up to v.1.5, Acrobat Distiller 3.01
+ % can use /Identity name here instead of a function.
+ exch oforce resolveidfnproc
+ 4 array astore
+ }
+ /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
+ }
+ /Indexed {
+ aload pop 3 -1 roll oforce resolvecolorspace
+ % Stack: /Indexed hival lookup basespace
+ % If the underlying space is a Lab space, we must scale
+ % the output of the lookup table as part of DecodeABC.
+ dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq {
+ dup 1 get /DecodeLMN known {
+ 1 get dup length dict copy
+ begin /DecodeABC [ 0 2 4 {
+ RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load
+ RangeABC 3 index get /add load
+ DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx
+ } for ] def
+ /RangeABC //01_3 def
+ currentdict end /CIEBasedABC exch 2 array astore
+ } if
+ } if
+ 3 1 roll
+ oforce dup type /stringtype ne {
+ % The color lookup table is a stream.
+ % Get its contents. Don't lose our place in PDFfile.
+ % Stack: /Indexed basespace hival lookup
+ PDFfile fileposition 5 1 roll true resolvestream
+ % Stack: filepos /Indexed basespace hival lookupstream
+ 1 index 1 add
+ % Stack: filepos /Indexed basespace hival lookupstream len
+ 3 index
+ dup dup type /arraytype eq { 0 get } if
+ //csncompdict exch get exec mul
+ string dup 3 1 roll readstring pop % the string is padded with 0s
+ length 1 index length lt {
+ ( **** Warning: Short look-up table in the Indexed color space was padded with 0's.\n)
+ pdfformaterror
+ } if
+ % Stack: filepos /Indexed basespace hival table table'
+ 5 -1 roll PDFfile exch setfileposition
+ }
+ if 4 array astore
+ % Replace the PDFColorSpace with the Indexed space if needed.
+ dup 1 get
+ dup type /arraytype eq {
+ dup length 2 ge {
+ dup 1 get type /dicttype eq {
+ dup 1 get /PDFColorSpace known {
+ dup 1 get /PDFColorSpace 3 index put
+ } if
+ } if
+ } if
+ } if pop
+ }
+ /Pattern {
+ dup type /nametype ne {
+ dup length 1 gt {
+ 1 oget resolvecolorspace
+ /Pattern exch 2 array astore
+ } if
+ } if
+ }
+.dicttomark readonly def
+
+/cssubst { % <csname> cssubst <cspace'> true
+ % <csname> cssubst false
+ dup resolvecolorspace
+ dup 1 index ne { exch pop true } { pop pop false } ifelse
+} bdef
+
+/csnames mark
+ /DeviceGray dup /DeviceRGB dup /DeviceCMYK dup /Pattern dup
+.dicttomark readonly def
+/csresolve { % <csresourcename> csresolve <cspace>
+ dup type /nametype ne {
+ (\n **** Warning: CS/cs (setcolorspace) operand not a name: ) pdfformaterror
+ dup stderrfile dup 3 -1 roll write==only flushfile
+ ( ****\n) pdfformaterror
+ dup type /arraytype eq { % Adobe InDesign + PDF Library has array
+ resolvecolorspace
+ } if
+ } {
+ dup Page /ColorSpace rget {
+ exch pop resolvecolorspace
+ } {
+ //csnames 1 index known not { /undefined cvx signalerror } if
+ } ifelse
+ } ifelse
+} bdef
+/resolvecolorspace { % <cspace> resolvecolorspace <cspace'>
+ dup dup type /arraytype eq { 0 get } if
+ //csrdict exch .knownget
+ {
+ exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
+ } {
+ dup type /nametype eq { csresolve } { csset exch pop } ifelse
+ } ifelse
+} bdef
+
+/scresolve { % <c0> ... scresolve <multi>
+ % We can't really make sc[n] and SC[N] work, because
+ % the color space information isn't available at
+ % conversion time; so we hack it by assuming that
+ % all the operands on the stack are used, and that
+ % if the top operand is a name, it's a Pattern resource.
+ dup type /nametype eq
+ { Page /Pattern rget { resolvepattern } { null } ifelse }
+ if
+ dup type /dicttype eq {
+ % Check the PaintType, if any (shading patterns don't
+ % have one).
+ dup /PaintType knownoget { 2 eq } { false } ifelse
+ } {
+ .pdfcount 1 gt
+ } ifelse
+} bdef
+
+/.pdfpaintproc { % <patdict> <resdict> .pdfpaintproc -
+ PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Begin PaintProc) print dup === flush } if } if
+ % For uncolored patterns, we have to unbind the current
+ % color and color space before running the PaintProc.
+ % There's no harm in doing this for colored patterns,
+ % so for simplicity, we always do it.
+ PDFfile fileposition 3 1 roll
+ q
+ null sc1 null SC1
+
+ % save old value of pdfemptycount on opstack, set to new value
+ pdfemptycount /pdfemptycount count 3 sub def 3 1 roll
+ exch false resolvestream pdfopdict .pdfruncontext
+ % restore pdfemptycount
+ /pdfemptycount exch def
+
+ Q
+ PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%End PaintProc) print dup === flush } if } if
+ PDFfile exch setfileposition
+} bdef
+
+/resolvepattern { % <patternstreamdict> resolvepattern <patterndict>
+ % Don't do the resolvestream now: just capture the data
+ % from the file if necessary.
+ dup length dict copy
+ dup /FilePosition .knownget {
+ 1 index /File get dup fileposition 3 1 roll
+ % Stack: dict savepos pos file
+ dup 3 -1 roll setfileposition
+ dup 3 index /Length oget
+
+ dup 65535 le {
+ dup 0 eq {
+ pop pop ()
+ } {
+ string readstring pop
+ } ifelse
+ } {
+ () /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
+ PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Pattern: ) print dup === flush } if } if
+} bdef
+
+drawopdict begin
+ /g { /DeviceGray cssubst { cs sc1 } { g } ifelse } bdef
+ /rg { /DeviceRGB cssubst { cs sc* } { rg } ifelse } bdef
+ /k { k } bdef
+ /cs { csresolve cs } bdef
+ /sc { scresolve { sc* } { sc1 } ifelse } bdef
+ /scn /sc load def
+ /G { /DeviceGray cssubst { CS SC1 } { G } ifelse } bdef
+ /RG { /DeviceRGB cssubst { CS SC* } { RG } ifelse } bdef
+ /K { K } bdef
+ /CS { csresolve CS } bdef
+ /ri { ri } bdef
+ /SC { scresolve { SC* } { SC1 } ifelse } bdef
+ /SCN /SC load def
+end
+
+% ---------------- Paths ---------------- %
+
+drawopdict begin
+ % Path construction
+ /m /moveto load def
+ /l /lineto load def
+ /c /curveto load def
+ /v { currentpoint 6 2 roll curveto } def
+ /y { 2 copy curveto } def
+ /re {
+ 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto
+ closepath
+ } def
+ /h /closepath load def
+ % Path painting and clipping
+ /n { n } def
+ /S { S } def
+ /s { s } def
+ /f { f } def
+ /f* { f* } def
+ /B { B } def
+ /b { b } def
+ /B* { B* } def
+ /b* { b* } def
+ /W { W } def
+ /W* { W* } def
+ /sh { setfillstate resolvesh
+ gsave 0 .setoverprintmode
+ dup /.shading .knownget {
+ exch
+ pop
+ } {
+ dup
+ .buildshading
+ dup 3 1 roll /.shading exch put
+ } ifelse
+ .shfill grestore
+ } def
+end
+
+% ---------------- XObjects ---------------- %
+
+/xobjectprocs mark % <dict> -proc- -
+ /Image { DoImage }
+ /Form { DoForm }
+ /PS { DoPS }
+.dicttomark readonly def
+
+% Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
+% color space names.
+/defaultdecodedict mark
+ /DeviceGray { pop //01_1 } bind
+ /DeviceRGB { pop //01_3 } bind
+ /DeviceCMYK { pop //01_4 } bind
+ /CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind
+ /CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind
+ /ICCBased {
+ 1 oget dup /Range knownoget {
+ exch pop
+ }{
+ /N get [ exch {0 1} repeat ] readonly
+ } ifelse
+ } bind
+ /Separation { pop //01_1 } bind
+ /DeviceN {
+ 1 oget length [ exch {0 1} repeat ] readonly
+ } bind
+ /Indexed {
+ pop [ 0 1 BitsPerComponent bitshift 1 sub ]
+ } bind
+.dicttomark readonly def
+
+/checkaltimage { % <resdict> checkaltimage <resdict[']>
+ Printed {
+ dup /Alternates knownoget {
+ {
+ dup /DefaultForPrinting knownoget {
+ {
+ /Image oget exch pop exit
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } forall
+ } if
+ } if
+} bdef
+
+/makeimagedict { % <resdict> <newdict> makeimagedict <imagemask>
+ % On return, newdict' is currentdict
+ begin
+ /Width 2 copy oget def
+ /Height 2 copy oget def
+ % Handle missing BitsPerComponent later.
+ /BitsPerComponent 2 copy knownoget { def } { pop } ifelse
+ /Interpolate 2 copy knownoget { def } { pop } ifelse
+ makeimagekeys
+} bdef
+/makeimagekeys { % <resdict> makeimagekeys <imagemask>
+ % newdict is currentdict
+ % Assumes Width, Height, BPC, Interpolate already copied.
+ /ImageType 1 def
+ /ImageMatrix Width 0 0
+ % Handle 0-height images specially.
+ Height dup 0 eq { pop 1 } if neg 0 1 index neg
+ 6 array astore def
+ dup /ImageMask knownoget dup { and } if {
+ % Image mask
+ % Decode is required for the PostScript image operators.
+ % AI8 writes bogus decode array [0 1 0 0 0 0 0 0]
+ /Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def
+ % BitsPerComponent is optional for masks.
+ /BitsPerComponent 2 copy known { pop } { 1 def } ifelse
+ true
+ } {
+ % Opaque image
+ dup /ColorSpace oget resolvecolorspace /ColorSpace exch def
+ % Decode is required for the PostScript image operators.
+ /Decode 2 copy knownoget not {
+ ColorSpace //defaultdecodedict
+ ColorSpace dup type /arraytype eq { 0 get } if get exec
+ } if def
+ false
+ } 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).
+ exch false resolvestream /DataSource exch def
+} bdef
+
+/DoImage {
+ checkaltimage dup length 6 add dict
+ 1 index /SMask knownoget { 1 index exch /SMask exch put } if
+ 1 index /Mask knownoget { 1 index exch /Mask exch put } if
+ makeimagedict doimagesmask
+} bdef
+/makemaskimage { % <datasource> <imagemask> <Mask> makemaskimage
+ % <datasource> <imagemask>, updates currentdict =
+ % imagedict
+ dup type /arraytype eq {
+ /ImageType 4 def
+ % Check that every element of the Mask is an integer.
+ //false 1 index {
+ type /integertype ne or
+ } forall {
+ (\n **** Warning: Some elements of Mask array are not integers.\n)
+ pdfformaterror
+ [ exch { 0.5 add cvi } forall ] % following AR4, 5, 6 implementation
+ } if
+ % Check elements of array are within 0::(2**BitsPerComponent)-1
+ % This is a PostScript error, but AR ignores Mask in that case
+ 2 BitsPerComponent exp cvi 1 sub //false 2 index {
+ % stack: max_value result_bool value
+ dup 0 lt exch 3 index gt or or
+ } forall exch pop {
+ (\n **** Warning: Some elements of Mask array are out of range.\n)
+ pdfformaterror
+ pop /ImageType 1 def % revert to non-masked image
+ } {
+ /MaskColor exch 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 def
+ PDFfile exch setfileposition
+ currentdict end currentdict end
+ 5 dict begin
+ /ImageType 3 def
+ /InterleaveType 3 def
+ /DataDict exch def
+ /MaskDict exch def
+ /ColorSpace DataDict /ColorSpace get def
+ } ifelse
+} bdef
+
+/doimagesmask { % <imagemask> doimagesmask -
+ PDFusingtransparency { currentdict /SMask knownoget } { false } ifelse {
+ .begintransparencymaskimage
+ PDFfile fileposition exch
+ gsave //nodict begin
+ null /SoftMask gput
+ 1 .setopacityalpha 1 .setshapealpha
+ 0 .inittransparencymask 1 .inittransparencymask
+ /Compatible .setblendmode
+ DoImage
+ end grestore
+ PDFfile exch setfileposition
+ 0 .endtransparencymask
+ << /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
+ } {
+ doimage
+ } ifelse
+} bdef
+/doimage { % <imagemask> doimage -
+ % imagedict is currentdict, gets popped from dstack
+ DataSource exch
+ PDFusingtransparency {
+ currentdict /SMask knownoget
+ } {
+ false
+ } ifelse {
+ makesoftmaskimage
+ } {
+ currentdict /Mask knownoget {
+ makemaskimage
+ } if
+ } ifelse
+ % Stack: datasource imagemask
+ { currentdict end setfillstate { imagemask } }
+ { ColorSpace setgcolorspace currentdict end setfillblend { image } }
+ ifelse
+ stopped {
+ dup type /dicttype eq { pop } if % Sometimes image fails to restore the stack
+ $error /errorname get dup /ioerror eq {
+ pop (\n **** Warning: File has insufficient data for an image.\n)
+ pdfformaterror
+ } {
+ (\n **** Warning: File encountered ')
+ exch 40 string cvs concatstrings
+ (' error while processing an image.\n) concatstrings
+ pdfformaterror
+ } ifelse
+ } if
+ % Close the input stream, unless it is PDFfile or
+ % PDFsource.
+ dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
+} bdef
+
+/.paintform { % <formdict> <resdict> <stream> .paintform -
+ 3 -1 roll dup /Group known PDFusingtransparency and {
+ .paintgroupform
+ } {
+ pop pdfopdict .pdfruncontext
+ } ifelse
+} bdef
+
+/DoForm {
+ % Adobe 2nd edition of the PDF 1.3 spec makes /FormType
+ % and /Matrix keys optional. Cope with the missing keys.
+ begin <<
+ currentdict /FormType known not { /FormType 1 } if
+ currentdict /Matrix known not { /Matrix { 1 0 0 1 0 0 } cvlit } if
+ currentdict end { oforce } forall
+ >>
+ dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
+ 3 index false /resolvestream cvx
+ /.paintform cvx
+ ] cvx /PaintProc exch put
+ % Adjust pdfemptycount since we have an extra dictionary on the stack
+ pdfemptycount exch
+ /pdfemptycount where pop count 2 sub /pdfemptycount exch put
+ q execform Q % gsave / grestore around the Form
+ % Restore pdfemptycount
+ /pdfemptycount where pop exch /pdfemptycount exch put
+} bdef
+
+/_dops_save 1 array def
+
+/DoPS {
+ DOPS
+ {
+ //_dops_save 0 save put
+ true resolvestream cvx exec
+ //_dops_save 0 get restore
+ }
+ { pop }
+ ifelse
+} bdef
+
+currentdict /_dops_save undef
+
+drawopdict begin
+ /Do {
+ setfillblend
+ PDFfile fileposition exch
+ dup Page /XObject rget {
+ exch pop dup /Subtype get xobjectprocs exch get
+ % Don't leave extra objects on the stack while executing
+ % the definition of the form.
+ 3 -1 roll 2 .execn
+ } {
+ % This should cause an error, but Acrobat Reader can
+ % continue, so we do too.
+ ( **** Undefined XObject resource: )
+ exch =string cvs concatstrings (\n) concatstrings
+ pdfformaterror
+ } ifelse
+ PDFfile exch setfileposition
+ } bdef
+end
+
+% ---------------- In-line images ---------------- %
+
+% Undo the abbreviations in an in-line image dictionary.
+% Note that we must look inside array values.
+% /I is context-dependent.
+/unabbrevkeydict mark
+ /BPC /BitsPerComponent /CS /ColorSpace /D /Decode /DP /DecodeParms
+ /F /Filter /H /Height /I /Interpolate /IM /ImageMask /W /Width
+.dicttomark readonly def
+/unabbrevvaluedict mark
+ /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CC /CalCMYK
+ /CCF /CCITTFaxDecode /CG /CalGray /CR /CalRGB
+ /DCT /DCTDecode /CMYK /DeviceCMYK /Fl /FlateDecode
+ /G /DeviceGray /RGB /DeviceRGB
+ /I /Indexed /LZW /LZWDecode /RL /RunLengthDecode
+.dicttomark readonly def
+/unabbrevtypedict mark
+ /nametype {
+ //unabbrevvaluedict 1 index .knownget { exch pop } if
+ }
+ /arraytype {
+ dup 0 1 2 index length 1 sub {
+ 2 copy get unabbrevvalue put dup
+ } for pop
+ }
+.dicttomark readonly def
+/unabbrevvalue { % <obj> unabbrevvalue <obj'>
+ oforce //unabbrevtypedict 1 index type .knownget { exec } if
+} bdef
+
+drawopdict begin
+ /BI { mark } bdef
+ /ID {
+ counttomark 2 idiv dup 7 add dict begin {
+ exch //unabbrevkeydict 1 index .knownget { exch pop } if
+ exch unabbrevvalue def
+ } repeat pop
+ /IDFlag true def % flag for stream processing.
+ /File PDFsource def
+ currentdict makeimagekeys doimage
+ % The Adobe documentation says that the data following ID
+ % consists of "lines", and some PDF files (specifically, some files
+ % produced by PCL2PDF from Visual Software) contain garbage bytes
+ % between the last byte of valid data and an EOL.
+ % Some files (PDFOUT v3.8d by GenText) have EI immediately following
+ % the stream. Some have no EOL and garbage bytes.
+ % Therefore, we skip all bytes before EI or EOL
+ 0
+ { PDFsource read not { //true exit } if
+ dup 10 eq 1 index 13 eq or
+ { pop PDFsource token pop /EI ne exit
+ }
+ if
+ exch 69 eq 1 index 73 eq and { //false exit } if % 'EI'
+ }
+ loop
+ exch pop
+ { /ID cvx /syntaxerror signalerror
+ }
+ if
+ } bdef
+end
+
+% ================================ Text ================================ %
+
+drawopdict begin
+ % Text control
+ /BT { BT } def
+ /ET { ET } def
+ /Tc { Tc } def
+ /TL { TL } def
+ /Tr { Tr } def
+ /Ts { Ts } def
+ /Tw { Tw } def
+ /Tz { Tz } def
+ % Text positioning
+ /Td { Td } def
+ /TD { TD } def
+ /Tm { Tm } def
+ /T* { T* } def
+ % Text painting
+ /Tj { Tj } def
+ /' { ' } def
+ /" { " } def
+ /TJ { TJ } def
+
+ /Tform { Tform } def % Text formatting and painting for AcroForm
+ % without appearance streams.
+end
+
+% ============================== Annotations ============================== %
+
+
+
+% Get and normalize an annotation's rectangle.
+/annotrect { % <annot> annotrect <x> <y> <w> <h>
+ /Rect get aload pop
+ exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if
+ exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if
+} bdef
+
+% Set an annotation color.
+/annotsetcolor { % <annot> annotsetcolor -
+ /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse
+} bdef
+
+% Draw the border. Currently, we ignore requests for beveling, and we
+% don't round the corners of rectangles.
+/strokeborder { % <annot> <width> <dash> strokeborder -
+ 1 index 0 ne { % do not draw if border width is 0
+ gsave
+ 2 index annotsetcolor
+ 0 setdash dup setlinewidth
+ exch annotrect
+ 2 { 4 index sub 4 1 roll } repeat
+ 2 { 4 index 0.5 mul add 4 1 roll } repeat
+ rectstroke pop
+ grestore
+ } {
+ pop pop pop
+ } ifelse
+} bdef
+
+% Draw an annotation border.
+/drawborder { % <annot> drawborder -
+ gsave
+ dup /BS known 1 index /Border known or {
+ dup /BS knownoget {
+ dup type /dicttype ne % <annot> <border> <bad?>
+ } {
+ dup /Border oget
+ dup type /arraytype ne % <annot> [border] <bad?>
+ } ifelse
+ {
+ ( **** Warning: Wrong type of annotation border object.\n)
+ pdfformaterror
+ } if
+ dup type /dicttype eq {
+ dup /W knownoget not { 1 } if
+ % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is
+ % expressed in points (an absolute unit), so compensate here for any
+ % scaling of the PostScript user space done due to /UserUnit.
+ % Scaling due to -dPDFFitPage is not undone, to keep the correct border width
+ % compared to the size of the surrounding marks.
+ //systemdict /NoUserUnit .knownget not { false } if not
+ //systemdict /PDFFitPage known not and { % UserUnit is ignored if -dPDFFitPage
+ Page /UserUnit knownoget { div } if
+ } if
+ [] 2 index /S knownoget {
+ /D eq { 2 index /D knownoget not { [3] } if exch pop } if
+ } if 3 -1 roll pop strokeborder
+ } {
+ dup 2 get
+ exch dup length 3 gt { 3 get } { pop [] } ifelse
+ strokeborder
+ } ifelse
+ } {
+ 1 [] strokeborder
+ } ifelse
+ grestore
+} bdef
+
+%
+% The PDF annotation F (flags) integer is bit encoded.
+% Bit 1 (LSB) Invisible: 1 --> Do not display if no handler.
+% Note: We have no handlers but we ignore this bit.
+% Bit 2 Hidden: 1 --> Do not display. We will not display if this bit is set.
+% Bit 3 Print: 1 --> Display if printing. We will display if this bit set
+% (and not hidden) and Printed is true
+% Bit 4 NoZoom: 1 --> Do not zoom annotation even if image is zoomed.
+% Bit 5 NoRotate: 1 --> Do not rotate annotation even if image is rotated.
+% Bit 6 NoView: 0 --> Display if this is a 'viewer'. We will display
+% if this bit is not set (and not hidden) and Printed is false
+% Bit 7 Read Only - 1 --> No interaction. We ignore this bit
+%
+/annotvisible { % <annot> annotvisible <visible>
+ /F knownoget not { 0 } if % Get flag value
+ dup 2 and 0 eq % Check hidden flag
+ exch dup 4 and 0 ne Printed and % Check print flag
+ exch 32 and 0 eq Printed not and % Check noview flag
+ or % Combine print and view
+ and % Combine with 'hidden' flag test
+} bdef
+
+/drawwidget { % <scalefactor> <annot> drawwidget -
+ dup /AP knownoget {
+ dup /N known not {
+ ( **** Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n)
+ pdfformaterror
+ } if
+ false
+ [/N /R /D] {
+ % stack: scale annot appearance false key
+ dup 3 index exch known {
+ exch pop true exit
+ } if
+ pop
+ } forall
+ % stack: scale annot appearance key true
+ % stack: scale annot appearance false
+ dup {
+ pop
+ oget
+ % Acrobat Distiller produces files in which this Form
+ % XObject lacks Type and Subtype keys. This is illegal,
+ % but Acrobat Reader accepts it. The only way we can
+ % tell whether this is a Form or a set of sub-appearances
+ % is by testing for the stream Length or File key.
+ % If the stream lacks Length key, try File key.
+ dup /Length known 1 index /File known or {
+ % If this is a form then simply use it
+ true
+ } {
+ 1 index /AS knownoget not {
+ % If we do not have AS then use any appearance
+ { exch pop oforce exit } forall true
+ } {
+ % Stack: annot Ndict AS
+ % Get the specified appearance. If no appearance, then
+ % display nothing - set stack = false.
+ knownoget
+ } ifelse
+ } ifelse
+ } {
+ exch pop % discard useless AP dictionary
+ } ifelse
+
+ % Stack: scale annot appearance true
+ % Stack: scale annot false
+ {
+ % Draw appearance
+ % Initialize graphic following "7.4.4 Appearance Streams"
+ q graphicsbeginpage textbeginpage
+ 1 index annotrect pop pop translate
+ 2 index dup scale % Apply scale factor
+ DoForm Q
+ } if
+ } {
+ dup /FT knownoget {
+ /Tx eq {
+ % Stack: scale annot
+ dup /DA known 1 index /V known and {
+ dup /DA oget
+ q graphicsbeginpage textbeginpage
+ 1 index annotrect pop pop translate
+ 2 index dup scale % Apply scale factor
+ cvx exec
+ dup /V oget
+ 0 0 moveto dup false charpath pathbbox newpath 3 -1 roll
+ sub abs 3 1 roll sub abs
+ 3 index annotrect 4 2 roll pop pop
+ 6 index mul exch 6 index mul
+ % stack: scale annot V vsize hsize vrect hrect
+ % Calculate horizontal justification first
+ % horizontal can be left (Q=0), center (Q=1), or right (Q=2) justification
+ 3 -1 roll
+ % stack: scale annot V vsize vrect hrect hsize
+ 5 index /Q knownoget not { 0 } if % default 0 == left
+ dup 0 eq {
+ pop pop pop 0 % left justified
+ } {
+ 1 eq {
+ 2 div exch 2 div exch sub % centered
+ } {
+ sub % right justified (hrect - hsize)
+ } ifelse
+ } ifelse
+ % stack: scale annot V vsize vrect hoffset
+ % Center the text vertically in the rect (Acrobat Reader seems to do this)
+ 3 1 roll 2 div exch 2 div sub abs
+ % stack: scale annot V hoffset voffset
+ moveto show
+ Q
+ } if
+ } if
+ } if
+ } ifelse
+ pop pop
+} bdef
+
+% For stamp object we have to determine the size of the output rectangle
+% and the size of the BBox for the stamp image. From these we calculate
+% a scale factor for drawing the stamp.
+/calcstampscale { % <annot> calcstampscale scale
+ dup /Rect known {
+ dup annotrect 4 -2 roll pop pop % get width height size in user space
+ 3 -1 roll /AP knownoget {
+ /N knownoget {
+ dup /Matrix knownoget {
+ % transform /Annot /Rect xwidth to Form space
+ 4 -2 roll 3 -1 roll dtransform 3 -1 roll
+ } if
+ /BBox knownoget {
+ exch pop % discard y height
+ aload pop pop exch pop sub % BBox width
+ dup 0 eq {
+ ( **** Warning: /BBox has zero width which is not allowed.\n)
+ pdfformaterror
+ pop pop 1 1 % 0 width -- revert to unity scaling
+ } if
+ div % scale x widths
+ dup 0 lt { neg } if % get magnitude
+ } {
+ pop pop 1 % default to unity scaling
+ } ifelse % if we have /BBox
+ } {
+ pop pop 1
+ } ifelse % if we have /N
+ } {
+ pop pop 1
+ } ifelse % if we have /AP
+ } {
+ ( **** Warning: /Annot dict is missing required /Rect entry.\n)
+ pdfformaterror
+ pop 1
+ } ifelse
+} bdef
+
+/drawlink { % <annot> drawlink -
+ dup drawborder dup calcstampscale exch drawwidget
+} bdef
+
+% Draw an annotation.
+/drawannottypes mark
+ /Link { drawlink } bind
+.dicttomark readonly def
+/drawannot { % <annot> drawannot -
+ dup annotvisible {
+ gsave
+ dup dup /Subtype knownoget {
+ //drawannottypes exch .knownget {
+ exec
+ } {
+ dup calcstampscale exch drawwidget % Use drawwidget for everything else
+ } ifelse % type known
+ } {
+ pop
+ ( **** Warning: /Annot dict without required /Subtype entry is ignored.\n)
+ pdfformaterror
+ } ifelse
+ grestore
+ } if pop % annotvisible
+} bdef
+currentdict /drawannottypes undef
+
+% ============================ AcroForm fields ============================ %
+
+% Get an attribure of the 0th annotation of a node
+/annot_oget { % <annot> /Name annot_oget <value>
+ 1 index /Kids knownoget {
+ 0 oget exch oget exch pop
+ } {
+ oget
+ } ifelse
+} bdef
+
+% All procedures have the signature:
+% <acroform> <field> <annot|field> foo <acroform> <field> <annot|field>
+/draw_terminal_field_dict 4 dict begin
+
+/Btn {
+ 1 index /Tf pget not { 0 } if
+ dup 16#20000 and 0 ne {
+ pop % Push button
+ dup /AP known {
+ dup 1 exch 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 exch drawwidget
+ } forall
+ } {
+ (Radio button without appearance stream is not yet implemented) =
+ } ifelse
+ } {
+ % Checkbox
+ dup /AP known {
+ dup 1 exch drawwidget
+ } {
+ (CkeckBox without appearance stream is not yet implemented) =
+ } ifelse
+ } ifelse
+ } ifelse
+} bdef
+
+/Tx {
+ dup /AP known {
+ dup 1 exch drawwidget
+ } {
+ 2 index /NeedAppearances knownoget not { //false } if {
+ dup /AP << /N 10 dict dup cvx begin >> put
+ /Subtype /Form def
+ /BBox [ 0 0 4 index /Rect oget { oforce } forall 3 -1 roll sub abs 3 1 roll sub abs exch ] def
+ /Resources 3 index /DR pget not { 0 dict } if def
+ /File 1000 string dup 3 1 roll def
+ /Length 0 def
+ % <acroform> <field> <annot> (string)
+ /NullEncode filter % <acroform> <field> <annot> file
+
+ dup (BT ) writestring
+ 2 index /DA pget not { () } if
+ [ exch
+ { token {
+ dup /Tf eq {
+ 2 index 0 eq {
+ /BBox load 3 get
+ 0.75 mul % empirical constant
+ 4 -1 roll pop 3 1 roll
+ } if
+ } if
+ exch
+ } {
+ exit
+ } ifelse
+ } loop
+ ]
+ { 1 index exch write== } forall
+ dup 3 index /MaxLen pget not { 0 } if write=
+ dup 3 index /V pget not { () } if write==
+ dup 3 index /Ff pget not { 0 } if write=
+ dup 3 index /Q pget not { 0 } if write=
+ dup (Tform ET) write=
+ end
+ closefile % <acroform> <field> <annot>
+ dup 1 exch drawwidget
+ } if
+ } ifelse
+} bdef
+
+/Ch {
+ (Ch is not yet implemened) ==
+} bdef
+
+/Sig {
+ (Sig is not yet implemened ) ==
+} bdef
+
+currentdict end def
+
+/draw_terminal_field { % <field> draw_terminal_field -
+ dup /Kids knownoget { 0 oget } { dup } ifelse
+ dup /P knownoget {
+ /Page load eq {
+ //draw_terminal_field_dict 2 index /FT pget not { 0 } if .knownget {
+ exec
+ } if
+ } if
+ } if
+ pop pop
+} bdef
+
+% We distinguish 4 types of nodes on the form field tree:
+% - non-terminal field - has a kid that refers to the parent (or anywhere else)
+% - terminal field with separate widget annotations - has a kid that doesn't 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 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
+ } {
+ draw_terminal_field % merged annotation % -
+ } ifelse
+} bdef
+
+/draw_acro_form { % <form> draw_acro_form -
+ dup /Fields knownoget {
+ { oforce draw_form_field } forall
+ } if
+ pop
+} bdef
+
+currentdict /draw_terminal_field_dict undef
+
+end % pdfdict
+end % GS_PDF_ProcSet
+.setglobal