]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/pdf_draw.ps
merge
[plan9front.git] / sys / lib / ghostscript / pdf_draw.ps
1 %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
2
3 % This software is provided AS-IS with no warranty, either express or
4 % implied.
5
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.
9
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.
15
16 % $Id: pdf_draw.ps,v 1.98 2005/10/05 14:37:59 ray Exp $
17 % pdf_draw.ps
18 % PDF drawing operations (graphics, text, and images).
19
20 /.setlanguagelevel where { pop 2 .setlanguagelevel } if
21 .currentglobal true .setglobal
22 /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
23 GS_PDF_ProcSet begin
24 pdfdict begin
25
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
29
30 % ================================ Graphics ================================ %
31
32 % ---------------- Functions ---------------- %
33
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.
38
39 /fnrdict mark
40   0 { .resolvefn0 }
41   2 { .resolvefn2 }
42   3 { .resolvefn3 }
43   4 { .resolvefn4 }
44 .dicttomark readonly def
45
46 /.resolvefn0 {
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
54   
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
62   7 add 8 idiv string
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
67 } bdef
68
69 /.resolvefn2 {
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
74 } bdef
75
76 /.resolvefn3 {
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 {
81     oforce .resolvefn
82   } forall
83   counttomark -1 roll astore exch pop put
84 } bdef
85
86 /.resolvefn4 {
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
91   exch dup token not {
92     () /rangecheck cvx signalerror
93   } if
94   exch token {
95     /rangecheck cvx signalerror
96   } if
97                 % Use .bind to avoid idiom recognition.
98   .bind
99   1 index /Function 3 -1 roll put
100   exch PDFfile exch setfileposition
101 } bdef
102
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
108 } bdef
109
110 /resolvefunction {      % <fndict> resolvefunction <function>
111   .resolvefn
112   PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Function: ) print dup === flush } if } if
113 } bdef
114
115 /resolvefnproc {        % <fndict> resolvefnproc <proc>
116   resolvefunction .buildfunction
117 } bdef
118
119 /resolveidfnproc {      % <fndict> resolveidfnproc <proc>
120   dup /Identity eq { pop { } } { resolvefnproc } ifelse
121 } bdef
122
123 /resolvedefaultfnproc { % <fndict> <default> resolved'fnproc <proc>
124   1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
125 } bdef
126
127 % ---------------- Shadings ---------------- %
128
129 /shrdict mark
130   /ColorSpace {
131     resolvecolorspace
132   }
133   /Function {
134     dup type /dicttype eq {
135       resolvefunction
136     } {
137       [ exch { oforce resolvefunction } forall ]
138     } ifelse
139   }
140 .dicttomark readonly def
141
142 /resolveshading {       % <shadingstream> resolveshading <shading>
143   PDFfile fileposition exch
144   mark exch {
145     oforce //shrdict 2 index .knownget { exec } if
146   } forall .dicttomark
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
153 } bdef
154 /resolvesh {            % <shname> resolveshading <shading>
155   Page /Shading rget {
156     resolveshading
157   } {
158     null
159   }ifelse
160 } bdef
161
162 % ---------------- Halftones ---------------- %
163
164 /spotfunctions mark
165   /Round {
166     abs exch abs 2 copy add 1 le {
167       dup mul exch dup mul add 1 exch sub 
168     } {
169       1 sub dup mul exch 1 sub dup mul add 1 sub
170     } ifelse
171   }
172   /Diamond {
173     abs exch abs 2 copy add .75 le {
174       dup mul exch dup mul add 1 exch sub
175     } {
176       2 copy add 1.23 le {
177         .85 mul add 1 exch sub
178       } {
179         1 sub dup mul exch 1 sub dup mul add 1 sub
180       } ifelse
181     } ifelse
182   }
183   /Ellipse {
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
186     } {
187       dup 1 gt {
188         pop 1 exch sub dup mul exch 1 exch sub
189         .75 div dup mul add 4 div 1 sub
190       } {
191         .5 exch sub exch pop exch pop
192       } ifelse
193     } ifelse
194   }
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 }
201   /LineX { pop }
202   /LineY { exch pop }
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 }
212   /InvertedDouble {
213     exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
214   }
215 .dicttomark readonly def
216
217 /htrdict mark
218   1 { .resolveht1 }
219   5 { .resolveht5 }
220         % We don't support types 6, 10, or 16 yet.
221 .dicttomark readonly def
222
223 /.resolveht1 {
224   mark exch {
225     oforce
226     1 index /SpotFunction eq {
227       dup type /nametype eq
228         { //spotfunctions exch get } { resolvefnproc }
229       ifelse
230     } {
231       1 index /TransferFunction eq {
232         resolveidfnproc
233       } if
234     } ifelse
235   } forall .dicttomark
236 } bdef
237
238 /.resolveht5 {
239   mark exch {
240     oforce dup type /dicttype eq { resolvehalftone } if
241   } forall .dicttomark
242 } bdef
243
244 /resolvehalftone {      % <dict> resolvehalftone <halftone>
245   dup /HalftoneType get
246   dup //htrdict exch .knownget {
247     exch pop exec
248   } {
249     (\n\n   **** Unsupported HalftoneType ) pdfformaterror
250     =string cvs pdfformaterror (. ***\n\n) pdfformaterror
251     /resolvehalftone cvx /unregistered signalerror
252   } ifelse
253 } bdef
254
255 % ---------------- Graphics state management ---------------- %
256
257 /cmmatrix matrix def
258 drawopdict begin
259                         % Graphics state stack
260   /q { q } def
261   /Q { Q } def
262                         % Graphics state setting
263   /cm { { //false upath } stopped {
264           pop   % discard 'false' (upath failed, probably no currentpoint).
265           //cmmatrix astore concat
266         } {
267           % update the CTM, then uappend.
268           7 1 roll //cmmatrix astore concat
269           newpath { mark exch uappend } stopped 
270           cleartomark
271         } ifelse
272       } def
273   /i { 1 .min setflat } def
274   /J /setlinecap load def
275   /d /setdash load def
276   /j /setlinejoin load def
277   /w /setlinewidth load def
278   /M { 1 .max setmiterlimit } bdef
279   /gs { gs } def
280 end
281
282 % Each entry in this dictionary is
283 %       <gsres> <value> -proc- <gsres>
284 /gsbg {
285   /BGDefault load resolvedefaultfnproc setblackgeneration
286 } bdef
287 /gsucr {
288   /UCRDefault load resolvedefaultfnproc setundercolorremoval
289 } bdef
290 /gstr {
291   dup type /arraytype eq {
292     { oforce /TRDefault load resolvedefaultfnproc } forall
293     setcolortransfer
294   } {
295     /TRDefault load resolvedefaultfnproc settransfer
296   } ifelse
297 } bdef
298 /gsparamdict mark
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 }
308   /HT {
309     dup /Default eq {
310       pop .setdefaulthalftone
311     } {
312         %****** DOESN'T IMPLEMENT THE STREAM CASE YET ******
313       resolvehalftone sethalftone
314     } ifelse
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)
318     dup /TR2 .knownget {
319       dup /Default eq { oforce gsparamdict /TR2 get exec } { pop } ifelse
320     } {
321       dup /TR .knownget {
322         /dup /Default eq { oforce gsparamdict /TR get exec } { pop } ifelse
323       } if
324     } ifelse
325   }
326   /HTP {
327         % HTP may be present even if this isn't a DPS interpreter.
328     /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
329   }
330         % PDF 1.3
331   /Font { aload pop Tf }
332   /LW { setlinewidth }
333   /LC { setlinecap }
334   /LJ { setlinejoin }
335   /ML { 1 .max setmiterlimit }
336   /D { aload pop setdash }
337   /RI { ri }
338   /op { op }
339   /OPM { OPM }
340   /BG2 { gsbg }
341   /UCR2 { gsucr }
342   /TR2 { gstr }
343   /FL { 1 .min setflat }
344   /SM {
345         % SM may be present even if this is only a Level 2 interpreter.
346     /setsmoothness where { pop setsmoothness } { pop } ifelse
347   }
348         % PDF 1.4
349         % All of these require the "transparency" feature in the interpreter.
350   /ca { ca }
351   /CA { CA }
352   /SMask { gssmask }
353   /AIS { AIS }
354   /BM { BM }
355   /TK { TK }
356 .dicttomark readonly def
357 /gs {                   % <gsres> gs -
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.
361     dup {
362       oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
363     } forall pop
364   } if
365 } bdef
366
367 % ------ Transparency support ------ %
368
369 /gssmask {
370   dup /None eq PDFusingtransparency not or {
371     pop null
372   } {
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
378     dup /BC knownoget {
379       dup /Background exch 4 2 roll
380       gsave
381         1 index /G oget /Group oget /CS knownoget {
382           csresolve dup setgcolorspace csput
383         } if
384         aload pop setcolor [ currentgray ]
385       grestore
386       /GrayBackground exch 3 2 roll
387     } if
388     dup /TR knownoget {
389       resolveidfnproc /TransferFunction exch 3 2 roll
390     } if    
391     dup /G oget dup /BBox oget /BBox exch 4 2 roll
392     /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
393     pop .dicttomark
394   } ifelse SMask
395 } bdef
396
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
400         % the color space.
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
410   } stopped {
411     .discardtransparencymask stop
412   } if
413   PDFfile exch setfileposition 
414   setcolorspace
415 } bdef
416 % Paint a Form+Group XObject, either for a transparency mask or for a Do.
417 /.execgroup {           % <resdict> <stream> .execgroup -
418   gsave //nodict begin
419   null SMask
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
425   end grestore
426 } bdef
427
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
433   pop .dicttomark
434                 % Stack: bbox paramdict
435   exch aload pop
436   .begintransparencygroup
437 } bdef
438
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
444   .beginformgroup {
445     .execgroup
446   } stopped {
447     .discardtransparencygroup stop
448   } if .endtransparencygroup
449 } bdef
450
451 % Make an ImageType 103 (soft-masked) image.
452 /makesoftmaskimage {    % <datasource> <imagemask> <SMask> makesoftmaskimage
453                         %   <datasource> <imagemask>, updates currentdict =
454                         %   imagedict
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
468     /Intent 1
469     /AsyncRead true
470   .dicttomark .reusablestreamdecode def
471   PDFfile exch setfileposition
472   currentdict end currentdict end
473   5 dict begin
474   /ImageType 103 def
475   /DataDict exch def
476   dup /InterleaveType 3 put
477   DataDict /Matte knownoget {
478     /Matte exch def
479   } if
480   AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
481   /ColorSpace DataDict /ColorSpace get def
482 } bdef
483
484 % ---------------- Color setting ---------------- %
485
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
489
490 % The keys here are resolved (PostScript, not PDF) color space names.
491 /csncompdict mark
492   /DeviceGray { pop 1 }
493   /DeviceRGB { pop 3 }
494   /DeviceCMYK { pop 4 }
495   /CIEBasedA { pop 1 }
496   /CIEBasedABC { pop 3 }
497   /ICCBased { 1 oget /N oget }
498   /Separation { pop 1 }
499   /DeviceN { 1 oget length }
500 .dicttomark readonly def
501
502 /csrdict mark
503   /DeviceGray { }
504   /DeviceRGB { }
505   /DeviceCMYK { }
506   /CalGray {
507     1 oget 6 dict begin
508     dup /Gamma knownoget {
509       /exp load 2 packedarray cvx /DecodeA exch def
510     } if
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
516     } if
517     /PDFColorSpace exch def [ /CIEBasedA currentdict end ]
518   }
519   /CalRGB {
520     1 oget 6 dict begin
521     dup /Gamma knownoget {
522       [ exch { /exp load 2 packedarray cvx } forall
523       ] /DecodeABC exch def
524     } if
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 ]
529   }
530   /CalCMYK {
531     pop /DeviceCMYK             % not defined by Adobe
532   }
533   /Lab {
534     1 oget 6 dict begin
535     dup /Range knownoget not { [-100 100 -100 100] } if
536     [0 100 null null null null] dup 2 4 -1 roll putinterval
537     /RangeABC exch def
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)
543       pdfformaterror
544       /WhitePoint [0.9505 1 1.089] def
545     } ifelse
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 }
548     /DecodeLMN [
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
553     ] def pop
554     /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
555   }
556   /ICCBased {
557     dup 1 get type /dicttype ne {       % don't resolve more than once
558     PDFfile fileposition exch
559     dup dup 1 oget
560     mark exch { oforce } forall .dicttomark
561     dup dup true resolvestream
562     /ReusableStreamDecode filter /DataSource exch put
563     1 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
570     ifelse
571     } if
572   } bind
573   /Separation {
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
578     4 array astore
579   }
580   /DeviceN {
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
586     4 array astore
587   }
588   /Indexed {
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
600         } for ] def
601         /RangeABC //01_3 def
602         currentdict end /CIEBasedABC exch 2 array astore
603       } if
604     } if
605     3 1 roll
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
612         1 index 1 add
613                 % Stack: filepos /Indexed basespace hival lookupstream len
614         3 index
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
620     }
621     if 4 array astore
622                 % Replace the PDFColorSpace with the Indexed space if needed.
623     dup 1 get
624     dup type /arraytype eq {
625       dup length 2 ge {
626         dup 1 get type /dicttype eq {
627           dup 1 get /PDFColorSpace known {
628             dup 1 get /PDFColorSpace 3 index put
629           } if
630         } if
631       } if
632     } if pop
633   }
634   /Pattern {
635     dup type /nametype ne {
636       dup length 1 gt {
637         1 oget resolvecolorspace
638         /Pattern exch 2 array astore
639       } if
640     } if
641   }
642 .dicttomark readonly def
643
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
648 } bdef
649
650 /csnames mark
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
659       resolvecolorspace
660     } if
661   } {
662     dup Page /ColorSpace rget {
663       exch pop resolvecolorspace
664     } {
665       //csnames 1 index known not { /undefined cvx signalerror } if
666     } ifelse
667   } ifelse
668 } bdef
669 /resolvecolorspace {    % <cspace> resolvecolorspace <cspace'>
670   dup dup type /arraytype eq { 0 get } if
671   //csrdict exch .knownget
672   {
673     exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
674   } {
675     dup type /nametype eq { csresolve } { csset exch pop } ifelse
676   } ifelse
677 } bdef
678
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 }
687   if
688   dup type /dicttype eq {
689                 % Check the PaintType, if any (shading patterns don't
690                 % have one).
691     dup /PaintType knownoget { 2 eq } { false } ifelse
692   } {
693     .pdfcount 1 gt
694   } ifelse
695 } bdef
696
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
704   q
705   null sc1 null SC1
706
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
712
713   Q
714   PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%End PaintProc) print dup === flush } if } if
715   PDFfile exch setfileposition
716 } bdef
717
718 /resolvepattern {       % <patternstreamdict> resolvepattern <patterndict>
719                 % Don't do the resolvestream now: just capture the data
720                 % from the file if necessary.
721   dup length dict copy
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
727
728     dup 65535 le {
729       string readstring pop
730     } {
731       () /SubFileDecode filter /ReusableStreamDecode filter
732     } ifelse
733                 % Stack: dict savepos file string
734     3 1 roll exch setfileposition
735     1 index /File 3 -1 roll put
736     dup /FilePosition undef
737   } if
738   dup /Shading knownoget {
739     resolveshading 1 index /Shading 3 -1 roll put
740   } if
741   dup /PaintProc [
742                 % Bind the resource dictionary into the PaintProc.
743     2 index /Resources knownoget { oforce } { 0 dict } ifelse
744     /.pdfpaintproc cvx
745   ] cvx put
746   PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Pattern: ) print dup === flush } if } if
747 } bdef
748
749 drawopdict begin
750   /g { /DeviceGray cssubst { cs sc1 } { g } ifelse } bdef
751   /rg { /DeviceRGB cssubst { cs sc* } { rg } ifelse } bdef
752   /k { k } bdef
753   /cs { csresolve cs } bdef
754   /sc { scresolve { sc* } { sc1 } ifelse } bdef
755   /scn /sc load def
756   /G { /DeviceGray cssubst { CS SC1 } { G } ifelse } bdef
757   /RG { /DeviceRGB cssubst { CS SC* } { RG } ifelse } bdef
758   /K { K } bdef
759   /CS { csresolve CS } bdef
760   /ri { ri } bdef
761   /SC { scresolve { SC* } { SC1 } ifelse } bdef
762   /SCN /SC load def
763 end
764
765 % ---------------- Paths ---------------- %
766
767 drawopdict begin
768                         % Path construction
769   /m /moveto load def
770   /l /lineto load def
771   /c /curveto load def
772   /v { currentpoint 6 2 roll curveto } def
773   /y { 2 copy curveto } def
774   /re {
775    4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
776    closepath
777   } def
778   /h /closepath load def
779                         % Path painting and clipping
780   /n { n } def
781   /S { S } def
782   /s { s } def
783   /f { f } def
784   /f* { f* } def
785   /B { B } def
786   /b { b } def
787   /B* { B* } def
788   /b* { b* } def
789   /W { W } def
790   /W* { W* } def
791   /sh { setfillstate resolvesh shfill } def
792 end
793
794 % ---------------- XObjects ---------------- %
795
796 /xobjectprocs mark              % <dict> -proc- -
797   /Image { DoImage }
798   /Form { DoForm }
799   /PS { DoPS }
800 .dicttomark readonly def
801
802 % Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
803 % color space names.
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
810   /ICCBased {
811      1 oget dup /Range knownoget {
812        exch pop
813      }{
814        /N get [ exch {0 1} repeat ] readonly
815      } ifelse
816   } bind
817   /Separation { pop //01_1 } bind
818   /DeviceN {
819     1 oget length [ exch {0 1} repeat ] readonly
820   } bind
821   /Indexed {
822     pop [ 0 1 BitsPerComponent bitshift 1 sub ]
823   } bind
824 .dicttomark readonly def
825
826 /checkaltimage {        % <resdict> checkaltimage <resdict[']>
827   Printed {
828     dup /Alternates knownoget {
829       {
830         dup /DefaultForPrinting knownoget {
831           {
832             /Image oget exch pop exit
833           } {
834             pop
835           } ifelse
836         } {
837           pop
838         } ifelse
839       } forall
840     } if
841   } if
842 } bdef
843
844 /makeimagedict {        % <resdict> <newdict> makeimagedict <imagemask>
845                         % On return, newdict' is currentdict
846   begin
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
852   makeimagekeys
853 } bdef
854 /makeimagekeys {        % <resdict> makeimagekeys <imagemask>
855                 % newdict is currentdict
856                 % Assumes Width, Height, BPC, Interpolate already copied.
857   /ImageType 1 def
858   /ImageMatrix Width 0 0
859                 % Handle 0-height images specially.
860     Height dup 0 eq { pop 1 } if neg 0 1 index neg
861     6 array astore def
862   dup /ImageMask knownoget dup { and } if {
863                 % Image mask
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
869     true
870   } {
871                 % Opaque image
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
877     } if def
878     false
879   } ifelse
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
884 } bdef
885
886 /DoImage {
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
891 } bdef
892 /makemaskimage {        % <datasource> <imagemask> <Mask> makemaskimage
893                         %   <datasource> <imagemask>, updates currentdict =
894                         %   imagedict
895   dup type /arraytype eq {
896     /ImageType 4 def
897                 % Check that every element of the Mask is an integer.
898     //false 1 index {
899       type /integertype ne or
900     } forall {
901       (\n   **** Warning: Some elements of Mask array are not integers.\n)
902       pdfformaterror
903       [ exch { 0.5 add cvi } forall ]  % following AR4, 5, 6 implementation
904     } if
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
910     } forall exch pop {
911       (\n   **** Warning: Some elements of Mask array are out of range.\n)
912       pdfformaterror
913       pop /ImageType 1 def              % revert to non-masked image
914     } {
915       /MaskColor exch def
916     } ifelse
917   } {
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
929       /Intent 1
930       /AsyncRead true
931     .dicttomark .reusablestreamdecode def
932     PDFfile exch setfileposition
933     currentdict end currentdict end
934     5 dict begin
935     /ImageType 3 def
936     /InterleaveType 3 def
937     /DataDict exch def
938     /MaskDict exch def
939     /ColorSpace DataDict /ColorSpace get def
940   } ifelse
941 } bdef
942 /doimagesmask { % <imagemask> doimagesmask -
943   PDFusingtransparency { currentdict /SMask knownoget } { false } ifelse {
944     .begintransparencymaskimage
945     PDFfile fileposition exch
946     gsave //nodict begin
947     null /SoftMask gput
948     1 .setopacityalpha 1 .setshapealpha
949     0 .inittransparencymask 1 .inittransparencymask
950     /Compatible .setblendmode
951     DoImage
952     end grestore
953     PDFfile exch setfileposition
954     0 .endtransparencymask
955     << /Subtype /Group /Isolated true >> 0 0 1 1 .begintransparencygroup
956     doimage
957     .endtransparencygroup
958   } {
959     doimage
960   } ifelse
961 } bdef
962 /doimage {      % <imagemask> doimage -
963                 % imagedict is currentdict, gets popped from dstack
964   DataSource exch
965   PDFusingtransparency {
966     currentdict /SMask knownoget
967   } {
968     false
969   } ifelse {
970     makesoftmaskimage
971   } {
972     currentdict /Mask knownoget {
973       makemaskimage
974     } if
975   } ifelse
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 }
981   ifelse
982   .systemvar stopped {
983     pop
984     $error /errorname get dup /ioerror eq {
985       pop (\n   **** Warning: File has insufficient data for an image.\n)
986       pdfformaterror
987     } {
988       (\n   **** Warning: File encountered ')
989       exch 40 string cvs concatstrings
990       (' error while processing an image.\n) concatstrings
991       pdfformaterror
992     } ifelse
993   } if
994                 % Close the input stream, unless it is PDFfile or
995                 % PDFsource.
996   dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
997 } bdef
998
999 /.paintform {   % <formdict> <resdict> <stream> .paintform -
1000   3 -1 roll dup /Group known PDFusingtransparency and {
1001     .paintgroupform
1002   } {
1003     pop pdfopdict .pdfruncontext
1004   } ifelse
1005 } bdef
1006
1007 /DoForm {
1008     % Adobe 2nd edition of the PDF 1.3 spec makes /FormType
1009     % and /Matrix keys optional. Cope with the missing keys.
1010   begin <<
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
1014   >>
1015   dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
1016   3 index false /resolvestream cvx
1017   /.paintform cvx
1018   ] cvx /PaintProc exch put
1019     % Adjust pdfemptycount since we have an extra dictionary on the stack
1020   pdfemptycount exch
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
1025 } bdef
1026
1027 /_dops_save 1 array def
1028
1029 /DoPS {
1030   DOPS
1031    {
1032      //_dops_save 0 save put
1033      true resolvestream cvx exec
1034      //_dops_save 0 get restore
1035    }
1036    { pop }
1037   ifelse
1038 } bdef
1039
1040 currentdict /_dops_save undef
1041
1042 drawopdict begin
1043   /Do {
1044     setfillblend
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.
1050       3 -1 roll 2 .execn
1051     } {
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
1056       pdfformaterror
1057     } ifelse
1058     PDFfile exch setfileposition
1059   } bdef
1060 end
1061
1062 % ---------------- In-line images ---------------- %
1063
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
1079   /nametype {
1080     //unabbrevvaluedict 1 index .knownget { exch pop } if
1081   }
1082   /arraytype {
1083     dup 0 1 2 index length 1 sub {
1084       2 copy get unabbrevvalue put dup
1085     } for pop
1086   }
1087 .dicttomark readonly def
1088 /unabbrevvalue {        % <obj> unabbrevvalue <obj'>
1089   oforce //unabbrevtypedict 1 index type .knownget { exec } if
1090 } bdef
1091
1092 drawopdict begin
1093   /BI { mark } bdef
1094   /ID {
1095     counttomark 2 idiv dup 7 add dict begin {
1096       exch //unabbrevkeydict 1 index .knownget { exch pop } if
1097       exch unabbrevvalue def
1098     } repeat pop
1099     /IDFlag true def  % flag for stream processing.
1100     /File PDFsource def
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 
1109     0
1110       { PDFsource read not { //true exit } if
1111         dup 10 eq 1 index 13 eq or
1112           { pop PDFsource token pop /EI ne exit
1113           }
1114         if
1115         exch 69 eq 1 index 73 eq and { //false exit } if  % 'EI'
1116       }
1117     loop
1118     exch pop
1119       { /ID cvx /syntaxerror signalerror
1120       }
1121     if
1122   } bdef
1123 end
1124
1125 % ================================ Text ================================ %
1126
1127 drawopdict begin
1128                         % Text control
1129   /BT { BT } def
1130   /ET { ET } def
1131   /Tc { Tc } def
1132   /TL { TL } def
1133   /Tr { Tr } def
1134   /Ts { Ts } def
1135   /Tw { Tw } def
1136   /Tz { Tz } def
1137                         % Text positioning
1138   /Td { Td } def
1139   /TD { TD } def
1140   /Tm { Tm } def
1141   /T* { T* } def
1142                         % Text painting
1143   /Tj { Tj } def
1144   /' { ' } def
1145   /" { " } def
1146   /TJ { TJ } def
1147 end
1148
1149 % ============================== Annotations ============================== %
1150
1151
1152
1153 % Get and normalize an annotation's rectangle.
1154 /annotrect {            % <annot> annotrect <x> <y> <w> <h>
1155   /Rect get aload pop
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
1158 } bdef
1159
1160 % Set an annotation color.
1161 /annotsetcolor {        % <annot> annotsetcolor -
1162   /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse
1163 } bdef
1164
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
1169     gsave
1170     2 index annotsetcolor
1171     0 setdash dup setlinewidth
1172     exch annotrect
1173     2 { 4 index sub 4 1 roll } repeat
1174     2 { 4 index 0.5 mul add 4 1 roll } repeat
1175     rectstroke pop
1176     grestore
1177   } {
1178     pop pop pop
1179   } ifelse
1180 } bdef
1181
1182 % Draw an annotation border.
1183 /drawborder {           % <annot> drawborder -
1184   gsave
1185   dup /BS knownoget {
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
1190   } {
1191     dup /Border knownoget {
1192       dup 2 get
1193       exch dup length 3 gt { 3 get } { pop [] } ifelse
1194       strokeborder
1195     } {
1196       1 [] strokeborder
1197     } ifelse
1198   } ifelse
1199   grestore
1200 } bdef
1201
1202 %
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
1214 %
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
1222 } bdef
1223
1224 /drawwidget {                   % <scalefactor> <annot> drawwidget -
1225   dup /AP knownoget {
1226     false
1227     [/N /R /D] {
1228         % stack: scale annot appearance false key
1229       dup 3 index exch known {
1230         exch pop true exit 
1231       } if
1232       pop
1233     } forall
1234         % stack: scale annot appearance key true
1235         % stack: scale annot appearance false
1236     dup {
1237       pop
1238       oget
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.
1244       dup /Length known {
1245                 % If this is a form then simply use it
1246         true
1247       } {
1248         1 index /AS knownoget not {
1249                 % If we do not have AS then use any appearance
1250           { exch pop oforce exit } forall true
1251         } { 
1252                 % Stack: annot Ndict AS
1253                 % Get the specified appearance.  If no appearance, then
1254                 % display nothing - set stack = false.
1255           knownoget
1256         } ifelse
1257       } ifelse
1258     } {
1259       exch pop  % discard useless AP dictionary
1260     } ifelse
1261
1262                 % Stack: scale annot appearance true
1263                 % Stack: scale annot false
1264     {
1265                 % Draw appearance
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
1270       DoForm Q
1271     } if
1272   } if pop pop
1273 } bdef
1274
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
1279   dup /Rect known {
1280     dup annotrect 4 -2 roll pop pop      % get width height size in user space
1281     3 -1 roll /AP knownoget {
1282       /N knownoget {
1283         dup /Matrix knownoget {
1284           % transform /Annot /Rect xwidth to Form space
1285           4 -2 roll 3 -1 roll dtransform 3 -1 roll
1286         } if
1287         /BBox knownoget {
1288           exch pop      % discard y height
1289           aload pop pop exch pop sub    % BBox width
1290           dup 0 eq {
1291             (   **** Warning: /BBox has zero width which is not allowed.\n)
1292             pdfformaterror
1293             pop pop 1 1         % 0 width -- revert to unity scaling
1294           } if
1295           div           % scale x widths
1296           dup 0 lt { neg } if           % get magnitude
1297         } {
1298           pop pop 1             % default to unity scaling
1299         } ifelse                        % if we have /BBox
1300       } {
1301         pop pop 1
1302       } ifelse                  % if we have /N
1303     } {
1304       pop pop 1
1305     } ifelse                    % if we have /AP
1306   } {
1307     (   **** Warning: /Annot dict is missing required /Rect entry.\n)
1308     pdfformaterror
1309     pop 1
1310   } ifelse
1311 } bdef
1312
1313 /drawlink {                     % <annot> drawlink -
1314   dup drawborder dup calcstampscale exch drawwidget
1315 } bdef
1316
1317 % Draw an annotation.
1318 /drawannottypes mark
1319   /Link { drawlink } bind
1320 .dicttomark readonly def
1321 /drawannot {            % <annot> drawannot -
1322   dup annotvisible {
1323     gsave
1324     dup dup /Subtype get //drawannottypes exch .knownget {
1325       exec
1326     } {
1327       dup calcstampscale exch drawwidget        % Use drawwidget for everything else
1328     } ifelse                    % type known
1329     grestore
1330   } if pop                      % annotvisible
1331 } bdef
1332 currentdict /drawannottypes undef
1333
1334 end                     % pdfdict
1335 end                     % GS_PDF_ProcSet
1336 .setglobal