]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/opdfread.ps
merge
[plan9front.git] / sys / lib / ghostscript / opdfread.ps
1 %!PS-Adobe-2.0
2 %
3 %        Copyright (C) 2002 artofcode LLC.      All rights reserved.
4
5 % This software is provided AS-IS with no warranty, either express or
6 % implied.
7
8 % This software is distributed under license and may not be copied,
9 % modified or distributed except as expressly authorized under the terms
10 % of the license contained in the file LICENSE in this distribution.
11
12 % For more information about licensing, please refer to
13 % http://www.ghostscript.com/licensing/. For information on
14 % commercial licensing, go to http://www.artifex.com/licensing/ or
15 % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
16 % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
17
18 % $Id: opdfread.ps,v 1.84 2005/09/07 20:43:36 leonardo Exp $
19 % pdfread.ps - A procset for interpreting an ordered PDF 1.3 file.
20
21 % This module defines routines for interpreting a PDF file with
22 % a Postscript interpreter. To convert a PDF file into Postscript 
23 % just pre-contcatenate this file. The PDF file must satisfy 
24 % few constraints :
25 %
26 % 1. It must contain only Postscript level 2 objects encoded with
27 % the PDF 1.3 language. Higher PDF levels must be re-distilled
28 % with CompatibilityLevel=1.3 .
29 %
30 % 2. Objects must be ordered so that any resource be defined before
31 % its usage.
32 %
33 % 3. The PDF file must not include other PDF files.
34 % Consequently we have a single instance of the PDF reader.
35 % We use this fact to simplify binding of the routines.
36
37 % 4. The PDF root object must always have the object id 1.
38
39 % 5. Generations besides 0 are not allowed.
40 %
41 % 6. xref must appear after all objects.
42 %
43 % Assuming the currentfile isn't positionable.
44 % As a consequence, the reader fully ignores xref.
45
46
47 true setglobal
48
49 % ====================== Error handler =======================
50 % A general error handler prints an error to page.
51
52 10 dict begin % A dictionary for local binding
53
54 /this currentdict def
55 /y 720 def
56 /ebuf 200 string def
57
58 /prnt {
59   36 //this /y get moveto //ebuf cvs show
60   //this /y 2 copy get 12 sub put
61 } bind def
62
63 /newline {
64   36 //this /y get moveto
65   //this /y 2 copy get 12 sub put
66 } bind def
67
68 errordict /handleerror
69 { systemdict begin
70   $error begin
71   newerror
72   { (%%[ Error handled by opdfread.ps : ) print errorname //ebuf cvs print (; OffendingCommand: )
73     print /command load //ebuf cvs print ( ]%%) = flush
74     /newerror false store vmstatus pop pop 0 ne
75     { grestoreall
76     } if
77     errorname (VMerror) ne
78     { showpage
79     } if
80     initgraphics
81     0 720 moveto
82     errorname (VMerror) eq
83     { //this /ehsave known
84       { clear //this /ehsave get restore 2 vmreclaim
85       } if
86       vmstatus exch pop exch pop 
87     }
88     /Courier 12 selectfont
89     {
90       (ERROR: ) //prnt exec errorname //prnt exec
91       (OFFENDING COMMAND: ) //prnt exec
92       /command load //prnt exec
93       $error /ostack known {
94         (%%[STACK:) =
95         (STACK:) //prnt exec
96         $error /ostack get aload length {
97           //newline exec
98           dup mark eq {
99             (-mark-) dup = show
100           } {
101             dup type /nametype eq { 
102               dup xcheck not {
103                 (/) show
104                 (/) print
105              } if
106           } if
107           dup = //ebuf cvs show
108           } ifelse
109         } repeat
110       } if
111     } ifelse
112     (%%]%) =
113     //systemdict /showpage get exec
114     quit
115   } if
116   end
117   end
118 } bind readonly put
119
120 end % A dictionary for local binding
121
122
123 50 dict begin
124
125 % ===================== Debugging =========================================
126
127 /DefaultSwitch  % <name> DefaultSwitch -
128 {
129   dup where {
130     pop pop
131   } {
132     false def
133   } ifelse
134 } bind def
135
136 /=string 256 string def
137
138 /=only {
139   //=string cvs print
140 } bind def
141
142 /HexDigits (0123456789ABCDEF) readonly def
143
144 /PrintHex  % <int> PrintHex -
145 { 8 {
146     dup -28 bitshift //HexDigits exch 1 getinterval //=only exec
147     4 bitshift
148   } repeat
149   pop
150 } bind def
151
152 /PDFR_DEBUG DefaultSwitch
153 /PDFR_DUMP DefaultSwitch
154 /PDFR_STREAM DefaultSwitch
155 /TTFDEBUG DefaultSwitch
156 /RotatePages DefaultSwitch
157 /FitPages DefaultSwitch
158 /SetPageSize DefaultSwitch
159
160 /error  %  mark <object> .... error -
161 { % A stub for a while.
162   counttomark 1 sub -1 0 {
163     index dup type /arraytype eq { == } { =only } ifelse
164   } for
165   () =
166   cleartomark
167   % Assuming ....Undefined is never defined. 
168   % Use it to emit an error.
169   ....Undefined
170 } bind def
171
172 //SetPageSize {
173   //RotatePages //FitPages or {
174     mark (/RotatePages, /FitPages are not allowed with /SetPageSize) //error exec
175   } if
176 } if
177
178 % ===================== Utilities =========================================
179
180 /knownget % <dict> <key> knownget <value> true
181           % <dict> <key> knownget false
182 {
183   2 copy known {
184     get true
185   } {
186     pop pop false
187   } ifelse
188 } bind def
189
190 /IsUpper  % <int> IsUpper <bool>
191 { dup (A) 0 get ge exch (Z) 0 get le and
192 } bind def
193
194 % ===================== Work Data =========================================
195
196 /BlockBuffer 65535 string def % Make it big to load entire TrueType font
197 /PDFReader currentdict def
198 /ObjectRegistry 50 array def % may grow later
199 /CurrentObject null def
200 /DoneDocumentStructure false def
201 /GraphicState 20 dict begin
202   /InitialTextMatrix matrix def
203   /InitialMatrix matrix currentmatrix def
204 currentdict end def
205 /TempMatrix matrix def
206 /GraphicStateStack 20 array def
207 /GraphicStateStackPointer 0 def
208 /PDFColorSpaces 50 dict def
209 /InstalledFonts 50 dict def
210 /MacRomanEncodingInverse null def
211
212 % We need some structures in local VM, put then into the userdict :
213 currentglobal false setglobal
214 userdict /PDFR_InitialGS gstate put
215 userdict /PDFR_Patterns 50 dict put
216 userdict /FuncDataReader 10 dict put
217 setglobal
218
219 % ===================== Constants =========================================
220
221 /InitialExtGState 20 dict begin
222   /BG2 currentblackgeneration def
223   /UCR2 currentundercolorremoval def
224   /TR2 [ currentcolortransfer ] def
225   /HT currenthalftone def
226 currentdict end readonly def
227
228 /InitialGraphicState 20 dict begin
229   /FontSize 0 def
230   /CharacterSpacing 0 def
231   /TextLeading 0 def
232   /TextRenderingMode 0 def
233   /WordSpacing 0 def
234 currentdict end readonly def
235
236 /SimpleColorSpaceNames 15 dict begin
237   /DeviceGray true def
238   /DeviceRGB true def
239   /DeviceCMYK true def 
240 currentdict end readonly def
241
242 /1_24_bitshift_1_sub 1 24 bitshift 1 sub def
243
244 /ReadFontProcs 10 dict def % Will be filled below.
245
246 % ===================== Reading PDF objects ===============================
247
248 /Register % <DefaultDaemon> <id> <obj> Register -
249 {
250   exch dup                                              % d obj id id
251   //PDFReader /ObjectRegistry get length ge {
252     dup dup 2 idiv add array dup                        % d obj id [n] [n]
253     //PDFReader /ObjectRegistry get dup length          % d obj id [n] [n] [o] l
254     3 2 roll exch                                       % d obj id [n] [o] [n] l
255     0 exch getinterval copy pop                         % d obj id [n]
256     //PDFReader exch /ObjectRegistry exch put           % d obj id
257   } if
258   exch //PDFReader /ObjectRegistry get                  % d id obj r
259   3 1 roll                                              % d r id obj
260   3 copy pop get                                        % d r id obj e
261   dup xcheck {                                          % d r id obj e
262     5 4 roll pop                                        % r id obj e
263     //PDFR_DEBUG {
264       (Have a daemon for ) print 2 index =
265     } if
266     % We've got a definition daemon, execute it :
267     exec
268   } {                                                   % d r id obj e
269     dup null ne {                                       % d r id obj e
270       mark (The object ) 4 index ( already defined : ) 4 index //error exec
271     } {
272       pop
273     } ifelse
274     4 3 roll                                            % r id obj d
275     % Execute the default daemon :
276     exec
277   } ifelse                                              % r id obj
278   put                                                   %
279 } bind def
280
281 /IsRegistered % <id> GetRegistered <bool>
282 {
283   //PDFReader /ObjectRegistry get                       % id r
284   dup length                                            % id r l
285   2 index le {                                          % id r
286     pop pop false
287   } {
288     exch get                                            % id e
289     null ne
290   } ifelse
291 } bind def
292
293 /GetRegistered % <id> GetRegistered <obj>
294 {
295   //PDFReader /ObjectRegistry get                       % id r
296   dup length                                            % id r l
297   2 index le {                                          % id r
298     exch mark exch (Object ) exch ( isn't defined before needed (1).) //error exec 
299   } if
300   1 index get                                           % id e
301   dup xcheck {
302     exch mark exch (Object ) exch ( isn't defined before needed (2).) //error exec 
303   } { 
304     dup null eq {
305       exch mark exch (Object ) exch ( isn't defined before needed (3).) //error exec 
306     } if
307     exch pop                                            % e
308   } ifelse
309 } bind def
310
311 /StandardFontNames <<
312   /Times-Roman true 
313   /Helvetica true
314   /Courier true
315   /Symbol true
316   /Times-Bold true
317   /Helvetica-Bold true
318   /Courier-Bold true
319   /ZapfDingbats true
320   /Times-Italic true
321   /Helvetica-Oblique true
322   /Courier-Oblique true
323   /Times-BoldItalic true
324   /Helvetica-BoldOblique true
325   /Courier-BoldOblique true
326 >> def
327
328 /CleanAllResources % - CleanAllResources  -
329 { //PDFR_DEBUG {
330     (CleanAllResources beg) =
331   } if
332   //PDFReader /ObjectRegistry get
333   dup length 0 exch 1 exch 1 sub {                     % R i
334     2 copy get dup xcheck {
335       % Don't clean a daemon.
336       pop pop
337     } {
338       dup null eq {
339         pop pop
340       } {
341         dup type /dicttype eq { /.Global known } { pop false } ifelse {
342           pop
343         } {
344           //PDFR_DEBUG {
345             (Dropping ) print dup =
346           } if
347           1 index exch /DroppedObject put
348         } ifelse
349       } ifelse
350     } ifelse
351   } for
352   pop
353   FontDirectory length dict begin
354   FontDirectory { 
355     pop    
356     dup //StandardFontNames exch known not {
357       dup null def
358     } if
359     pop
360   } forall
361   currentdict
362   end {
363     pop
364     //PDFR_DEBUG {
365        (Undefining font ) print dup =
366     } if
367     undefinefont
368   } forall
369   //PDFR_DEBUG {
370     (CleanAllResources end) =
371   } if
372 } bind def
373
374 /PrintReference % <array> PrintReference <array>
375 {
376   //PDFR_DEBUG {
377     ({ ) print
378     dup {
379       =only ( ) print
380     } forall
381     ( }) =
382   } if
383 } bind def
384
385 /R % <id> <gen> R <daemon>
386 { % Make a reference daemon.
387   0 ne {
388     exch mark exch (A referred object generation ) exch ( isn't 0.) //error exec
389   } if                                                  % id
390   [ % <id> proc <obj>
391     exch //GetRegistered /exec load 
392   ] cvx
393   //PrintReference exec
394 } bind def
395
396 /IsObjRef %  <any> IsObjRef <bool>
397
398   dup type /arraytype eq {
399     dup length 3 eq {
400       dup xcheck exch
401       dup 0 get type /integertype eq 3 2 roll and exch
402       dup 1 get //GetRegistered eq 3 2 roll and exch
403       2 get /exec load eq and
404     } {
405       pop false
406     } ifelse
407   } {
408     pop false
409   } ifelse
410 } bind def
411
412 /DoNothing 
413 {
414 } def
415
416 /RunTypeDaemon  % <id> <obj> RunTypeDaemon <id> <obj>
417 {
418   dup type /dicttype eq {
419     dup /Type //knownget exec {
420       //PDFReader /TypeDaemons get exch
421       //knownget exec {
422         exec
423       } if
424     } if
425   } if
426 } bind def
427
428 /obj % <id> <generation> obj <id>
429 {
430   //PDFR_DEBUG {
431     (Defining ) print 1 index =only ( ) print dup =only ( obj) =
432   } if
433   0 ne {
434     exch mark exch (An object generation ) exch ( isn't 0.) //error exec
435   } if
436 } bind def
437
438 /endobj  % <id> <obj> endobj -
439 {
440   //PDFR_DEBUG {
441     (endobj ) =
442   } if
443   dup type /dicttype eq {
444     dup /.endobj_daemon //knownget exec {
445       //PDFR_DEBUG { (.endobj_daemon for ) print 2 index = } if
446       exec
447     } if
448   } if
449   dup type /dicttype eq { dup /ImmediateExec known } { false } ifelse {
450     pop pop
451   } {
452     //PDFR_DEBUG {
453       (Storing ) print 1 index =
454     } if
455     //RunTypeDaemon exec
456     //DoNothing 3 1 roll //Register exec
457   } ifelse
458 } bind def
459
460 /StoreBlock % <buf> StoreBlock -
461 { % Stores a (encoded) stream data block to the current object.
462   //PDFR_DEBUG {
463     (StoreBlock ) print //PDFReader /BlockCount get =only (, Length = ) print dup length =
464   } if
465   dup length string copy
466   //PDFReader /BlockCount get exch                      % i s
467   //PDFReader /CurrentObject get 3 1 roll               % o i s
468   put                                                   %
469   //PDFReader /BlockCount get 1 add
470   //PDFReader exch /BlockCount exch put
471 } bind def
472
473 /CheckLength % <val> CheckNumber <val>
474 { dup type /integertype ne {
475     mark (Object length isn't an integer.) //error exec
476   } if
477 } bind def
478
479 /ResolveD % <dict> <key> <check> ResolveD <value>
480 {
481   3 copy pop get                                        % <> key {} e
482   dup //IsObjRef exec {
483     % We've got a reference daemon, execute it :
484     //PDFR_DEBUG {
485       (Resolving ) print //PrintReference exec
486     } if
487     exec                                                % <> key {} val
488     exch exec                                           % <> key val
489   } {
490     exch pop
491   } ifelse
492   dup 4 1 roll                                          % val <> key val
493   put                                                   % val
494 } bind def
495
496 /ResolveA   % <array> <index> <check> ResolveA <value>
497 { 2 index 2 index get
498   dup //IsObjRef exec {
499     exec
500     exch exec
501     3 copy put
502   } {
503     exch pop
504   } ifelse
505   exch pop exch pop
506 } bind def
507
508 /StoreStream  % <id> <obj> StoreStream <id> <obj>
509 { % Stores a (encoded) data stream copy to the current object.
510   dup //PDFReader exch /CurrentObject exch put          % id obj
511   //PDFReader /BlockCount 0 put
512   dup /Length //CheckLength //ResolveD exec             % id obj l
513   //PDFR_DEBUG {
514     (StoreStream Length = ) print dup =
515   } if
516   currentfile exch () /SubFileDecode filter             % id obj file
517   { dup //BlockBuffer readstring {                      % id obj file buf
518       //StoreBlock exec
519     } {
520       //StoreBlock exec
521       exit
522     } ifelse                                            % id obj file
523   } loop
524   pop                                                   % id obj
525   //PDFReader /CurrentObject null put
526   //PDFR_DEBUG {
527     (StoreStream end.) =
528   } if
529 } bind def
530
531 /MakeStreamDumper % <file> MakeStreamDumper <file>
532 { % Debug purpose only.
533   //PDFR_DEBUG {
534     (MakeStreamDumper beg.) =
535   } if
536   currentglobal exch dup gcheck setglobal
537   [ exch                      % f
538     1 dict dup /c 0 put exch  % d f
539     1024 string               % d f s
540     { readstring pop          % d s
541       (StreamDumper ) print 1 index /c get =string cvs print ( ) print 
542       dup length =string cvs print ( <) print dup print (>\n) print
543       dup length              % d s l
544       3 2 roll                % s l d
545       dup /c get              % s l d c
546       3 2 roll                % s d c l
547       add /c exch put         % s
548     } /exec load    
549   ] 
550   cvx 0 () /SubFileDecode filter
551   exch setglobal
552   //PDFR_DEBUG {
553     (MakeStreamDumper end.) =
554   } if
555 } bind def
556
557 /ShortFilterNames 15 dict begin
558   /AHx /ASCIIHexDecode def
559   /A85 /ASCII85Decode def
560   /LZW /LZWDecode def
561   /Fl  /FlateDecode def
562   /RL  /RunLengthDecode def
563   /CCF /CCITTFaxDecode def
564   /DCT /DCTDecode def
565 currentdict end readonly def
566
567 /AppendFilters  % <file> <dict> AppendFilters <file>
568 {
569   //PDFR_DEBUG {
570     (AppendFilters beg.) =
571   } if
572   dup 3 1 roll                                      % d f d
573   /Filter //knownget exec {                         % d f F
574     dup type /nametype eq {                         % d f /F
575       dup //ShortFilterNames exch //knownget exec {
576         exch pop
577       } if
578       2 index /DecodeParms //knownget exec {        % d f p /F
579         exch
580       } if
581       filter                                        % d f'
582     } {                                             % d f []
583       dup 0 exch 1 exch length 1 sub {              % d f [] i
584         2 copy get                                  % d f [] i /F
585         dup //ShortFilterNames exch //knownget exec {
586           exch pop
587         } if
588         3 1 roll                                    % d f /F [] i
589         4 index /DecodeParms //knownget exec {      % d f /F [] i DP
590           exch get                                  % d f /F [] dp
591         } {                                         % d f /F [] i
592           pop null                                  % d f /F [] dp
593         } ifelse
594         dup null eq {                               % d f /F [] dp
595           pop 3 1 roll filter exch                  % d f' []
596         } {                                         % d f /F [] dp
597           3 1 roll                                  % d f dp /F []
598           4 1 roll filter exch                      % d f' []
599         } ifelse
600       } for
601       pop                                           % d f'
602     } ifelse
603     //PDFR_DEBUG //PDFR_DUMP and  {
604       //MakeStreamDumper exec
605     } if
606   } if
607   exch pop
608   //PDFR_DEBUG {
609     (AppendFilters end.) =
610   } if
611 } bind def
612
613 /ExecuteStream  % <id> <obj> ExecuteStream <id> <obj>
614 { % Executes a (encoded) data stream.
615   dup //PDFReader exch /CurrentObject exch put          % id obj
616   dup /Length //CheckLength //ResolveD exec             % id obj l
617   //PDFR_DEBUG {
618     (ExecuteStream id = ) print 2 index =only ( Length = ) print dup =
619   } if
620   //PDFReader /InitialGraphicState get 
621   //PDFReader /GraphicState get copy pop
622   //PDFReader /Operators get begin
623   % currentfile exch () /SubFileDecode filter           % id obj file
624   % We would like to use the code above, 
625   % but HP LaserJet 1320 continues parsing after the byte count exceeds.
626   pop currentfile 0 (endstream) /SubFileDecode filter   % id obj file
627   1 index //AppendFilters exec
628   cvx mark exch                                         % id obj mark file
629   exec
630   counttomark 0 ne {
631     mark (Data left on ostack after an immediate stream execution.) //error exec
632   } if
633   cleartomark                                           % id obj
634   end % Operators
635   //PDFR_DEBUG {
636     (ExecuteStream end.) =
637   } if
638   //PDFReader /CurrentObject null put
639   dup /IsPage known {
640     dup /Context get /NumCopies //knownget exec {
641       1 sub {
642         copypage
643       } repeat
644     } if
645     showpage
646   } if
647 } bind def
648
649 /stream  % <id> <obj> stream <id> <obj>
650
651   //PDFR_DEBUG {
652     1 index =only ( stream) =
653   } if                                                  % id obj
654   % Run the object definition daemon, if exists :
655   //PDFReader /ObjectRegistry get dup length 3 index    % id obj r l id
656   gt {                                                  % id obj r
657     2 index get 
658     dup xcheck {
659       exec
660       % Disable the daemon :
661       //PDFReader /ObjectRegistry get 2 index null put
662     } {
663       pop
664     } ifelse
665   } {
666     pop
667   } ifelse                                              % id obj
668   dup /ImmediateExec known {
669     dup /GlobalExec //knownget exec {
670       currentglobal 4 1 roll
671       setglobal
672       //ExecuteStream exec
673       3 2 roll setglobal
674     } {
675       //ExecuteStream exec
676     } ifelse
677   } {
678     //StoreStream exec
679   } ifelse
680   dup /.CleanResources //knownget exec {
681     /All eq {
682       //CleanAllResources exec
683     } if
684   } if
685 } bind def
686
687 /HookFont % <id> <obj> <font_descriptor> HookFont <id> <obj>
688
689     //PDFR_DEBUG {
690       (Loaded the font ) print dup /FontName get =
691     } if
692     {
693       dup /FontFileType get dup /Type1 eq exch /MMType1 eq or {  % id obj fd
694         % We assume that the Type 1 font has same name with no prefix
695         % due to pdfwrite specifics.
696         % We use it to find the font after it is defined.
697         % We could redefine 'definefont' for hooking the font, 
698         % but we don't think that it could be guaranteedly portable : 
699         % a 3d party PS interpreter may set a special context 
700         % when running the font file.
701         % Note that this mechanizm does not depend on the
702         % font name uniquity, because the last 'definefont'
703         % is only important.
704         dup /FontName get                               % id obj fd fn
705         //PDFReader /RemoveFontNamePrefix get exec 
706         currentglobal true setglobal exch               % id obj fd g fn
707         findfont                                        % id obj fd g f
708         exch setglobal                                  % id obj fd f
709         exit
710       } if
711       dup /FontFileType get /TrueType eq {              % id obj fd
712         //PDFReader /MakeType42 get exec
713         //PDFR_DEBUG {
714           (Font dict <<) =
715           dup {
716             1 index /sfnts eq {
717               exch pop
718               (/sfnts [) print
719               {
720                 (-string\() print length //=only exec (\)- ) =
721               } forall
722               (]) =
723             } {
724               exch //=only exec ( ) print ==
725             } ifelse
726           } forall
727           (>>) =
728         } if
729         dup /FontName get exch definefont
730         exit
731       } if
732       mark (FontHook has no proc for ) 2 index /FontFileType get //error exec
733     } loop
734     /Font exch put                                      % id obj
735 } bind def
736
737 /endstream % <id> <obj> endstream <id> <obj>
738
739 } bind def
740
741 /xref % - xref -
742
743   //PDFR_DEBUG {
744     (xref) =
745     //PDFR_DUMP {
746       //PDFReader /ObjectRegistry get ==
747     } if
748   } if
749   end % The procset
750   count 0 ne {
751     mark (Excessive data on estack at the end of the interpretation.) //error exec
752   } if
753   currentfile flushfile
754 } bind def
755
756 % ===================== Restoring the PDF Document Structure ===============
757
758 /ResolveDict  % <dict> /ResolveDict -
759 { dup {                                                 % d key val
760     pop 1 index exch                                    % d cp key
761     //DoNothing //ResolveD exec                         % d obj
762     pop                                                 % d
763   } forall
764   pop                                                   %
765 } bind def
766
767 /SetupPageView  % <obj> SetupPageView -
768 {
769   //PDFR_DEBUG {
770     (SetupPageView beg) =
771   } if
772   //GraphicState /InitialMatrix get setmatrix
773   /MediaBox get aload pop                               % bx0 by0 bx1 by1
774   3 index neg 3 index neg translate % Temporary move to origin
775   3 -1 roll sub 3 1 roll exch sub exch                  % bw bh
776   userdict  /.HWMargins //knownget exec {
777     aload pop
778   } {
779     currentpagedevice /.HWMargins //knownget exec {
780       aload pop
781     } {
782       0 0 0 0
783     } ifelse
784   } ifelse
785   currentpagedevice /PageSize get aload pop
786   3 -1 roll sub 3 1 roll exch sub exch                  % bw bh px0 py0 px1 py1
787   exch 3 index sub exch 3 index sub                     % bw bh px0 py0 pw ph
788   //SetPageSize {
789     //PDFR_DEBUG {
790       (Setting page size to ) print 1 index //=only exec ( ) print dup =
791     } if
792     pop pop 3 index 3 index 2 copy                      % bw bh px0 py0 bw bh bw bh
793     currentglobal false setglobal 3 1 roll              % bw bh px0 py0 bw bh bool bw bh
794     2 array astore                                      % bw bh px0 py0 bw bh bool []
795     << exch /PageSize exch >> setpagedevice             % bw bh px0 py0 bw bh bool
796     userdict /PDFR_InitialGS gstate put
797     setglobal                                           % bw bh px0 py0 bw bh
798   } if
799   //RotatePages {
800     2 copy gt 6 index 6 index gt ne {
801       % a rotation is useful except it fits with no rotation.
802       1 index 5 index le 1 index 5 index le and not
803     } {
804       false
805     } ifelse
806   } {
807     false
808   } ifelse
809   { //FitPages {
810       1 index 5 index div 1 index 7 index div           % bw bh px0 py0 pw ph sx sy
811       2 copy gt {
812         exch
813       } if
814       pop dup scale                                     % bw bh px0 py0 pw ph
815     } if
816     90 rotate
817     0 5 index neg translate
818   } {
819     //FitPages {
820       1 index 6 index div 1 index 6 index div           % bw bh px0 py0 pw ph sx sy
821       2 copy gt {
822         exch
823       } if
824       pop dup scale                                     % bw bh px0 py0 pw ph
825     } if
826   } ifelse                                               
827   pop pop                                               % bw bh px0 py0
828   translate                                             % bw bh
829   pop pop                                               %
830   //PDFR_DEBUG {
831     (SetupPageView end) =
832   } if
833 } bind def
834
835 /PageContentsDaemon % <id> <obj> <node> PageContentsDaemon <id> <obj>
836 { % Note: an excessive operand from a prebond procedure.
837   //PDFR_DEBUG {
838     (Executing PageContentsDaemon for ) print 2 index =
839   } if                                                  % id obj node
840   1 index exch /Context exch put                        % id obj
841   dup /ImmediateExec true put
842   dup /IsPage true put
843   dup /Context get //SetupPageView exec
844 } bind def
845
846 /FontFileDaemon % <id> <obj> <font_descriptor> FontFileDaemon <id> <obj>
847 { % Note: an excessive operand from a prebond procedure.
848   //PDFR_DEBUG {
849     (Executing FontFileDaemon for ) print 2 index =
850   } if
851   % We need any font resource that refers this descriptor
852   % to know the font type. Assuming that FontDescriptorDaemon
853   % provided FontFileType.
854   dup /FontFileType get                                 % id obj fd ft
855   2 index exch                                          % id obj fd obj ft
856   dup //ReadFontProcs exch //knownget exec {            % id obj fd obj ft proc
857      exch pop exec                                      % id obj fd
858   } {
859     mark (FontFile reader for ) 2 index ( isn't implemented yet.) //error exec
860   } ifelse
861   //PDFR_DEBUG {
862     (FontFileDaemon end) =
863   } if                                                  % id obj fd
864   pop
865 } bind def
866
867 /FontDescriptorDaemon % <id> <obj> <font_resource> FontDescriptorDaemon <id> <obj>
868 { % Note: an excessive operand from a prebond procedure.
869   //PDFR_DEBUG {
870     (Executing FontDescriptorDaemon for ) print 2 index =
871   } if                                                  % id obj fr
872   %HACK BEG assuming an own font for each font descriptor
873           % to provide an access to PDFEncoding
874           % from MakeType42, ComposeCharStrings.
875     2 copy /FontResource exch put
876   %HACK END
877   /Subtype get 1 index exch /FontFileType exch put
878 } bind def
879
880 /TypeDaemons <<  % <id> <obj> proc <id> <obj>
881   /Page 
882   { //PDFR_DEBUG {
883       (Recognized a page.) =
884     } if
885     dup /Contents //knownget exec {                     % id obj c
886       0 get //DoNothing exch                            % id obj dn id1
887       [ % <id> <obj> proc <id> <obj>
888         3 index //PageContentsDaemon /exec load
889       ] cvx                                             % id obj {}
890       //Register exec                                   % id obj
891     } {
892       (fixme: page with no Contents won't be printed.) =
893     } ifelse
894   } bind
895   /FontDescriptor
896   { //PDFR_DEBUG {
897       (Recognized a font descriptor.) =
898     } if
899     {
900       dup dup /FontFile known {/FontFile} {/FontFile2} ifelse 
901       //knownget exec {                                 % id obj ff
902         0 get //DoNothing exch                          % id obj dn id1
903         [ % <id> <obj> proc <id> <obj>
904           3 index //FontFileDaemon /exec load
905         ] cvx                                           % id obj {}
906         //Register exec                                 % id obj
907         exit
908       } if
909       % FontFile3 are not implemented yet.
910       (Font descriptor ) print 1 index =only ( has no FontFile.) =
911     } loop
912   } bind
913   /Font
914   { //PDFR_DEBUG {
915       (Recognized a font resource.) =
916     } if
917     dup /BaseFont //knownget exec {
918       % cache the installed font (if any) before replacing it.
919       //PDFReader /RemoveFontNamePrefix get exec
920       currentglobal exch % A hack against HP LaserJet 1320 bug :
921                          % It sets the local allocation mode
922                          % when 'resourcestatus' fails.
923       dup /Font resourcestatus {
924         pop pop
925         //PDFReader /GetInstalledFont get exec pop
926       } {
927         pop
928       } ifelse
929       setglobal
930     } if
931     dup /FontDescriptor //knownget exec {               % id obj fd
932       0 get                                             % id obj id1
933       dup //IsRegistered exec {                         % id obj id1
934         //PDFR_DEBUG {
935           (already registered ) print dup =
936         } if
937         pop
938       } {
939         //DoNothing exch                                % id obj dn id1
940         [ % <id> <obj> proc <id> <obj>
941           3 index //FontDescriptorDaemon /exec load
942         ] cvx                                           % id obj {}
943        //Register exec                                  % id obj
944       } ifelse
945     } if
946   } bind
947 >> def
948
949 /MakeStreamReader % <obj> MakeStreamReader <file>
950 { dup
951   [ 
952     exch
953     //PDFR_DEBUG {
954       (Stream proc )
955       /print load
956       //PDFR_STREAM {
957         (<)
958         /print load
959       } if
960     } if
961     1 dict dup /i -1 put
962     /dup load
963     /i 
964     /get load
965     1
966     /add load
967     /dup load
968     3 
969     1 
970     /roll load
971     /i
972     /exch load
973     /put load
974     //knownget
975     /exec load 
976     /not load
977     { () }
978     /if load
979     //PDFR_DEBUG {
980       //PDFR_STREAM {
981         /dup load
982         /print load
983         (>)
984         /print load
985       } if
986       ( end of stream proc.\n)
987       /print load
988     } if
989   ] cvx
990   //PDFR_DEBUG {
991     (Stream reader ) print dup ==
992   } if
993   0 () /SubFileDecode filter
994   exch //AppendFilters exec
995 } bind def
996
997 /RunDelayedStream % <stream_obj> RunDelayedStream -
998 {
999   //MakeStreamReader exec                                       % file
1000   mark exch
1001   cvx exec                                                      %
1002   counttomark 0 ne {
1003     mark (Data left on ostack after a delayed stream execution.) //error exec
1004   } if
1005   cleartomark
1006 } bind def
1007
1008 % ===================== Font Management ======================
1009
1010 //ReadFontProcs begin
1011   /Type1   % <font_descriptor> <FontFile_object> Type1 <font_descriptor>
1012   { //PDFR_DEBUG {
1013       (ReadFontProcs.Type1) =
1014     } if
1015     dup /.endobj_daemon [ 4 index //HookFont /exec load ] cvx put
1016     dup /ImmediateExec true put
1017     /GlobalExec true put
1018   } bind def
1019   /MMType1 //Type1 def
1020   /TrueType   % <font_descriptor> <FontFile_object> TrueType <font_descriptor>
1021   { //PDFR_DEBUG {
1022       (ReadFontProcs.TrueType) =
1023     } if
1024     dup /.endobj_daemon [ 4 index //HookFont /exec load ] cvx put
1025     pop
1026   } bind def
1027 end
1028
1029 /MakeType42 % <FontFile_object> <font_descriptor> MakeType42 <FontFile_object> <font_descriptor> <font>
1030 {
1031   //PDFR_DEBUG {
1032     (MakeType42 beg) =
1033   } if
1034   10 dict begin
1035     /FontName 1 index /FontName get def
1036     /FontType 42 def
1037     /FontMatrix [1 0 0 1 0 0] def
1038     /FontBBox 1 index /FontBBox get def          % fo fd
1039     dup /FontResource get                        % fo fd fr
1040     dup /Encoding known {                        % fo fd fr
1041        //PDFReader /ObtainEncoding get exec      % fo fd fr
1042        /Encoding get                             % fo fd e
1043     } {
1044       pop null
1045     } ifelse 
1046     /PDFEncoding exch def                        % fo fd
1047     /CharStrings 2 index //PDFReader /MakeTTCharStrings get exec def
1048     /sfnts [ 3 index //MakeStreamReader exec 65535 string readstring pop ] def
1049     /Encoding StandardEncoding def % A stub - will be replaced by font resource.
1050     /PaintType 0 def
1051   currentdict end
1052   //PDFR_DEBUG {
1053     (MakeType42 end) =
1054   } if
1055 } bind def
1056
1057 /GetInstalledFont % <name> GetInstalledFont <font>
1058 { currentglobal exch true setglobal                             % g n
1059   dup //InstalledFonts exch knownget {                          % g n f
1060     exch pop                                                    % g f
1061   } {                                                           % g n
1062     dup findfont dup 3 1 roll                                   % g f n f
1063     //InstalledFonts 3 1 roll put                               % g f
1064   } ifelse
1065   exch setglobal
1066 } bind def
1067
1068 /RemoveFontNamePrefix % <name> RemoveFontNamePrefix <name>
1069 { //=string cvs true
1070   0 1 5 {
1071     2 index exch get //IsUpper exec not {
1072       pop false exit
1073     } if
1074   } for
1075   { (+) search {
1076       pop pop
1077     } if
1078   } if
1079   cvn
1080 } bind def
1081
1082 /CheckFont % <key> <val> CheckFont <key> <val>
1083 { dup /Type get /Font ne {
1084     mark (Resource ) 3 index ( must have /Type/Font .) //error exec
1085   } if
1086 } bind def
1087
1088 /CheckEncoding %  <key> <val> CheckEncoding <key> <val>
1089 { dup type /nametype ne {
1090     dup /Type get /Encoding ne {
1091       mark (Resource ) 3 index ( must have /Type/Encoding .) //error exec
1092     } if
1093   } if
1094 } bind def
1095
1096 /ObtainEncoding % <font_resource> ObtainEncoding <font_resource>
1097 { dup /Encoding known {
1098     dup dup /Encoding //CheckEncoding //ResolveD exec   % fr fr er|e|n
1099     dup type dup /arraytype eq exch /packedarraytype eq or {
1100       % Already resolved.
1101       pop pop
1102     } {
1103       dup type /nametype eq {
1104         /Encoding findresource                          % fr fr e
1105       } {
1106         dup /BaseEncoding //knownget exec not {
1107           /StandardEncoding
1108         } if
1109         /Encoding findresource                          % fr fr er e
1110         exch                                            % fr fr e er
1111         /Differences //knownget exec {                  % fr fr e d
1112           exch dup length array copy exch
1113           0 exch                                        % fr fr e 0 d
1114           {                                             % fr fr e i v
1115             dup type /integertype eq {
1116               exch pop
1117             } {
1118               3 copy put pop                            % fr fr e i
1119               1 add
1120             } ifelse
1121           } forall
1122           pop                                           % fr fr e
1123          } if                                           % fr fr e
1124       } ifelse                                          % fr fr e
1125       /Encoding exch put                                % fr
1126     } ifelse
1127   } {
1128     dup /Encoding /StandardEncoding /Encoding findresource put
1129   } ifelse
1130 } bind def
1131
1132 /ObtainMetrics % <font_resource> ObtainMetrics <font_resource>
1133 { dup /Widths //knownget exec {                         % fr W
1134     1 index /Encoding get                               % fr W E
1135     256 dict                                            % fr W E M
1136     3 index /Subtype get /TrueType eq {
1137       1000
1138     } {
1139       1
1140     } ifelse                                            % fr W E M s
1141     4 index /MissingWidth //knownget exec not {
1142       0
1143     } if                                                % fr W E M s mw
1144     5 index /FirstChar //knownget exec not {
1145       0
1146     } if                                                % fr W E M s mw c0
1147     6 5 roll                                            % fr E M s mw c0 W
1148     dup 0 exch 1 exch length 1 sub {                    % fr E M s mw c0 W i
1149       2 copy get                                        % fr E M s mw c0 W i w
1150       exch 3 index add                                  % fr E M s mw c0 W w c
1151       7 index exch get                                  % fr E M s mw c0 W w n
1152       dup null ne {
1153         6 index 3 1 roll exch                           % fr E M s mw c0 W M n w
1154         6 index div                                     
1155         3 copy pop //knownget exec {
1156           0 eq
1157         } {
1158           true
1159         } ifelse
1160         { put                                           % fr E M s mw c0 W
1161         } {
1162           pop pop pop
1163         } ifelse
1164       } {
1165         pop pop
1166       } ifelse
1167     } for
1168     pop pop pop pop exch pop                            % fr M
1169     1 index exch /Metrics exch put                      % fr
1170   } {
1171     dup /MissingWidth //knownget exec {                 % fr mw
1172       256 dict                                          % fr mw M
1173       2 index /Encoding get {                           % fr mw M e
1174         dup null ne {
1175           3 copy 3 2 roll put                           % fr mw M e
1176         } if
1177         pop                                             % fr mw M
1178       } forall
1179       exch pop                                          % fr M
1180       1 index exch /Metrics exch put                    % fr
1181     } if
1182   } ifelse
1183 } bind def
1184
1185 /NotDef % - NotDef -
1186 { % A Type 3 font is on dstack.
1187   FontMatrix aload pop pop pop exch pop exch pop        % sx sy
1188   1 exch div exch
1189   1 exch div exch                                       % wx wy
1190   1 index 0 setcharwidth
1191   o setlinewidth
1192   0 0 moveto
1193   2 copy rlineto
1194   1 index 0 rlineto
1195   neg exch neg exch rlineto                             %
1196   closepath stroke
1197 } bind def
1198
1199 /BuildChar  % <font> <char_code> BuildChar -
1200 { //PDFR_DEBUG {
1201     (BuildChar ) print dup //=only exec ( ) print
1202   } if
1203   exch begin
1204   Encoding exch get                                     % n
1205   //PDFR_DEBUG {
1206     dup =
1207   } if
1208   dup null eq {
1209     pop //NotDef exec                                   %
1210   } {                                                   % n
1211     CharProcs exch //knownget exec {                    % cp_stream
1212       //RunDelayedStream exec
1213     } {
1214       //NotDef exec
1215     } ifelse
1216   } ifelse                                              %
1217   end % font
1218 } bind def
1219
1220 /printdict % <dict> printdict -
1221 { (<<) =
1222   { exch = == } forall
1223   (>>) =
1224 } bind def
1225
1226 /printfont % <dict> printfont -
1227 {
1228   dup {
1229     exch dup =
1230     dup /Encoding eq {
1231       pop =
1232     } {
1233       dup /FontInfo eq exch /Private eq or {
1234         //printdict exec
1235       } {
1236         ==
1237       } ifelse
1238     } ifelse
1239   } forall
1240 } bind def
1241
1242 /ScaleMetrics % <Metrics> <scale> ScaleMetrics <Metrics>
1243 { 1 index {           % M s n v
1244     2 index div       % M s n v'
1245     3 index           % M s n v' M
1246     3 1 roll put      % M s
1247   } forall
1248   pop
1249 } bind def
1250
1251 /ResolveAndSetFontAux  % <resource_name> <size> ResolveAndSetFont -
1252 { exch dup                                              % s rn rn
1253   //PDFReader /CurrentObject get /Context get /Resources get
1254   /Font //DoNothing //ResolveD exec
1255   exch //CheckFont //ResolveD exec                      % s rn fr
1256   dup /Font //knownget exec {                           % s rn fr f
1257     exch pop exch pop
1258   } {
1259     {
1260       dup /Subtype get dup dup /Type1 eq exch /TrueType eq or exch /MMType1 eq or {
1261                                                         % s rn fr
1262         exch pop                                        % s fr
1263         dup /BaseFont get                               % s fr n
1264         //RemoveFontNamePrefix exec                     % s fr n
1265         //PDFR_DEBUG {
1266           (Font ) print dup =
1267         } if                                            % s fr n
1268         1 index /FontDescriptor known {                 % s fr n
1269           //PDFR_DEBUG {
1270             (Font from a font descriptor.) =
1271           } if
1272           1 index                                       % s fr n fr
1273           /FontDescriptor //DoNothing //ResolveD exec   % s fr n fd
1274           /Font //knownget exec {
1275             exch pop                                    % s fr fd
1276           } {
1277             //PDFR_DEBUG {
1278               (Font descriptor has no Font resolved.) =
1279             } if
1280             //GetInstalledFont exec                     % s fr f
1281           } ifelse
1282         } {
1283           //GetInstalledFont exec                       % s fr f
1284         } ifelse
1285         exch                                            % s f fr
1286         dup /Encoding known not {
1287           1 index /Encoding get 1 index exch /Encoding exch put
1288         } if
1289         //ObtainEncoding exec
1290         //ObtainMetrics exec
1291         exch
1292         dup length dict copy                            % s fr f
1293         dup 2 index /Encoding get                       % s fr f f e
1294         /Encoding exch put                              % s fr f
1295         1 index /Metrics //knownget exec {              % s fr f M
1296           2 index /Subtype get /TrueType ne {
1297             % Adjust Metrics for fonts converted from TrueTypes by 3d party.
1298             1 index /FontMatrix get 0 get 0.001 div
1299             //ScaleMetrics exec
1300           } if
1301           1 index exch /Metrics exch put                % s fr f
1302         } if
1303         1 index /BaseFont get                           % s fr f n
1304         exch
1305         dup /FID undef
1306         dup /UniqueID undef
1307         definefont                                      % s fr f
1308         dup 3 1 roll                                    % s f fr f
1309         /Font exch put                                  % s f
1310         exit
1311       } if
1312       dup /Subtype get /Type3 eq {                      % s rn fr
1313         //ObtainEncoding exec
1314         2 copy exch /FontName exch put
1315         dup /CharProcs get //ResolveDict exec
1316         dup /FontType 3 put
1317         dup /BuildChar //BuildChar put
1318         dup dup /Font exch put
1319         % Ignore Metrics because pdfwrite duplicates it 
1320         % from setcharwidth/setcachedevice.
1321         dup 3 1 roll                                    % s fr rn fr
1322         definefont                                      % s fr f
1323         2 copy ne { 
1324           % The interpreter copied the font dictionary while 'definefont'
1325           % Need to update the font pointer in the resource.
1326           2 copy /Font exch put                         % s fr f
1327         } if
1328         exch pop                                        % s f
1329         exit
1330       } if
1331       dup /Subtype get /Type0 eq {                      % s rn fr
1332       } if
1333       dup /Subtype get /CIDFontType0 eq {               % s rn fr
1334       } if
1335       dup /Subtype get /CIDFontType2 eq {               % s rn fr
1336       } if
1337       mark (Unknown font type ) 2 index /Subtype get //error exec
1338     } loop
1339   } ifelse                                              % s f
1340   exch scalefont setfont                                %
1341 } bind def
1342
1343 /ResolveAndSetFont  % <resource_name> <size> ResolveAndSetFont -
1344 { currentglobal true setglobal 3 1 roll
1345   //ResolveAndSetFontAux exec
1346   setglobal
1347 } bind def
1348
1349 %%beg TrueType
1350 % ================= Auxiliary procedures for True Type cmap Decoder =============
1351
1352 /.knownget 
1353 { 2 copy known {
1354     get true
1355   } {
1356     pop pop false
1357   } ifelse
1358 } bind def
1359
1360 /.min 
1361 { 2 copy lt {
1362     exch
1363   } if
1364   pop
1365 } bind def
1366
1367 /.dicttomark
1368 { >>
1369 } bind def
1370
1371 % ===================== True Type cmap Decoder =============
1372 % The following procedures are copied from gs/lib/gs_ttf.ps with no change.
1373
1374 % <string> <index> getu16 <integer>
1375 /getu16 {
1376   2 copy get 8 bitshift 3 1 roll 1 add get add
1377 } bind def
1378
1379 % <string> <index> gets16 <integer>
1380 /gets16 {
1381   getu16 16#8000 xor 16#8000 sub
1382 } bind def
1383
1384 % <string> <index> getu32 <integer>
1385 /getu32 {
1386   2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
1387 } bind def
1388
1389 % <string> <index> gets32 <integer>
1390 /gets32 {
1391   2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
1392 } bind def
1393
1394 % Each procedure in this dictionary is called as follows:
1395 %       <encodingtable> proc <glypharray>
1396 /cmapformats mark
1397   0 {           % Apple standard 1-to-1 mapping.
1398     6 256 getinterval { } forall 256 packedarray
1399   } bind
1400   2 {           % Apple 16bit CJK (ShiftJIS etc)
1401
1402     % /sHK_sz           subHeaderKey_size       % 1 * uint16
1403     % /sH_sz            subHeader_size          % 4 * uint16
1404     % /sH_len           subHeader_length
1405     % /cmapf2_tblen     total table length
1406     % /cmapf2_lang      language code (not used)
1407     % /sHKs             subHeaderKeys
1408
1409     /sHK_sz 2 def
1410     /sH_sz 8 def
1411     dup 2 getu16 /cmapf2_tblen exch def
1412
1413     dup 4 getu16 /cmapf2_lang exch def
1414
1415     dup 6 256 sHK_sz mul getinterval /sHKs exch def
1416
1417     0           % initialization value for /sH_len
1418     0 1 255 {
1419        sHKs exch
1420        2 mul getu16
1421        1 index  % get current max
1422        1 index  % get current subHeaderKey
1423        lt {exch} if pop
1424     } for
1425     /sH_len exch def
1426
1427     dup 6 256 sHK_sz mul add
1428     cmapf2_tblen 1 index sub getinterval
1429     /sH_gIA exch def
1430
1431     /cmapf2_glyph_array 65535 array def
1432
1433     /.cmapf2_putGID {
1434         /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
1435         firstCode cmapf2_ch_lo le
1436         cmapf2_ch_lo firstCode entryCount add lt
1437         and { % true: j is inside
1438             sH_offset idRangeOffset add         % offset to gI
1439             cmapf2_ch_lo firstCode sub 2 mul    % rel. pos. in range
1440             add 6 add                           % offset in sH_gIA
1441             sH_gIA exch getu16
1442             dup 0 gt { %
1443                 idDelta add
1444                 cmapf2_glyph_array exch cmapf2_ch exch put
1445             } {
1446                 pop
1447                 % cmapf2_glyph_array cmapf2_ch 0 put
1448             } ifelse
1449         } {   % false: j is outside
1450             % cmapf2_glyph_array cmapf2_ch 0 put
1451         } ifelse
1452     } def
1453
1454     16#00 1 16#ff { % hi_byte scan
1455         /cmapf2_ch_hi exch def
1456         sHKs cmapf2_ch_hi sHK_sz mul getu16
1457         /sH_offset exch def
1458         sH_gIA sH_offset sH_sz getinterval
1459             dup 0 getu16 /firstCode exch def
1460             dup 2 getu16 /entryCount exch def
1461             dup 4 gets16 /idDelta exch def
1462             dup 6 getu16 /idRangeOffset exch def
1463         pop
1464         sH_offset 0 eq {
1465            /cmapf2_ch_lo cmapf2_ch_hi def
1466            /cmapf2_ch_hi 0 def
1467            .cmapf2_putGID
1468         } {
1469            16#00 1 16#ff { % lo_byte scan
1470                /cmapf2_ch_lo exch def
1471                .cmapf2_putGID
1472            } for
1473         } ifelse
1474      } for
1475      pop
1476      0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
1477         dup cmapf2_glyph_array exch get
1478         null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse
1479      } for
1480      cmapf2_glyph_array
1481   } bind
1482   4 {           % Microsoft/Adobe segmented mapping.
1483     /etab exch def
1484     /nseg2 etab 6 getu16 def
1485     14 /endc etab 2 index nseg2 getinterval def
1486                 % The Apple TrueType documentation omits the 2-byte
1487                 % 'reserved pad' that follows the endCount vector!
1488     2 add
1489     nseg2 add /startc etab 2 index nseg2 getinterval def
1490     nseg2 add /iddelta etab 2 index nseg2 getinterval def
1491     nseg2 add /idroff etab 2 index nseg2 getinterval def
1492                 % The following hack allows us to properly handle
1493                 % idiosyncratic fonts that start at 0xf000:
1494     pop
1495     /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
1496     /putglyph {
1497       glyphs code 3 -1 roll put /code code 1 add def
1498     } bind def
1499                 % Do a first pass to compute the size of the glyphs array.
1500     /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
1501                 % Stack: /glyphs numglyphs i2
1502       /i2 exch def
1503       /scode startc i2 getu16 def
1504       /ecode endc i2 getu16 def
1505       numcodes scode firstcode sub
1506                 % Hack for fonts that have only 0x0000 and 0xf000 ranges
1507       %dup 16#e000 ge { 255 and } if
1508       % the previous line is obstructive to CJK fonts, so it was removed
1509       exch sub 0 .max ecode scode sub 1 add add
1510       exch 1 index add exch
1511       numcodes add /numcodes exch def
1512     } for array def
1513     % prefill the array with 0's faster than a { 0 putglyph } repeat
1514     glyphs length 1024 ge {
1515       .array1024z 0 1024 glyphs length 1023 sub { glyphs exch 2 index putinterval } for
1516       glyphs dup length 1024 sub 3 -1 roll
1517       putinterval
1518     } {
1519       0 1 glyphs length 1 sub { glyphs exch 0 put } for
1520     } ifelse
1521                 % Now fill in the array.
1522     /numcodes 0 def /code 0 def
1523     0 2 nseg2 3 sub {
1524       /i2 exch def
1525       /scode startc i2 getu16 def
1526       /ecode endc i2 getu16 def
1527       numcodes scode firstcode sub
1528                 % Hack for fonts that have only 0x0000 and 0xf000 ranges
1529       %dup 16#e000 ge { 255 and } if
1530       % the previous line is obstructive to CJK fonts, so it was removed
1531       exch sub 0 .max dup /code exch code exch add def
1532       ecode scode sub 1 add add numcodes add /numcodes exch def
1533       /delta iddelta i2 gets16 def
1534       TTFDEBUG {
1535         (scode=) print scode =only
1536         ( ecode=) print ecode =only
1537         ( delta=) print delta =only
1538         ( droff=) print idroff i2 getu16 =
1539       } if
1540       idroff i2 getu16 dup 0 eq {
1541         pop scode delta add 65535 and 1 ecode delta add 65535 and
1542         { putglyph } for
1543       } {       % The +2 is for the 'reserved pad'.
1544         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
1545         0 1 ecode scode sub {
1546           2 mul gloff add etab exch getu16
1547           dup 0 ne { delta add 65535 and } if putglyph
1548         } for
1549       } ifelse
1550     } for glyphs /glyphs null def       % for GC
1551   } bind
1552   6 {           % Single interval lookup.
1553     dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
1554     firstcode ng add array
1555                 % Stack: tab array
1556                 % Fill elements 0 .. firstcode-1 with 0
1557     0 1 firstcode 1 sub { 2 copy 0 put pop } for
1558     dup firstcode ng getinterval
1559                 % Stack: tab array subarray
1560                 % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
1561     0 1 ng 1 sub {
1562       dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
1563     } for pop exch pop
1564   } bind
1565 .dicttomark readonly def                % cmapformats
1566
1567 % <cmaptab> cmaparray <glypharray>
1568 /cmaparray {
1569   dup 0 getu16 cmapformats exch .knownget {
1570     TTFDEBUG {
1571       (cmap: format ) print 1 index 0 getu16 = flush
1572     } if exec
1573   } {
1574     (Can't handle format ) print 0 getu16 = flush
1575     0 1 255 { } for 256 packedarray
1576   } ifelse
1577   TTFDEBUG {
1578     (cmap: length=) print dup length = dup ==
1579   } if
1580 } bind def
1581
1582 % Define remapping for misnamed glyphs in TrueType 'post' tables.
1583 % There are probably a lot more than this!
1584 /postremap mark
1585   /Cdot /Cdotaccent
1586   /Edot /Edotaccent
1587   /Eoverdot /Edotaccent
1588   /Gdot /Gdotaccent
1589   /Ldot /Ldotaccent
1590   /Zdot /Zdotaccent
1591   /cdot /cdotaccent 
1592   /edot /edotaccent 
1593   /eoverdot /edotaccent
1594   /gdot /gdotaccent 
1595   /ldot /ldotaccent
1596   /zdot /zdotaccent 
1597 .dicttomark readonly def
1598
1599 % Each procedure in this dictionary is called as follows:
1600 %       posttable <<proc>> glyphencoding
1601 /postformats mark
1602   16#00010000  {        % 258 standard Macintosh glyphs.
1603     pop MacGlyphEncoding
1604   }
1605   16#00020000  {        % Detailed map, required by Microsoft fonts.
1606     dup length 36 lt {
1607       TTFDEBUG { (post format 2.0 invalid.) = flush } if
1608       pop [ ]
1609     } {
1610     /postglyphs exch def
1611       postglyphs 32 getu16 /numglyphs exch def
1612       /glyphnames numglyphs 2 mul 34 add def
1613       % Build names array in the order they occur in the 'post' table
1614       /postpos glyphnames def
1615       [ numglyphs 1 sub {
1616         postpos postglyphs length ge { exit } if
1617         % No name available, /postnames will be defined as an empty
1618         % array and the glyph won't get a name attached.
1619         postglyphs postpos get 
1620         postglyphs postpos 1 add 2 index getinterval cvn
1621         exch postpos add 1 add /postpos exch def
1622       } repeat
1623       ] /postnames exch def
1624       [ 0 1 numglyphs 1 sub {
1625         2 mul 34 add postglyphs exch getu16
1626         dup 258 lt {
1627           MacGlyphEncoding exch get
1628         } {
1629           dup 32768 ge {
1630                 % According to the published TrueType spec, such values are
1631                 % "reserved for future use", but at least some PDF files
1632                 % produced by the Adobe PDF library contain entries with a
1633                 % value of 16#ffff.
1634             pop /.notdef
1635           } {
1636             % Get the name for this glyph
1637             258 sub dup postnames length ge {
1638               TTFDEBUG { (   *** warning: glyph index past end of 'post' table) = flush } if
1639               exit
1640             } if
1641             postnames exch get
1642             % At least some of Microsoft's TrueType fonts use incorrect
1643             % (Adobe-incompatible) names for some glyphs.
1644             % Correct for this here.
1645             postremap 1 index .knownget { exch pop } if
1646           } ifelse
1647         } ifelse
1648       } for ]
1649     }
1650     ifelse
1651   } bind
1652   16#00030000  {        % No map.
1653     pop [ ]
1654   } bind
1655 .dicttomark readonly def                % postformats
1656
1657 % - .getpost -
1658 % Uses post, defines glyphencoding
1659 /.getpost {
1660   /glyphencoding post null eq {
1661     TTFDEBUG { (post missing) = flush } if [ ]
1662   } {
1663     postformats post 0 getu32 .knownget {
1664       TTFDEBUG {
1665         (post: format ) print
1666         post 0 getu16 =only (,) print post 2 getu16 = flush
1667       } if
1668       post exch exec
1669     } {
1670       TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
1671     } ifelse
1672   } ifelse def
1673 } bind def
1674
1675 % ===================== True Type Interpretation =============
1676
1677 /TTParser <<
1678   /Pos 0
1679   /post null
1680 >> def
1681
1682 /readu8   % <file> readu8 <int>
1683 { read not {
1684     mark (Insufficient data in the stream.) //error exec
1685   } if
1686 } bind def
1687
1688 /readu16   % <file> readu16 <int>
1689 { dup //readu8 exec 8 bitshift exch //readu8 exec or
1690 } bind def
1691
1692 /reads16   % <file> reads16 <int>
1693 { //readu16 exec 16#8000 xor 16#8000 sub
1694 } bind def
1695
1696 /readu32   % <file> readu32 <int>
1697 { dup //readu16 exec 16 bitshift exch //readu16 exec or
1698 } bind def
1699
1700 /reads32   % <file> reads32 <int>
1701 { dup //reads16 exec 16 bitshift exch //readu16 exec or
1702 } bind def
1703
1704 /SkipToPosition % <file> <int> SkipToPosition -
1705 { dup //TTParser /Pos get                               % f P P p
1706   exch //TTParser exch /Pos exch put                    % f P p
1707   sub                                                   % f P-p
1708   //PDFR_DEBUG {
1709     (Skipping ) print dup //=only exec ( bytes.) =
1710   } if
1711   dup 0 eq {
1712     pop pop
1713   } {
1714     //BlockBuffer exch 0 exch getinterval readstring not {
1715       mark (Insufficient data in the stream for SkipToPosition.) //error exec
1716     } if                                                % s
1717     pop                                                 %
1718   } ifelse
1719 } bind def
1720
1721 /TagBuffer 4 string def
1722
1723 /ParseTTTableDirectory  % <file> ParseTTTableDirectory <dict>
1724 { //PDFR_DEBUG {
1725     (ParseTTTableDirectory beg) =
1726   } if
1727   15 dict begin
1728     dup //readu32 exec 16#00010000 ne {
1729       mark (Unknown True Type version.) //error exec
1730     } if
1731     dup //readu16 exec /NumTables exch def
1732     dup //readu16 exec /SearchRange exch def
1733     dup //readu16 exec /EntrySelector exch def
1734     dup //readu16 exec /RangeShift exch def
1735     //PDFR_DEBUG {
1736       (NumTables = ) print NumTables =
1737     } if
1738     NumTables {
1739       dup //TagBuffer readstring not {
1740         mark (Could not read TT tag.) //error exec
1741       } if
1742       cvn
1743       [ 2 index //readu32 exec pop % CheckSum
1744         2 index //readu32 exec  % Offset
1745         3 index //readu32 exec  % Length
1746       ]
1747       //PDFR_DEBUG {
1748         2 copy exch //=only exec ( ) print ==
1749       } if
1750       def
1751     } repeat
1752     pop  % file
1753     //TTParser /Pos 12 NumTables 16 mul add put
1754   currentdict end
1755   //PDFR_DEBUG {
1756     (ParseTTTableDirectory end) =
1757   } if
1758 } bind def
1759
1760 /ParseTTcmap  % <file> <TableDirectory> ParseTTcmap <dict>
1761 { //PDFR_DEBUG {
1762     (ParseTTcmap beg) =
1763   } if
1764   /cmap get aload pop                                   % f o L
1765   3 1 roll                                              % L f o
1766   7 dict begin
1767     //PDFR_DEBUG {
1768       (Current position = ) print //TTParser /Pos get =
1769       (cmap position = ) print dup =
1770     } if
1771     1 index exch //SkipToPosition exec                  % L f
1772     //TTParser /Pos get /TablePos exch def
1773     dup //readu16 exec pop % version
1774     dup //readu16 exec /NumEncodings exch def
1775     //PDFR_DEBUG {
1776       (NumEncodings = ) print NumEncodings =
1777     } if
1778     null                                                % L f null
1779     NumEncodings {
1780       1 index //readu32 exec % platformID, specificID   % L f null id
1781       2 index //readu32 exec % offset                   % L f null id o
1782       3 array dup 3 2 roll 0 exch put                   % L f []|null id []
1783       2 index null ne {
1784         dup 0 get 3 index 0 get sub                     % L f []|null id [] l
1785         3 index exch 1 exch put                         % L f []|null id []
1786       } if
1787       dup 4 3 roll pop 3 1 roll                         % L f [] id []
1788       def
1789     } repeat                                            % L f []
1790     dup 0 get                                           % L f [] o
1791     4 3 roll exch sub                                   % f [] L-o
1792     1 exch put                                          % f
1793     //PDFR_DEBUG {
1794       currentdict {
1795         exch dup type /integertype eq {
1796           //PrintHex exec ( ) print ==
1797         } {
1798           pop pop
1799         } ifelse
1800       } forall
1801     } if
1802     4 NumEncodings 8 mul add /HeaderLength exch def
1803     //TTParser /Pos //TTParser /Pos get HeaderLength add put
1804     0                                                  % f o
1805     NumEncodings {
1806       16#7FFFFFF null                                  % f o om null|[]
1807       % Choosing a table with minimal offset greater than 'o' :
1808       currentdict {                                    
1809         1 index type /integertype eq {                 % f o om null|[] id []
1810           exch pop dup 0 get                           % f o om null|[] [] oi
1811           dup 5 index gt {
1812             dup 4 index lt {
1813               4 1 roll                                 % f o oi om null|[] []
1814               exch pop exch pop                        % f o oi []
1815             } {
1816               pop pop            
1817             } ifelse
1818           } {
1819             pop pop
1820           } ifelse                                     % f o oi []
1821         } {
1822           pop pop
1823         } ifelse
1824       } forall                                         % f o om' []
1825       //PDFR_DEBUG {
1826         (Obtaining subtable for ) print dup ==
1827       } if
1828       3 2 roll pop                                     % f o' []
1829       3 copy pop                                       % f o' [] f o'
1830       TablePos add //SkipToPosition exec               % f o' []
1831       3 copy exch pop 1 get                            % f o' [] l
1832       //TTParser /Pos //TTParser /Pos get 3 index add put
1833       string                                           % f o' [] f ()
1834       readstring not {
1835         mark (Can't read a cmap subtable.) //error exec
1836       } if                                             % f o' [] ()
1837       2 exch put                                       % f o'
1838     } repeat
1839     pop pop                                            %
1840   currentdict end                                      
1841   //PDFR_DEBUG {
1842     (ParseTTcmap end) =
1843   } if
1844 } bind def
1845
1846 /GetTTEncoding   % <file> <TTcmapHeader> <platformIDspecificID> GetTTEncoding <array>
1847 { //PDFR_DEBUG {
1848     (GetTTEncoding beg) =
1849   } if
1850   get                                      % f []
1851   exch pop                                 % []
1852   2 get
1853   10 dict begin % For local variables.
1854     /TTFDEBUG //PDFR_DEBUG def
1855     //cmaparray exec
1856   end
1857   //PDFR_DEBUG {
1858     (GetTTEncoding end) =
1859     dup ==
1860   } if
1861 } bind def
1862
1863 /InverseEncoding % <encoding> InverseEncoding <dict>
1864 {
1865   256 dict begin
1866     dup length 1 sub -1 0 {                       % E i
1867       2 copy get                                  % E i n
1868       exch                                        % E n i
1869       1 index currentdict exch //knownget exec {  % E n i e
1870         dup type /arraytype eq {
1871           aload length 1 add array astore         % E n e'
1872         } {
1873           2 array astore                          % E n e'
1874         } ifelse
1875       } if
1876       def
1877     } for
1878     pop
1879    currentdict end
1880 } bind def
1881
1882 /GetMacRomanEncodingInverse
1883 { //PDFReader /MacRomanEncodingInverse get 
1884   dup null eq {
1885     pop
1886     MacRomanEncoding //InverseEncoding exec
1887     dup //PDFReader exch /MacRomanEncodingInverse exch put
1888   } if
1889 } bind def
1890
1891 /PutCharStringSingle    % <cmap_array> <glyph_name> <char_code> PutCharStringSingle  <cmap_array>
1892 {
1893   dup 3 index length lt {                               % cmap name code
1894     2 index exch get                                    % cmap name glyphindex
1895     dup 0 ne {
1896       def                                               % cmap
1897     } {
1898       pop pop
1899     } ifelse
1900   } {
1901     pop pop                                             % cmap
1902   } ifelse
1903 } bind def
1904
1905 /PutCharString  % <cmap_array> <glyph_name> <char_code> PutCharString  <cmap_array>
1906 { 1 index type /nametype ne {
1907     mark (Bad charstring name) //error exec
1908   } if
1909   dup type /arraytype eq {
1910     {                                                   % cmap name code
1911       3 copy //PutCharStringSingle exec                 % cmap name code cmap
1912       pop pop                                           % cmap name
1913     } forall
1914     pop                                                 % cmap
1915   } {
1916     //PutCharStringSingle exec
1917   } ifelse
1918 } bind def
1919
1920 /ComposeCharStrings % <cmaparray> <dict> ComposeCharStrings <dict>
1921
1922   //PDFR_DEBUG {
1923     (ComposeCharStrings beg) =
1924   } if
1925   1 index length 1 add dict begin                       % cmap d
1926   % fixme : the dict length estimation doesn't account 'post'.
1927   /.notdef 0 def
1928   exch                                                  % d cmap
1929   //TTParser /post get                                  % d cmap [post]|null
1930   dup null ne {
1931     exch                                                % d [] cmap
1932     1 index length 1 sub -1 0 {                         % d [] cmap code
1933       dup 3 index exch get exch                         % d [] cmap name code
1934       dup 0 eq {
1935         pop pop
1936       } {
1937         def
1938       } ifelse
1939     } for
1940   } if
1941   exch pop exch                                         % cmap d
1942   {                                                     % cmap name code
1943     //PutCharString exec
1944   } forall                                              % cmap
1945   pop                                                   %
1946   currentdict end
1947   //PDFR_DEBUG {
1948     (ComposeCharStrings end) =
1949   } if
1950 } bind def
1951
1952 /ParseTTpost   % <file> <TableDirectory> ParseTTpost -
1953 { % Defines TTparser.post - an array, 
1954   % which maps glyph indices to glyph names.
1955   //PDFR_DEBUG {
1956     (ParseTTpost beg) =
1957   } if
1958   /post get aload pop                                   % f o L
1959   3 1 roll                                              % L f o
1960   //PDFR_DEBUG {
1961     (Current position = ) print //TTParser /Pos get =
1962     (post position = ) print dup =
1963   } if
1964   1 index exch //SkipToPosition exec                    % L f
1965   //TTParser /Pos //TTParser /Pos get 4 index add put
1966   exch string                                           % f s
1967   readstring not {
1968     mark (Insufficient data in the stream for ParseTTpost.) //error exec
1969   } if                                                  % s
1970   1 dict begin % A bridge to the code from /gs/lib/gs_ttf.ps .
1971     /post exch def
1972     //.getpost exec
1973     //TTParser /post glyphencoding put
1974     //PDFR_DEBUG {
1975       (ParseTTpost end) =
1976       glyphencoding ==
1977     } if
1978   end
1979 } bind def
1980
1981 /MakeTTCharStrings % <FontFile_object> MakeTTCharStrings <CharStrings>
1982 { //MakeStreamReader exec                               % f
1983   dup dup //ParseTTTableDirectory exec                  % f f d
1984   % Since the file isn't positionable,
1985   % we must pick up either 'post' or 'cmap' first.
1986   % Deside which one we do first :
1987   //TTParser /post null put
1988   dup /post //knownget exec {
1989     0 get
1990     1 index /cmap get 0 get
1991     lt {
1992       2 copy //ParseTTpost exec                         % f f d
1993       //ParseTTcmap exec                                % f ch
1994     } {
1995       2 copy //ParseTTcmap exec                         % f f d ch
1996       3 1 roll                                          % f ch f d
1997       //ParseTTpost exec                                % f ch
1998     } ifelse
1999   } {
2000     //ParseTTcmap exec                                  % f ch
2001   } ifelse
2002   {
2003     dup 16#00030001 known {
2004       //PDFR_DEBUG {
2005         (Using the TT cmap encoding for Windows Unicode.) =
2006       } if
2007       16#00030001 //GetTTEncoding exec
2008       AdobeGlyphList //ComposeCharStrings exec
2009       exit
2010     } if
2011     dup 16#00010000 known {
2012       //PDFR_DEBUG {
2013         (Using the TT cmap encoding for Macintosh Roman.) =
2014       } if
2015       16#00010000 //GetTTEncoding exec 
2016       PDFEncoding dup null eq {
2017         pop //GetMacRomanEncodingInverse exec
2018       } {
2019         //InverseEncoding exec
2020       } ifelse
2021       //ComposeCharStrings exec
2022       exit
2023     } if
2024     dup 16#00030000 known {
2025       //PDFR_DEBUG {
2026         (Using the TT cmap encoding 3.0 - not sure why Ghostscript writes it since old versions.) =
2027       } if
2028       % Same algorithm as for 16#00010000.
2029       16#00030000 //GetTTEncoding exec
2030       PDFEncoding dup null eq {
2031         pop //GetMacRomanEncodingInverse exec
2032       } {
2033         //InverseEncoding exec
2034       } ifelse
2035       //ComposeCharStrings exec
2036       exit
2037     } if
2038     mark (True Type cmap has no useful encodings.) //error exec
2039   } loop
2040   //PDFR_DEBUG {
2041     (CharStrings <<) =
2042     dup {
2043       exch
2044       dup type /nametype eq { 
2045         //=only exec 
2046       } {
2047         ==
2048       } ifelse
2049       ( ) print ==
2050     } forall
2051     (>>) =
2052   } if
2053 } bind def
2054
2055 %%end TrueType
2056
2057 % ===================== Functions ============================
2058
2059 /ScaleVal % <value> <Range> ScaleVal <scaled_value>
2060 {
2061   aload pop                                             % v r0 r1
2062   1 index sub                                           % v r0 r1-r0
2063   3 2 roll mul add
2064 } bind def
2065
2066 /ScaleArg % <arg> <Domain> ScaleArg <scaled_arg>
2067 {
2068   aload pop                                             % a d0 d1
2069   1 index sub                                           % a d0 d1-d0
2070   3 1 roll                                              % d1-d0 a d0
2071   sub exch div                                          % (a-d0)/(d1-d0)
2072 } bind def
2073
2074 /ScaleArgN % <arg1> ... <argN> <Domain> ScaleArg <scaled_arg1> ... <scaled_argN>
2075 {
2076   dup length 2 sub -2 0 {                               % a1 ... an [] 2i
2077     2                                                   % a1 ... an [] 2i 2
2078     2 index 3 1 roll getinterval                        % a1 ... an [] []
2079     3 2 roll                                            % a1 ... [] [] an
2080     exch //ScaleArg exec                                % a1 ... [] an'
2081     1 index length 2 idiv 1 add 1 roll                  % an' a1 ... []
2082   } for                                                 % a1' ... an' []
2083   pop                                                   % a1' ... an'
2084 } bind def
2085
2086
2087 /ComputeFunction_10 % <scaled_arg> <sample_array> ComputeFunction_10 <result>
2088 { % Assuming a 1-argument 1-result function type 0.
2089   //PDFR_DEBUG {
2090     (ComputeFunction_10 beg ) print 1 index //=only exec ( stack=) print count =
2091   } if
2092   exch                                                  % [] x
2093   dup 1 eq {
2094     pop dup length 1 sub get                            % y
2095   } {
2096     1 index length 1 sub mul                            % [] x*(l-1)
2097     dup dup floor sub                                   % [] x*(l-1) f
2098     dup 0 eq {
2099       pop cvi get                                       % y
2100     } {
2101       3 1 roll floor cvi                                % f [] i
2102       2 getinterval                                     % f []
2103       aload pop                                         % f y0 y1
2104       2 index mul 3 2 roll 1 exch sub 3 2 roll mul add  % y1*f+(1-f)*y0
2105     } ifelse
2106   } ifelse
2107   //PDFR_DEBUG {
2108     (ComputeFunction_10 end ) print dup //=only exec ( stack=) print count =
2109   } if
2110 } bind def
2111
2112 /ComputeFunction_n0 % <arg1> .... <argn> <sample_array> <n> ComputeFunction_n0 <result>
2113 { % Assuming a n-argument 1-result function type 0.
2114   //PDFR_DEBUG {
2115     (ComputeFunction_n0 beg N=) print dup //=only exec ( stack=) print count =
2116   } if
2117   dup 0 eq {                                   % v 0
2118     pop                                        % v
2119   } {                                          
2120     dup 2 add -1 roll                          % a2 .... an [] n a1
2121     dup 3 index length 1 sub ge {
2122       pop 1 sub                                % a2 .... an [] n-1
2123       exch dup length 1 sub get exch
2124       //PDFReader /ComputeFunction_n0 get exec
2125     } {
2126       dup floor cvi dup                        % a2 .... an [] n a1 i i
2127       4 index exch get                         % a2 .... an [] n a1 i [i]
2128       3 index dup                              % a2 .... an [] n a1 i [i] n n
2129       5 add copy                               % a2 .... an [] n a1 i [i] n a2 .... an [] n a1 i [i] n
2130       6 2 roll                                 % a2 .... an [] n a1 i [i] n a2 .... an [i] n [] n a1 i
2131       pop pop pop pop                          % a2 .... an [] n a1 i [i] n a2 .... an [i] n 
2132       1 sub                                    % a2 .... an [] n a1 i [i] n a2 .... an [i] n-1
2133       //PDFReader /ComputeFunction_n0 get exec % a2 .... an [] n a1 i [i] n v0
2134       3 2 roll pop                             % a2 .... an [] n a1 i n v0
2135       exch                                     % a2 .... an [] n a1 i v0 n
2136       4 3 roll exch                            % a2 .... an [] n i v0 a1 n
2137       4 add 2 roll 1 add                       % v0 a1 a2 .... an [] n i+1
2138       3 2 roll exch get                        % v0 a1 a2 .... an n [i+1]
2139       exch 1 sub                               % v0 a1 a2 .... an [i+1] n-1
2140       //PDFReader /ComputeFunction_n0 get exec % v0 a1 v1
2141       1 index mul                              % v0 a1 v1*a1
2142       3 1 roll                                 % v1*a1 v0 a1
2143       1 exch sub mul add                       % v1*a1+v0*(1-a1)
2144     } ifelse
2145   } ifelse
2146   //PDFR_DEBUG {
2147     (ComputeFunction_n0 end ) print dup //=only exec ( stack=) print count =
2148   } if
2149 } bind def
2150
2151 /FunctionToProc_x01 % <function_dict> FunctionToProc_x01 <proc>
2152 { % Assuming a n-argument 1-result function type 0.
2153   % The stream is already converted to the array /Data.
2154   dup /Domain get exch
2155   dup /Data get 0 get exch
2156   /Size get length 
2157   [ 4 1 roll
2158     //PDFR_DEBUG {
2159       { (function beg, stack =) print count //=only exec (\n) print } /exec load
2160       5 2 roll
2161     } if
2162     dup 1 gt {                                 % a1 ... an Domain Data n
2163       { mark exch                              % a1 ... an Domain Data [ n
2164         3 add 2 roll                           % Data [ a1 ... an Domain
2165         //ScaleArgN exec                       % Data [ a1 ... an
2166         counttomark dup                        % Data [ a1 ... an n n
2167         3 add -2 roll                          % a1 ... an n Data [
2168         pop exch                               % a1 ... an Data n
2169         //ComputeFunction_n0 exec
2170       } /exec load
2171     } {
2172       pop                                      % a1 Domain Data
2173       3 1 /roll load //ScaleArg /exec load     % Data a1s
2174       /exch load
2175       //ComputeFunction_10 /exec load
2176     } ifelse
2177     //PDFR_DEBUG {
2178       (function end, stack =) /print load /count load //=only /exec load (\n) /print load
2179     } if
2180   ] cvx
2181   //PDFR_DEBUG {
2182     (Made a procedure for the 1-result function :) =
2183     dup ==
2184   } if
2185 } bind def
2186
2187 /FunctionProcDebugBeg  %  - FunctionProcDebugBeg -
2188 { (FunctionProcDebugBeg ) print count =
2189 } bind def
2190
2191 /FunctionProcDebugEnd  %  - FunctionProcDebugEnd -
2192 { (FunctionProcDebugEnd ) print count =
2193 } bind def
2194
2195 /FunctionToProc_x0n % <function_dict> <m> FunctionToProc_x0n <proc>
2196 { % Assuming a n-argument m-result function type 0.
2197   % The stream is already converted to the array /Data.
2198   %
2199   % Making the procedure : { Domain //ScaleArg exec ... n copy {} exec n+1 1 roll ... }
2200   % except "n copy" for the last chunk.
2201   %
2202   PDFR_DEBUG {
2203     (FunctionToProc_x0n beg m=) print dup =
2204   } if
2205   1 index /Size get length exch                         % f n m
2206   dup 7 mul 2 add array                                 % f n m []
2207   PDFR_DEBUG {
2208     dup 0 //FunctionProcDebugBeg put
2209   } {
2210     dup 0 //DoNothing put
2211   } ifelse
2212   dup 1 /exec load put
2213   dup 2 5 index /Domain get put
2214   2 index 1 eq {
2215     dup 3 //ScaleArg put
2216   } {
2217     dup 3 //ScaleArgN put
2218   } ifelse
2219   dup 4 /exec load put
2220   1 index 1 sub 0 exch 1 exch {                         % f n m [] i
2221     dup 7 mul 5 add                                     % f n m [] i i1
2222     1 index 4 index 1 sub ne {
2223       dup 3 index exch 6 index put 1 add
2224       dup 3 index exch /copy load put 1 add
2225     } if
2226     [                                                   % f n m [] i i1 [
2227       6 index /Data get 3 index get                     % f n m [] i i1 [ di
2228       6 index 1 eq {
2229         //ComputeFunction_10 /exec load
2230       } {
2231         6 index
2232         //ComputeFunction_n0 /exec load
2233       } ifelse
2234     ] cvx                                               % f n m [] i i1 {}
2235     3 index exch 2 index exch put 1 add                 % f n m [] i i1
2236     2 index 1 index /exec load put 1 add
2237     1 index 4 index 1 sub ne {
2238       2 index 1 index 6 index 1 add put 1 add
2239       2 index 1 index 1 put 1 add
2240       2 index 1 index /roll load put                    % f n m [] i i1
2241     } if
2242     pop pop                                             % f n m []
2243   } for
2244   PDFR_DEBUG {
2245     dup dup length 2 sub //FunctionProcDebugEnd put
2246   } {
2247     dup dup length 2 sub //DoNothing put
2248   } ifelse
2249   dup dup length 1 sub /exec load put
2250   cvx exch pop exch pop exch pop
2251   //PDFR_DEBUG {
2252     (Made a procedure for the n-argument function :) =
2253     dup ==
2254   } if
2255   PDFR_DEBUG {
2256     (FunctionToProc_x0n end) =
2257   } if
2258 } bind def
2259
2260 /MakeTableRec % <func_obj> <n> MakeTableRec <array>
2261 {
2262   0 % to be bound below
2263   exec
2264 } bind def
2265
2266 /MakeTable % <func_obj> <n> MakeTable <array>
2267 { //PDFR_DEBUG {
2268     (MakeTable beg ) print count =
2269   } if
2270   1 index /Size get exch                                % f S N
2271   1 sub dup                                             % f S n n
2272   3 1 roll                                              % f n S n
2273   get                                                   % f n s
2274   array                                                 % f n []
2275   1 index 0 eq {
2276     exch pop exch pop                                   % []
2277   } {
2278     dup length 1 sub -1 0 {                             % f n [] i
2279       3 index 3 index //MakeTableRec exec               % f n [] i []
2280       2 index 3 1 roll put                              % f n []
2281     } for
2282     exch pop exch pop
2283   } ifelse
2284   //PDFR_DEBUG {
2285     (MakeTable end ) print count =
2286   } if
2287 } bind def
2288
2289 //MakeTableRec 0 //MakeTable put
2290
2291 /StoreSample  % <value> <table> <dimensions> StoreSample -
2292 { % The reader is on the dictionary stack.
2293   1 sub 
2294   dup 0 eq {
2295     pop                                                 % v []
2296   } {
2297     -1 1 {                                              % v T i
2298       I exch get get                                    % v T[I[i]]
2299     } for                                               % v []
2300   } ifelse
2301   I 0 get 3 2 roll put
2302 } bind def
2303
2304 /ReadSample32   % - ReadSample32 <value>
2305 {
2306   4 {
2307     File read not {
2308       mark (Insufficient data for function.) //error exec
2309     } if
2310   } repeat
2311   pop % Ignore the last byte because it can't fit into 'real'.
2312   3 1 roll exch
2313   256 mul add 256 mul add
2314   //1_24_bitshift_1_sub div
2315 } bind def
2316
2317 /ReadSample   % - ReadSample <value>
2318 { % The reader in on the dictionary stack.
2319   Buffer BitsLeft BitsPerSample
2320   { 2 copy ge {
2321       exit
2322     } if
2323     3 1 roll 
2324     8 add 3 1 roll
2325     256 mul File read not {
2326       mark (Insufficient data for function.) //error exec
2327     } if
2328     add
2329     3 1 roll
2330   } loop                                                % b bl pbs
2331   sub dup                                               % b bl-bps bl-bps
2332   2 index exch                                          % b bl-bps b bl-bps
2333   neg bitshift                                          % b bl-bps v
2334   2 copy exch bitshift                                  % b bl-bps v v<<(bl-bps)
2335   4 3 roll exch sub                                     % bl-bps v b-(v<<(bl-bps))
2336   /Buffer exch def                                      % bl-bps v
2337   exch /BitsLeft exch def                               % v
2338   Div div                                               % v/(1<<pbs-1)
2339 } bind def
2340
2341 /ReadSamplesRec % <dimensions> ReadSamplesRec -
2342 { 0 % Will be bound below
2343   exec
2344 } bind def
2345
2346 /ReadSamples % <dimensions> ReadSamples -
2347 { % The reader in on the dictionary stack.
2348   //PDFR_DEBUG {
2349     (ReadSamples beg ) print count =
2350   } if
2351   dup 1 eq {
2352     pop
2353     0 1 Size 0 get 1 sub {
2354       I exch 0 exch put
2355       0 1 M 1 sub {
2356         dup Range exch 2 mul 2 getinterval              % m r 
2357         //PDFR_DEBUG {
2358           (Will read a sample ... ) print
2359         } if
2360         BitsPerSample 32 eq { //ReadSample32 } { //ReadSample } ifelse
2361         exec exch //ScaleVal exec                       % m v
2362         //PDFR_DEBUG {
2363           (value=) print dup =
2364         } if
2365         exch Table exch get                             % v []
2366         Size length //StoreSample exec                  %
2367       } for
2368     } for
2369   } {
2370     1 sub 
2371     dup Size exch get 0 exch 1 exch 1 sub {             % d-1 i
2372       I exch 2 index exch put                           % d-1
2373       dup //ReadSamplesRec exec                         % d-1
2374     } for
2375     pop
2376   } ifelse
2377   //PDFR_DEBUG {
2378     (ReadSamples end ) print count =
2379   } if
2380 } bind def
2381
2382 //ReadSamplesRec 0 //ReadSamples put
2383
2384 /StreamToArray % <obj> StreamToArray -
2385 { //PDFR_DEBUG {
2386     (StreamToArray beg ) print count =
2387   } if
2388   currentglobal true setglobal exch
2389   userdict /FuncDataReader get begin                    % g f
2390     dup /BitsPerSample get /BitsPerSample exch def
2391     dup /Size get length /N exch def
2392     dup /Range get length 2 idiv /M exch def
2393     1 BitsPerSample bitshift 1 sub /Div exch def
2394     /BitsLeft 0 def
2395     /Buffer 0 def
2396     dup /Size get /Size exch def                        % g f
2397     dup /Range get /Range exch def                      % g f
2398     /File 1 index //MakeStreamReader exec def           % g f
2399     /I [ N { 0 } repeat ] def                           % g f
2400     M array                                             % g f []
2401     dup length 1 sub -1 0 {                             % g f [] m
2402       2 index N //MakeTable exec                        % g f [] m T
2403       2 index 3 1 roll put                              % g f []
2404     } for
2405     /Table exch def                                     % g f
2406     N //ReadSamples exec                                % g f
2407     PDFR_DEBUG {
2408       (Table = ) print Table ==
2409     } if
2410     /Data Table put                                     % g
2411   end
2412   setglobal                                             %
2413   //PDFR_DEBUG {
2414     (StreamToArray end ) print count =
2415   } if
2416 } bind def
2417
2418 /FunctionToProc10 % <function_dict> FunctionToProc10 <proc>
2419 { % Assuming a 1-argument function type 0.
2420   PDFR_DEBUG {
2421     (FunctionToProc10 beg, Range = ) print dup /Range get ==
2422   } if
2423   dup /Order //knownget exec {
2424     1 ne {
2425       (Underimplemented function Type 0 Order 3.) =
2426     } if
2427   } if
2428   dup //StreamToArray exec                              % f
2429   dup /Range get length dup 2 eq {
2430     pop //FunctionToProc_x01 exec                       % proc
2431   } {
2432     2 idiv //FunctionToProc_x0n exec                    % proc
2433   } ifelse
2434   PDFR_DEBUG {
2435     (FunctionToProc10 end) =
2436   } if
2437 } bind def
2438
2439 /FunctionToProc12 % <function_dict> FunctionToProc12 <proc>
2440 { begin
2441     currentdict /C0 //knownget exec { length 1 eq } { true } ifelse {
2442       N
2443       currentdict /C0 //knownget exec {
2444         0 get
2445       } {
2446         0
2447       } ifelse
2448       currentdict /C1 //knownget exec {
2449         0 get
2450       } {
2451         1
2452       } ifelse
2453       1 index sub
2454       [ 4 1 roll
2455         {               % x n c0 c1-c0
2456           4 2 roll      % c0 c1-c0 x n
2457           excp mul add  % y
2458         } aload pop
2459       ] cvx
2460     } { 
2461         [ 
2462           0 1 C0 length 1 sub {
2463             N                                           % [ ... i n
2464             C0 2 index get                              % [ ... i n c0
2465             C1 3 index get                              % [ ... i n c0 c1
2466             4 3 roll pop                                % [ ... n c0 c1
2467             1 index sub                                 % [ ... n c0 c1-c0
2468             [ /dup load                                 % [ ... n c0 c1-c0 [ dup
2469               5 2 roll                                  % [ ... [ dup n c0 c1-c0
2470               {                 % x x n c0 c1-c0        
2471                 4 2 roll        % x c0 c1-c0 x n
2472                 exp mul add     % x y
2473                 exch            % y x
2474               } aload pop
2475             ] cvx 
2476             /exec load
2477           } for
2478           /pop load
2479         ] cvx
2480     } ifelse
2481   end
2482   //PDFR_DEBUG {
2483     (FunctionType2Proc : ) print dup == 
2484   } if
2485 } bind def
2486
2487
2488 /FunctionToProc14 % <function_dict> FunctionToProc14 <proc>
2489 { //MakeStreamReader exec cvx exec
2490   //PDFR_DEBUG {
2491     (FunctionType4Proc : ) print dup == 
2492   } if
2493 } bind def
2494
2495 /FunctionToProc1 % <function_dict> FunctionToProc <proc>
2496 { % Assuming a 1-argument function.
2497   dup /FunctionType get
2498   { dup 0 eq {
2499       pop //FunctionToProc10 exec exit
2500     } if
2501     dup 2 eq {
2502       pop //FunctionToProc12 exec exit
2503     } if
2504     dup 4 eq {
2505       pop //FunctionToProc14 exec exit
2506     } if
2507     mark exch (Function type ) exch ( isn't implemented yet.) //error exec
2508   } loop
2509 } bind def
2510
2511 /FunctionToProc20 % <function_dict> FunctionToProc20 <proc>
2512 { % Assuming a 2-argument function type 0.
2513   PDFR_DEBUG {
2514     (FunctionToProc20, Range = ) print dup /Range get ==
2515   } if
2516   dup /Order //knownget exec {
2517     1 ne {
2518       (Underimplemented function Type 0 Order 3.) =
2519     } if
2520   } if
2521   dup //StreamToArray exec                              % f
2522   dup /Range get length dup 2 eq {
2523     pop //FunctionToProc_x01 exec                       % proc
2524   } {
2525     2 idiv //FunctionToProc_x0n exec                    % proc
2526   } ifelse
2527 } bind def
2528
2529 /FunctionToProc % <function_dict> FunctionToProc <proc>
2530 { //PDFR_DEBUG {
2531     (FunctionToProc beg ) print count =
2532   } if
2533   dup /Domain get length 2 idiv
2534   {
2535     dup 1 eq {
2536       pop //FunctionToProc1 exec exit
2537     } if
2538     dup 2 eq {
2539       pop //FunctionToProc20 exec exit
2540     } if
2541     mark (Functions with many arguments aren't implemented yet.) //error exec
2542   } loop
2543   //PDFR_DEBUG {
2544     (FunctionToProc end ) print count =
2545   } if
2546 } bind def
2547
2548 /spotfunctions mark  % Copied from pdf_draw.ps 
2549   /Round {
2550     abs exch abs 2 copy add 1 le {
2551       dup mul exch dup mul add 1 exch sub 
2552     } {
2553       1 sub dup mul exch 1 sub dup mul add 1 sub
2554     } ifelse
2555   }
2556   /Diamond {
2557     abs exch abs 2 copy add .75 le {
2558       dup mul exch dup mul add 1 exch sub
2559     } {
2560       2 copy add 1.23 le {
2561         .85 mul add 1 exch sub
2562       } {
2563         1 sub dup mul exch 1 sub dup mul add 1 sub
2564       } ifelse
2565     } ifelse
2566   }
2567   /Ellipse {
2568     abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
2569       pop dup mul exch .75 div dup mul add 4 div 1 exch sub
2570     } {
2571       dup 1 gt {
2572         pop 1 exch sub dup mul exch 1 exch sub
2573         .75 div dup mul add 4 div 1 sub
2574       } {
2575         .5 exch sub exch pop exch pop
2576       } ifelse
2577     } ifelse
2578   }
2579   /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
2580   /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
2581   /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
2582   /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
2583   /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
2584   /Line { exch pop abs neg }
2585   /LineX { pop }
2586   /LineY { exch pop }
2587   /Square { abs exch abs 2 copy lt { exch } if pop neg }
2588   /Cross { abs exch abs 2 copy gt { exch } if pop neg }
2589   /Rhomboid { abs exch abs 0.9 mul add 2 div }
2590   /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
2591   /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
2592   /SimpleDot { dup mul exch dup mul add 1 exch sub }
2593   /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
2594   /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
2595   /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
2596   /InvertedDouble {
2597     exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
2598   }
2599 .dicttomark readonly def
2600
2601 % ===================== Color Spaces and Colors ==============
2602
2603 /CheckColorSpace %  <key> <val> CheckColorSpace  <key> <val>
2604 {
2605   dup type /arraytype ne {
2606     mark (Resource ) 3 index ( must be an array.) //error exec
2607   } if
2608 } bind def
2609
2610 /SubstitutePDFColorSpaceRec  % <array> SubstitutePDFColorSpace <array>
2611 { 0 % Will be bound below
2612   exec
2613 } bind def
2614
2615 /SubstitutePDFColorSpace % <array> SubstitutePDFColorSpace <array>
2616 { currentglobal true setglobal exch
2617   { 
2618     dup 0 get /Pattern eq {
2619       dup length 1 gt {
2620         dup dup 1 //CheckColorSpace //ResolveA exec
2621         dup type /nametype ne {
2622           //SubstitutePDFColorSpaceRec exec
2623         } if
2624         1 exch put
2625       } if
2626       exit
2627     } if
2628     dup 0 get /Indexed eq {
2629       exit
2630     } if
2631     dup 0 get /Separation eq {
2632       dup dup 2 //CheckColorSpace //ResolveA exec
2633       dup type /nametype ne {
2634         //SubstitutePDFColorSpaceRec exec
2635       } if
2636       2 exch put
2637       exit
2638     } if
2639     dup 0 get /CalGray eq {
2640       1 get                                             % dict
2641       dup /Gamma //knownget exec {
2642         [ exch /exp load ] cvx
2643         1 index exch /DecodeLMN exch put
2644       } if                              
2645       [ exch /CIEBasedA exch ]                          % []
2646       exit
2647     } if
2648     dup 0 get /CalRGB eq {
2649       1 get                                             % dict
2650       dup /Matrix //knownget exec { 
2651         1 index exch /MatrixLMN exch put
2652       } if
2653       dup /Gamma //knownget exec {
2654         aload pop
2655         [ exch /exp load ] cvx
2656         3 1 roll
2657         [ exch /exp load ] cvx
2658         3 1 roll
2659         [ exch /exp load ] cvx
2660         3 1 roll
2661         3 array astore
2662         1 index exch /DecodeLMN exch put
2663       } if                              
2664       [ exch /CIEBasedABC exch ]                        % []
2665       exit
2666     } if
2667     dup 0 get /Lab eq {
2668       1 get                                             % dict
2669       begin
2670         currentdict /Range //knownget exec { aload pop } { -100 100 -100 100 } ifelse
2671           0 100 6 2 roll 6 array astore 
2672           /RangeABC exch def
2673         /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
2674         /MatrixABC [1 1 1 1 0 0 0 0 -1] def
2675         { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
2676         /DecodeLMN [
2677           % Store white point implicitly inside procedures.
2678           [ 3 index aload pop WhitePoint 0 get /mul load ] cvx
2679           [ 4 index aload pop WhitePoint 1 get /mul load ] cvx
2680           [ 5 index aload pop WhitePoint 2 get /mul load ] cvx
2681         ] def pop
2682         //PDFR_DEBUG {
2683           (Constructed from Lab <<) =
2684           currentdict { exch = == } forall
2685           (>>) =
2686         } if
2687         [ /CIEBasedABC currentdict ]                    % []
2688       end
2689       exit
2690       pop
2691     } if
2692     mark exch (Unimplemented color space ) exch //error exec
2693   } loop
2694   exch setglobal
2695 } bind def
2696
2697 //SubstitutePDFColorSpaceRec 0 //SubstitutePDFColorSpace put
2698
2699 /ResolveArrayElement  % <array> <index> ResolveArrayElement <array>
2700 { 2 copy get xcheck {
2701     2 copy get exec
2702     2 index 4 1 roll put
2703   } {
2704     pop
2705   } ifelse
2706 } bind def
2707
2708 /ResolveColorSpaceArrayRec  % <color_space> ResolveColorSpaceArrayRec <color_space>
2709 { 0 % Will be bond below.
2710   exec
2711 } bind def
2712
2713 /SetColorSpaceSafe % <color_space> SetColorSpaceSafe -
2714 {
2715   % This works against applying a pattern over a pattern space,
2716   % which may happen due to duplication of stroking and non-stroking colors.
2717   % gs3.70 fails when setting a pattern space and 
2718   % the (old) current color space is a pattern space.
2719   %
2720   % If the new color space is an array and it appears equal to the old one, 
2721   % do nothing. Otherwise set the new color space.
2722   PDFR_DEBUG {
2723     (SetColorSpaceSafe beg) =
2724   } if
2725   currentcolorspace dup type /arraytype eq {     % cs cs'
2726     1 index type /arraytype eq {
2727       dup length 2 index length eq {
2728         false exch                               % cs b cs'
2729         dup length 0 exch 1 exch 1 sub {         % cs b cs' i
2730           dup                                    % cs b cs' i i
2731           4 index exch get exch                  % cs b cs' csi i
2732           2 index exch get                       % cs b cs' csi cs'i
2733           ne {                                   % cs b cs'
2734             exch pop true exch exit
2735           } if
2736         } for                                    % cs b cs'
2737         pop                                      % cs b
2738         { 
2739           setcolorspace
2740         } {
2741           pop
2742         } ifelse                                 %
2743       } {
2744         pop setcolorspace
2745       } ifelse
2746     } {
2747       pop setcolorspace
2748     } ifelse
2749   } {                                            % cs cs'
2750     pop setcolorspace
2751   } ifelse
2752   PDFR_DEBUG {
2753     (SetColorSpaceSafe end) =
2754   } if
2755 } bind def
2756
2757 /ResolveColorSpaceArray  % <color_space> ResolveColorSpaceArray <color_space>
2758 {
2759   //PDFR_DEBUG {
2760     (ResolveColorSpaceArray beg ) print dup ==
2761   } if
2762   currentglobal true setglobal exch
2763   dup 0 get /Indexed eq {
2764     1 //ResolveArrayElement exec
2765     dup dup 1 get 
2766     dup type /arraytype eq {
2767       //SubstitutePDFColorSpace exec 
2768       //ResolveColorSpaceArrayRec exec
2769       1 exch put
2770     } {
2771       pop pop
2772     } ifelse
2773   } if
2774   dup 0 get /Separation eq {
2775     3 //ResolveArrayElement exec
2776     dup 3 get //FunctionToProc exec
2777     2 copy 3 exch put
2778     pop
2779   } if
2780   PDFR_DEBUG {
2781     (Construcrted color space :) =
2782     dup ==
2783   } if
2784   exch setglobal
2785   //PDFR_DEBUG {
2786     (ResolveColorSpaceArray end ) print dup ==
2787   } if
2788 } bind def
2789
2790 //ResolveColorSpaceArrayRec 0 //ResolveColorSpaceArray put
2791
2792 /ResolveColorSpace  % <name> ResolveColorSpace <color_space>
2793
2794   //PDFR_DEBUG {
2795     (ResolveColorSpace beg ) print dup =
2796   } if
2797   dup //SimpleColorSpaceNames exch known not {
2798     dup //PDFColorSpaces exch //knownget exec {
2799       exch pop
2800       //PDFR_DEBUG {
2801         (ResolveColorSpace known ) =
2802       } if
2803     } {
2804       dup                                               % n n
2805       //PDFReader /CurrentObject get /Context get /Resources get 
2806       /ColorSpace //DoNothing //ResolveD exec
2807       exch //CheckColorSpace //ResolveD exec            % n cs
2808       dup type /arraytype eq {
2809         //SubstitutePDFColorSpace exec
2810         //ResolveColorSpaceArray exec
2811         dup //PDFColorSpaces 4 2 roll put               % []
2812       } if
2813     } ifelse
2814   } if
2815   //PDFR_DEBUG {
2816     (ResolveColorSpace end ) print dup ==
2817   } if
2818 } bind def
2819
2820 /CheckPattern %  <key> <val> CheckPattern  <key> <val>
2821 {
2822   dup /PatternType //knownget exec {
2823     dup 1 ne {
2824       mark (Resource ) 4 index ( is a shading, which can't be handled at level 2. ) //error exec
2825     } if
2826     pop
2827   } if
2828   dup /Type get /Pattern ne {
2829     mark (Resource ) 4 index ( must have /Type/Pattern .) //error exec
2830   } if
2831 } bind def
2832
2833 /PaintProc % 
2834 { /Context get                                          % pattern_object
2835   //RunDelayedStream exec
2836 } bind def
2837
2838 /ResolvePattern % <name> ResolvePattern <pattern>
2839 {
2840   dup                                                   % n n
2841   % Since makepattern makes a local dictionary,
2842   % we cahche them in userdict, which is in local VM.
2843   % Assuming unique resource name through the document
2844   userdict /PDFR_Patterns get                           % n n d
2845   exch //knownget exec {                                % n p
2846     exch pop                                            % p
2847   } {                                                   % n
2848     dup                                                 % n n
2849     //PDFReader /CurrentObject get /Context get /Resources get 
2850     /Pattern //DoNothing //ResolveD exec
2851     exch //CheckPattern //ResolveD exec                 % n o
2852     dup dup /Context exch put
2853     dup /Resources //DoNothing //ResolveD exec pop
2854     dup /PaintProc //PaintProc put
2855     gsave userdict /PDFR_InitialGS get setgstate
2856     currentglobal exch false setglobal % gs3_70 compatibility
2857     dup /Matrix get
2858     makepattern                                         % n p
2859     exch setglobal % gs3_70 compatibility
2860     grestore
2861     dup userdict /PDFR_Patterns get                     % n p p d
2862     4 2 roll                                            % p d n p
2863     put                                                 % p
2864   } ifelse
2865 } bind def
2866
2867 /SetColor % Same arguments and result as for scn
2868 { //PDFR_DEBUG {
2869     (SetColor beg) =
2870   } if
2871   currentcolorspace dup type /nametype eq {
2872     pop setcolor    
2873   } {
2874     0 get /Pattern eq {
2875       //ResolvePattern exec setpattern
2876     } {
2877       setcolor
2878     } ifelse
2879   } ifelse
2880   //PDFR_DEBUG {
2881     (SetColor end) =
2882   } if
2883 } bind def
2884
2885 % ===================== Images ===============================
2886
2887 /ImageKeys 15 dict begin
2888   /BPC /BitsPerComponent def
2889   /CS /ColorSpace def
2890   /D /Decode def
2891   /DP /DecodeParms def
2892   /F /Filter def
2893   /H /Height def
2894   /IM /ImageMask def
2895   % /Intent is undefined - pdfwrite must take care of.
2896   /I /Interpolate def
2897   /W /Width def
2898 currentdict end readonly def
2899
2900 /ImageValues 15 dict begin
2901   /G   /DeviceGray def
2902   /RGB /DeviceRGB def
2903   /CMYK /DeviceCMYK def 
2904   /I   /Indexed def
2905   /AHx /ASCIIHexDecode def
2906   /A85 /ASCII85Decode def
2907   /LZW /LZWDecode def
2908   /Fl  /FlateDecode def
2909   /RL  /RunLengthDecode def
2910   /CCF /CCITTFaxDecode def
2911   /DCT /DCTDecode def
2912 currentdict end readonly def
2913
2914 /GetColorSpaceRange
2915 { 2 index /ColorSpace get
2916   dup type /arraytype eq {
2917     1 get
2918   } if
2919   exch //knownget exec {
2920     exch pop
2921   } if
2922 } bind def
2923
2924 /DecodeArrays 15 dict begin
2925   /DeviceGray { [0 1] } def
2926   /DeviceRGB { [0 1 0 1 0 1] } def
2927   /DeviceCMYK { [0 1 0 1 0 1 0 1] } def 
2928   /Indexed { dup /ColorSpace get 2 get [ exch 0 exch ] } def
2929   /Separation { [0 1] } def
2930   /CIEBasedA { [0 1]  /RangeA //GetColorSpaceRange exec } def
2931   /CIEBasedABC { [0 1 0 1 0 1] /RangeABC //GetColorSpaceRange exec } def
2932 currentdict end readonly def
2933
2934 /Substitute % <key> <dict> Substitute <key>
2935 { 1 index //knownget exec {
2936     exch pop
2937   } if
2938 } bind def
2939
2940 /DebugImagePrinting  % <image_dict> DebugImagePrinting <image_dict>
2941 {
2942   //PDFR_DEBUG {
2943     (Image :) =
2944     dup { exch //=only exec ( ) print == 
2945     } forall
2946   } if
2947 } bind def
2948
2949 /CompleteImage  % <dict> CompleteImage <image_dict>
2950 {
2951   dup /ColorSpace known {
2952     dup /ColorSpace //CheckColorSpace //ResolveD exec pop
2953   } if
2954   dup /Decode known not {
2955     dup /ColorSpace //knownget exec { 
2956       dup type /arraytype eq {
2957         0 get
2958       } if
2959       //DecodeArrays exch get exec 
2960     } {
2961       [0 1]
2962     } ifelse
2963     1 index exch /Decode exch put
2964   } if
2965   dup /ImageMatrix [2 index /Width get 0 0 5 index /Height get neg 
2966                                         0 7 index /Height get] put % Not sure why upside down ?
2967   //DebugImagePrinting exec
2968 } bind def
2969
2970 /CompleteInlineImage  % <dict> CompleteInlineImage <image_dict>
2971 {
2972   //PDFR_DEBUG {
2973     (CompleteInlineImage beg) =
2974   } if
2975   dup /ImageType known not {
2976     dup /ImageType 1 put
2977   } if
2978   dup length dict exch {                            % d key val
2979     exch //ImageKeys //Substitute exec
2980     dup /Filter eq {
2981       exch //ImageValues //Substitute exec exch
2982     } if
2983     dup /ColorSpace eq {
2984       exch 
2985       dup //ImageValues exch //knownget exec {
2986         exch pop
2987       } {
2988         //ResolveColorSpace exec
2989       } ifelse
2990       exch
2991     } if
2992     exch
2993     2 index 3 1 roll put
2994   } forall
2995   //CompleteImage exec
2996   dup /DataSource 2 copy get                        % d d /n f
2997   2 index //AppendFilters exec put
2998   //PDFR_DEBUG {
2999     (CompleteInlineImage end) =
3000   } if
3001 } bind def
3002
3003 /CompleteOutlineImage  % <dict> CompleteOutlineImage <image_dict>
3004
3005   currentglobal exch dup gcheck setglobal
3006   //PDFR_DEBUG {
3007     (CompleteOutlineImage beg) =
3008   } if
3009   % todo: ResetStreamReader if DataSource already exists.
3010   dup dup //MakeStreamReader exec /DataSource exch put
3011   dup /ImageType known not {
3012     //CompleteImage exec
3013     dup /ImageType 1 put
3014     dup /ColorSpace known {
3015       dup /ColorSpace //CheckColorSpace //ResolveD exec
3016       dup type /arraytype eq {
3017         //ResolveColorSpaceArray exec
3018         //SubstitutePDFColorSpace exec
3019         1 index exch /ColorSpace exch put
3020       } {
3021         pop
3022       } ifelse
3023     } if
3024   } if
3025   //PDFR_DEBUG {
3026     (CompleteOutlineImage end) =
3027   } if
3028   exch setglobal
3029 } bind def
3030
3031 /DoImage % <image_dict> DoImage -
3032 {
3033   //PDFR_DEBUG {
3034     (DoImage beg) =
3035   } if
3036   gsave
3037   dup /ColorSpace //knownget exec { setcolorspace } if
3038   dup /ImageMask //knownget exec not { false } if
3039   { imagemask } { image } ifelse 
3040   grestore
3041   //PDFR_DEBUG {
3042     (DoImage end) =
3043   } if
3044 } bind def
3045
3046 % ===================== Viewer State ===============
3047
3048 /GSave % - GSave -
3049 {
3050   gsave
3051   //PDFReader /GraphicStateStackPointer get
3052   dup //GraphicStateStack exch get null eq {
3053     currentglobal true setglobal exch
3054     dup //GraphicStateStack exch //InitialGraphicState length dict put 
3055     exch setglobal
3056   } if
3057   dup //GraphicStateStack exch get
3058   //GraphicState exch copy pop
3059   1 add //PDFReader exch /GraphicStateStackPointer exch put
3060 } bind def
3061
3062 /GRestore % - GRestore -
3063 {
3064   grestore
3065   //PDFReader /GraphicStateStackPointer get
3066   1 sub dup
3067   //PDFReader exch /GraphicStateStackPointer exch put
3068   //GraphicStateStack exch get
3069   //GraphicState copy pop
3070 } bind def
3071
3072
3073 % ===================== Interpret Data Streams ===============
3074
3075 /SetFont  % <resource_name> <size> SetFont -
3076 { dup //GraphicState exch /FontSize exch put
3077   //ResolveAndSetFont exec
3078 } bind def
3079
3080 /ShowText  % <string> ShowText -
3081 { //GraphicState /TextRenderingMode get 0 eq {
3082     //GraphicState /WordSpacing get 0
3083     32
3084     //GraphicState /CharacterSpacing get 0
3085     6 5 roll awidthshow
3086   } {
3087     //GraphicState /CharacterSpacing get 0 eq
3088     //GraphicState /WordSpacing get 0 eq and {
3089       true charpath
3090     } {
3091       % Emulate with "{ charpath } cshow".
3092       % Not sure how it works with CID fonts.
3093       {                                                 % c wx wy
3094         currentpoint 5 4 roll                           % wx wy x y c
3095         ( ) dup 0 3 index put true charpath             % wx wy x y c
3096         5 1 roll                                        % c wx wy x y
3097         moveto rmoveto                                  % c
3098         //GraphicState /CharacterSpacing get 0 rmoveto  % c
3099         32 eq {                                         %
3100           //GraphicState /WordSpacing get 0 rmoveto
3101         } if
3102       }
3103       exch cshow
3104     } ifelse
3105   } ifelse
3106 } bind def
3107
3108 /ShowTextBeg  % - ShowTextBeg -
3109 { //GraphicState /TextRenderingMode get 0 ne {
3110         currentpoint newpath moveto
3111   } if
3112 } bind def
3113
3114 /ShowTextEnd  % - ShowTextEnd -
3115 { //GraphicState /TextRenderingMode get
3116   { dup 1 eq {
3117       stroke exit
3118     } if
3119     dup 2 eq {
3120       gsave fill grestore stroke exit
3121     } if
3122     dup 3 eq {
3123       currentpoint newpath moveto
3124     } if
3125     dup 4 eq {
3126       gsave fill grestore clip exit
3127     } if
3128     dup 5 eq {
3129       gsave stroke grestore clip exit
3130     } if
3131     dup 6 eq {
3132       gsave fill grestore gsave stroke grestore fill exit
3133     } if
3134     dup 7 eq {
3135       clip exit
3136     } if
3137     exit
3138   } loop
3139   pop
3140 } bind def
3141
3142 /ShowTextWithGlyphPositioning % <array> ShowTextWithGlyphPositioning -
3143 { //ShowTextBeg exec
3144   { dup type /stringtype eq {
3145       //ShowText exec
3146     } {
3147       neg 1000 div //GraphicState /FontSize get mul 0 rmoveto
3148     } ifelse
3149   } forall
3150   //ShowTextEnd exec
3151 } bind def
3152
3153 /CheckFont % key val CheckFont key val
3154 { dup /Type get /ExtGState ne {
3155     mark (Resource ) 3 index ( must have /Type/ExtGState.) //error exec
3156   } if
3157 } bind def
3158
3159 /SetTransfer % <operand> SetTransfer -
3160 {
3161   //PDFR_DEBUG { (SetTransfer beg ) print count = } if
3162   dup type /arraytype eq 1 index xcheck not and {
3163     0 4 getinterval aload pop 
3164     setcolortransfer
3165   } {
3166     settransfer
3167   } ifelse
3168   //PDFR_DEBUG { (SetTransfer end ) print count = } if
3169 } bind def
3170
3171 /CheckExtGState % <id> <obj> CheckExtGState <id> <obj>
3172 { dup /Type get /ExtGState ne {
3173     mark (Resource ) 3 index ( must have /Type/ExtGState.) //error exec
3174   } if
3175 } bind def
3176
3177 /CheckHalftone % <id> <obj> CheckHalftone <id> <obj>
3178 { dup /HalftoneType known not {
3179     mark (Resource ) 3 index ( must have /HalftoneType.) //error exec
3180   } if
3181 } bind def
3182
3183 /ResolveFunction % <dict> <name> ResolveFunction <dict> <proc>
3184 {
3185   //PDFR_DEBUG { (ResolveFunction beg ) print dup = count = } if
3186   2 copy get //IsObjRef exec {
3187     2 copy //DoNothing //ResolveD exec
3188     3 copy put pop
3189   } if
3190   2 copy get dup type /arraytype eq exch xcheck and not {
3191     2 copy get
3192     dup type /arraytype eq 1 index xcheck not and {
3193       dup length 1 sub -1 0 {
3194         2 copy //DoNothing ResolveA
3195         dup /Identity eq {
3196           pop 2 copy {} put
3197         } {
3198           //FunctionToProc exec
3199           3 copy put pop
3200         } ifelse
3201         pop
3202       } for
3203     } {
3204       dup /Default eq {
3205         % Leave it. ExtGState methods will resolve.
3206       } {
3207         dup /Identity eq {
3208           pop {}
3209         } { dup type /nametype eq {
3210             //spotfunctions exch get
3211           } {
3212             //FunctionToProc exec
3213           } ifelse
3214         } ifelse
3215       } ifelse
3216     } ifelse
3217     3 copy put
3218     exch pop
3219   } {
3220     1 index exch get
3221   } ifelse
3222   //PDFR_DEBUG { (ResolveFunction end ) print dup == count = } if
3223 } bind def
3224
3225 /ResolveFunctionSafe % <dict> <name> ResolveFunctionSafe <dict>
3226 { 2 copy known {
3227   //ResolveFunction exec
3228   } if
3229   pop
3230 } bind def
3231
3232 /CreateHalftoneThresholds  % <halftone_dict> CreateHalftoneThresholds <halftone_dict>
3233 {
3234   dup /Thresholds known not {
3235     dup /HalftoneType get 10 eq {
3236       dup dup //MakeStreamReader exec
3237       /Thresholds exch put
3238     } if
3239     dup /HalftoneType get dup 3 eq exch 6 eq or {
3240       dup dup //MakeStreamReader exec
3241       //BlockBuffer readstring pop
3242       dup length 
3243       dup 0 eq {
3244         mark (Could not read Thresholds) //error exec
3245       } if
3246       string copy /Thresholds exch put
3247       dup /HalftoneType 3 put % replace Type 6 with Type 3.
3248     } if
3249   } if
3250 } bind def
3251
3252
3253 /SetExtGState % <name> SetExtGState -
3254 {
3255   //PDFReader /CurrentObject get /Context get /Resources get 
3256   /ExtGState //DoNothing //ResolveD exec
3257   exch //CheckExtGState //ResolveD exec         % s gs
3258   dup /LW //knownget exec {
3259     setlinewidth
3260   } if
3261   dup /LC //knownget exec {
3262     setlinecap
3263   } if
3264   dup /LJ //knownget exec {
3265     setlinejoin
3266   } if
3267   dup /ML //knownget exec {
3268     setmeterlimit
3269   } if
3270   dup /D //knownget exec {
3271     setdash
3272   } if
3273   dup /RI //knownget exec {
3274     % Ghostscript never writes it.
3275     mark (Unimplemented ExtGState.RI) //error exec
3276   } if
3277   dup /OP //knownget exec {
3278     % pdfwrite must take care of stroking/filling
3279     setoverprint
3280   } if
3281   dup /op //knownget exec {
3282     setoverprint
3283   } if
3284   dup /OPM //knownget exec {
3285     % pdfwrite must take care of.
3286     mark (Unimplemented ExtGState.OPM) //error exec
3287   } if
3288   dup /Font //knownget exec {
3289     % Ghostscript never writes it.
3290     mark (Unimplemented ExtGState.Font) //error exec
3291   } if
3292   dup /BG known {
3293     /BG //ResolveFunction exec
3294     setblackgeneration
3295   } if
3296   dup /BG2 known {
3297     /BG2 //ResolveFunction exec
3298     dup /Default eq {
3299       //InitialExtGState /BG2 get
3300     } if
3301     setblackgeneration
3302   } if
3303   dup /UCR known {
3304     /UCR //ResolveFunction exec
3305     setundercolorremoval
3306   } if
3307   dup /UCR2 known {
3308     /UCR2 //ResolveFunction exec
3309     dup /Default eq {
3310       //InitialExtGState /UCR2 get
3311     } if
3312     setundercolorremoval
3313   } if
3314   dup /TR known {
3315     /TR //ResolveFunction exec
3316     //SetTransfer exec
3317   } if
3318   dup /TR2 known {
3319     /TR2 //ResolveFunction exec
3320     dup /Default eq {
3321       pop //InitialExtGState /TR2 get
3322       aload pop setcolortransfer
3323     } {
3324       //SetTransfer exec
3325     } ifelse
3326   } if
3327   dup /HT //knownget exec {
3328     dup /Default eq {
3329       pop //InitialExtGState /HT get
3330       sethalftone
3331     } {
3332       //PDFR_DEBUG { (Ht beg) = } if
3333       pop dup /HT //CheckHalftone //ResolveD exec
3334       /SpotFunction //ResolveFunctionSafe exec
3335       /TransferFunction //ResolveFunctionSafe exec
3336       null exch
3337       dup /HalftoneType get dup 5 eq exch dup 4 eq exch 2 eq or or {
3338         dup {                             % null h n v
3339           dup //IsObjRef exec {
3340             pop
3341             1 index exch //CheckHalftone ResolveD
3342           } if
3343           dup type /dicttype eq {
3344             dup /SpotFunction //ResolveFunctionSafe exec
3345             /TransferFunction //ResolveFunctionSafe exec
3346             //CreateHalftoneThresholds exec
3347             dup /HalftoneType get 5 gt {    % null h n v
3348               4 3 roll pop 
3349               dup 4 1 roll
3350             } if
3351           } if
3352           pop pop
3353         } forall
3354       } if
3355       //CreateHalftoneThresholds exec
3356       //PDFR_DEBUG {
3357         (HT:)= 
3358         dup { 
3359           1 index /Default eq {
3360             (Default <<)=
3361               exch pop
3362               { exch = == } forall
3363             (>>)=
3364           } {
3365             exch = ==
3366           } ifelse
3367         } forall 
3368         (HT end)= flush
3369       } if
3370       exch dup null ne {
3371         (Warning: Ignoring a halftone with a Level 3 component halftone Type ) print dup /HalftoneType get =
3372         pop pop
3373       } {
3374         pop
3375         dup /HalftoneType get 5 gt {
3376           (Warning: Ignoring a Level 3 halftone Type ) print dup /HalftoneType get =
3377           pop
3378         } {
3379           sethalftone
3380         } ifelse
3381       } ifelse
3382       //PDFR_DEBUG { (HT set)= flush } if
3383     } ifelse
3384   } if
3385   dup /FL //knownget exec {
3386     setflattness
3387   } if
3388   dup /SM //knownget exec {
3389     setsmoothness
3390   } if
3391   dup /SA //knownget exec {
3392     setstrokeadjust
3393   } if
3394   dup /BM //knownget exec {
3395     % pdfwrite must take care of.
3396     mark (Unimplemented ExtGState.BM) //error exec
3397   } if
3398   dup /SMask //knownget exec {
3399     % pdfwrite must take care of.
3400     mark (Unimplemented ExtGState.SMask) //error exec
3401   } if
3402   dup /CA //knownget exec {
3403     % pdfwrite must take care of.
3404     mark (Unimplemented ExtGState.CA) //error exec
3405   } if
3406   dup /ca //knownget exec {
3407     % pdfwrite must take care of.
3408     mark (Unimplemented ExtGState.ca) //error exec
3409   } if
3410   dup /AIS //knownget exec {
3411     % pdfwrite must take care of.
3412     mark (Unimplemented ExtGState.AIS) //error exec
3413   } if
3414   dup /TK //knownget exec {
3415     % pdfwrite must take care of.
3416     mark (Unimplemented ExtGState.TK) //error exec
3417   } if
3418   pop
3419 } bind def
3420
3421 /CheckXObject  % <id> <obj> CheckHalftone <id> <obj>
3422 { dup /Subtype get dup /Image ne exch dup /Form ne exch /PS ne and and {
3423     mark (Resource ) 3 index ( must have /Subtype /Image or /Form or /PS.) //error exec
3424   } if
3425 } bind def
3426
3427 /DoXObject % <name> DoXObject -
3428 {
3429   //PDFReader /CurrentObject get /Context get /Resources get 
3430   /XObject //DoNothing //ResolveD exec
3431   exch //CheckXObject //ResolveD exec
3432   dup /Subtype get
3433   dup /Image eq {
3434     pop
3435     //CompleteOutlineImage exec
3436     //DoImage exec
3437   } {
3438     dup /PS eq {
3439       PDFR_DEBUG {
3440         (Executing a PS Xobject) =
3441       } if
3442       pop
3443       //RunDelayedStream exec
3444     } {
3445       dup /Form eq {
3446         pop
3447         PDFR_DEBUG {
3448           (Executing a Form XObject) =
3449         } if
3450         //PDFReader /CurrentObject get exch
3451         dup //PDFReader exch << exch /Context exch >> /CurrentObject exch put
3452         dup /Matrix get concat
3453         dup /BBox get aload pop exch 3 index sub exch 2 index sub rectclip
3454         //RunDelayedStream exec
3455         //PDFReader exch /CurrentObject exch put
3456       } {
3457         mark exch (unimplemented XObject type ) exch //error exec
3458       } ifelse
3459     } ifelse
3460   } ifelse
3461 } bind def
3462
3463 /Operators 50 dict begin
3464   /q { //GSave exec } bind def
3465   /Q { //GRestore exec } bind def
3466   /cm { //TempMatrix astore concat } bind def
3467   /i { 1 .min setflat } bind def
3468   /J /setlinecap load def
3469   /d /setdash load def
3470   /j /setlinejoin load def
3471   /w /setlinewidth load def
3472   /M /setmiterlimit load def
3473   /gs { SetExtGState } bind def
3474
3475   /g /setgray load def
3476   /rg /setrgbcolor load def
3477   /k /setcmykcolor load def
3478   /cs { //ResolveColorSpace exec //SetColorSpaceSafe exec
3479       } bind def
3480   /sc /setcolor load def
3481   /scn { //SetColor exec } bind def
3482   /G /setgray load def
3483   /RG /setrgbcolor load def
3484   /K /setcmykcolor load def
3485   /CS //cs def
3486   /ri { SetColorRenderingIntent } bind def
3487   /SC /setcolor load def
3488   /SCN { //SetColor exec } bind def
3489
3490   /m /moveto load def
3491   /l /lineto load def
3492   /c /curveto load def
3493   /v { currentpoint 6 2 roll curveto } bind def
3494   /y { 2 copy curveto } bind def
3495   /re {
3496     4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
3497     closepath
3498   } def
3499   /h /closepath load def
3500   /n /newpath load def
3501   /S /stroke load def
3502   /s { closepath stroke } bind def
3503   /f /fill load def
3504   /f* /eofill load def
3505   /B { gsave fill grestore stroke } bind def
3506   /b { closepath gsave fill grestore stroke } bind def
3507   /B* { gsave eofill grestore stroke } bind def
3508   /b* { closepath gsave eofill grestore stroke } bind def
3509   /W /clip load def
3510   /W* /eoclip load def
3511   /sh { % Reserved for ps3write.
3512         ResolveShading 
3513         dup /Background known {
3514           gsave
3515           dup /ColorSpace get setcolorspace
3516           dup /Background get aload pop setcolor
3517           pathbbox               % x0 y0 x1 y1
3518           2 index sub exch 3 index sub exch
3519           rectfill
3520           grestore
3521         } if
3522         shfill 
3523       } bind def
3524
3525   /Do { //DoXObject exec } bind def
3526
3527   /BI { currentglobal false setglobal << } bind def
3528   /ID { >>
3529         dup /DataSource currentfile 
3530         % HACK BEG
3531         % This hack provides a compatibility to HP LaserJet 1320,
3532         % which sometimes closes the underlying stream when EOD 
3533         % is reached in the ASCII85Decode filter.
3534         % This portion is not required by the Postscript language definition.
3535         2 index /F //knownget exec {
3536           /A85 eq {
3537             0 (~>) /SubFileDecode filter 
3538           } if
3539         } if
3540         % HACK END
3541         put
3542         //CompleteInlineImage exec
3543         exch setglobal
3544         //DoImage exec
3545       } bind def
3546   /EI {} bind def
3547
3548   /BT { gsave //GraphicState /InitialTextMatrix get currentmatrix pop } bind def
3549   /ET { grestore } bind def
3550   /Tc { //GraphicState exch /CharacterSpacing exch put } bind def
3551   /TL { //GraphicState exch /TextLeading exch put } bind def
3552   /Tr { //GraphicState exch /TextRenderingMode exch put } bind def
3553   /Ts {  % Ghostscript never generates it.
3554         mark (Unimplemented SetTextRise) //error exec
3555       } bind def
3556   /Tw { //GraphicState exch /WordSpacing exch put } bind def
3557   /Tz { % Ghostscript never generates it.
3558             mark (Unimplemented SetHorizontalTextScaling) //error exec
3559       } bind def
3560   /Td { translate 0 0 moveto } bind def
3561   /TD { dup neg //TL exec //Td exec } bind def
3562   /Tm { //GraphicState /InitialTextMatrix get setmatrix
3563         //TempMatrix astore concat
3564         0 0 moveto } bind def
3565   /T* { 0 //GraphicState /TextLeading get neg //Td exec } bind def
3566   /Tj { //ShowTextBeg exec  //ShowText exec  //ShowTextEnd exec } bind def
3567   /'  { //T* exec  //ShowText exec  //ShowTextEnd exec } bind def
3568   /"  { 3 2 roll //Tw exec exch //Tc exec //' exec} bind def
3569   /TJ //ShowTextWithGlyphPositioning def
3570   /Tf //SetFont def
3571
3572   /d0 /setcharwidth load def
3573   /d1 /setcachedevice load def
3574
3575   /BDC { BeginMarkedContentSequenceWithPropertyList } bind def
3576   /BMC { BeginMarkedContentSequence } bind def
3577   /EMC { EndMarkedContentSequence } bind def
3578   /BX { BeginCompatibilitySection } bind def
3579   /EX { EndCompatibilitySection } bind def
3580   /DP { DefineMarkedContentPointWithPropertyList } bind def
3581   /MP { DefineMarkedContentPoint } bind def
3582   /PS { cvx exec } bind def
3583 currentdict end def
3584
3585 //PDFR_STREAM {
3586   % Rebind operators with a debug tracing.
3587   //Operators length dict begin
3588   //Operators {                                 % n p
3589     exch dup                                    % p n n
3590     [ exch //=only /exec load                   % p n [ n =only exec
3591       ( ) /print load                           % p n [ n =only exec () print
3592       8 7 roll                                  % n [ n =only exec () print p
3593       dup type /arraytype eq {
3594         /exec load                              % n [ n =only exec () print p exec
3595       } if
3596       ( ) /print load
3597     ] cvx                                       % n {}
3598     def
3599   } forall
3600   currentdict end /Operators exch def
3601 } if
3602
3603 % Functions for handling Ghostscript library files that define encodings.
3604
3605 /.registerencoding
3606 { pop pop
3607 } bind def
3608
3609 /.defineencoding
3610 { def
3611 } bind def
3612
3613 /.findencoding
3614 { load
3615 } bind def
3616
3617
3618 % Leaving the procset on the dictionary stack to provide 
3619 % definitions of obj, endobj, stream, endstream, R, xref.
3620 %%EndPrologue
3621