% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% For more information about licensing, please refer to
% http://www.ghostscript.com/licensing/. For information on
% commercial licensing, go to http://www.artifex.com/licensing/ or
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
% $Id: pdf_draw.ps 9850 2009-07-09 00:28:02Z alexcher $
% pdf_draw.ps
% PDF drawing operations (graphics, text, and images).
/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal true .setglobal
/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
GS_PDF_ProcSet begin
pdfdict begin
% For simplicity, we use a single interpretation dictionary for all
% PDF graphics operations, even though this is too liberal.
/drawopdict 100 dict def
% ================================ Graphics ================================ %
% ---------------- Functions ---------------- %
% Note that resolvefunction converts a PDF Function to a PostScript Function;
% resolve*fnproc converts a PDF function to a PostScript procedure.
% We need to process all required and optional parameters to resolve any
% use of indirect references.
/fnrdict mark
0 { .resolvefn0 }
2 { .resolvefn2 }
3 { .resolvefn3 }
4 { .resolvefn4 }
.dicttomark readonly def
/.resolvefn0 {
dup length 1 add dict .copydict % make room for DataSource
% now resolve any indirect references
dup /Size 2 copy knownoget { put } { pop pop } ifelse
dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse
dup /Order 2 copy knownoget { put } { pop pop } ifelse
dup /Encode 2 copy knownoget { put } { pop pop } ifelse
dup /Decode 2 copy knownoget { put } { pop pop } ifelse
% Don't lose our place in PDFfile.
PDFfile fileposition exch
dup //true resolvestream
% The stream isn't positionable, so read all the data now.
% Stack: filepos fndict stream
1 index /Range get length 2 idiv 2 index /BitsPerSample get mul
2 index /Size get { mul } forall
7 add 8 idiv
dup 65535 le {
string 1 index exch readstring pop
} {
1 index exch () /SubFileDecode filter /ReusableStreamDecode filter
} ifelse
exch closefile
% Stack: filepos fndict data
exch dup /DataSource 4 -1 roll put
exch PDFfile exch setfileposition
} bdef
/.resolvefn2 {
dup length dict .copydict
dup /C0 2 copy knownoget { put } { pop pop } ifelse
dup /C1 2 copy knownoget { put } { pop pop } ifelse
dup /N 2 copy knownoget { put } { pop pop } ifelse
} bdef
/.resolvefn3 {
dup length dict .copydict
dup /Bounds 2 copy knownoget { put } { pop pop } ifelse
dup /Encode 2 copy knownoget { put } { pop pop } ifelse
dup /Functions 2 copy oget mark exch dup {
oforce .resolvefn
} forall
counttomark -1 roll astore exch pop put
} bdef
/.resolvefn4 {
PDFfile fileposition exch % filepos fndict
dup true resolvestream % filepos fndict stream
exch dup length dict copy % filepos stream fndict2
dup /Function undef % filepos stream fndict2
exch dup token not {
() /rangecheck cvx signalerror
} if
exch token {
/rangecheck cvx signalerror
} if
% Use .bind to avoid idiom recognition.
.bind
1 index /Function 3 -1 roll put
exch PDFfile exch setfileposition
} bdef
/.resolvefn { % <fndict> .resolvefn <fndict'>
dup length dict .copydict
dup /Domain 2 copy knownoget { put } { pop pop } ifelse
dup /Range 2 copy knownoget { put } { pop pop } ifelse
dup /FunctionType oget //fnrdict exch get exec
} bdef
/resolvefunction { % <fndict> resolvefunction <function>
.resolvefn
PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%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 1 index //null eq or PDFusingtransparency not or {
pop null
} {
% Preprocess the SMask value into a parameter dictionary for
% .begintransparencymaskgroup, with added /BBox and /Draw keys.
mark exch % Stack: mark smaskdict
dup /S oget /Subtype exch 3 2 roll
% Stack: mark ... smaskdict
dup /BC knownoget {
dup /Background exch 4 2 roll
gsave //nodict begin
1 index /G oget /Group oget /CS knownoget {
resolvecolorspace dup setgcolorspace csput
} if
aload pop setcolor [ currentgray ]
end grestore
/GrayBackground exch 3 2 roll
} if
dup /TR knownoget {
dup /Identity eq {
pop
} {
resolvefnproc /TransferFunction exch 3 2 roll
} ifelse
} if
dup /G oget dup /BBox oget /BBox exch 4 2 roll
/.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
pop .dicttomark
} ifelse SMask
} bdef
% Functions specific to the Device* colorspaces to force the switch to
% the Device* colorspace so that the SMask will not get a CIEBased* colorspace
% in the case when UseCIEColor changes the Device* colorspace to something else.
% Also see the logic in pdf_main.ps:pdfopen that similarly defines these resources.
/forceDefaultCS <<
{
currentcolorspace setcolorspace % this will switch to Device colorspace
} bind
/DeviceGray exch
/DeviceRGB 1 index
/DeviceCMYK 1 index
>>
def
% This procedure is called to actually render the soft mask.
/.execmaskgroup { % <masknum> <paramdict> <formdict> .execmaskgroup -
% Save our place in PDFfile. Do not use gsave-grestore when creating
% a soft mask with .begintransparencygroup because high level devices
% need to modify the graphic state by storing the soft mask ID.
% Save the ExtGState (//nodict begin) BEFORE changing the colorspace
mark currentcolor counttomark dup 4 add exch roll pop
currentcolorspace 4 1 roll .getuseciecolor 4 1 roll //nodict begin
PDFfile fileposition 4 1 roll
% We have to select the group's color space so that the
% background color will be interpreted correctly.
% [save/restore]DefaultCS make sure that the SMask logic sees
% the Device* spaces, not CIEBased* that UseCIEColor may have
% established.
false .setuseciecolor % SMask gets processed without UseCIEColor
dup /Group oget /CS knownoget {
resolvecolorspace dup setgcolorspace csput
//true % use currentcolorspace
} {
% inheriting the colorspace -- make sure Device* spaces are not CIEBased
forceDefaultCS currentcolorspace 0 get .knownget { exec } if
//false % no defined colorspace
} ifelse
3 -1 roll dup /BBox get aload pop .begintransparencymaskgroup {
dup /Resources knownoget { oforce } { 0 dict } ifelse
exch false resolvestream
.execgroup .endtransparencymask
} stopped {
.discardtransparencymask stop
} if
PDFfile exch setfileposition
.setuseciecolor setcolorspace setcolor end % restore colorspace, color and ExtGState (end)
} bdef
% Paint a Form+Group XObject, either for a transparency mask or for a Do.
/.execgroup { % <resdict> <stream> .execgroup -
gsave //nodict begin
newpath null SMask
1 .setopacityalpha 1 .setshapealpha
/Compatible .setblendmode
% Execute the body of the Form, similar to DoForm.
pdfopdict .pdfruncontext
end grestore
} bdef
/.beginformgroup { % groupdict bbox .beginformgroup -
exch mark exch % bbox mark groupdict
dup /CS knownoget { resolvecolorspace setgcolorspace } if
dup /I knownoget { /Isolated exch 3 2 roll } if
dup /K knownoget { /Knockout exch 3 2 roll } if
pop .dicttomark
% Stack: bbox paramdict
exch aload pop
.begintransparencygroup
} bdef
% .paintgroupform implements the Form PaintProc in the case where the
% Form XObject dictionary includes a Group key. See .paintform below.
/.paintgroupform { % <resdict> <stream> <formdict> .paintgroupform -
dup /Group oget exch /BBox oget
% Stack: resdict stream groupdict bbox
.beginformgroup {
.execgroup
} stopped {
.discardtransparencygroup stop
} if .endtransparencygroup
} bdef
% Make an ImageType 103 (soft-masked) image.
/makesoftmaskimage { % <datasource> <imagemask> <SMask> makesoftmaskimage
% <datasource> <imagemask>, updates currentdict =
% imagedict
% See the ImageType 3 case of makemaskimage below.
% SMask is a stream, another Image XObject.
% Stack: datasource imagemask(false) smaskstreamdict
PDFfile fileposition exch
dup /Matte knownoget { /Matte exch def } if
dup length dict makeimagedict pop
% In order to prevent the two data sources from being
% aliased, we need to make at least one a reusable stream.
% We pick the mask, since it's smaller (in case we need to
% read all its data now).
% Stack: datasource imagemask(false) savedpos
% maskdict is currentdict
/DataSource DataSource mark
/Intent 1
/AsyncRead true
.dicttomark .reusablestreamdecode def
PDFfile exch setfileposition
currentdict end currentdict end
5 dict begin
/ImageType 103 def
/DataDict exch def
dup /InterleaveType 3 put
DataDict /Matte knownoget {
/Matte exch def
} if
AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
/ColorSpace DataDict /ColorSpace get def
} bdef
% ---------------- Color setting ---------------- %
/01_1 [0 1] readonly def
/01_3 [0 1 0 1 0 1] readonly def
/01_4 [0 1 0 1 0 1 0 1] readonly def
% The keys here are resolved (PostScript, not PDF) color space names.
/csncompdict 8 dict begin
/DeviceGray { pop 1 } bdef
/DeviceRGB { pop 3 } bdef
/DeviceCMYK { pop 4 } bdef
/CIEBasedA { pop 1 } bdef
/CIEBasedABC { pop 3 } bdef
/ICCBased { 1 oget /N oget } bdef
/Separation { pop 1 } bdef
/DeviceN { 1 oget length } bdef
currentdict end readonly def
/csrdict 13 dict begin
/DeviceGray { } bdef
/DeviceRGB { } bdef
/DeviceCMYK { } bdef
/CalGray {
1 oget 6 dict begin
dup /Gamma knownoget {
/exp load 2 packedarray cvx /DecodeA exch def
} if
dup /BlackPoint knownoget { /BlackPoint exch def } if
dup /WhitePoint knownoget {
dup /WhitePoint exch def
dup /MatrixA exch def
/RangeLMN [ 3 2 roll { 0 exch } forall ] def
} if
/PDFColorSpace exch def [ /CIEBasedA currentdict end ]
} bdef
/CalRGB {
1 oget 6 dict begin
dup /Gamma knownoget {
[ exch { /exp load 2 packedarray cvx } forall
] /DecodeABC exch def
} if
dup /Matrix knownoget { /MatrixABC exch def } if
dup /BlackPoint knownoget { /BlackPoint exch def } if
dup /WhitePoint knownoget { /WhitePoint exch def } if
/PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
} bdef
/CalCMYK {
pop /DeviceCMYK % not defined by Adobe
} bdef
/Lab {
1 oget 6 dict begin
dup /Range knownoget not { [-100 100 -100 100] } if
[0 100 null null null null] dup 2 4 -1 roll putinterval
/RangeABC exch def
/DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
/MatrixABC [1 1 1 1 0 0 0 0 -1] def
dup /BlackPoint knownoget { /BlackPoint exch def } if
dup /WhitePoint knownoget { /WhitePoint exch def } {
( **** Warning: Lab colorspace is missing WhitePoint.\n)
pdfformaterror
/WhitePoint [0.9505 1 1.089] def
} ifelse
% scaling function g() for DecodeLMN construction
{ dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
/DecodeLMN [
% Store white point implicitly inside procedures.
[ 3 index aload pop WhitePoint 0 get /mul .systemvar ] cvx bind
[ 4 index aload pop WhitePoint 1 get /mul .systemvar ] cvx bind
[ 5 index aload pop WhitePoint 2 get /mul .systemvar ] cvx bind
] def pop
/PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
} bdef
/ICCBased {
dup 1 get type /dicttype ne { % don't resolve more than once
PDFfile fileposition exch
dup dup 1 oget
mark exch { oforce } forall .dicttomark
dup dup true resolvestream
/ReusableStreamDecode filter /DataSource exch put
1 exch put
exch PDFfile exch setfileposition
% Resolve alternate color space
dup 1 get % Get colorspace dictionary
dup /Alternate .knownget % Check for alternate color space
{ oforce resolvecolorspace /Alternate exch put } % resolve and replace
{ pop } % remove colorspace dictionary
ifelse
} if
} bdef
/Separation {
aload pop exch oforce resolvecolorspace
% Contrary to PDF manuals up to v.1.5, Acrobat Distiller 3.01
% can use /Identity name here instead of a function.
exch oforce resolveidfnproc
4 array astore
} bdef
/DeviceN {
[ exch aload pop ] % Copy into a new array
dup dup 1 oget % Resolve Names array
[ exch { oforce } forall ] % resolve each of the names
1 exch put
dup dup 2 oget resolvecolorspace
2 exch put
dup dup 3 oget resolvefnproc
3 exch put
dup length 4 gt { % Check for attributes dict
dup dup 4 oget % devn_array devn_array attr_dict
dup /Colorants knownoget % Check for Colorants Dict
{ % Create a new attribute dict with only a Colorants dict entry.
% Resolve all of the Colorant dict entries. This is needed
% to prevent a conflict if we attempt to resolve the tint
% transform functions of the Colorant color spaces multiple
% times.
exch pop % Remove old attributes dict
<< exch % Start new attributes dict
% Build new Colorants dict with resolved entries
<< exch { oforce resolvecolorspace } forall >>
/Colorants exch >> % Finish new attributes dict
} if
4 exch put % Put resolved or new attributes dict
} if
} bdef
/Indexed {
aload pop 3 -1 roll oforce resolvecolorspace
% Stack: /Indexed hival lookup basespace
% If the underlying space is a Lab space, we must scale
% the output of the lookup table as part of DecodeABC.
dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq {
dup 1 get /DecodeLMN known {
1 get dup length dict copy
begin /DecodeABC [ 0 2 4 {
RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load
RangeABC 3 index get /add load
DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx
} for ] def
/RangeABC //01_3 def
currentdict end /CIEBasedABC exch 2 array astore
} if
} if
3 1 roll
oforce dup type /stringtype ne {
% The color lookup table is a stream.
% Get its contents. Don't lose our place in PDFfile.
% Stack: /Indexed basespace hival lookup
PDFfile fileposition 5 1 roll true resolvestream
% Stack: filepos /Indexed basespace hival lookupstream
1 index 1 add
% Stack: filepos /Indexed basespace hival lookupstream len
3 index
dup dup type /arraytype eq { 0 get } if
//csncompdict exch get exec mul
string dup 3 1 roll readstring pop % the string is padded with 0s
length 1 index length lt {
( **** Warning: Short look-up table in the Indexed color space was 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
} bdef
/I { % Bug 689815
( **** Warning: The name /Indexed cannot be abbreviated to /I in the color space\n)
pdfformaterror
dup 0 /Indexed put
//Indexed exec
} bdef
/Pattern {
dup type /nametype ne {
dup length 1 gt {
1 oget resolvecolorspace
/Pattern exch 2 array astore
} if
} if
} bdef
currentdict end readonly def
/cssubst { % <csname> cssubst <cspace'> true
% <csname> cssubst false
dup resolvecolorspace
dup 1 index ne { exch pop true } { pop pop false } ifelse
} bdef
/csnames mark
/DeviceGray dup /DeviceRGB dup /DeviceCMYK dup /Pattern dup
.dicttomark readonly def
/csresolve { % <csresourcename> csresolve <cspace>
dup type /nametype ne {
(\n **** Warning: CS/cs (setcolorspace) operand not a name: ) 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
PDFfile fileposition 3 1 roll
q
1 index /PaintType oget 1 eq {
% For colored patterns, set default fill and stroke colors.
0 g 0 G
} {
% For uncolored patterns, we have to unbind the current
% color and color space before running the PaintProc.
//null sc1 //null SC1
} ifelse
% Save old values on opstack, set pdfemptycount to new value.
pdfemptycount countdictstack
/pdfemptycount count 3 sub def 4 2 roll
%
% Stack: ... <old emptycount> <dictcount> <patdict> <resdict>
% |
% New empty count points here -----+
exch //false resolvestream pdfopdict .pdfruncontext
countdictstack exch sub dup 0 gt {
( **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
pdfformaterror
{ Q } repeat
} {
pop
} ifelse
% restore pdfemptycount
/pdfemptycount exch def
Q
PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if
PDFfile exch setfileposition
} bdef
/resolvepattern { % <patternstreamdict> resolvepattern <patterndict>
% Don't do the resolvestream now: just capture the data
% from the file if necessary.
dup length dict copy
dup /FilePosition .knownget {
1 index /File get dup fileposition 3 1 roll
% Stack: dict savepos pos file
dup 3 -1 roll setfileposition
dup 3 index /Length knownoget {
dup 65535 le {
dup 0 eq {
pop pop ()
} {
string readstring pop
} ifelse
} {
() /SubFileDecode filter /ReusableStreamDecode filter
} ifelse
} {
0 (endstream) /SubFileDecode filter /ReusableStreamDecode filter
} ifelse
% Stack: dict savepos file string
3 1 roll exch setfileposition
1 index /File 3 -1 roll put
dup /FilePosition undef
} if
dup /Shading knownoget {
resolveshading 1 index /Shading 3 -1 roll put
} if
dup /PaintProc [
% Bind the resource dictionary into the PaintProc.
2 index /Resources knownoget { oforce } { 0 dict } ifelse
/.pdfpaintproc cvx
] cvx put
dup /.pattern_uses_transparency 1 index patternusestransparency put
PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Pattern: ) print dup === flush } if } if
} bdef
/ignore_color_op ( **** Warning: Ignoring a color operation in a cached context.\n) readonly def
drawopdict begin
/g { .incachedevice { % Bug 689302
pop //ignore_color_op pdfformaterror
} {
/DeviceGray cssubst { cs sc1 } { g } ifelse
} ifelse
} bdef
/rg { .incachedevice {
pop pop pop //ignore_color_op pdfformaterror
} {
/DeviceRGB cssubst { cs sc* } { rg } ifelse
} ifelse
} bdef
/k { .incachedevice {
pop pop pop pop //ignore_color_op pdfformaterror
} {
k
} ifelse
} bdef
/cs { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
csresolve cs
} ifelse
} bdef
/sc { .incachedevice {
.pdfcount { pop } repeat //ignore_color_op pdfformaterror
} {
scresolve { sc* } { sc1 } ifelse
} ifelse
} bdef
/scn /sc load def
/G { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
/DeviceGray cssubst { CS SC1 } { G } ifelse
} ifelse
} bdef
/RG { .incachedevice {
pop pop pop //ignore_color_op pdfformaterror
} {
/DeviceRGB cssubst { CS SC* } { RG } ifelse
} ifelse
} bdef
/K { .incachedevice {
pop pop pop pop //ignore_color_op pdfformaterror
} {
K
} ifelse
} bdef
/CS { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
csresolve CS
} ifelse
} bdef
/ri { .incachedevice {
pop //ignore_color_op pdfformaterror
} {
ri
} ifelse
} bdef
/SC { .incachedevice {
.pdfcount { pop } repeat //ignore_color_op pdfformaterror
} {
scresolve { SC* } { SC1 } ifelse
} ifelse
} bdef
/SCN /SC load def
end
currentdict /ignore_color_op undef
% ---------------- Paths ---------------- %
drawopdict begin
% Path construction
/m /moveto load def
/l /lineto load def
/c /curveto load def
/v { currentpoint 6 2 roll curveto } def
/y { 2 copy curveto } def
/re {
4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto
closepath
} def
/h /closepath load def
% Path painting and clipping
/n { n } def
/S { S } def
/s { s } def
/f { f } def
/f* { f* } def
/B { B } def
/b { b } def
/B* { B* } def
/b* { b* } def
/W { W } def
/W* { W* } def
/sh { setfillstate resolvesh
gsave 0 .setoverprintmode
dup /.shading .knownget {
exch
pop
} {
dup
.buildshading
dup 3 1 roll /.shading exch put
} ifelse
.shfill grestore
} def
end
% ---------------- XObjects ---------------- %
/xobjectprocs mark % <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
% <string> <index> getu16 <integer>
/getu16 {
2 copy get 8 bitshift 3 1 roll 1 add get add
} bind def
% <string> <index> getu32 <integer>
/getu32 {
2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
} bind def
% Process jp2 blocks (aka boxes). All procedures have the signature
% <file> <length> -> ... <file> <flush_length>
/jp2_tag_dict <<
/jp2h { % descend into a sub-stream, never return.
() /SubFileDecode filter 0
} bind
/ihdr {
14 sub % file len-14
1 index 14 string readstring pop % file len-14 (14)
/Components 1 index 8 getu16 % file len-14 (14) /Components NC
def % file len-14 (14)
10 get 16#7F and 1 add
/BitsPerComponent exch def % file len-14
} bind
/colr {
3 sub
1 index 3 string readstring pop % file len-3 (3)
0 get 1 eq {
4 sub % file len-7
1 index 4 string readstring pop % file len-16 (4)
0 getu32 % file len-16 enum
dup 16 eq {
% Don't set device-independent color space now
% to avoid raster differences
pop /ColorSpace /DeviceRGB % /sRGB
def % file len-7
} {
17 eq {
% See above.
/ColorSpace /DeviceGray % /sGray
def % file len-7
} if
} ifelse
} {
string 1 index exch readstring pop % file ()
/ColorSpace exch % file /ColorSpace ()
% ICC ColorSpace is not yet implemented
pop pop
%
0 % file 0
} ifelse
} bind
>> readonly def
% Parse jp2 file format to get color space and image depth info.
% <file> get_jp2_csp -
/get_jp2_csp {
{
dup (01234567) readstring pop % f (LBoxTBox)
dup length 8 lt {
pop exit
} if
dup 4 4 getinterval exch % f (TBox) (LBoxTBox)
0 getu32 % f (TBox) LBox
dup 0 eq {
pop pop exit % cannot happen
} {
dup 1 eq {
pop 1 index (01234567) readstring pop
4 getu32 % f (TBox) LBox
16 sub
} {
8 sub
} ifelse
} ifelse % f (TBox) LBox-8..16
PDFDEBUG {
2 copy 2 packedarray == % f (TBox) LBox-8..16
} if
//jp2_tag_dict 3 -1 roll .knownget {
exec
} if % f flush
dup 0 ne {
1 index exch % f f flush
() /SubFileDecode filter flushfile % skip unwanted blocks
} {
pop
} ifelse
} loop
pop
} bind def
currentdict /jp2_tag_dict .undef
/makeimagedict { % <resdict> <newdict> makeimagedict <imagemask>
% On return, newdict' is currentdict
begin
/Width 2 copy oget def
/Height 2 copy oget def
% Handle missing BitsPerComponent later.
/BitsPerComponent 2 copy knownoget { def } { pop } ifelse
/Interpolate 2 copy knownoget { def } { pop } ifelse
makeimagekeys
} bdef
/makeimagekeys { % <resdict> makeimagekeys <imagemask>
% newdict is currentdict
% Assumes Width, Height, BPC, Interpolate already copied.
/ImageType 1 def
/ImageMatrix Width 0 0
% Handle 0-height images specially.
Height dup 0 eq { pop 1 } if neg 0 1 index neg
6 array astore def
dup /ImageMask knownoget dup { and } if {
% Image mask
% Decode is required for the PostScript image operators.
% AI8 writes bogus decode array [0 1 0 0 0 0 0 0]
/Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def
% BitsPerComponent is optional for masks.
/BitsPerComponent 2 copy known { pop } { 1 def } ifelse
% Even though we're going to read data,
% pass false to resolvestream so that
% it doesn't try to use Length (which may not be present).
//false resolvestream /DataSource exch def
//true
} {
% Opaque image
dup /ColorSpace oknown
1 index /BitsPerComponent oknown and not {
dup /Filter knownoget {
dup type /arraytype eq {
dup length
dup 0 gt {
1 sub get oforce
} {
pop
} ifelse
} if
/JPXDecode eq {
% JPXDecode filters can omit the /ColorSpace and /BitsPerComponent
% keys, in which case the interpreter must retrieve this information
% from inside the compressed stream. Here we substitute the most
% likely values as a work-around.
dup /IDFlag known {
( **** Warning: PDF spec bans inline JPX images.\n) pdfformaterror
% Inline stream is not positionable. Cannot get ColorSpace.
} {
% Drop the last filter (JPXDecode) from the pipeline
dup dup length dict copy
dup /Filter oget
dup type /arraytype eq {
dup length 1 gt {
dup length 1 sub 0 exch getinterval
1 index exch /Filter exch put
dup /Params knownoget {
dup type /arraytype eq {
dup length 1 gt {
dup length 1 sub 0 exch getinterval
1 index exch /Params exch put
} {
pop
dup /Params undef
} ifelse
} {
pop
dup /Params undef
} ifelse
} if
} {
pop
dup /Filter undef
dup /Params undef
} ifelse
} {
pop
dup /Filter undef
dup /Params undef
} ifelse
//false resolvestream get_jp2_csp
} ifelse
} if
} if
currentdict /BitsPerComponent oknown not {
( **** Warning: image has no /BitsPerComponent key; assuming 8 bit.\n)
pdfformaterror
/BitsPerComponent 8 def
} if
} if
currentdict /ColorSpace knownoget not {
dup /ColorSpace knownoget not {
( **** Warning: image has no /ColorSpace key; assuming /DeviceRGB.\n)
pdfformaterror
/DeviceRGB
} if
} if
resolvecolorspace /ColorSpace exch def
% Decode is required for the PostScript image operators.
/Decode 2 copy knownoget not {
ColorSpace //defaultdecodedict
ColorSpace dup type /arraytype eq { 0 get } if get exec
} if def
% Even though we're going to read data,
% pass false to resolvestream so that
% it doesn't try to use Length (which may not be present).
//false resolvestream /DataSource exch def
//false
} ifelse
} bdef
/DoImage {
checkaltimage dup length 6 add dict
1 index /SMask knownoget { 1 index exch /SMask exch put } if
1 index /Mask knownoget { 1 index exch /Mask exch put } if
makeimagedict doimagesmask
} bdef
/makemaskimage { % <datasource> <imagemask> <Mask> makemaskimage
% <datasource> <imagemask>, updates currentdict =
% imagedict
dup type /arraytype eq {
/ImageType 4 def
% Check that every element of the Mask is an integer.
//false 1 index {
type /integertype ne or
} forall {
(\n **** Warning: Some elements of Mask array are not integers.\n)
pdfformaterror
[ exch { 0.5 add cvi } forall ] % following AR4, 5, 6 implementation
} if
% Check elements of array are within 0::(2**BitsPerComponent)-1
% This is a PostScript error, but AR ignores Mask in that case
1 BitsPerComponent bitshift 1 sub //false 2 index {
% stack: max_value result_bool value
dup 0 lt exch 3 index gt or or
} forall exch pop {
(\n **** Warning: Some elements of Mask array are out of range.\n)
pdfformaterror
[ exch { 0 .max 1 BitsPerComponent bitshift 1 sub .min } forall ]
} if
/MaskColor exch def
} {
% Mask is a stream, another Image XObject.
% Stack: datasource imagemask(false) maskstreamdict
PDFfile fileposition exch
dup length dict makeimagedict pop
% In order to prevent the two data sources from being
% aliased, we need to make at least one a reusable stream.
% We pick the mask, since it's smaller (in case we need to
% read all its data now).
% Stack: datasource imagemask(false) savedpos
% maskdict is currentdict
/DataSource DataSource mark
/Intent 1
/AsyncRead true
.dicttomark .reusablestreamdecode def
PDFfile exch setfileposition
currentdict end currentdict end
5 dict begin
/ImageType 3 def
/InterleaveType 3 def
/DataDict exch def
/MaskDict exch def
/ColorSpace DataDict /ColorSpace get def
} ifelse
} bdef
/doimagesmask { % <imagemask> doimagesmask -
PDFusingtransparency {
currentdict /SMask knownoget
} {
false
} ifelse
{ % We are doing transparency and SMask is present in the image
% stack: <imagemask> <SMask>
currentdevice .devicename /pdfwrite eq {
pop % pdfwrite will process SMask directly during 'doimage'
} {
.begintransparencymaskimage
PDFfile fileposition exch
gsave //nodict begin
null /SoftMask gput
1 .setopacityalpha 1 .setshapealpha
/Compatible .setblendmode
DoImage
end grestore
PDFfile exch setfileposition
0 .endtransparencymask
} ifelse
<< /Subtype /Group /Isolated true
/.image_with_SMask true % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c
>> 0 0 1 1 .begintransparencygroup
doimage
.endtransparencygroup
} {
SoftMask //null ne {
% the image doesn't have an SMask, but the ExtGState does, force a group.
<< /Subtype /Group /Isolated true >> 0 0 1 1 .begintransparencygroup
doimage
.endtransparencygroup
}
{ doimage }
ifelse
} ifelse
} bdef
% For development needs we define a special option for running with a new handler
% for images with a soft mask.
//systemdict /NEW_IMAGE3X .knownget not { //false } if {
/doimagesmask { % <imagemask> doimagesmask -
doimage
} bdef
} if
/is_big_mask { % - is_big_mask <bool>
1 0 dtransform dup mul exch dup mul sqrt add
0 1 dtransform dup mul exch dup mul sqrt add mul
currentdevice getdeviceprops .dicttomark /BufferSpace .knownget not {
4000000 % hack: Can't get the real default value from C source.
} if
2 % arbitrary
div gt
} bind def
% For development needs we define a special option for running with a new handler
% for images with a soft mask.
//systemdict /NEW_IMAGE3X .knownget not { //false } if {
/is_big_mask { % - is_big_mask <bool>
//false
} bdef
} if
/doimage { % <imagemask> doimage -
% imagedict is currentdict, gets popped from dstack
DataSource exch
PDFusingtransparency
currentdevice .devicename /pdfwrite ne {
% This is a temporary workaround for the bug 689080,
% which is done under a rush of 8.63 release.
% The purpose is to disable a conversion of an image with soft mask
% into a Type 103 image, which currently allocates a full mask buffer
% before writing clist.
% With this workaround the Matte color is not working (ignored).
is_big_mask not
} {
true % pdfwrite doesn't need the workaround explained above,
% and cannot work with it.
} ifelse
and {
currentdict /SMask knownoget
} {
false
} ifelse {
makesoftmaskimage
} {
currentdict /Mask knownoget {
makemaskimage
} if
} ifelse
% Stack: datasource imagemask
{ currentdict end setfillstate { imagemask } }
{ ColorSpace setgcolorspace currentdict end setfillblend { image } }
ifelse
stopped {
dup type /dicttype eq { pop } if % Sometimes image fails to restore the 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 countdictstack 3 -1 roll
/pdfemptycount count 1 sub store
q execform % gsave / grestore around the Form
% Restore pdfemptycount
countdictstack exch sub
dup 1 gt {
( **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
pdfformaterror
} if
{ Q } repeat
/pdfemptycount exch store
} bdef
/_dops_save 1 array def
/DoPS {
DOPS
{
//_dops_save 0 save put
true resolvestream cvx exec
//_dops_save 0 get restore
}
{ pop }
ifelse
} bdef
currentdict /_dops_save undef
drawopdict begin
/Do {
setfillblend
PDFfile fileposition exch
dup Page /XObject rget {
exch pop dup /Subtype get xobjectprocs exch get
% Don't leave extra objects on the stack while executing
% the definition of the form.
3 -1 roll 2 .execn
} {
% This should cause an error, but Acrobat Reader can
% continue, so we do too.
( **** Undefined XObject resource: )
exch =string cvs concatstrings (\n) concatstrings
pdfformaterror
} ifelse
PDFfile exch setfileposition
} bdef
end
% ---------------- In-line images ---------------- %
% Undo the abbreviations in an in-line image dictionary.
% Note that we must look inside array values.
% /I is context-dependent.
/unabbrevkeydict mark
/BPC /BitsPerComponent /CS /ColorSpace /D /Decode /DP /DecodeParms
/F /Filter /H /Height /I /Interpolate /IM /ImageMask /W /Width
.dicttomark readonly def
/unabbrevvaluedict mark
/AHx /ASCIIHexDecode /A85 /ASCII85Decode /CC /CalCMYK
/CCF /CCITTFaxDecode /CG /CalGray /CR /CalRGB
/DCT /DCTDecode /CMYK /DeviceCMYK /Fl /FlateDecode
/G /DeviceGray /RGB /DeviceRGB
/I /Indexed /LZW /LZWDecode /RL /RunLengthDecode
.dicttomark readonly def
/unabbrevtypedict mark
/nametype {
//unabbrevvaluedict 1 index .knownget { exch pop } if
}
/arraytype {
dup 0 1 2 index length 1 sub {
2 copy get unabbrevvalue put dup
} for pop
}
.dicttomark readonly def
/unabbrevvalue { % <obj> unabbrevvalue <obj'>
oforce //unabbrevtypedict 1 index type .knownget { exec } if
} bdef
/is_space_dict << 0 0 9 9 10 10 12 12 13 13 32 32 >> readonly def
drawopdict begin
/BI { mark } bdef
/ID {
counttomark 2 idiv dup 7 add dict begin {
exch //unabbrevkeydict 1 index .knownget { exch pop } if
exch unabbrevvalue def
} repeat pop
/IDFlag true def % flag for stream processing.
/File PDFsource def
currentdict makeimagekeys doimage
% The Adobe documentation says that the data following ID
% consists of "lines", and some PDF files (specifically, some files
% produced by PCL2PDF from Visual Software) contain garbage bytes
% between the last byte of valid data and an EOL.
% Some files (PDFOUT v3.8d by GenText) have EI immediately following
% the stream. Some have no EOL and garbage bytes.
% Sometimes (bug 690300) CCITTDecode filter consumes 'E' in 'EI'.
% Therefore, we search for <start>I<sp|end> or <start|sp>EI<sp|end>
PDFsource read not {
/ID cvx /syntaxerror signalerror
} if
dup 73 eq {
pop 10 69 73 % Seed to: <sp>EI
} {
10 10 3 -1 roll % Seed to: <sp><sp><any>
} ifelse
{ PDFsource read not dup { 10 exch } if
//is_space_dict 2 index known
3 index 73 eq and 4 index 69 eq and
//is_space_dict 6 index known and {
pop pop pop pop pop exit
} {
{
pop pop pop /ID cvx /syntaxerror signalerror
} {
4 -1 roll pop
} ifelse
} ifelse
} loop
} bdef
end
currentdict /is_space_dict undef
% ================================ Text ================================ %
drawopdict begin
% Text control
/BT { 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.
/QBT {
Q BT
( **** Warning: invalid operator QBT processed as Q BT .\n)
pdfformaterror % Bug 690089
} def
end
% ============================== Annotations ============================== %
% Get and normalize an annotation's rectangle.
/annotrect { % <annot> annotrect <x> <y> <w> <h>
/Rect oget 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 eq {
dup length 3 lt
} {
//true
} ifelse % <annot> [border] <bad?>
} ifelse {
( **** Warning: Wrong annotation border object, no border is drawn.\n)
pdfformaterror
pop { 0 0 0 }
} if
dup type /dicttype eq {
dup /W knownoget not { 1 } if
% Per PDF1.6 Reference table 8.13, /W in the border style dictionary is
% expressed in points (an absolute unit), so compensate here for any
% scaling of the PostScript user space done due to /UserUnit.
% Scaling due to -dPDFFitPage is not undone, to keep the correct border 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_x> <scalefactor_y> <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: scalex scaley annot appearance false key
2 index exch knownogetdict {
exch not exit
} if
} forall
% stack: scalex scaley annot appearance value true
% stack: scalex scaley annot appearance false
dup {
pop exch pop
% Acrobat Distiller produces files in which this Form
% XObject lacks Type and Subtype keys. This is illegal,
% but Acrobat Reader accepts it. The only way we can
% tell whether this is a Form or a set of sub-appearances
% is by testing for the stream Length or File key.
% If the stream lacks Length key, try File key.
dup /Length known 1 index /File known or {
% If this is a form then simply use it
//true
} {
1 index /AS knownoget not {
% If we do not have AS then use any appearance
{ exch pop oforce exit } forall //true
} {
% Stack: annot Ndict AS
% Get the specified appearance. If no appearance, then
% display nothing - set stack = false.
knownoget
} ifelse
} ifelse
} {
exch pop % discard useless AP dictionary
} ifelse
% Stack: scalex scaley annot appearance true
% Stack: scalex scaley annot false
{
% Draw appearance
% Initialize graphic following "7.4.4 Appearance Streams"
q graphicsbeginpage textbeginpage
1 index annotrect pop pop translate
3 index 3 index scale % Apply scale factors
dup /BBox knownoget {
1 index /Matrix knownoget not { {1 0 0 1 0 0} } if
.bbox_transform pop pop
% Compensate for non-zero origin of BBox
neg exch neg exch translate
} if
DoForm Q
} if
} {
dup /FT knownoget {
/Tx eq {
% Stack: scalex scaley annot
dup /DA known 1 index /V known and {
dup /DA oget
q graphicsbeginpage textbeginpage
1 index annotrect pop pop translate
3 index 3 index scale % Apply scale factors
cvx exec
dup /V oget
0 0 moveto dup false charpath pathbbox newpath 3 -1 roll
sub abs 3 1 roll sub abs
3 index annotrect 4 2 roll pop pop
6 index mul exch 6 index mul
% stack: scale annot V vsize hsize vrect hrect
% Calculate horizontal justification first
% horizontal can be left (Q=0), center (Q=1), or right (Q=2) justification
3 -1 roll
% stack: scalex scaley annot V vsize vrect hrect hsize
5 index /Q knownoget not { 0 } if % default 0 == left
dup 0 eq {
pop pop pop 0 % left justified
} {
1 eq {
2 div exch 2 div exch sub % centered
} {
sub % right justified (hrect - hsize)
} ifelse
} ifelse
% stack: scalex scaley annot V vsize vrect hoffset
% Center the text vertically in the rect (Acrobat Reader seems to do this)
3 1 roll 2 div exch 2 div sub abs
% stack: scalex scaley annot V hoffset voffset
moveto show
Q
} if
} if
} if
} ifelse
pop pop pop
} bdef
% For annotation object we have to determine the size of the output rectangle
% and the size of the BBox for the form XObject. From these we calculate
% a scale factors for drawing it.
/calc_annot_scale { % <annot> calc_annot_scale <x_scale> <y_scale>
dup /Rect knownoget {
pop dup annotrect 4 2 roll pop pop % get width height size in user space
3 -1 roll /AP knownoget {
/N knownogetdict {
dup /Matrix knownoget not { {1 0 0 1 0 0} } if
exch /BBox knownoget { % x y {matrix} [box]
exch .bbox_transform % x y x0 y0 x1 y1
3 -1 roll sub % x y x0 x1 y1-y0
3 1 roll exch sub % x y y1-y0 x1-x0
2 copy mul 0 eq {
( **** Warning: /BBox has zero width or height, which is not allowed.\n)
pdfformaterror
pop pop pop pop 1 1 % zero size -- revert to unity scaling
} {
3 1 roll div % x x1-x0 y/(y1-y0)
3 1 roll div % y/(y1-y0) x/(x1-x0)
exch % x/(x1-x0) y/(y1-y0)
} ifelse
} {
pop pop pop 1 1 % default to unity scaling
} ifelse % if we have /BBox
} {
pop pop 1 1
} ifelse % if we have /N
} {
pop pop 1 1
} ifelse % if we have /AP
} {
( **** Warning: /Annot dict is missing required /Rect entry.\n)
pdfformaterror
pop 1 1
} ifelse
} bdef
/drawlink { % <annot> drawlink -
dup drawborder dup calc_annot_scale 3 -1 roll drawwidget
} bdef
% Draw an annotation.
/drawannottypes mark
/Link { drawlink } bind
.dicttomark readonly def
/drawannot { % <annot> drawannot -
dup annotvisible {
gsave
dup dup /Subtype knownoget {
//drawannottypes exch .knownget {
exec
} {
dup calc_annot_scale 3 -1 roll drawwidget % Use drawwidget for 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 {
1 1 2 index drawwidget
} {
(Push button without appearance stream is not yet implemented) =
} ifelse
} {
16#10000 and 0 ne {
% Radio button
dup /AP known {
1 index /Kids oget {
1 1 3 -1 roll drawwidget
} forall
} {
(Radio button without appearance stream is not yet implemented) =
} ifelse
} {
% Checkbox
dup /AP known {
dup 1 1 3 -1 roll drawwidget
} {
(CkeckBox without appearance stream is not yet implemented) =
} ifelse
} ifelse
} ifelse
} bdef
/Tx {
dup /AP known {
dup 1 1 3 -1 roll drawwidget
} {
2 index /NeedAppearances knownoget not { //false } if {
dup /AP << /N 10 dict dup cvx begin >> put
/Subtype /Form def
/BBox [ 0 0 4 index /Rect oget { oforce } forall 3 -1 roll sub abs 3 1 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 1 3 -1 roll drawwidget
} if
} ifelse
} bdef
/Ch {
(Ch is not yet implemened) ==
} bdef
/Sig {
(Sig is not yet implemened ) ==
} bdef
currentdict end def
/draw_terminal_field { % <field> draw_terminal_field -
dup /Kids knownoget { 0 oget } { dup } ifelse
dup /P knownoget {
/Page load eq {
//draw_terminal_field_dict 2 index /FT pget not { 0 } if .knownget {
exec
} if
} if
} if
pop pop
} bdef
% We distinguish 4 types of nodes on the form field tree:
% - non-terminal field - has a kid that refers to the parent (or anywhere else)
% - terminal field with separate widget annotations - has a kid that doesn't 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
Copyright 2K16 - 2K18 Indonesian Hacker Rulez