1 % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
3 % This software is provided AS-IS with no warranty, either express or
6 % This software is distributed under license and may not be copied,
7 % modified or distributed except as expressly authorized under the terms
8 % of the license contained in the file LICENSE in this distribution.
10 % For more information about licensing, please refer to
11 % http://www.ghostscript.com/licensing/. For information on
12 % commercial licensing, go to http://www.artifex.com/licensing/ or
13 % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
16 % $Id: pdf_font.ps,v 1.80 2005/09/29 15:24:53 leonardo Exp $
17 % PDF font operations.
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.
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.
33 /.setlanguagelevel where { pop 2 .setlanguagelevel } if
34 .currentglobal true .setglobal
35 /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
39 % We cache the PostScript font in an additional element of the
40 % font resource dictionary, called PSFont.
42 % ---------------- Encodings ---------------- %
44 /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
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
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
58 pop 1 index length .max array dup 0 4 -1 roll putinterval
60 % Stack: enc' code element
63 { 3 copy put pop 1 add }
68 % Get the Encoding for a font.
69 /getencoding % <base-encoding> <font-resource> getencoding <enc>
71 { dup type /nametype eq
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.
79 dup dup dup /MacRomanEncoding eq
80 exch /MacExpertEncoding eq or
81 exch /WinAnsiEncoding eq or
82 { exch pop findencoding
88 { dup /BaseEncoding knownoget
92 ( **** Warning: Ignoring bad BaseEncoding name.\n) pdfformaterror
93 % as found in a PDF file from J.D.Edwards OneWorld (B7333), bug 687786
96 findencoding 3 -1 roll pop exch
101 /Differences knownoget { updateencoding } if
108 /checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode -
111 dup /FontInfo .knownget {
112 /GlyphNames2Unicode .knownget {
113 (Has GlyphNames2Unicode) =
114 pop % { exch == ==} forall
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'>
125 3 copy .processToUnicode
126 getfontmetrics 5 -1 roll pop .updatefont { dup /FontName get exch definefont } if
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
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
150 % stack: false index glyphname Diff_element at_index
152 % stack: false index glyphname at_index
154 true 5 1 roll % stack: true false index glyphname at_index
158 1 add % at_index++ stack: false index glyphname at_index'
161 % stack: true false index glyphname
162 % or : false index glyphname at_index
166 /unique_name { % <dict> </root> unique_name </unique>
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~).
172 .namestring % <<>> (root)
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)
181 exch pop exit % <<>> (root~GS~0)
185 exch pop cvn % /root0
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
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)
217 Widths 2 index 4 index sub dup 2 index length ge {
218 ( **** Warning: Font Widths array size is smaller than character range.\n)
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
227 % Stack: font font-res mscale first-char index charname width
229 % The following 'loop' is only context for 'exit'.
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 {
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.
246 /Encoding Encoding dup length array copy def
249 % To prevent too many new names, check whether
250 % we can use one already created for same glyph.
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
264 } { % f r s c i n w b n1
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
273 % Stack: font font-res mscale first-char index new_name width
276 2 copy Metrics 3 1 roll put
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 {
289 /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
291 % Stack: font font-res mscale missing-width metrics charname
292 % Work around the abovementioned pdfTeX bug.
294 2 copy known not { 2 copy 4 index put } if pop
302 exch Encoding Metrics GlyphMap end
308 currentdict /unique_name undef
309 currentdict /match_in_diff undef
311 /ToUnicodeCMapReader 3 dict def
312 //ToUnicodeCMapReader begin
313 /defineresource % <name> <dict> <cat-name> defineresource <dict>
316 dup userdict exch /.lastToUnicode exch put
321 ( **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n) pdfformaterror
323 } bind def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed.
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 ()
334 /copy&def % <key> <value> <bool> copy&def -
344 { currentglobal currentdict gcheck setglobal
345 exch dup length string copy exch
351 /.convert_ToUnicode-into-g2u % <GlyphNames2Unicode> <Encoding|null> <CMap> .convert_ToUnicode-into-g2u -
354 (.convert_ToUnicode-into-g2u beg) =
357 /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "CMap operators".
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)
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 ==
379 1 index length 0 eq {
381 exch pop exch pop exch pop exch % e [] i (values) offset
384 } if % e [] i (values) cid|name
387 ( defined single: ) print 1 index =string cvs print ( ) print dup ==
389 false copy&def % e [] i
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
398 ( keyL=) print dup =string cvs print
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
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
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)
413 ( defined from range: ) print 1 index =string cvs print ( ) print dup ==
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)
422 pop pop pop pop pop pop pop % e []
430 (.convert_ToUnicode-into-g2u end) =
434 /.processToUnicode % <font-resource> <font-dict> <encoding|null> .processToUnicode -
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 {
440 (.processToUnicode beg) =
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
448 PDFfile fileposition exch
450 //ToUnicodeCMapReader begin
453 PDFfile exch setfileposition
454 1 index /FontInfo .knownget not {
455 1 index /FontInfo 5 dict dup 4 1 roll put
457 dup /GlyphNames2Unicode .knownget not {
458 currentglobal exch dup gcheck setglobal
459 dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput
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
469 (.processToUnicode end) =
475 % ---------------- Descriptors ---------------- %
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
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
500 % ---------------- Utilities ---------------- %
503 /.pdforigfontcache_g 20 dict def
504 currentglobal false setglobal
505 systemdict /.pdforigfontcache_l 20 dict .forceput
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 {
513 dup .pdforigfontcache_l exch .knownget {
517 dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse
518 % Stack : font_name font font cache
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
532 /.remove_font_name_prefix { % <name> .remove_font_name_prefix <name>
533 dup .namestring (+) search {
535 { dup 65 lt exch 90 gt or {
548 % Find a font (except for embedded ones), and adjust its encoding if necessary.
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
555 dup /Font resourcestatus {
556 pop pop pdffindcachedfont
558 1 index /FontDescriptor knownoget {
559 % Stack: font-res fontname fontdesc
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
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 {
574 ( **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
576 pop 2 index % grab the BaseFont from the stack.
578 .remove_font_name_prefix
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
591 dup 3 index ne QUIET not and {
592 (Substituting font ) print dup =only
593 ( for ) print 2 index =only (.) = flush
596 % Stack: font-res fontname fontdesc font
597 % If this is a small-caps font, replace the CharString
599 exch /Flags oget 16#20000 and 0 ne {
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
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
620 dup /FontName get 2 index ne {
622 2 copy exch /FontName exch put
626 % No descriptor available, use the default algorithm.
633 % ---------------- Type 1 fonts ---------------- %
635 /buildType1 % <Type1-font-resource> buildType1 <font>
636 { dup /BaseFont get pdffindfont
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.
655 % Read an embedded Type 1 font.
656 /readfontfilter { % <proc> readfontfilter <filter>
657 0 () /SubFileDecode filter
659 /readtype1dict 5 dict dup begin
661 dup topFontDict eq topFontDict null eq or {
662 dup wcheck not { dup length dict copy } if
663 exch pop savedFontName exch
665 //systemdict /definefont get exec
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
677 /undef_proc_warning {
678 /Repaired true store % flag that we have warnings
679 UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put
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
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.
695 PDFfile fileposition 3 1 roll
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
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
707 /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
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.
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
731 % Execute the appropriate reading procedure.
732 /type1read % <dict> type1read <string>
734 { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
735 ( ) leftstr copy cvs pop end
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
746 { dup =only ( read ) print
747 1 index length =only (: ) print
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
756 1 index 0 get 16#80 eq {
757 ( **** Warning: Embedded Type1 font in PFB format is not valid PDF.\n)
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
766 ( **** Warning: Type 1 PFB segment length and Length 1 value do not match.\n)
768 exch % keep the PFB length instead
771 buffer type1readdata % go ahead and read a block
773 if % if not PFB, return pfbhdr string (first char of file, usually %).
776 % Read the next block of the initial text portion.
777 /type1read1 { % <left> type1read1 <string> <left'>
778 PDFDEBUG { (read1 ) print } if
780 pop sectionstr 0 2 put
782 % Determine whether to hexify data for eexec.
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
796 ( **** Warning: Type 1 PFB segment length and Length 2 value do not match.\n)
798 exch % keep the PFB length instead
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
808 /buffer2 buffer def % We don't need an intermediate buffer.
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
823 % Read the next block of the encrypted portion.
825 (0000000000000000000000000000000000000000000000000000000000000000\n\
826 0000000000000000000000000000000000000000000000000000000000000000\n\
827 0000000000000000000000000000000000000000000000000000000000000000\n\
828 0000000000000000000000000000000000000000000000000000000000000000\n\
829 0000000000000000000000000000000000000000000000000000000000000000\n\
830 0000000000000000000000000000000000000000000000000000000000000000\n\
831 0000000000000000000000000000000000000000000000000000000000000000\n\
832 0000000000000000000000000000000000000000000000000000000000000000\n\
835 /type1read2 { % <left> type1read2 <string> <left'>
836 PDFDEBUG { (read2 ) print } if
838 { pop sectionstr 0 3 put
841 { PDFDEBUG { (trailer ) print } if
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
854 ( **** Warning: Type 1 PFB segment length and Length 3 value do not match.\n)
856 exch % keep the PFB length instead
864 { buffer2 type1readdata exch hexify exch
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
876 % ---------------- Type 3 fonts ---------------- %
878 /buildType3 { % <Type3-font-resource> buildType3 <font>
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
891 /Resources 1 index /Resources knownoget {
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 {
901 /FirstChar 1 index /FirstChar oget def
902 /LastChar 1 index /LastChar oget def
904 /FontName 1 index /Name .knownget not {
905 PDFfile fileposition 16 10 string cvrs cvn
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.
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 }
921 PDFfile fileposition exch
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
929 PDFfile exch setfileposition
932 dup currentdict Encoding .processToUnicode
933 FontName currentdict end definefont exch pop
935 /.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'>
938 CharCode FirstChar ge CharCode LastChar le and {
939 exch pop Widths CharCode FirstChar sub get exch
944 % ---------------- TrueType fonts ---------------- %
948 /Arial,Italic /Helvetica-Oblique
949 /Arial,Bold /Helvetica-Bold
950 /Arial,BoldItalic /Helvetica-BoldOblique
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
959 /buildTrueType { % <TrueType-font-resource> buildTrueType <font>
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 {
965 (Substituting font ) print dup =only
966 ( for ) print 1 index =only (.) = flush
968 exch 3 1 roll pdffindfont
970 2 copy exch /FontName exch put
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.
982 PDFfile fileposition 3 1 roll
983 true resolvestream readfontfilter
984 % Stack: filepos fontres stream
985 1 index /Subtype get /CIDFontType2 eq {
987 % Stack: filepos fontres cidfont
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
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
1002 PDFfile 3 -1 roll setfileposition
1003 % Ignore both the Encoding and the Widths.
1007 % ---------------- Type 0 fonts ---------------- %
1009 % Predefine the known CMaps, but only create them on demand.
1011 /Identity-H { /Identity-H 0 makeIdentityCMap }
1012 /Identity-V { /Identity-V 1 makeIdentityCMap }
1015 /makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap -
1016 .currentglobal true .setglobal 3 1 roll
1017 /CIDInit /ProcSet findresource begin
1022 /CIDSystemInfo 3 dict dup begin
1023 /Registry (Adobe) def
1024 /Ordering (Identity) def
1027 %/CMapName (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>
1038 % <0001> <00ff> 1 <0100> <ffff> 256
1042 CMapName currentdict /CMap defineresource
1043 knownCMaps CMapName 2 index put
1045 end % CIDInit ProcSet
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
1056 knownCMaps 1 index .knownget
1057 { exch pop exec } { /undefined signalerror } ifelse
1060 PDFfile fileposition exch
1061 dup /CMapName get exch true resolvestream cvx exec
1063 exch PDFfile exch setfileposition
1066 3 index /DescendantFonts oget { exec resourcefont } forall
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
1080 % ---------------- CIDFontType0/2 fonts ---------------- %
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.
1089 /.pdfDefaultDW 1000 def
1090 /.pdfDefaultDW2 [ 880 -1000 ] def
1092 /addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
1093 dup length 5 add dict .copydict
1097 % Insert the widths into the font.
1099 % Stack: pdfresource newfont
1101 1 index /DW .knownget {
1102 1 index /DW 3 -1 roll put
1104 dup /DW .pdfDefaultDW put
1107 1 index /W .knownget {
1108 dup 2 index /W 3 -1 roll put
1109 .pdfMakeInternalW 1 index /.internalW 3 -1 roll put
1112 1 index /DW2 .knownget {
1113 1 index /DW2 3 -1 roll put
1115 dup /DW2 .pdfDefaultDW2 put
1118 1 index /W2 .knownget {
1119 dup 2 index /W2 3 -1 roll put
1120 .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
1123 dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
1127 /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
1129 % convert /W or /W2 to internal expression
1131 % mtx_array: original /W or /W2 array
1132 % item_size: number of metrics values per CID
1134 % for detail of the metrics list format in PDF,
1135 % refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
1137 % format of single entry in internal expression
1140 % [cid_begin cid_end]
1141 % value_is_varied (bool)
1142 % [ [values for cid_begin...]
1143 % [values for cid_begin + 1]
1151 /M exch def % original /W or /W2
1153 /Mi { M i get } def % W[i]
1154 /Mi1 { M i 1 add get } def % W[i + 1]
1158 [Mi Mi Mi1 length itemSize idiv add 1 sub]
1161 0 itemSize Mi1 length 1 sub {
1162 [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
1172 [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
1180 [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
1184 /.pdfMakeInternalW { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
1185 /.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
1187 /.pdfGetMTXByCID { % <internalMTXArray> <cid>
1189 % { <MTXEntry> true | false }
1191 % get values for given CID from internal format of /W or /W2
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
1204 dup type /arraytype eq { exch pop true } { pop false } ifelse
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
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
1217 currentdict /DW .knownget not { % no DW
1218 .pdfDefaultDW exit % replace <w0x> by defaultDW
1221 currentdict /.internalW .knownget not { % no W
1222 exit % use already-stacked DW
1225 dup length 0 eq { % W is null array
1226 pop % discard unusable W
1227 exit % use already-stacked DW
1230 % W is finite array, try to get W_cid
1231 2 index .pdfGetMTXByCID { % got W, discard DW
1240 1000 div % <w0x'> (normalized W)
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'>
1248 % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
1252 % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
1254 currentdict /DW2 .knownget not { % no DW2, use defaultDW2
1258 currentdict /.internalW2 .knownget not { % has DW2, no W2
1259 exit % use already-stacked DW2
1262 dup length 0 eq { % W2 is null array
1263 pop % discard unusable W2
1264 exit % use already-stacked DW2
1267 2 index .pdfGetMTXByCID { % got W2_cid, discard DW2
1272 % could not get W2_cid
1277 exch pop % discard <cid>
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
1285 FontType 11 eq {{1000 div}} {{}} ifelse forall
1287 end % recover currentdict
1291 % <string> <match> tailmatch ==> <pre> true
1292 % ==> <string> false
1294 2 copy length 1 index length .min
1295 dup 2 index length exch sub exch getinterval
1297 length 1 index length exch sub
1298 0 exch getinterval true
1306 /strokewidth exch def
1307 /basecidfont exch def
1308 /FontMatrix [ 1 0 0 1 0 0 ] def
1310 /CIDFontName /.boldfont def
1313 /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
1314 /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
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
1322 /tmpstr 2 string def
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
1333 0 0 moveto tmpstr false charpath stroke
1334 0 0 moveto tmpstr show
1335 currentpoint setcharwidth
1342 dup /CIDFontName get exch /CIDFont defineresource
1345 % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
1346 % CIDFont-resource is not modified.
1349 dup /CIDFont resourcestatus {
1350 pop pop /CIDFont findresource
1353 .remove_font_name_prefix
1354 dup dup length string cvs
1357 cvn findCIDFont 0.03 makeboldfont
1360 (,Italic) tailmatch {
1363 [ 1 0 0.3 1 0 0 ] makefont
1366 (,BoldItalic) tailmatch {
1368 cvn findCIDFont 0.03 makeboldfont
1369 [ 1 0 0.3 1 0 0 ] makefont
1374 1 index /CIDSystemInfo get begin Registry (-) Ordering end
1375 concatstrings concatstrings
1378 (Substituting CID font resource) print dup ==only
1379 ( for ) print 1 index ==only (.\n) print
1382 /CIDFont findresource
1387 /buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font>
1388 dup /BaseFont get findCIDFont exch pop
1391 /buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font>
1392 dup /BaseFont get findCIDFont exch pop
1395 /processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont>
1396 1 index /CIDToGIDMap knownoget {
1397 PDFfile fileposition 4 1 roll
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.
1408 % Stack: filepos fontres font mapstream array
1409 dup 1 get length 65534 add
1414 % Stack: filepos fontres font mapstream array/string CIDCount
1415 3 index exch /CIDCount exch put
1417 dup /CIDMap 4 -1 roll put
1419 3 2 roll PDFfile exch setfileposition
1423 % Adjust a CIDFontType0 DW[2] in the font resource.
1424 /adjustCIDType0 { % <font-resource> <font> adjustfont <font'>
1426 dup /CIDFontName get exch /CIDFont defineresource
1429 % Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource.
1430 /adjustCIDType2 { % <font-resource> <font> adjustfont <font'>
1433 dup /CIDFontName get exch /CIDFont defineresource
1436 % ---------------- Other embedded fonts ---------------- %
1439 /Type1C /readType1C cvx
1440 /CIDFontType0C /readCIDFontType0C cvx
1441 .dicttomark readonly def
1443 % Read an embedded compressed font.
1444 /readType1C { % <font-resource> <stream-dict> readType1C <font>
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
1451 closefile closefile pop
1452 PDFfile 3 -1 roll setfileposition
1453 /FontDescriptor oget /FontName oget pdfaddcachedfont
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
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
1474 % ---------------- Font lookup ---------------- %
1476 /fonttypeprocs mark % <font-resource> -proc- <font>
1479 /MMType1 //buildType1
1481 /TrueType //buildTrueType
1482 /CIDFontType0 //buildCIDType0
1483 /CIDFontType2 //buildCIDType2
1484 .dicttomark readonly def
1486 /adjustfonttypes mark
1488 /MMType1 //adjustfont
1489 /TrueType //adjustfont
1490 /CIDFontType0 //adjustCIDType0
1491 /CIDFontType2 //adjustCIDType2
1492 .dicttomark readonly def
1494 /resourcefont % <font-resource> resourcefont <font>
1495 { dup /PSFont .knownget
1496 { /FID knownoget { type /fonttype eq } { //false } ifelse }
1500 { dup dup /FontDescriptor knownoget { % Stack: font-res font-res font-desc
1501 dup /FontObject .knownget {
1504 dup /FontFile knownoget
1505 { dup /Length oget 0 eq
1506 { pop pop dup /Subtype get fonttypeprocs exch get exec }
1507 { exch pop readtype1 }
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 }
1521 1 index /FontDescriptor oget
1522 1 index /FontObject exch put % Save pointer to the font
1526 { dup /Subtype get fonttypeprocs exch dup () cvn eq {
1527 ( **** Warning: Font missing required Subtype, /Type1 assumed.\n)
1533 % Stack: font-res font
1535 1 index /Subtype get
1536 //adjustfonttypes exch .knownget { exec } { exch pop } ifelse
1537 dup 3 1 roll /PSFont exch put
1540 dup checkGlyphNames2Unicode
1545 .adjustcharwidth setcharwidth
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
1555 5 -1 roll pop 0 5 1 roll % set wy to 0
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
1565 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
1569 1 index Page /Font rget not { 1 index /invalidfont signalerror } if
1570 resourcefont exch Tf pop
1575 end % GS_PDF_ProcSet