]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/pdf_font.ps
merge
[plan9front.git] / sys / lib / ghostscript / pdf_font.ps
1 %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
2
3 % This software is provided AS-IS with no warranty, either express or
4 % implied.
5
6 % This software is distributed under license and may not be copied,
7 % modified or distributed except as expressly authorized under the terms
8 % of the license contained in the file LICENSE in this distribution.
9
10 % For more information about licensing, please refer to
11 % http://www.ghostscript.com/licensing/. For information on
12 % commercial licensing, go to http://www.artifex.com/licensing/ or
13 % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
16 % $Id: pdf_font.ps,v 1.80 2005/09/29 15:24:53 leonardo Exp $
17 % PDF font operations.
18
19 % Finding a font by name can't give a proper result when PDF font names aren't unique.
20 % But it is only the way to obtain a font in Postscript after a font file is executed.
21 % Therefore using a FontName (and findfont) is allowed only
22 % immediately after a font file is executed.
23 % In all other cases the font to be found by a pointer through PDF structures.
24 %
25 % This ideal logics can't work for documents,
26 % which define a font resource with an embedded font,
27 % and another font resource with same BaseFont but with no embedded font
28 % (and possibly with no font descriptor).
29 % Our testbase does contain such examples.
30 % In this case we do find font by FontName (with findfont),
31 % since there is no other way to get a reasonable result.
32
33 /.setlanguagelevel where { pop 2 .setlanguagelevel } if
34 .currentglobal true .setglobal
35 /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
36 GS_PDF_ProcSet begin
37 pdfdict begin
38
39 % We cache the PostScript font in an additional element of the
40 % font resource dictionary, called PSFont.
41
42 % ---------------- Encodings ---------------- %
43
44 /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
45
46 % Apply a list of differences to an Encoding.
47 % Note that the differences may cause the array to grow.
48 /updateencoding {       % <encoding|null> <differences> updateencoding <enc'>
49         % Calculate the length of the result.
50   % in case the incoming Encoding is null, use .notdefEncoding
51   exch dup null eq { pop .notdefEncoding } if
52   0 0 3 index {
53     dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse
54     % Differences list may not be in order, update the largest_index
55     % stack: <Differences> <encoding> <largest_index> <at_index>
56     2 copy lt { exch pop dup } if       % at_index is new largest
57   } forall
58   pop 1 index length .max array dup 0 4 -1 roll putinterval
59   exch 0 exch {
60                 % Stack: enc' code element
61     dup type /nametype ne
62       { exch pop oforce }
63       { 3 copy put pop 1 add }
64     ifelse
65   } forall pop
66 } bdef
67
68 % Get the Encoding for a font.
69 /getencoding            % <base-encoding> <font-resource> getencoding <enc>
70  { /Encoding knownoget
71     { dup type /nametype eq
72        {
73          % The published PDF specification says the Encoding name
74          % "must be" one of the 3 predefined Encodings, implying
75          % that an error should occur if it isn't.  However, Acrobat
76          % Reader simply ignores unknown names, and since there are
77          % some buggy applications that rely on this, we do the same.
78
79          dup dup dup /MacRomanEncoding eq
80          exch /MacExpertEncoding eq or 
81          exch /WinAnsiEncoding eq or
82            { exch pop findencoding
83            }
84            { pop
85            }
86          ifelse
87        }
88        { dup /BaseEncoding knownoget
89            {
90              dup / eq
91                { pop
92                  (   **** Warning: Ignoring bad BaseEncoding name.\n)  pdfformaterror
93                  % as found in a PDF file from J.D.Edwards OneWorld (B7333), bug 687786
94                }
95                {
96                  findencoding 3 -1 roll pop exch
97                }
98              ifelse
99            }
100          if
101          /Differences knownoget { updateencoding } if
102        }
103       ifelse
104     }
105    if
106  } bdef
107
108 /checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode -
109 {
110   PDFDEBUG {
111     dup /FontInfo .knownget { 
112       /GlyphNames2Unicode .knownget { 
113         (Has GlyphNames2Unicode) =
114         pop % { exch == ==} forall 
115       } if 
116     } if
117   } if
118   pop
119 } bind def
120
121 % Define a font using it's FontName as the key.
122 % Adjust a font according to the Encoding and Widths in the font resource.
123 /adjustfont {           % <font-resource> <font> adjustfont <font'>
124   getfontencoding
125   3 copy .processToUnicode
126   getfontmetrics 5 -1 roll pop .updatefont { dup /FontName get exch definefont } if
127 } bind def
128
129 % Get the (possibly modified) encoding of a font.
130 /getfontencoding {      % <font-resource> <font> getfontencoding
131                         %   <font-resource> <font> <Encoding|null>
132   1 index /Encoding known {
133     dup /Encoding knownoget { 2 index getencoding } { null } ifelse
134   } {
135     null
136   } ifelse
137 } bdef
138
139 % Returns true if the current glyph is in the Differences array at
140 % the specified index value. This is needed because the Widths
141 % array may map to the same glyph at different positions from the
142 % Encoding. We want to use the Width that was associated with the
143 % one specified in the Encoding::Differences list.
144 /match_in_diff     % <Differences> <index> <glyphname> match_in_diff <bool>
145 { false 4 1 roll 0 4 -1 roll    % stack: false index glyphname at_index==0 Differences
146   { exch 1 index type /nametype ne {
147       % stack: false index glyphname Diff_element at_index 
148       pop       % Diff_element is new at_index
149     } {
150       % stack: false index glyphname Diff_element at_index 
151       exch 2 index eq {
152         % stack: false index glyphname at_index 
153         dup 3 index eq {
154           true 5 1 roll % stack: true false index glyphname at_index
155           pop exit
156         } if
157       } if
158       1 add             % at_index++ stack: false index glyphname at_index' 
159     } ifelse
160   } forall
161   % stack: true  false index     glyphname
162   %  or  : false index glyphname at_index
163   pop pop pop
164 } bdef
165
166 /unique_name {  % <dict> </root> unique_name </unique> 
167   %
168   %  Note : this function interacts with pdf_write_encoding in src/gdevpdtw.c
169   %  and with copied_drop_extension_glyphs in src\gxfcopy.c
170   %  by adding a reserved substring (~GS~).
171   %
172   .namestring       % <<>> (root)
173   0 1 65535 {
174     5 string cvs    % <<>> (root) (0)
175     (~GS~) exch concatstrings
176     1 index exch    % <<>> (root) (root) (~GS~0)
177     concatstrings   % <<>> (root) (root~GS~0)
178     dup             % <<>> (root) (root~GS~0) (root~GS~0)
179     3 index exch    % <<>> (root) (root~GS~0) <<>> (root~GS~0)
180     known not {
181       exch pop exit % <<>> (root~GS~0)
182     } if
183     pop
184   } for
185   exch pop cvn      % /root0
186 } bdef
187                                
188 % Get the metrics of a font, if specified.
189 /getfontmetrics {       % <font-resource> <font> <Encoding|null> getfontmetrics
190                         %   <font-resource> <font> <Encoding|null>
191                         %   <Metrics|null> <GlyphMap|null>
192   2 index /Widths known {
193     dup null eq { pop dup /Encoding get } if
194     4 dict begin
195       dup length dict
196       /Metrics exch def
197       /Encoding exch def
198       /GlyphMap //null def
199       exch
200       dup /Widths oget /Widths exch def
201                 % Stack: font font-res
202                 % Note that widths are always based on a 1000-unit
203                 % character space, but the FontMatrix may specify
204                 % some other scale factor.  Compensate for this here,
205                 % by scaling the Widths if necessary.
206       0.001 2 index /FontMatrix get 0 get div
207                 % Stack: font font-res mscale
208       1 index /FirstChar oget dup 1 4 index /LastChar oget
209        {        % Stack: font font-res mscale first-char index
210          Encoding 1 index dup 2 index length ge {
211            (   **** Warning: Font Encoding array size is smaller than character range.\n)
212            pdfformaterror
213            pop pop /.notdef
214          } {
215            get
216          } ifelse
217          Widths 2 index 4 index sub dup 2 index length ge {
218            (   **** Warning: Font Widths array size is smaller than character range.\n)
219            pdfformaterror
220            % use MissingWidth if it's available, if not, default to 1000 (full width)
221            pop pop 4 index /FontDescriptor knownoget {
222              /MissingWidth knownoget not { 1000 } if
223            } { 1000 } ifelse
224          } {
225            oget
226          } ifelse
227                 % Stack: font font-res mscale first-char index charname width
228          4 index mul
229                 % The following 'loop' is only context for 'exit'.
230          {      
231                 % Work around a bug in pdfTeX, which can generate Encoding
232                 % vectors containing nulls :
233            1 index //null eq { exit } if
234            Metrics 2 index .knownget {
235              1 index ne
236            } {
237              //false
238            } ifelse {
239              % Two or more Encoding elements refer same glyph name,
240              % and Widths specify different wihts for it.
241              % Since a Postscript font can't have different 
242              % Metrics for same glyph name, 
243              % we generate an unique name, and create a new 
244              % Charstrings entry with same glyph value.
245              GlyphMap //null eq {
246                /Encoding Encoding dup length array copy def
247                /GlyphMap 4 dict def
248              } if
249              % To prevent too many new names, check whether
250              % we can use one already created for same glyph.
251              //true
252              GlyphMap {                           % f r s c i n w b n1 n2
253                4 index eq {                       % f r s c i n w b n1
254                  dup Metrics exch get             % f r s c i n w b n1 w1
255                  3 index eq {                     % f r s c i n w b n1
256                    4 3 roll pop                   % f r s c i w b n1
257                    3 1 roll pop                   % f r s c i n1 w
258                    Encoding 3 index 3 index put
259                    //false                        % f r s c i n1 w b
260                    exit
261                  } {
262                    pop
263                  } ifelse
264                } {                                % f r s c i n w b n1
265                  pop
266                } ifelse
267              } forall                             % f r s c i n w b
268              { % Do create a new name.
269                Metrics 2 index //unique_name exec % f r s c i n w nn
270                Encoding 4 index 2 index put
271                GlyphMap 1 index 5 -1 roll put     % f r s c i w nn
272                exch
273                   % Stack: font font-res mscale first-char index new_name width
274              } if
275            } if
276            2 copy Metrics 3 1 roll put
277            exit
278          } loop
279          pop pop pop
280        }
281       for pop
282                 % Now fill in the MissingWidth for any encoded characters
283                 % that aren't in Metrics already.  Note that built-in
284                 % fonts may have Widths/FirstChar/LastChar but no
285                 % FontDescriptor, so we must check for this.
286                 % Stack: font font-res mscale
287       1 index /FontDescriptor knownoget {
288         Metrics exch
289         /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
290         Encoding {
291                 % Stack: font font-res mscale missing-width metrics charname
292                 % Work around the abovementioned pdfTeX bug.
293           dup //null ne {
294             2 copy known not { 2 copy 4 index put } if pop
295           } {
296             pop
297           } ifelse
298         } forall pop pop pop
299       } {
300         pop
301       } ifelse
302     exch Encoding Metrics GlyphMap end
303   } {
304     //null //null
305   } ifelse
306 } bdef
307
308 currentdict /unique_name undef
309 currentdict /match_in_diff undef
310
311 /ToUnicodeCMapReader 3 dict def
312 //ToUnicodeCMapReader begin
313   /defineresource % <name> <dict> <cat-name> defineresource <dict> 
314   {
315     pop 
316     dup userdict exch /.lastToUnicode exch put
317     exch pop
318   } bind def
319   /CIDSystemInfo 
320   { 
321     (   **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n)  pdfformaterror
322     /CIDSystemInfo 
323   } bind def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed.
324 end
325
326 /string2number     % <string> string2number <number>
327 { 0 exch dup 0 exch 1 exch length 1 sub {     % n () i
328     1 index exch get                          % n () v
329     3 2 roll 256 mul add exch                 % v+n*256 ()
330   } for
331   pop                                         % N
332 } bind def
333
334 /copy&def    % <key> <value> <bool> copy&def -
335 {
336   { true
337   } {
338     currentdict gcheck { 
339       dup gcheck not
340     } {
341       false
342     } ifelse
343   } ifelse
344   { currentglobal currentdict gcheck setglobal 
345     exch dup length string copy exch 
346     setglobal
347   } if
348   def
349 } bind def
350
351 /.convert_ToUnicode-into-g2u % <GlyphNames2Unicode> <Encoding|null> <CMap> .convert_ToUnicode-into-g2u -
352 {
353   PDFDEBUG {
354     (.convert_ToUnicode-into-g2u beg) =
355   } if
356   3 2 roll begin
357   /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "CMap operators".
358   1 get % code maps
359   { 
360     PDFDEBUG {
361       dup ==
362     } if
363     dup length 1 sub 0 exch 5 exch {           % e [] i
364       2 copy get                               % e [] i (prefix)
365       string2number                            % e [] i prefix
366       2 index 2 index 1 add get                % e [] i prefix (key_size,?is_range,value_type,value_size)
367       dup 0 get 8 mul                          % e [] i prefix (key_size,?is_range,value_type,value_size) key_size*8
368       3 2 roll exch bitshift exch              % e [] i prefix<<key_size*8 (key_size,?is_range,value_type,value_size)
369       dup 0 get exch 3 get                     % e [] i offset key_size value_size
370       4 index 4 index 2 add get                % e [] i offset key_size value_size (keys)
371       5 index 5 index 3 add get                % e [] i offset key_size value_size (keys) (values)
372       PDFDEBUG {
373         ( offset=) print 4 index =string cvs print
374         ( key_size=) print 3 index =string cvs print
375         ( value_size=) print 2 index =
376         ( keys=)   print 1 index ==
377         ( values=) print dup ==
378       } if
379       1 index length 0 eq {
380         % A single pair.
381         exch pop exch pop exch pop exch        % e [] i (values) offset
382         4 index null ne {
383           4 index exch get
384         } if                                   % e [] i (values) cid|name
385         exch 
386         PDFDEBUG {
387           ( defined single: ) print 1 index =string cvs print ( ) print dup ==
388         } if
389         false copy&def                         % e [] i
390         pop                                    % e []
391       } {
392         % A range.                             % e [] i offset key_size value_size (keys) (values)
393         dup length string copy % protect the original string from modifications below.
394         0 4 index 2 mul 3 index length 1 sub { % e [] i offset key_size value_size (keys) (values) j
395           2 index 1 index 6 index getinterval          
396           string2number                        % e [] i offset key_size value_size (keys) (values) j keyL
397           PDFDEBUG {
398               ( keyL=) print dup =string cvs print
399           } if
400           3 index 2 index 7 index add 7 index getinterval
401           string2number                        % e [] i offset key_size value_size (keys) (values) j keyL keyH
402           PDFDEBUG {
403               ( keyH=) print dup =
404           } if
405           3 2 roll 6 index idiv 5 index mul    % e [] i offset key_size value_size (keys) (values) keyL keyH J
406           3 index exch 6 index getinterval     % e [] i offset key_size value_size (keys) (values) keyL keyH (valueL)
407           3 1 roll 1 exch {                    % e [] i offset key_size value_size (keys) (values) (value) k
408             9 index null ne {
409               9 index exch get                 % e [] i offset key_size value_size (keys) (values) (value) name
410             } if                               % e [] i offset key_size value_size (keys) (values) (value) cid|name
411             1 index                            % e [] i offset key_size value_size (keys) (values) (value) cid|name (value)
412             PDFDEBUG {
413               ( defined from range: ) print 1 index =string cvs print ( ) print dup ==
414             } if
415             true copy&def                      % e [] i offset key_size value_size (keys) (values) (value)
416             % Assuming the lowest byte of 'value' changes, others don't.
417             dup dup length 1 sub               % e [] i offset key_size value_size (keys) (values) (value) (value) l
418             2 copy get                         % e [] i offset key_size value_size (keys) (values) (value) (value) l v
419             1 add put                          % e [] i offset key_size value_size (keys) (values) (value')
420           } for                                % e [] i offset key_size value_size (keys) (values) (value)
421         } for
422         pop pop pop pop pop pop pop            % e []
423       } ifelse
424     } for
425     pop                                        % e
426   } forall
427   end
428   pop                                          %
429   PDFDEBUG {
430     (.convert_ToUnicode-into-g2u end) =
431   } if
432 } bind def
433
434 /.processToUnicode   % <font-resource> <font-dict> <encoding|null> .processToUnicode -
435 {
436   % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to 
437   % generate a ToUnicode CMaps. So don't bother with other devices.
438   currentdevice .devicename /pdfwrite eq {
439     PDFDEBUG {
440       (.processToUnicode beg) =
441     } if
442     2 index /ToUnicode knownoget {
443       dup type /nametype eq {
444         % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect.
445         (   **** Warning: Ignoring bad ToUnicode CMap.\n)  pdfformaterror
446         pop
447       } {
448         PDFfile fileposition exch
449         false resolvestream
450         //ToUnicodeCMapReader begin
451           cvx exec
452         end
453         PDFfile exch setfileposition
454         1 index /FontInfo .knownget not {
455           1 index /FontInfo 5 dict dup 4 1 roll put
456         } if
457         dup /GlyphNames2Unicode .knownget not {
458           currentglobal exch dup gcheck setglobal
459           dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput
460           3 2 roll setglobal
461         } if                                 % font-res font-dict encoding|null font-info g2u
462         exch pop exch                        % font-res font-dict g2u encoding|null
463         userdict /.lastToUnicode get         % font-res font-dict g2u Encoding|null CMap
464         .convert_ToUnicode-into-g2u          % font-res font-dict
465         null                                 % font-res font-dict null
466       } ifelse
467     } if
468     PDFDEBUG {
469       (.processToUnicode end) =
470     } if
471   } if
472   pop pop pop
473 } bind def
474
475 % ---------------- Descriptors ---------------- %
476
477 % Partial descriptors for the 14 built-in fonts.  Note that
478 % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
479 % object has undergone a subtle change in its meaning which has serious
480 % consequences for searching with Acrobat:
481 % In PDF 1.1, the flag meant: Font has StandardEncoding
482 % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
483 /standardfontdescriptors mark
484   /Courier mark /Flags 16#23 .dicttomark
485   /Courier-Oblique 1 index
486   /Courier-Bold 1 index
487   /Courier-BoldOblique 1 index
488   /Helvetica mark /Flags 16#20 .dicttomark
489   /Helvetica-Oblique 1 index
490   /Helvetica-Bold 1 index
491   /Helvetica-BoldOblique 1 index
492   /Times-Roman mark /Flags 16#22 .dicttomark
493   /Times-Bold 1 index
494   /Times-Italic mark /Flags 16#62 .dicttomark
495   /Times-BoldItalic 1 index
496   /Symbol mark /Flags 16#4 .dicttomark
497   /ZapfDingbats 1 index
498 .dicttomark readonly def
499
500 % ---------------- Utilities ---------------- %
501
502
503 /.pdforigfontcache_g 20 dict def
504 currentglobal false setglobal
505 systemdict /.pdforigfontcache_l 20 dict .forceput
506 setglobal
507
508 % Find an original font, using cache to prevent adjustfont to accumulate changes.
509 /pdffindcachedfont {   % <font_name> pdffindcachedfont <font>
510   dup //.pdforigfontcache_g exch .knownget {
511     exch pop
512   } {
513     dup .pdforigfontcache_l exch .knownget {
514       exch pop
515     } {
516       dup findfont dup    
517       dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse
518                      % Stack : font_name font font cache
519       4 2 roll .growput
520     } ifelse
521   } ifelse
522 } bind def
523
524 % Add original font to cache to prevent adjustfont to accumulate changes.
525 /pdfaddcachedfont {   % <font_name> pdfaddcachedfont <font>
526   dup findfont dup                   % name font font
527   dup gcheck { //.pdforigfontcache_g } {.pdforigfontcache_l} ifelse
528   4 2 roll                           % font d name font
529   put                                % font
530 } bind def
531
532 /.remove_font_name_prefix {  % <name>  .remove_font_name_prefix <name>
533   dup .namestring (+) search {
534     true exch
535     { dup 65 lt exch 90 gt or {
536         pop false exit
537       } if
538     } forall
539     { pop exch pop cvn
540     } {
541       pop pop
542     } ifelse
543   } {
544     pop
545   } ifelse
546 } bind def
547
548 % Find a font (except for embedded ones), and adjust its encoding if necessary.
549 /.pdfdfndict mark
550   /defaultfontname /Helvetica
551 .dicttomark readonly def
552 /pdffindfont {          % <font-resource> <fontname> pdffindfont <font>
553                 % If the font isn't available, synthesize one based on
554                 % its descriptor.
555   dup /Font resourcestatus {
556     pop pop pdffindcachedfont
557   } {
558     1 index /FontDescriptor knownoget {
559                 % Stack: font-res fontname fontdesc
560       dup /Flags oget
561       dup 16#40 and -6 bitshift         % 1, oblique/italic
562       1 index 16#40000 and -17 bitshift add     % 2, bold
563       exch 16#2 and 2 bitshift add      % 8, serif
564                 % We should look at the fixed flag, too.
565                 % Stack: font-res fontname fontdesc properties
566
567                 % Even though /FontName is a required key in FontDescriptor dict
568                 % (As of the PDF 1.4 Reference Manual), In the case of missing 
569                 % /FontName key, we substitue /BaseFont for the value of /FontName.
570                 % Yet another case of broken PDF's that Adobe Reader accepts.
571       1 index dup /FontName known {
572         /FontName oget
573       } {
574         (   **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
575         pdfformaterror
576         pop 2 index             % grab the BaseFont from the stack.
577       } ifelse
578       .remove_font_name_prefix
579       exch
580                 % Analyzes font name and extract "Narrow" property
581                 % which is not described by the FontDescriptor Flags.
582       0 2 index .fontnameproperties 4 and or
583                 % Rebind the default font name to Helvetica so that
584                 % fonts with no properties are handled correctly.
585       //.pdfdfndict begin .substitutefontname end
586                 % Stack: font-res fontname fontdesc substname|null
587       Fontmap 1 index known not {
588                 % No available good substitution, use the standard one.
589         pop 1 index .substitutefont
590       } if
591       dup 3 index ne QUIET not and {
592         (Substituting font ) print dup =only
593         ( for ) print 2 index =only (.) = flush
594       } if
595       pdffindcachedfont
596                 % Stack: font-res fontname fontdesc font
597                 % If this is a small-caps font, replace the CharString
598                 % entries for a..z.
599       exch /Flags oget 16#20000 and 0 ne {
600         true .copyfontdict
601         dup /CharStrings 2 copy get dup length dict .copydict
602         % stack: font-res fontname font font /CharStrings CharStringsdict
603         5 index /FirstChar get 97 .max
604         6 index /LastChar get 122 .min 1 exch {
605                 % Stack: font-res fontname font' font' /CharStrings charstrings code
606                 % Note that this only remaps a-z, not accented characters.
607           6 index /Widths oget 1 index 8 index /FirstChar get sub oget
608           1 string dup 0 5 -1 roll put
609                 % Stack: font-res font' font' /CharStrings charstrings code
610                 %   width (x)
611           2 index exch dup cvn exch
612           dup 0 2 copy get 32 sub put 4 -1 roll {
613                         % Stack: operand (X) width
614             0 setcharwidth exch pop
615             currentfont /FontMatrix get matrix invertmatrix concat
616             0.7 dup scale 0 0 moveto show
617           } /exec cvx 4 packedarray cvx put
618         } for put
619       } if
620       dup /FontName get 2 index ne {
621         true .copyfontdict
622         2 copy exch /FontName exch put
623       } if
624       definefont
625     } {
626                 % No descriptor available, use the default algorithm.
627       pdffindcachedfont
628     } ifelse
629   } ifelse
630   exch pop
631 } bdef
632
633 % ---------------- Type 1 fonts ---------------- %
634
635 /buildType1             % <Type1-font-resource> buildType1 <font>
636  { dup /BaseFont get pdffindfont
637  } bdef
638
639 % The state dictionary for the embedded Type 1 font reading procedure
640 % has the following keys and values:
641 %       data - stream (filter)
642 %       buffer, buffer2 - string
643 %       hexify - procedure to convert buffer to hex if needed
644 %       leftstr - string containing (non-negative) integer
645 %       sectionstr - string containing a character 0 .. 3
646 %       stream - (stream) dictionary
647 %       proc - procedure of the form {-dict- type1read}
648 %       pfbhdr - string containing 16#80 if PFB, 0 otherwise
649 % When the procedure is executing, this dictionary is current.
650 % leftstr and sectionstr are strings so that we can change their values
651 % reliably in case the font executes a restore!
652 % We also have to do something special about embedded fonts that
653 % execute definefont more than once -- that is the function of topFontDict.
654
655 % Read an embedded Type 1 font.
656 /readfontfilter {       % <proc> readfontfilter <filter>
657   0 () /SubFileDecode filter
658 } bdef
659 /readtype1dict 5 dict dup begin
660   /definefont {
661     dup topFontDict eq topFontDict null eq or {
662       dup wcheck not { dup length dict copy } if
663       exch pop savedFontName exch
664     } if
665     //systemdict /definefont get exec
666   } bdef
667   /eexec {
668         % Assume the font dictionary is directly below the file on the stack
669     count 0 gt { /topFontDict 2 index cvlit store } if
670     //.eexec_param_dict /eexecDecode filter
671     //systemdict begin readtype1dictcopy begin cvx stopped
672     currentdict readtype1dictcopy eq { end } if
673     currentdict //systemdict eq { end } if
674      { stop } if
675   } bdef
676
677   /undef_proc_warning {
678     /Repaired true store        % flag that we have warnings
679     UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put
680   } bdef
681
682   /-| { string currentfile exch readstring pop /-| undef_proc_warning } executeonly bdef
683   /RD { string currentfile exch readstring pop /RD undef_proc_warning } executeonly bdef
684   /|- { noaccess def /|- undef_proc_warning } executeonly bdef
685   /ND { noaccess def /ND undef_proc_warning } executeonly bdef
686   /|  { noaccess put /|  undef_proc_warning } executeonly bdef
687   /NP { noaccess put /NP undef_proc_warning } executeonly bdef
688
689 end readonly def
690 /readtype1 {            % <font-resource> <stream-dict> readtype1 <font>
691                 % Read the definition, using a procedure-based filter
692                 % that turns binary/hex conversion on and off
693                 % at the right times.
694    1 index exch
695    PDFfile fileposition 3 1 roll
696    11 dict begin
697      /leftstr (          ) 10 string copy def
698        dup /Length1 oget leftstr cvs pop
699      /sectionstr <00> 1 string copy def
700      /pfbhdr <00> 1 string copy def
701      /stream 1 index def
702      true resolvestream /data exch def
703      /buffer 1000 string def            % arbitrary
704      /buffer2 buffer length 2.1 div cvi 1 sub string def
705      /hexify /buf2hex load def
706    currentdict end
707    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
708    readfontfilter
709                 % Some buggy embedded fonts leave extra junk on the stack,
710                 % so we have to make a closure that records the stack depth
711                 % in a fail-safe way. Also restore dictstack depth.
712    //systemdict begin
713                 % The PDF specification is somewhat muddy about whether
714                 % an embedded font's name is supposed to be the BaseFont
715                 % from the Font object or the FontName from the descriptor.
716                 % Acrobat Distiller requires the former.  Save away the
717                 % name so we can substitute it at definefont time.
718    //readtype1dict dup length 3 add dict copy begin
719    1 index /BaseFont oget /savedFontName exch def
720    /topFontDict null def
721    /readtype1dictcopy currentdict def
722     { run } aload pop count 1 sub 2 packedarray cvx exec
723     % clean up the dictstack
724     { currentdict /topFontDict known not { end } { end end exit } ifelse } loop
725    count exch sub { pop } repeat
726    PDFfile 3 -1 roll setfileposition
727    /BaseFont oget pdfaddcachedfont
728    exch pop
729  } bdef
730
731 % Execute the appropriate reading procedure.
732 /type1read              % <dict> type1read <string>
733  { begin leftstr cvi
734     { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
735    (          ) leftstr copy cvs pop end
736  } bdef
737
738 % Read the next block of data into the buffer.
739 /type1readdata          % <left> <buffer> type1readdata <substring> <left'>
740  { 0 2 index 2 index length .min getinterval
741                 % Adobe requires readstring to signal an error if given
742                 % an empty string.  Work around this nonsense here.
743    dup length 0 ne { data exch readstring pop } if
744    dup length 3 -1 roll exch sub
745    PDFDEBUG
746     { dup =only ( read ) print
747       1 index length =only (: ) print
748       1 index == flush
749     } if
750  } bdef
751
752 % Read the initial byte to see if we need to skip a 6 byte PFB header
753 /type1read0 {           % <left> type1read0 <string> <left'>
754   sectionstr 0 1 put    % either way we go to the next stage
755   pfbhdr type1readdata
756   1 index 0 get 16#80 eq {
757     (   **** Warning: Embedded Type1 font in PFB format is not valid PDF.\n)
758     pdfformaterror
759     PDFDEBUG { (skipping PFB header) = flush } if
760     exch pop buffer 0 5 getinterval type1readdata exch
761     dup 4 get 256 mul 1 index 3 get add 256 mul
762     1 index 2 get add 256 mul 1 index 1 get add
763     PDFDEBUG { (PFB segment length = ) print dup = } if
764     exch pop  % discard the string keeping the PFB segment length
765     2 copy ne {
766       (   **** Warning: Type 1 PFB segment length and Length 1 value do not match.\n)
767       pdfformaterror
768       exch      % keep the PFB length instead
769     } if
770     pop
771     buffer type1readdata        % go ahead and read a block
772   }
773   if    % if not PFB, return pfbhdr string (first char of file, usually %).
774 } bdef
775
776 % Read the next block of the initial text portion.
777 /type1read1 {           % <left> type1read1 <string> <left'>
778   PDFDEBUG { (read1 ) print } if
779   dup 0 eq {
780     pop sectionstr 0 2 put
781     stream /Length2 oget
782                         % Determine whether to hexify data for eexec.
783     dup 8 lt {
784       type1read2        % Hexify.
785     } {
786       PDFDEBUG { (read2 ) print } if
787       pfbhdr 0 get 16#80 eq {
788         % eat 6 more bytes of PFB junk before proceeding
789         PDFDEBUG { (skipping PFB header in segment 2) = flush } if
790         buffer 0 6 getinterval type1readdata exch
791         dup 5 get 256 mul 1 index 4 get add 256 mul
792         1 index 3 get add 256 mul 1 index 2 get add
793         PDFDEBUG { (PFB segment length = ) print dup = } if
794         exch pop  % discard the string keeping the PFB segment length
795         2 copy ne {
796           (   **** Warning: Type 1 PFB segment length and Length 2 value do not match.\n)
797           pdfformaterror
798           exch          % keep the PFB length instead
799         } if
800           pop
801       } if
802       buffer2 type1readdata exch
803                         % The check doesn't have to be 100% accurate:
804                         % hexifying is always OK.
805       dup 0 8 getinterval 0 exch { or } forall
806       128 ge {
807         /hexify { } store
808         /buffer2 buffer def     % We don't need an intermediate buffer.
809       } if hexify exch
810     } ifelse
811   } {
812     buffer type1readdata
813   } ifelse
814 } bdef
815
816 % Convert a string from binary to hex for eexec.
817 % Free variables: buffer.
818 /buf2hex {              % <string> buf2hex <hexstring>
819   buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
820   buffer (>) search pop exch pop exch pop
821 } bdef
822
823 % Read the next block of the encrypted portion.
824 /type1trailer
825 (0000000000000000000000000000000000000000000000000000000000000000\n\
826 0000000000000000000000000000000000000000000000000000000000000000\n\
827 0000000000000000000000000000000000000000000000000000000000000000\n\
828 0000000000000000000000000000000000000000000000000000000000000000\n\
829 0000000000000000000000000000000000000000000000000000000000000000\n\
830 0000000000000000000000000000000000000000000000000000000000000000\n\
831 0000000000000000000000000000000000000000000000000000000000000000\n\
832 0000000000000000000000000000000000000000000000000000000000000000\n\
833 cleartomark\n)
834 readonly def
835 /type1read2 {           % <left> type1read2 <string> <left'>
836   PDFDEBUG { (read2 ) print } if
837    dup 0 eq
838     { pop sectionstr 0 3 put
839       stream /Length3 oget
840       dup 0 eq
841        { PDFDEBUG { (trailer ) print } if
842          type1trailer exch
843        }
844        { 
845          pfbhdr 0 get 16#80 eq {
846            % eat 6 more bytes of PFB junk before proceeding
847            PDFDEBUG { (skipping PFB header in segment 3) = flush } if
848            buffer 0 6 getinterval type1readdata exch
849            dup 5 get 256 mul 1 index 4 get add 256 mul
850            1 index 3 get add 256 mul 1 index 2 get add
851            PDFDEBUG { (PFB segment length = ) print dup = } if
852            exch pop  % discard the string keeping the PFB segment length
853            2 copy ne {
854            (   **** Warning: Type 1 PFB segment length and Length 3 value do not match.\n)
855            pdfformaterror
856              exch       % keep the PFB length instead
857            } if
858            pop
859          } if
860          type1read3
861        }
862       ifelse
863     }
864     { buffer2 type1readdata exch hexify exch
865     }
866    ifelse
867 } bdef
868
869 % Read the next block of the final text portion.
870 % When finished, this procedure returns an empty string.
871 /type1read3             % <left> type1read3 <string> <left'>
872  { PDFDEBUG { (read3 ) print } if
873    buffer type1readdata
874  } bdef
875
876 % ---------------- Type 3 fonts ---------------- %
877
878 /buildType3 {           % <Type3-font-resource> buildType3 <font>
879   8 dict begin
880     /FontType 3 def
881                 % If the font does not contain a Resources entry, then we use
882                 % the resources from our current context.  Page 391 of the PDF
883                 % 1.6 spec says that the Resources dict is optional and if not
884                 % present then we should use the Resources for the page.
885                 % However we have a test file (687989) which uses a Type3 font
886                 % inside a form XObject and the desired Resources are in the
887                 % XObject dict and not in the Page dict.  So we are going to
888                 % the parent object to find resources instead of only going to
889                 % the page dict when a font does not specify its required
890                 % resources.
891     /Resources 1 index /Resources knownoget {
892        oforce
893     } {
894        LocalResources
895     } ifelse def
896     /FontBBox 1 index /FontBBox get cvx def
897     /FontMatrix 1 index /FontMatrix oget def
898     /CharProcs 1 index /CharProcs oget def
899     1 index /Widths knownoget {
900       /Widths exch def
901       /FirstChar 1 index /FirstChar oget def
902       /LastChar 1 index /LastChar oget def
903     } if
904     /FontName 1 index /Name .knownget not { 
905        PDFfile fileposition 16 10 string cvrs cvn
906     } if def
907
908     /Encoding .notdefEncoding 2 index getencoding def
909                 % We have to define BuildChar rather than BuildGlyph:
910                 % there is no PDF equivalent of glyphshow, and we need
911                 % the character code to access the Widths.
912     /BuildChar {
913                 % Stack: font charcode
914       1 index begin 3 dict begin
915       /Font 3 -1 roll def /CharCode 1 index def
916       % Make unknown characters map to /.notdef
917       Encoding exch get dup CharProcs exch known
918         { CharProcs exch oget }
919         { pop CharProcs /.notdef oget }
920       ifelse
921       PDFfile fileposition exch
922       false resolvestream
923                 % Stack: filepos stream
924                 % Don't let setgcolor set the color inside the BuildGlyph
925                 % procedure, because this causes an /undefined error.
926       q null /FillColor gput null /StrokeColor gput
927       Font /Resources get exch pdfopdict .pdfruncontext
928       Q
929       PDFfile exch setfileposition
930       end end
931     } bdef
932     dup currentdict Encoding .processToUnicode
933     FontName currentdict end definefont exch pop
934 } bdef
935 /.adjustcharwidth {     % <wx> <wy> .adjustcharwidth <wx'> <wy'>
936   /Widths where {
937     begin
938     CharCode FirstChar ge CharCode LastChar le and {
939       exch pop Widths CharCode FirstChar sub get exch
940     } if end
941   } if
942 } bdef
943
944 % ---------------- TrueType fonts ---------------- %
945
946 /TTfonts mark
947   /Arial /Helvetica
948   /Arial,Italic /Helvetica-Oblique
949   /Arial,Bold /Helvetica-Bold
950   /Arial,BoldItalic /Helvetica-BoldOblique
951   /CourierNew /Courier
952   /CourierNew,Bold /Courier-Bold
953   /TimesNewRoman /Times-Roman
954   /TimesNewRoman,Italic /Times-Italic
955   /TimesNewRoman,Bold /Times-Bold
956   /TimesNewRoman,BoldItalic /Times-BoldItalic
957 .dicttomark readonly def
958
959 /buildTrueType {        % <TrueType-font-resource> buildTrueType <font>
960   dup /BaseFont oget
961   /Repaired true store  % flag that we had warnings
962   TTFWarnList 1 index true put  % Add fontname to the list
963   dup TTfonts exch .knownget {
964     QUIET not {
965       (Substituting font ) print dup =only
966       ( for ) print 1 index =only (.) = flush
967     } if
968     exch 3 1 roll pdffindfont
969     true .copyfontdict
970     2 copy exch /FontName exch put
971     definefont
972   } {
973     pdffindfont
974   } ifelse
975 } bdef
976
977 % Read an embedded TrueType font.
978 /readtruetype {         % <font-resource> <stream-dict> readtruetype <font>
979                 % This is much simpler than readtype1, because we don't
980                 % have to deal with the tripartite .PFB format.
981   1 index exch
982   PDFfile fileposition 3 1 roll
983   true resolvestream readfontfilter
984                 % Stack: filepos fontres stream
985   1 index /Subtype get /CIDFontType2 eq {
986     .loadttcidfont
987                 % Stack: filepos fontres cidfont
988   } {
989                                           % filepos fontres stream
990     1 index /FontDescriptor oget          % filepos fontres stream fd   
991     /Flags get 4 and 0 ne                 % filepos fontres stream is_symbolic
992     dup {
993       2 index null exch getencoding       % filepos fontres stream is_symbolic Encoding
994       dup 4 index exch                    % filepos fontres stream is_symbolic Encoding fontres Encoding
995       /prebuilt_encoding exch put         % filepos fontres stream is_symbolic Encoding
996     } {
997       null
998     } ifelse
999     .loadpdfttfont
1000   } ifelse
1001   exch pop
1002   PDFfile 3 -1 roll setfileposition
1003                 % Ignore both the Encoding and the Widths.
1004   exch pop
1005 } bdef
1006
1007 % ---------------- Type 0 fonts ---------------- %
1008
1009 % Predefine the known CMaps, but only create them on demand.
1010 /knownCMaps mark
1011   /Identity-H { /Identity-H 0 makeIdentityCMap }
1012   /Identity-V { /Identity-V 1 makeIdentityCMap }
1013 .dicttomark def
1014
1015 /makeIdentityCMap {             % <cmapname> <wmode> .makeIdentityCMap -
1016   .currentglobal true .setglobal 3 1 roll
1017   /CIDInit /ProcSet findresource begin
1018   12 dict begin
1019     begincmap
1020     /WMode exch def
1021     /CMapName exch def
1022     /CIDSystemInfo 3 dict dup begin
1023       /Registry (Adobe) def
1024       /Ordering (Identity) def
1025       /Supplement 0 def
1026     end def
1027     %/CMapName (see above)
1028     /CMapVersion 1 def
1029     /CMapType 1 def
1030     %WMode (see above)
1031         % The PDF documentation says that these CMaps map CIDs
1032         % "1 to 65,536".  This is a misprint for 0 to 65,535.
1033     1 begincodespacerange
1034         % <0001> <00ff>  <0100> <ffff>
1035       <0000> <ffff>
1036     endcodespacerange
1037     1 begincidrange
1038         % <0001> <00ff> 1   <0100> <ffff> 256
1039       <0000> <ffff> 0
1040     endcidrange
1041     endcmap
1042     CMapName currentdict /CMap defineresource
1043     knownCMaps CMapName 2 index put
1044   end           % CMap
1045   end           % CIDInit ProcSet
1046   exch .setglobal
1047 } bdef
1048
1049 /buildType0 {           % <Type0-font-resource> buildType0 <font>
1050   dup /BaseFont get     % FontName
1051   1 index /Encoding oget
1052   dup type /nametype eq {
1053     dup /CMap resourcestatus {
1054         pop pop /CMap findresource
1055     } {
1056         knownCMaps 1 index .knownget
1057           { exch pop exec } { /undefined signalerror } ifelse
1058     } ifelse
1059   } {
1060     PDFfile fileposition exch
1061     dup /CMapName get exch true resolvestream cvx exec
1062     /CMap findresource
1063     exch PDFfile exch setfileposition
1064   } ifelse              % CMap
1065   [
1066     3 index /DescendantFonts oget { exec resourcefont } forall
1067   ]                     % subfonts
1068   composefont   % composefont must insert FontInfo dictionary - see gs_cmap.ps .
1069                 % Stack: fontres font
1070   2 copy null .processToUnicode
1071   1 index /FontMatrix knownoget {
1072     dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
1073       1 index exch makefont exch /FontName get exch definefont
1074     } {
1075       pop
1076     } ifelse
1077   } if exch pop
1078 } bdef
1079
1080 % ---------------- CIDFontType0/2 fonts ---------------- %
1081
1082 % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
1083 % arrays and using a (currently very inefficient) CDevProc.
1084 % For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts".
1085 % It notes default DW is 0, but Acrobat Reader uses 1000 as default.
1086 % If DW is 0, currentpoint does not move by default in rendering text
1087 % horizontally, the result is unreadable. You can check it by Acrobat.
1088
1089 /.pdfDefaultDW  1000 def
1090 /.pdfDefaultDW2 [ 880 -1000 ] def
1091
1092 /addCIDmetrics {        % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
1093   dup length 5 add dict .copydict
1094   dup /FID undef
1095   dup /UniqueID undef
1096   dup /XUID undef
1097         % Insert the widths into the font.
1098
1099         % Stack: pdfresource newfont
1100
1101   1 index /DW .knownget {
1102     1 index /DW 3 -1 roll put
1103   } {
1104     dup /DW .pdfDefaultDW put
1105   } ifelse
1106
1107   1 index /W .knownget {
1108     dup 2 index /W 3 -1 roll put
1109     .pdfMakeInternalW 1 index /.internalW 3 -1 roll put
1110   } if
1111
1112   1 index /DW2 .knownget {
1113     1 index /DW2 3 -1 roll put
1114   } {
1115     dup /DW2 .pdfDefaultDW2 put
1116   } ifelse
1117
1118   1 index /W2 .knownget {
1119     dup 2 index /W2 3 -1 roll put
1120     .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
1121   } if
1122
1123   dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
1124   exch pop
1125 } bdef
1126
1127 /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
1128
1129   % convert /W or /W2 to internal expression
1130   %
1131   %   mtx_array: original /W or /W2 array
1132   %   item_size: number of metrics values per CID
1133   %
1134   %   for detail of the metrics list format in PDF,
1135   %   refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
1136   % 
1137   %   format of single entry in internal expression
1138   %
1139   %     [
1140   %       [cid_begin cid_end]
1141   %       value_is_varied (bool)
1142   %       [ [values for cid_begin...]
1143   %         [values for cid_begin + 1]
1144   %         ... ]
1145   %     ]
1146   %
1147
1148   7 dict
1149   begin
1150     /itemSize exch def
1151     /M exch def                 % original /W or /W2
1152     /Msize M length def
1153     /Mi { M i get } def         % W[i]
1154     /Mi1 { M i 1 add get } def  % W[i + 1]
1155     /putMTXEntry <<
1156       /arraytype   {
1157          [
1158            [Mi Mi Mi1 length itemSize idiv add 1 sub]
1159            true
1160            [
1161              0 itemSize Mi1 length 1 sub {
1162                [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
1163              } for
1164            ]
1165          ]
1166          /i i 2 add def
1167       }
1168       /integertype {
1169          [
1170            [Mi Mi1]
1171            false
1172            [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
1173          ]
1174          /i i 3 add def
1175       }
1176     >> def
1177
1178     /i 0 def
1179
1180     [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
1181   end
1182 } def
1183
1184 /.pdfMakeInternalW  { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
1185 /.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
1186
1187 /.pdfGetMTXByCID { % <internalMTXArray> <cid>
1188                    %     .pdfGetMTXByCID
1189                    %         { <MTXEntry> true | false }
1190
1191   % get values for given CID from internal format of /W or /W2
1192
1193   exch
1194   {
1195     { 
1196       dup 0 get {} forall      % Stack: <cid> <entry> <cid_0> <cid_1>
1197       3 index lt { pop pop false exit } if
1198       2 index exch sub dup 0 lt { pop pop false exit } if
1199       1 index 1 get not { pop 0 } if
1200       exch 2 get exch get true exit
1201     } loop
1202     { exit } if
1203   } forall
1204   dup type /arraytype eq { exch pop true } { pop false } ifelse
1205 } def
1206
1207
1208 % Apply the [D]W[2] metrics to a character before displaying.
1209 /CIDWProc {             % <w0x> <w0y> <llx> <lly> <urx> <ury>
1210                         %   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
1211                         %   <w0x'> ... <vy'>
1212   begin % push <font> to currentdict
1213     % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
1214     5 1 roll pop pop pop pop
1215
1216     {
1217       currentdict /DW .knownget not {   % no DW
1218         .pdfDefaultDW exit              % replace <w0x> by defaultDW
1219       } if
1220
1221       currentdict /.internalW .knownget not {    % no W
1222         exit                            % use already-stacked DW
1223       } if
1224
1225       dup length 0 eq {                 % W is null array
1226         pop                             % discard unusable W
1227         exit                            % use already-stacked DW
1228       } if
1229
1230       % W is finite array, try to get W_cid
1231       2 index .pdfGetMTXByCID {           % got W, discard DW
1232         exch pop {} forall
1233         exit
1234       } if
1235
1236       exit
1237     } loop
1238
1239     FontType 11 eq {
1240       1000 div                  % <w0x'> (normalized W)
1241     } if
1242     0                           % <w0y'>
1243
1244     % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
1245     9 -2 roll pop pop           % discard <w0x> <w0y>
1246     7  2 roll                   % put <w0x'> <w0y'>
1247
1248     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
1249     0                           % <w1x'>
1250     exch                        % put <w1x'>
1251
1252     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
1253     {
1254       currentdict /DW2 .knownget not {  % no DW2, use defaultDW2
1255         .pdfDefaultDW2 exit
1256       } if
1257
1258       currentdict /.internalW2 .knownget not {   % has DW2, no W2
1259         exit                            % use already-stacked DW2
1260       } if
1261
1262       dup length 0 eq {                 % W2 is null array
1263         pop                             % discard unusable W2
1264         exit                            % use already-stacked DW2
1265       } if
1266
1267       2 index .pdfGetMTXByCID {         % got W2_cid, discard DW2
1268         exch pop
1269         exit
1270       } if
1271
1272       % could not get W2_cid
1273       exit
1274
1275     } loop
1276
1277     exch pop                            % discard <cid>
1278
1279     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
1280     dup length 2 eq {                   % this is DW2
1281       FontType 11 eq {{1000 div}} {{}} ifelse forall exch
1282       8 index 2 div                     % <vx'> = <w0x'> / 2
1283       exch
1284     }{                                  % assume W2
1285       FontType 11 eq {{1000 div}} {{}} ifelse forall
1286     } ifelse
1287   end                                   % recover currentdict
1288
1289 } def
1290
1291 % <string> <match> tailmatch ==> <pre> true
1292 %                            ==> <string> false
1293 /tailmatch {
1294   2 copy length 1 index length .min
1295   dup 2 index length exch sub exch getinterval
1296   1 index eq {
1297     length 1 index length exch sub
1298     0 exch getinterval true
1299   } {
1300     pop false
1301   } ifelse
1302 } bind def
1303
1304 /makeboldfont {
1305   16 dict begin
1306     /strokewidth exch def
1307     /basecidfont exch def
1308     /FontMatrix [ 1 0 0 1 0 0 ] def
1309
1310     /CIDFontName /.boldfont def
1311     /CIDFontType 1 def
1312
1313     /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
1314     /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
1315
1316     /CIDSystemInfo dup basecidfont exch get def
1317     /FontBBox [ basecidfont /FontBBox get cvx exec
1318       4 2 roll basecidfont /FontMatrix get transform
1319       4 2 roll basecidfont /FontMatrix get transform
1320     ] def
1321
1322     /tmpstr 2 string def
1323     /BuildGlyph {
1324       gsave
1325       exch begin
1326         dup 256 idiv tmpstr exch 0 exch put
1327         256 mod tmpstr exch 1 exch put
1328         rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
1329         { basefont-V } { basefont-H } ifelse setfont
1330         strokewidth setlinewidth
1331         1 setlinejoin
1332         newpath
1333         0 0 moveto tmpstr false charpath stroke
1334         0 0 moveto tmpstr show
1335         currentpoint setcharwidth
1336       end
1337       grestore
1338     } bind def
1339
1340    currentdict
1341   end
1342   dup /CIDFontName get exch /CIDFont defineresource
1343 } bind def
1344
1345 % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
1346 %   CIDFont-resource is not modified.
1347 /findCIDFont {
1348   {
1349     dup /CIDFont resourcestatus {
1350       pop pop /CIDFont findresource
1351       exit
1352     } if
1353     .remove_font_name_prefix
1354     dup dup length string cvs
1355     (,Bold) tailmatch {
1356       exch pop
1357       cvn findCIDFont 0.03 makeboldfont
1358       exit
1359     } if
1360     (,Italic) tailmatch {
1361       exch pop
1362       cvn findCIDFont
1363       [ 1 0 0.3 1 0 0 ] makefont
1364       exit
1365     } if
1366     (,BoldItalic) tailmatch {
1367       exch pop
1368       cvn findCIDFont 0.03 makeboldfont
1369       [ 1 0 0.3 1 0 0 ] makefont
1370       exit
1371     } if
1372     pop
1373
1374     1 index /CIDSystemInfo get begin Registry (-) Ordering end
1375     concatstrings concatstrings
1376     cvn
1377     QUIET not {
1378       (Substituting CID font resource) print dup ==only
1379       ( for ) print 1 index ==only (.\n) print
1380     } if
1381     exch pop
1382     /CIDFont findresource
1383     exit
1384   } loop
1385 } bdef
1386
1387 /buildCIDType0 {        % <CIDFontType0-font-resource> buildCIDType0 <font>
1388   dup /BaseFont get findCIDFont exch pop
1389 } bdef
1390
1391 /buildCIDType2 {        % <CIDFontType2-font-resource> buildCIDType2 <font>
1392   dup /BaseFont get findCIDFont exch pop
1393 } bdef
1394
1395 /processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont>
1396   1 index /CIDToGIDMap knownoget {
1397     PDFfile fileposition 4 1 roll
1398     dup /Identity eq {
1399       pop
1400     } {
1401       true resolvestream
1402                 % Stack: filepos fontres font mapstream
1403         % Can't know the length of the decompressed stream, so allocate a big buffer...
1404       dup 65534 string readstring {
1405         % Length exceeded max string size, use an array of two strings
1406         1 index 65534 string readstring pop   % maybe a null string - not important.
1407         2 array astore
1408                 % Stack: filepos fontres font mapstream array 
1409         dup 1 get length 65534 add
1410       } {
1411         dup length
1412       } ifelse
1413       2 idiv
1414         % Stack: filepos fontres font mapstream array/string CIDCount
1415       3 index exch /CIDCount exch put
1416       exch closefile exch
1417       dup /CIDMap 4 -1 roll put
1418     } ifelse
1419     3 2 roll PDFfile exch setfileposition
1420   } if
1421 } bdef
1422
1423 % Adjust a CIDFontType0 DW[2] in the font resource.
1424 /adjustCIDType0 {               % <font-resource> <font> adjustfont <font'>
1425   addCIDmetrics
1426   dup /CIDFontName get exch /CIDFont defineresource
1427 } bind def
1428
1429 % Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource.
1430 /adjustCIDType2 {               % <font-resource> <font> adjustfont <font'>
1431   addCIDmetrics
1432   processCIDToGIDMap
1433   dup /CIDFontName get exch /CIDFont defineresource
1434 } bind def
1435
1436 % ---------------- Other embedded fonts ---------------- %
1437
1438 /fontloadprocs mark
1439   /Type1C /readType1C cvx
1440   /CIDFontType0C /readCIDFontType0C cvx
1441 .dicttomark readonly def
1442
1443 % Read an embedded compressed font.
1444 /readType1C {           % <font-resource> <stream-dict> readType1C <font>
1445   1 index exch
1446   PDFfile fileposition 3 1 roll
1447   dup true resolvestream dup readfontfilter
1448                 % Stack: pos resource streamdict stream filter
1449   3 index /FontDescriptor oget /FontName oget
1450   1 index FRD
1451   closefile closefile pop
1452   PDFfile 3 -1 roll setfileposition
1453   /FontDescriptor oget /FontName oget pdfaddcachedfont
1454   exch pop
1455 } bdef
1456
1457 % Read an embedded CFF CIDFont.
1458 /readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
1459   PDFfile fileposition 3 1 roll
1460   dup true resolvestream dup readfontfilter
1461                 % Stack: pos resource streamdict stream filter
1462   3 index /FontDescriptor oget /FontName oget
1463   1 index FRD
1464   closefile closefile pop
1465   PDFfile 3 -1 roll setfileposition
1466                 % Some broken Adobe software produces PDF files in which
1467                 % the FontName of the CFF font and the FontName in the
1468                 % FontDescriptor don't match the BaseFont in the font.
1469                 % Use the FontName, rather than the BaseFont, here.
1470   dup /FontDescriptor oget /FontName oget /CIDFont findresource
1471   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
1472 } bdef
1473
1474 % ---------------- Font lookup ---------------- %
1475
1476 /fonttypeprocs mark             % <font-resource> -proc- <font>
1477   /Type0 //buildType0
1478   /Type1 //buildType1
1479   /MMType1 //buildType1
1480   /Type3 //buildType3
1481   /TrueType //buildTrueType
1482   /CIDFontType0 //buildCIDType0
1483   /CIDFontType2 //buildCIDType2
1484 .dicttomark readonly def
1485
1486 /adjustfonttypes mark
1487   /Type1 //adjustfont
1488   /MMType1 //adjustfont
1489   /TrueType //adjustfont
1490   /CIDFontType0 //adjustCIDType0
1491   /CIDFontType2 //adjustCIDType2
1492 .dicttomark readonly def
1493
1494 /resourcefont                   % <font-resource> resourcefont <font>
1495 { dup /PSFont .knownget
1496   { /FID knownoget { type /fonttype eq } { //false } ifelse }
1497   { //false }
1498   ifelse
1499   { /PSFont get }
1500   { dup dup /FontDescriptor knownoget { % Stack: font-res font-res font-desc
1501       dup /FontObject .knownget {
1502         3 1 roll pop pop
1503       } {
1504         dup /FontFile knownoget
1505         { dup /Length oget 0 eq
1506           { pop pop dup /Subtype get fonttypeprocs exch get exec }
1507           { exch pop readtype1 }
1508           ifelse
1509         }
1510         {
1511           dup /FontFile2 knownoget
1512           { exch pop readtruetype }
1513           { /FontFile3 knownoget
1514             { dup /Subtype get fontloadprocs exch get exec }
1515             { dup /Subtype get fonttypeprocs exch get exec }
1516             ifelse
1517           }
1518           ifelse
1519         }
1520         ifelse
1521         1 index /FontDescriptor oget
1522         1 index /FontObject exch put        % Save pointer to the font
1523       }
1524       ifelse
1525     }
1526     { dup /Subtype get fonttypeprocs exch dup () cvn eq {
1527         (   **** Warning: Font missing required Subtype, /Type1 assumed.\n)
1528         pdfformaterror
1529         pop /Type1
1530       } if get exec
1531     }
1532     ifelse
1533         % Stack: font-res font
1534     1 index 3 1 roll
1535     1 index /Subtype get
1536     //adjustfonttypes exch .knownget { exec } { exch pop } ifelse
1537     dup 3 1 roll /PSFont exch put
1538   }
1539   ifelse
1540   dup checkGlyphNames2Unicode
1541 } bdef
1542
1543 drawopdict begin
1544   /d0 {
1545     .adjustcharwidth setcharwidth
1546   } bdef
1547   /d1 {
1548     4 index 0 ne {
1549       % invalid wy parameter for d1 in Type3 font (must be 0)
1550       % Even though the PDF 1.4 specification states that this must be 0,
1551       % Distiller sometimes creates Type3 fonts with non-zero wy. We set
1552       % it to 0 since this is apparently what Acrobat Reader 4 and 5 do,
1553       % but if the specification is ever changed to allow non-zero wy, this
1554       % will not work.
1555       5 -1 roll pop 0 5 1 roll    % set wy to 0
1556     } if
1557
1558     2 copy                           % ... llx lly urx ury | urx ury 
1559     0 ne exch 0 ne                   % ... llx lly urx ury | ury!=0 urx!=0
1560     3 index 6 index eq and           % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx)
1561     exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx) || (ury!=0 && lly==ury)
1562       % The bounding box is empty and likely incorrect. Don't cache.
1563       pop pop pop pop .adjustcharwidth setcharwidth
1564     } {
1565       6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
1566     } ifelse
1567   } bdef
1568   /Tf {
1569     1 index Page /Font rget not { 1 index /invalidfont signalerror } if
1570     resourcefont exch Tf pop
1571   } bdef
1572 end
1573
1574 end                     % pdfdict
1575 end                     % GS_PDF_ProcSet
1576 .setglobal