1 % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
3 % This software is provided AS-IS with no warranty, either express or
6 % This software is distributed under license and may not be copied,
7 % modified or distributed except as expressly authorized under the terms
8 % of the license contained in the file LICENSE in this distribution.
10 % For more information about licensing, please refer to
11 % http://www.ghostscript.com/licensing/. For information on
12 % commercial licensing, go to http://www.artifex.com/licensing/ or
13 % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
16 % $Id: pdf_draw.ps,v 1.98 2005/10/05 14:37:59 ray Exp $
18 % PDF drawing operations (graphics, text, and images).
20 /.setlanguagelevel where { pop 2 .setlanguagelevel } if
21 .currentglobal true .setglobal
22 /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
26 % For simplicity, we use a single interpretation dictionary for all
27 % PDF graphics operations, even though this is too liberal.
28 /drawopdict 100 dict def
30 % ================================ Graphics ================================ %
32 % ---------------- Functions ---------------- %
34 % Note that resolvefunction converts a PDF Function to a PostScript Function;
35 % resolve*fnproc converts a PDF function to a PostScript procedure.
36 % We need to process all required and optional parameters to resolve any
37 % use of indirect references.
44 .dicttomark readonly def
47 dup length 1 add dict .copydict % make room for DataSource
48 % now resolve any indirect references
49 dup /Size 2 copy knownoget { put } { pop pop } ifelse
50 dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse
51 dup /Order 2 copy knownoget { put } { pop pop } ifelse
52 dup /Encode 2 copy knownoget { put } { pop pop } ifelse
53 dup /Decode 2 copy knownoget { put } { pop pop } ifelse
55 % Don't lose our place in PDFfile.
56 PDFfile fileposition exch
57 dup true resolvestream
58 % The stream isn't positionable, so read all the data now.
59 % Stack: filepos fndict stream
60 1 index /Range get length 2 idiv 2 index /BitsPerSample get mul
61 2 index /Size get { mul } forall
63 1 index exch readstring pop exch closefile
64 % Stack: filepos fndict data
65 exch dup /DataSource 4 -1 roll put
66 exch PDFfile exch setfileposition
70 dup length dict .copydict
71 dup /C0 2 copy knownoget { put } { pop pop } ifelse
72 dup /C1 2 copy knownoget { put } { pop pop } ifelse
73 dup /N 2 copy knownoget { put } { pop pop } ifelse
77 dup length dict .copydict
78 dup /Bounds 2 copy knownoget { put } { pop pop } ifelse
79 dup /Encode 2 copy knownoget { put } { pop pop } ifelse
80 dup /Functions 2 copy oget mark exch dup {
83 counttomark -1 roll astore exch pop put
87 PDFfile fileposition exch % filepos fndict
88 dup true resolvestream % filepos fndict stream
89 exch dup length dict copy % filepos stream fndict2
90 dup /Function undef % filepos stream fndict2
92 () /rangecheck cvx signalerror
95 /rangecheck cvx signalerror
97 % Use .bind to avoid idiom recognition.
99 1 index /Function 3 -1 roll put
100 exch PDFfile exch setfileposition
103 /.resolvefn { % <fndict> .resolvefn <fndict'>
104 dup length dict .copydict
105 dup /Domain 2 copy knownoget { put } { pop pop } ifelse
106 dup /Range 2 copy knownoget { put } { pop pop } ifelse
107 dup /FunctionType oget //fnrdict exch get exec
110 /resolvefunction { % <fndict> resolvefunction <function>
112 PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Function: ) print dup === flush } if } if
115 /resolvefnproc { % <fndict> resolvefnproc <proc>
116 resolvefunction .buildfunction
119 /resolveidfnproc { % <fndict> resolveidfnproc <proc>
120 dup /Identity eq { pop { } } { resolvefnproc } ifelse
123 /resolvedefaultfnproc { % <fndict> <default> resolved'fnproc <proc>
124 1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
127 % ---------------- Shadings ---------------- %
134 dup type /dicttype eq {
137 [ exch { oforce resolvefunction } forall ]
140 .dicttomark readonly def
142 /resolveshading { % <shadingstream> resolveshading <shading>
143 PDFfile fileposition exch
145 oforce //shrdict 2 index .knownget { exec } if
147 dup /ShadingType get 4 ge {
148 dup dup true resolvestream
149 % Make a reusable stream so that the shading doesn't
150 % reposition PDFfile at unexpected times.
151 /ReusableStreamDecode filter /DataSource exch put
152 } if exch PDFfile exch setfileposition
154 /resolvesh { % <shname> resolveshading <shading>
162 % ---------------- Halftones ---------------- %
166 abs exch abs 2 copy add 1 le {
167 dup mul exch dup mul add 1 exch sub
169 1 sub dup mul exch 1 sub dup mul add 1 sub
173 abs exch abs 2 copy add .75 le {
174 dup mul exch dup mul add 1 exch sub
177 .85 mul add 1 exch sub
179 1 sub dup mul exch 1 sub dup mul add 1 sub
184 abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
185 pop dup mul exch .75 div dup mul add 4 div 1 exch sub
188 pop 1 exch sub dup mul exch 1 exch sub
189 .75 div dup mul add 4 div 1 sub
191 .5 exch sub exch pop exch pop
195 /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
196 /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
197 /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
198 /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
199 /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
200 /Line { exch pop abs neg }
203 /Square { abs exch abs 2 copy lt { exch } if pop neg }
204 /Cross { abs exch abs 2 copy gt { exch } if pop neg }
205 /Rhomboid { abs exch abs 0.9 mul add 2 div }
206 /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
207 /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
208 /SimpleDot { dup mul exch dup mul add 1 exch sub }
209 /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
210 /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
211 /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
213 exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
215 .dicttomark readonly def
220 % We don't support types 6, 10, or 16 yet.
221 .dicttomark readonly def
226 1 index /SpotFunction eq {
227 dup type /nametype eq
228 { //spotfunctions exch get } { resolvefnproc }
231 1 index /TransferFunction eq {
240 oforce dup type /dicttype eq { resolvehalftone } if
244 /resolvehalftone { % <dict> resolvehalftone <halftone>
245 dup /HalftoneType get
246 dup //htrdict exch .knownget {
249 (\n\n **** Unsupported HalftoneType ) pdfformaterror
250 =string cvs pdfformaterror (. ***\n\n) pdfformaterror
251 /resolvehalftone cvx /unregistered signalerror
255 % ---------------- Graphics state management ---------------- %
259 % Graphics state stack
262 % Graphics state setting
263 /cm { { //false upath } stopped {
264 pop % discard 'false' (upath failed, probably no currentpoint).
265 //cmmatrix astore concat
267 % update the CTM, then uappend.
268 7 1 roll //cmmatrix astore concat
269 newpath { mark exch uappend } stopped
273 /i { 1 .min setflat } def
274 /J /setlinecap load def
276 /j /setlinejoin load def
277 /w /setlinewidth load def
278 /M { 1 .max setmiterlimit } bdef
282 % Each entry in this dictionary is
283 % <gsres> <value> -proc- <gsres>
285 /BGDefault load resolvedefaultfnproc setblackgeneration
288 /UCRDefault load resolvedefaultfnproc setundercolorremoval
291 dup type /arraytype eq {
292 { oforce /TRDefault load resolvedefaultfnproc } forall
295 /TRDefault load resolvedefaultfnproc settransfer
299 /SA { setstrokeadjust }
300 /OP { 1 index /op known not { dup op } if OP }
301 % The PDF 1.3 specification says that the name /Default is only
302 % recognized for {BG,UCR,TR}2. However, PDF 1.3 files produced
303 % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default
304 % with the older keys, so we have to implement this.
305 /BG { 1 index /BG2 known { pop } { gsbg } ifelse }
306 /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse }
307 /TR { 1 index /TR2 known { pop } { gstr } ifelse }
310 pop .setdefaulthalftone
312 %****** DOESN'T IMPLEMENT THE STREAM CASE YET ******
313 resolvehalftone sethalftone
315 % the transfer function may dependent on the halftone, so make sure
316 % it is set if included in the graphic state (otherwise this is
317 % subject to order of a dictionary forall, which is unpredictable)
319 dup /Default eq { oforce gsparamdict /TR2 get exec } { pop } ifelse
322 /dup /Default eq { oforce gsparamdict /TR get exec } { pop } ifelse
327 % HTP may be present even if this isn't a DPS interpreter.
328 /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
331 /Font { aload pop Tf }
335 /ML { 1 .max setmiterlimit }
336 /D { aload pop setdash }
343 /FL { 1 .min setflat }
345 % SM may be present even if this is only a Level 2 interpreter.
346 /setsmoothness where { pop setsmoothness } { pop } ifelse
349 % All of these require the "transparency" feature in the interpreter.
356 .dicttomark readonly def
358 Page /ExtGState rget {
359 % We keep the dictionary on the stack during the forall so that
360 % keys that interact with each other have access to it.
362 oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
367 % ------ Transparency support ------ %
370 dup /None eq PDFusingtransparency not or {
373 % Preprocess the SMask value into a parameter dictionary for
374 % .begintransparencymaskgroup, with added /BBox and /Draw keys.
375 mark exch % Stack: mark smaskdict
376 dup /S oget /Subtype exch 3 2 roll
377 % Stack: mark ... smaskdict
379 dup /Background exch 4 2 roll
381 1 index /G oget /Group oget /CS knownoget {
382 csresolve dup setgcolorspace csput
384 aload pop setcolor [ currentgray ]
386 /GrayBackground exch 3 2 roll
389 resolveidfnproc /TransferFunction exch 3 2 roll
391 dup /G oget dup /BBox oget /BBox exch 4 2 roll
392 /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
397 % This procedure is called to actually render the soft mask.
398 /.execmaskgroup { % <masknum> <paramdict> <formdict> .execmaskgroup -
399 % Save our place in PDFfile, and do a gsave to avoid resetting
401 currentcolorspace 4 1 roll
402 PDFfile fileposition 4 1 roll
403 % We have to select the group's color space so that the
404 % background color will be interpreted correctly.
405 dup /Group oget /CS knownoget { csresolve dup setgcolorspace csput } if
406 exch dup /BBox get aload pop .begintransparencymaskgroup {
407 dup /Resources knownoget { oforce } { 0 dict } ifelse
408 exch false resolvestream
409 .execgroup .endtransparencymask
411 .discardtransparencymask stop
413 PDFfile exch setfileposition
416 % Paint a Form+Group XObject, either for a transparency mask or for a Do.
417 /.execgroup { % <resdict> <stream> .execgroup -
420 1 .setopacityalpha 1 .setshapealpha
421 0 .inittransparencymask 1 .inittransparencymask
422 /Compatible .setblendmode
423 % Execute the body of the Form, similar to DoForm.
424 pdfopdict .pdfruncontext
428 /.beginformgroup { % groupdict bbox .beginformgroup -
429 exch mark exch % bbox mark groupdict
430 dup /CS knownoget { csresolve setgcolorspace } if
431 dup /I knownoget { /Isolated exch 3 2 roll } if
432 dup /K knownoget { /Knockout exch 3 2 roll } if
434 % Stack: bbox paramdict
436 .begintransparencygroup
439 % .paintgroupform implements the Form PaintProc in the case where the
440 % Form XObject dictionary includes a Group key. See .paintform below.
441 /.paintgroupform { % <resdict> <stream> <formdict> .paintgroupform -
442 dup /Group oget exch /BBox oget
443 % Stack: resdict stream groupdict bbox
447 .discardtransparencygroup stop
448 } if .endtransparencygroup
451 % Make an ImageType 103 (soft-masked) image.
452 /makesoftmaskimage { % <datasource> <imagemask> <SMask> makesoftmaskimage
453 % <datasource> <imagemask>, updates currentdict =
455 % See the ImageType 3 case of makemaskimage below.
456 % SMask is a stream, another Image XObject.
457 % Stack: datasource imagemask(false) smaskstreamdict
458 PDFfile fileposition exch
459 dup /Matte knownoget { /Matte exch def } if
460 dup length dict makeimagedict pop
461 % In order to prevent the two data sources from being
462 % aliased, we need to make at least one a reusable stream.
463 % We pick the mask, since it's smaller (in case we need to
464 % read all its data now).
465 % Stack: datasource imagemask(false) savedpos
466 % maskdict is currentdict
467 /DataSource DataSource mark
470 .dicttomark .reusablestreamdecode def
471 PDFfile exch setfileposition
472 currentdict end currentdict end
476 dup /InterleaveType 3 put
477 DataDict /Matte knownoget {
480 AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
481 /ColorSpace DataDict /ColorSpace get def
484 % ---------------- Color setting ---------------- %
486 /01_1 [0 1] readonly def
487 /01_3 [0 1 0 1 0 1] readonly def
488 /01_4 [0 1 0 1 0 1 0 1] readonly def
490 % The keys here are resolved (PostScript, not PDF) color space names.
492 /DeviceGray { pop 1 }
494 /DeviceCMYK { pop 4 }
496 /CIEBasedABC { pop 3 }
497 /ICCBased { 1 oget /N oget }
498 /Separation { pop 1 }
499 /DeviceN { 1 oget length }
500 .dicttomark readonly def
508 dup /Gamma knownoget {
509 /exp load 2 packedarray cvx /DecodeA exch def
511 dup /BlackPoint knownoget { /BlackPoint exch def } if
512 dup /WhitePoint knownoget {
513 dup /WhitePoint exch def
514 dup /MatrixA exch def
515 /RangeLMN [ 3 2 roll { 0 exch } forall ] def
517 /PDFColorSpace exch def [ /CIEBasedA currentdict end ]
521 dup /Gamma knownoget {
522 [ exch { /exp load 2 packedarray cvx } forall
523 ] /DecodeABC exch def
525 dup /Matrix knownoget { /MatrixABC exch def } if
526 dup /BlackPoint knownoget { /BlackPoint exch def } if
527 dup /WhitePoint knownoget { /WhitePoint exch def } if
528 /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
531 pop /DeviceCMYK % not defined by Adobe
535 dup /Range knownoget not { [-100 100 -100 100] } if
536 [0 100 null null null null] dup 2 4 -1 roll putinterval
538 /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
539 /MatrixABC [1 1 1 1 0 0 0 0 -1] def
540 dup /BlackPoint knownoget { /BlackPoint exch def } if
541 dup /WhitePoint knownoget { /WhitePoint exch def } {
542 ( **** Warning: Lab colorspace is missing WhitePoint.\n)
544 /WhitePoint [0.9505 1 1.089] def
546 % scaling function g() for DecodeLMN construction
547 { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
549 % Store white point implicitly inside procedures.
550 [ 3 index aload pop WhitePoint 0 get /mul .systemvar ] cvx bind
551 [ 4 index aload pop WhitePoint 1 get /mul .systemvar ] cvx bind
552 [ 5 index aload pop WhitePoint 2 get /mul .systemvar ] cvx bind
554 /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
557 dup 1 get type /dicttype ne { % don't resolve more than once
558 PDFfile fileposition exch
560 mark exch { oforce } forall .dicttomark
561 dup dup true resolvestream
562 /ReusableStreamDecode filter /DataSource exch put
564 exch PDFfile exch setfileposition
565 % Resolve alternate color space
566 dup 1 get % Get colorspace dictionary
567 dup /Alternate .knownget % Check for alternate color space
568 { oforce resolvecolorspace /Alternate exch put } % resolve and replace
569 { pop } % remove colorspace dictionary
574 aload pop exch oforce resolvecolorspace
575 % Contrary to PDF manuals up to v.1.5, Acrobat Distiller 3.01
576 % can use /Identity name here instead of a function.
577 exch oforce resolveidfnproc
581 0 4 getinterval % ignore attributes
582 aload pop 3 -1 roll oforce % resolve names array
583 [ exch { oforce } forall ] % resolve each of the names
584 3 -1 roll oforce resolvecolorspace
585 3 -1 roll oforce resolvefnproc
589 aload pop 3 -1 roll oforce resolvecolorspace
590 % Stack: /Indexed hival lookup basespace
591 % If the underlying space is a Lab space, we must scale
592 % the output of the lookup table as part of DecodeABC.
593 dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq {
594 dup 1 get /DecodeLMN known {
595 1 get dup length dict copy
596 begin /DecodeABC [ 0 2 4 {
597 RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load
598 RangeABC 3 index get /add load
599 DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx
602 currentdict end /CIEBasedABC exch 2 array astore
606 oforce dup type /stringtype ne {
607 % The color lookup table is a stream.
608 % Get its contents. Don't lose our place in PDFfile.
609 % Stack: /Indexed basespace hival lookup
610 PDFfile fileposition 5 1 roll true resolvestream
611 % Stack: filepos /Indexed basespace hival lookupstream
613 % Stack: filepos /Indexed basespace hival lookupstream len
615 dup dup type /arraytype eq { 0 get } if
616 //csncompdict exch get exec mul
617 string readstring pop
618 % Stack: filepos /Indexed basespace hival table
619 5 -1 roll PDFfile exch setfileposition
622 % Replace the PDFColorSpace with the Indexed space if needed.
624 dup type /arraytype eq {
626 dup 1 get type /dicttype eq {
627 dup 1 get /PDFColorSpace known {
628 dup 1 get /PDFColorSpace 3 index put
635 dup type /nametype ne {
637 1 oget resolvecolorspace
638 /Pattern exch 2 array astore
642 .dicttomark readonly def
644 /cssubst { % <csname> cssubst <cspace'> true
645 % <csname> cssubst false
646 dup resolvecolorspace
647 dup 1 index ne { exch pop true } { pop pop false } ifelse
651 /DeviceGray dup /DeviceRGB dup /DeviceCMYK dup /Pattern dup
652 .dicttomark readonly def
653 /csresolve { % <csresourcename> csresolve <cspace>
654 dup type /nametype ne {
655 (\n **** Warning: CS/cs (setcolorspace) operand not a name: ) pdfformaterror
656 dup stderrfile dup 3 -1 roll write==only flushfile
657 ( ****\n) pdfformaterror
658 dup type /arraytype eq { % Adobe InDesign + PDF Library has array
662 dup Page /ColorSpace rget {
663 exch pop resolvecolorspace
665 //csnames 1 index known not { /undefined cvx signalerror } if
669 /resolvecolorspace { % <cspace> resolvecolorspace <cspace'>
670 dup dup type /arraytype eq { 0 get } if
671 //csrdict exch .knownget
673 exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
675 dup type /nametype eq { csresolve } { csset exch pop } ifelse
679 /scresolve { % <c0> ... scresolve <multi>
680 % We can't really make sc[n] and SC[N] work, because
681 % the color space information isn't available at
682 % conversion time; so we hack it by assuming that
683 % all the operands on the stack are used, and that
684 % if the top operand is a name, it's a Pattern resource.
685 dup type /nametype eq
686 { Page /Pattern rget { resolvepattern } { null } ifelse }
688 dup type /dicttype eq {
689 % Check the PaintType, if any (shading patterns don't
691 dup /PaintType knownoget { 2 eq } { false } ifelse
697 /.pdfpaintproc { % <patdict> <resdict> .pdfpaintproc -
698 PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Begin PaintProc) print dup === flush } if } if
699 % For uncolored patterns, we have to unbind the current
700 % color and color space before running the PaintProc.
701 % There's no harm in doing this for colored patterns,
702 % so for simplicity, we always do it.
703 PDFfile fileposition 3 1 roll
707 % save old value of pdfemptycount on opstack, set to new value
708 pdfemptycount /pdfemptycount count 3 sub def 3 1 roll
709 exch false resolvestream pdfopdict .pdfruncontext
710 % restore pdfemptycount
711 /pdfemptycount exch def
714 PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%End PaintProc) print dup === flush } if } if
715 PDFfile exch setfileposition
718 /resolvepattern { % <patternstreamdict> resolvepattern <patterndict>
719 % Don't do the resolvestream now: just capture the data
720 % from the file if necessary.
722 dup /FilePosition .knownget {
723 1 index /File get dup fileposition 3 1 roll
724 % Stack: dict savepos pos file
725 dup 3 -1 roll setfileposition
726 dup 3 index /Length oget
729 string readstring pop
731 () /SubFileDecode filter /ReusableStreamDecode filter
733 % Stack: dict savepos file string
734 3 1 roll exch setfileposition
735 1 index /File 3 -1 roll put
736 dup /FilePosition undef
738 dup /Shading knownoget {
739 resolveshading 1 index /Shading 3 -1 roll put
742 % Bind the resource dictionary into the PaintProc.
743 2 index /Resources knownoget { oforce } { 0 dict } ifelse
746 PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Pattern: ) print dup === flush } if } if
750 /g { /DeviceGray cssubst { cs sc1 } { g } ifelse } bdef
751 /rg { /DeviceRGB cssubst { cs sc* } { rg } ifelse } bdef
753 /cs { csresolve cs } bdef
754 /sc { scresolve { sc* } { sc1 } ifelse } bdef
756 /G { /DeviceGray cssubst { CS SC1 } { G } ifelse } bdef
757 /RG { /DeviceRGB cssubst { CS SC* } { RG } ifelse } bdef
759 /CS { csresolve CS } bdef
761 /SC { scresolve { SC* } { SC1 } ifelse } bdef
765 % ---------------- Paths ---------------- %
772 /v { currentpoint 6 2 roll curveto } def
773 /y { 2 copy curveto } def
775 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto
778 /h /closepath load def
779 % Path painting and clipping
791 /sh { setfillstate resolvesh shfill } def
794 % ---------------- XObjects ---------------- %
796 /xobjectprocs mark % <dict> -proc- -
800 .dicttomark readonly def
802 % Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
804 /defaultdecodedict mark
805 /DeviceGray { pop //01_1 } bind
806 /DeviceRGB { pop //01_3 } bind
807 /DeviceCMYK { pop //01_4 } bind
808 /CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind
809 /CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind
811 1 oget dup /Range knownoget {
814 /N get [ exch {0 1} repeat ] readonly
817 /Separation { pop //01_1 } bind
819 1 oget length [ exch {0 1} repeat ] readonly
822 pop [ 0 1 BitsPerComponent bitshift 1 sub ]
824 .dicttomark readonly def
826 /checkaltimage { % <resdict> checkaltimage <resdict[']>
828 dup /Alternates knownoget {
830 dup /DefaultForPrinting knownoget {
832 /Image oget exch pop exit
844 /makeimagedict { % <resdict> <newdict> makeimagedict <imagemask>
845 % On return, newdict' is currentdict
847 /Width 2 copy oget def
848 /Height 2 copy oget def
849 % Handle missing BitsPerComponent later.
850 /BitsPerComponent 2 copy knownoget { def } { pop } ifelse
851 /Interpolate 2 copy knownoget { def } { pop } ifelse
854 /makeimagekeys { % <resdict> makeimagekeys <imagemask>
855 % newdict is currentdict
856 % Assumes Width, Height, BPC, Interpolate already copied.
858 /ImageMatrix Width 0 0
859 % Handle 0-height images specially.
860 Height dup 0 eq { pop 1 } if neg 0 1 index neg
862 dup /ImageMask knownoget dup { and } if {
864 % Decode is required for the PostScript image operators.
865 % AI8 writes bogus decode array [0 1 0 0 0 0 0 0]
866 /Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def
867 % BitsPerComponent is optional for masks.
868 /BitsPerComponent 2 copy known { pop } { 1 def } ifelse
872 dup /ColorSpace oget resolvecolorspace /ColorSpace exch def
873 % Decode is required for the PostScript image operators.
874 /Decode 2 copy knownoget not {
875 ColorSpace //defaultdecodedict
876 ColorSpace dup type /arraytype eq { 0 get } if get exec
880 % Even though we're going to read data,
881 % pass false to resolvestream so that
882 % it doesn't try to use Length (which may not be present).
883 exch false resolvestream /DataSource exch def
887 checkaltimage dup length 6 add dict
888 1 index /SMask knownoget { 1 index exch /SMask exch put } if
889 1 index /Mask knownoget { 1 index exch /Mask exch put } if
890 makeimagedict doimagesmask
892 /makemaskimage { % <datasource> <imagemask> <Mask> makemaskimage
893 % <datasource> <imagemask>, updates currentdict =
895 dup type /arraytype eq {
897 % Check that every element of the Mask is an integer.
899 type /integertype ne or
901 (\n **** Warning: Some elements of Mask array are not integers.\n)
903 [ exch { 0.5 add cvi } forall ] % following AR4, 5, 6 implementation
905 % Check elements of array are within 0::(2**BitsPerComponent)-1
906 % This is a PostScript error, but AR ignores Mask in that case
907 2 BitsPerComponent exp cvi 1 sub //false 2 index {
908 % stack: max_value result_bool value
909 dup 0 lt exch 3 index gt or or
911 (\n **** Warning: Some elements of Mask array are out of range.\n)
913 pop /ImageType 1 def % revert to non-masked image
918 % Mask is a stream, another Image XObject.
919 % Stack: datasource imagemask(false) maskstreamdict
920 PDFfile fileposition exch
921 dup length dict makeimagedict pop
922 % In order to prevent the two data sources from being
923 % aliased, we need to make at least one a reusable stream.
924 % We pick the mask, since it's smaller (in case we need to
925 % read all its data now).
926 % Stack: datasource imagemask(false) savedpos
927 % maskdict is currentdict
928 /DataSource DataSource mark
931 .dicttomark .reusablestreamdecode def
932 PDFfile exch setfileposition
933 currentdict end currentdict end
936 /InterleaveType 3 def
939 /ColorSpace DataDict /ColorSpace get def
942 /doimagesmask { % <imagemask> doimagesmask -
943 PDFusingtransparency { currentdict /SMask knownoget } { false } ifelse {
944 .begintransparencymaskimage
945 PDFfile fileposition exch
948 1 .setopacityalpha 1 .setshapealpha
949 0 .inittransparencymask 1 .inittransparencymask
950 /Compatible .setblendmode
953 PDFfile exch setfileposition
954 0 .endtransparencymask
955 << /Subtype /Group /Isolated true >> 0 0 1 1 .begintransparencygroup
957 .endtransparencygroup
962 /doimage { % <imagemask> doimage -
963 % imagedict is currentdict, gets popped from dstack
965 PDFusingtransparency {
966 currentdict /SMask knownoget
972 currentdict /Mask knownoget {
976 % Stack: datasource imagemask
977 % image and imagemask can be redefined in gs_init.ps to tweak interpolation
978 % after device-specific files are run. Don't bind them here.
979 { currentdict end setfillstate /imagemask }
980 { ColorSpace setgcolorspace currentdict end setfillblend /image }
984 $error /errorname get dup /ioerror eq {
985 pop (\n **** Warning: File has insufficient data for an image.\n)
988 (\n **** Warning: File encountered ')
989 exch 40 string cvs concatstrings
990 (' error while processing an image.\n) concatstrings
994 % Close the input stream, unless it is PDFfile or
996 dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
999 /.paintform { % <formdict> <resdict> <stream> .paintform -
1000 3 -1 roll dup /Group known PDFusingtransparency and {
1003 pop pdfopdict .pdfruncontext
1008 % Adobe 2nd edition of the PDF 1.3 spec makes /FormType
1009 % and /Matrix keys optional. Cope with the missing keys.
1011 currentdict /FormType known not { /FormType 1 } if
1012 currentdict /Matrix known not { /Matrix { 1 0 0 1 0 0 } cvlit } if
1013 currentdict end { oforce } forall
1015 dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
1016 3 index false /resolvestream cvx
1018 ] cvx /PaintProc exch put
1019 % Adjust pdfemptycount since we have an extra dictionary on the stack
1021 /pdfemptycount where pop count 2 sub /pdfemptycount exch put
1022 q execform Q % gsave / grestore around the Form
1023 % Restore pdfemptycount
1024 /pdfemptycount where pop exch /pdfemptycount exch put
1027 /_dops_save 1 array def
1032 //_dops_save 0 save put
1033 true resolvestream cvx exec
1034 //_dops_save 0 get restore
1040 currentdict /_dops_save undef
1045 PDFfile fileposition exch
1046 dup Page /XObject rget {
1047 exch pop dup /Subtype get xobjectprocs exch get
1048 % Don't leave extra objects on the stack while executing
1049 % the definition of the form.
1052 % This should cause an error, but Acrobat Reader can
1053 % continue, so we do too.
1054 ( **** Undefined XObject resource: )
1055 exch =string cvs concatstrings (\n) concatstrings
1058 PDFfile exch setfileposition
1062 % ---------------- In-line images ---------------- %
1064 % Undo the abbreviations in an in-line image dictionary.
1065 % Note that we must look inside array values.
1066 % /I is context-dependent.
1067 /unabbrevkeydict mark
1068 /BPC /BitsPerComponent /CS /ColorSpace /D /Decode /DP /DecodeParms
1069 /F /Filter /H /Height /I /Interpolate /IM /ImageMask /W /Width
1070 .dicttomark readonly def
1071 /unabbrevvaluedict mark
1072 /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CC /CalCMYK
1073 /CCF /CCITTFaxDecode /CG /CalGray /CR /CalRGB
1074 /DCT /DCTDecode /CMYK /DeviceCMYK /Fl /FlateDecode
1075 /G /DeviceGray /RGB /DeviceRGB
1076 /I /Indexed /LZW /LZWDecode /RL /RunLengthDecode
1077 .dicttomark readonly def
1078 /unabbrevtypedict mark
1080 //unabbrevvaluedict 1 index .knownget { exch pop } if
1083 dup 0 1 2 index length 1 sub {
1084 2 copy get unabbrevvalue put dup
1087 .dicttomark readonly def
1088 /unabbrevvalue { % <obj> unabbrevvalue <obj'>
1089 oforce //unabbrevtypedict 1 index type .knownget { exec } if
1095 counttomark 2 idiv dup 7 add dict begin {
1096 exch //unabbrevkeydict 1 index .knownget { exch pop } if
1097 exch unabbrevvalue def
1099 /IDFlag true def % flag for stream processing.
1101 currentdict makeimagekeys doimage
1102 % The Adobe documentation says that the data following ID
1103 % consists of "lines", and some PDF files (specifically, some files
1104 % produced by PCL2PDF from Visual Software) contain garbage bytes
1105 % between the last byte of valid data and an EOL.
1106 % Some files (PDFOUT v3.8d by GenText) have EI immediately following
1107 % the stream. Some have no EOL and garbage bytes.
1108 % Therefore, we skip all bytes before EI or EOL
1110 { PDFsource read not { //true exit } if
1111 dup 10 eq 1 index 13 eq or
1112 { pop PDFsource token pop /EI ne exit
1115 exch 69 eq 1 index 73 eq and { //false exit } if % 'EI'
1119 { /ID cvx /syntaxerror signalerror
1125 % ================================ Text ================================ %
1149 % ============================== Annotations ============================== %
1153 % Get and normalize an annotation's rectangle.
1154 /annotrect { % <annot> annotrect <x> <y> <w> <h>
1156 exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if
1157 exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if
1160 % Set an annotation color.
1161 /annotsetcolor { % <annot> annotsetcolor -
1162 /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse
1165 % Draw the border. Currently, we ignore requests for beveling, and we
1166 % don't round the corners of rectangles.
1167 /strokeborder { % <annot> <width> <dash> strokeborder -
1168 1 index 0 ne { % do not draw if border width is 0
1170 2 index annotsetcolor
1171 0 setdash dup setlinewidth
1173 2 { 4 index sub 4 1 roll } repeat
1174 2 { 4 index 0.5 mul add 4 1 roll } repeat
1182 % Draw an annotation border.
1183 /drawborder { % <annot> drawborder -
1186 dup /W knownoget not { 1 } if
1187 [] 2 index /S knownoget {
1188 /D eq { 2 index /D knownoget not { [3] } if exch pop } if
1189 } if 3 -1 roll pop strokeborder
1191 dup /Border knownoget {
1193 exch dup length 3 gt { 3 get } { pop [] } ifelse
1203 % The PDF annotation F (flags) integer is bit encoded.
1204 % Bit 1 (LSB) Invisible: 1 --> Do not display if no handler.
1205 % Note: We have no handlers but we ignore this bit.
1206 % Bit 2 Hidden: 1 --> Do not display. We will not display if this bit is set.
1207 % Bit 3 Print: 1 --> Display if printing. We will display if this bit set
1208 % (and not hidden) and Printed is true
1209 % Bit 4 NoZoom: 1 --> Do not zoom annotation even if image is zoomed.
1210 % Bit 5 NoRotate: 1 --> Do not rotate annotation even if image is rotated.
1211 % Bit 6 NoView: 0 --> Display if this is a 'viewer'. We will display
1212 % if this bit is not set (and not hidden) and Printed is false
1213 % Bit 7 Read Only - 1 --> No interaction. We ignore this bit
1215 /annotvisible { % <annot> annotvisible <visible>
1216 /F knownoget not { 0 } if % Get flag value
1217 dup 2 and 0 eq % Check hidden flag
1218 exch dup 4 and 0 ne Printed and % Check print flag
1219 exch 32 and 0 eq Printed not and % Check noview flag
1220 or % Combine print and view
1221 and % Combine with 'hidden' flag test
1224 /drawwidget { % <scalefactor> <annot> drawwidget -
1228 % stack: scale annot appearance false key
1229 dup 3 index exch known {
1234 % stack: scale annot appearance key true
1235 % stack: scale annot appearance false
1239 % Acrobat Distiller produces files in which this Form
1240 % XObject lacks Type and Subtype keys. This is illegal,
1241 % but Acrobat Reader accepts it. The only way we can
1242 % tell whether this is a Form or a set of sub-appearances
1243 % is by testing for the stream Length key.
1245 % If this is a form then simply use it
1248 1 index /AS knownoget not {
1249 % If we do not have AS then use any appearance
1250 { exch pop oforce exit } forall true
1252 % Stack: annot Ndict AS
1253 % Get the specified appearance. If no appearance, then
1254 % display nothing - set stack = false.
1259 exch pop % discard useless AP dictionary
1262 % Stack: scale annot appearance true
1263 % Stack: scale annot false
1266 % Initialize graphic following "7.4.4 Appearance Streams"
1267 q graphicsbeginpage textbeginpage
1268 1 index annotrect pop pop translate
1269 2 index dup scale % Apply scale factor
1275 % For stamp object we have to determine the size of the output rectangle
1276 % and the size of the BBox for the stamp image. From these we calculate
1277 % a scale factor for drawing the stamp.
1278 /calcstampscale { % <annot> calcstampscale scale
1280 dup annotrect 4 -2 roll pop pop % get width height size in user space
1281 3 -1 roll /AP knownoget {
1283 dup /Matrix knownoget {
1284 % transform /Annot /Rect xwidth to Form space
1285 4 -2 roll 3 -1 roll dtransform 3 -1 roll
1288 exch pop % discard y height
1289 aload pop pop exch pop sub % BBox width
1291 ( **** Warning: /BBox has zero width which is not allowed.\n)
1293 pop pop 1 1 % 0 width -- revert to unity scaling
1295 div % scale x widths
1296 dup 0 lt { neg } if % get magnitude
1298 pop pop 1 % default to unity scaling
1299 } ifelse % if we have /BBox
1302 } ifelse % if we have /N
1305 } ifelse % if we have /AP
1307 ( **** Warning: /Annot dict is missing required /Rect entry.\n)
1313 /drawlink { % <annot> drawlink -
1314 dup drawborder dup calcstampscale exch drawwidget
1317 % Draw an annotation.
1318 /drawannottypes mark
1319 /Link { drawlink } bind
1320 .dicttomark readonly def
1321 /drawannot { % <annot> drawannot -
1324 dup dup /Subtype get //drawannottypes exch .knownget {
1327 dup calcstampscale exch drawwidget % Use drawwidget for everything else
1328 } ifelse % type known
1330 } if pop % annotvisible
1332 currentdict /drawannottypes undef
1335 end % GS_PDF_ProcSet