plan9fox/sys/lib/ghostscript/pdf_draw.ps
2011-03-30 19:35:09 +03:00

1336 lines
40 KiB
PostScript

% 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,v 1.98 2005/10/05 14:37:59 ray Exp $
% 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
/ColorSpace {
resolvecolorspace
}
/Function {
dup type /dicttype eq {
resolvefunction
} {
[ exch { oforce resolvefunction } forall ]
} ifelse
}
.dicttomark readonly def
/resolveshading { % <shadingstream> resolveshading <shading>
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
} bdef
/resolvesh { % <shname> resolveshading <shading>
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 { { //false upath } stopped {
pop % discard 'false' (upath failed, probably no currentpoint).
//cmmatrix astore concat
} {
% update the CTM, then uappend.
7 1 roll //cmmatrix astore concat
newpath { mark exch uappend } stopped
cleartomark
} ifelse
} def
/i { 1 .min setflat } def
/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 {
0 4 getinterval % ignore attributes
aload pop 3 -1 roll oforce % resolve names array
[ exch { oforce } forall ] % resolve each of the names
3 -1 roll oforce resolvecolorspace
3 -1 roll oforce resolvefnproc
4 array astore
}
/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 readstring pop
% Stack: filepos /Indexed basespace hival 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 {
string readstring pop
} {
() /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 shfill } 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 >> 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
% image and imagemask can be redefined in gs_init.ps to tweak interpolation
% after device-specific files are run. Don't bind them here.
{ currentdict end setfillstate /imagemask }
{ ColorSpace setgcolorspace currentdict end setfillblend /image }
ifelse
.systemvar stopped {
pop
$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
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 knownoget {
dup /W knownoget not { 1 } if
[] 2 index /S knownoget {
/D eq { 2 index /D knownoget not { [3] } if exch pop } if
} if 3 -1 roll pop strokeborder
} {
dup /Border knownoget {
dup 2 get
exch dup length 3 gt { 3 get } { pop [] } ifelse
strokeborder
} {
1 [] strokeborder
} ifelse
} 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 {
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 key.
dup /Length known {
% 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
} if 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 get //drawannottypes exch .knownget {
exec
} {
dup calcstampscale exch drawwidget % Use drawwidget for everything else
} ifelse % type known
grestore
} if pop % annotvisible
} bdef
currentdict /drawannottypes undef
end % pdfdict
end % GS_PDF_ProcSet
.setglobal