Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
1334
 
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
 
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