You are on page 1of 32

% % % % % % % % % % % % % %

Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861.

% $Id: pdf_font.ps 9897 2009-07-28 16:20:51Z ken $ % PDF font operations. % % % % % Since PDF font are not unique and can collide with external font or each other, use font dictionaries obtained from PDF directly, register them as resources or look them up by name. Use findfont for non-embedded fonts only. CIDFont resources still use the old described below. resources never oparator logic

% Finding a font by name can't give a proper result when PDF font names aren't u nique. % But it is only the way to obtain a font in Postscript after a font file is exe cuted. % Therefore using a FontName (and findfont) is allowed only % immediately after a font file is executed. % In all other cases the font to be found by a pointer through PDF structures. % % This ideal logics can't work for documents, % which define a font resource with an embedded font, % and another font resource with same BaseFont but with no embedded font % (and possibly with no font descriptor). % Our testbase does contain such examples. % In this case we do find font by FontName (with findfont), % since there is no other way to get a reasonable result. /.setlanguagelevel where { pop 2 .setlanguagelevel } if .currentglobal true .setglobal /pdfdict where { pop } { /pdfdict 100 dict def } ifelse GS_PDF_ProcSet begin pdfdict begin % We cache the PostScript font in an additional element of the % font resource dictionary, called PSFont. % ---------------- Encodings ---------------- % /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def % Apply a list of differences to an Encoding. % Note that the differences may cause the array to grow. /updateencoding { % <encoding|null> <differences> updateencoding <enc'> % Calculate the length of the result. % in case the incoming Encoding is null, use .notdefEncoding exch dup null eq { pop .notdefEncoding } if 0 0 3 index {

dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse % Differences list may not be in order, update the largest_index % stack: <Differences> <encoding> <largest_index> <at_index> 2 copy lt { exch pop dup } if % at_index is new largest } forall pop 1 index length .max array dup 0 4 -1 roll putinterval exch 0 exch { % Stack: enc' code element dup type /nametype ne { exch pop oforce } { 3 copy put pop 1 add } ifelse } forall pop } bdef /good_encoding_names << /MacRomanEncoding 0 /MacExpertEncoding 0 /WinAnsiEncoding 0 >> readonly def /known_symbolic_fonts << /Wingdings2 0 >> readonly def % Get the Encoding for a font. /getencoding % <base-encoding> <font-resource> getencoding <enc> { dup /Encoding knownoget { dup type /nametype eq { % The published PDF specification says the Encoding name % "must be" one of the 3 predefined Encodings, implying % that an error should occur if it isn't. However, Acrobat % Reader simply ignores unknown names, and since there are % some buggy applications that rely on this, we do the same. //good_encoding_names 1 index known { exch /BaseFont knownoget not { 0 } if % Ignore named encodings for known symbolic fonts. See bug 690135. //known_symbolic_fonts exch known { pop } { exch pop findencoding } ifelse } { pop pop } ifelse } { exch pop dup type /arraytype eq { exch pop ( **** Warning: Encoding is an array, not name or dictionary.\n) p dfformaterror } { dup /BaseEncoding knownoget { dup / eq { pop ( **** Warning: Ignoring bad BaseEncoding name.\n) pdfform aterror % as found in a PDF file from J.D.Edwards OneWorld (B7333), b ug 687786 }

{ findencoding 3 -1 roll pop exch } ifelse } if /Differences knownoget { updateencoding } if } ifelse } ifelse } { pop ( **** Warning: Encoding not present.\n) pdfformaterror } ifelse } bdef currentdict /good_encoding_names undef currentdict /known_symbolic_fonts undef /checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode { PDFDEBUG { dup /FontInfo .knownget { /GlyphNames2Unicode .knownget { (Has GlyphNames2Unicode) = pop % { exch == ==} forall } if } if } if pop } bind def % Define a font using it's FontName as the key. % Adjust a font according to the Encoding and Widths in the font resource. /adjustfont { % <font-resource> <font> adjustfont <font'> getfontencoding 3 copy .processToUnicode getfontmetrics 5 -1 roll pop .updatefont { .completefont } if } bind def % Get the (possibly modified) encoding of a font. /getfontencoding { % <font-resource> <font> getfontencoding % <font-resource> <font> <Encoding|null> //systemdict /IgnoreTTEncoding .knownget not { //false } if { 1 index /Subtype get /TrueType eq } { //false } ifelse { //null } { 1 index /Encoding known { dup /Encoding knownoget { 2 index getencoding } { //null } ifelse } { //null } ifelse } ifelse } bdef % % % % % Returns true if the current glyph is in the Differences array at the specified index value. This is needed because the Widths array may map to the same glyph at different positions from the Encoding. We want to use the Width that was associated with the one specified in the Encoding::Differences list.

/match_in_diff % <Differences> <index> <glyphname> match_in_diff <bool> { false 4 1 roll 0 4 -1 roll % stack: false index glyphname at_index==0 Diffe rences { exch 1 index type /nametype ne { % stack: false index glyphname Diff_element at_index pop % Diff_element is new at_index } { % stack: false index glyphname Diff_element at_index exch 2 index eq { % stack: false index glyphname at_index dup 3 index eq { true 5 1 roll % stack: true false index glyphname at_index pop exit } if } if 1 add % at_index++ stack: false index glyphname at_index' } ifelse } forall % stack: true false index glyphname % or : false index glyphname at_index pop pop pop } bdef /unique_name { % <dict> </root> unique_name </unique> % % Note : this function interacts with pdf_write_encoding in src/gdevpdtw.c % and with copied_drop_extension_glyphs in src\gxfcopy.c % by adding a reserved substring (~GS~). % .namestring % <<>> (root) 0 1 65535 { 5 string cvs % <<>> (root) (0) (~GS~) exch concatstrings 1 index exch % <<>> (root) (root) (~GS~0) concatstrings % <<>> (root) (root~GS~0) dup % <<>> (root) (root~GS~0) (root~GS~0) 3 index exch % <<>> (root) (root~GS~0) <<>> (root~GS~0) known not { exch pop exit % <<>> (root~GS~0) } if pop } for exch pop cvn % /root0 } bdef % Get the metrics of a font, if specified. /getfontmetrics { % <font-resource> <font> <Encoding|null> getfontmetrics % <font-resource> <font> <Encoding|null> % <Metrics|null> <GlyphMap|null> 2 index /Widths known { dup //null eq { pop dup /Encoding get } if 7 dict begin dup length dict /Metrics exch def /Encoding exch def /GlyphMap //null def exch dup /Widths oget /Widths exch def % Stack: font font-res

% Note that widths are always based on a 1000-unit % character space, but the FontMatrix may specify % some other scale factor. Compensate for this here, % by scaling the Widths if necessary. 0.001 2 index /FontMatrix get 0 get dup 0 eq { % FontMatrix.xx == 0, so we cannot scale down by xx. % - FontMatrix[0] == 0 implies either FontMatrix[1] <> 0 or % FontMatrix cannot be inverted. In the 1st case we have % FontMatrixNonHV == true and will render text with cshow + xs how. % forced % [by altering metrics in PS glyph space]. % HACK: % - we scale down by FontMatrix[1]; % - given the format of Metrics entries we use, wy = 0 in glyph space; % - as a result, the cshow procedure receives as wy the value we % need for wx (all of this in PS user space). pop 2 index /FontMatrix get 1 get dup 0 eq { pop 1 } if % sorry, no way to enforce PDF metrics by altering the font } if div % Stack: font font-res mscale /FirstChar 2 index /FirstChar oget def /LastChar 2 index /LastChar oget def Encoding length LastChar le { ( **** Warning: Font Encoding array size is smaller than character ra nge.\n) pdfformaterror } if 1 index /FontDescriptor knownoget { /MissingWidth knownoget not { 0 } if } { 1000 } ifelse /MissingWidth exch def Widths length LastChar FirstChar sub le { ( **** Warning: Font Widths array size is smaller than character rang e.\n) pdfformaterror /Widths [Widths aload length LastChar FirstChar sub exch sub MissingWid th exch {dup} repeat] def } if FirstChar 0 Encoding { % Stack: font font-res mscale first-char index charname 1 index FirstChar lt { MissingWidth } { 1 index LastChar gt { MissingWidth } { Widths 2 index FirstChar sub g et } ifelse } ifelse In the 2nd case, metrics in the PDF Font object cannot be en

% Stack: font font-res mscale first-char index charname width 4 index mul % The following 'loop' is only context for 'exit'. { % Work around a bug in pdfTeX, which can generate Encoding % vectors containing nulls : 1 index //null eq { exit } if Metrics 2 index .knownget { 1 index ne } { //false } ifelse { % Two or more Encoding elements refer same glyph name, % and Widths specify different wihts for it. % Since a Postscript font can't have different % Metrics for same glyph name, % we generate an unique name, and create a new % Charstrings entry with same glyph value. GlyphMap //null eq { /Encoding Encoding dup length array copy def /GlyphMap 4 dict def } if % To prevent too many new names, check whether % we can use one already created for same glyph. //true GlyphMap { % f r s c i n w b n1 n2 4 index eq { % f r s c i n w b n1 dup Metrics exch get % f r s c i n w b n1 w1 3 index eq { % f r s c i n w b n1 4 3 roll pop % f r s c i w b n1 3 1 roll pop % f r s c i n1 w Encoding 3 index 3 index put //false % f r s c i n1 w b exit } { pop } ifelse } { % f r s c i n w b n1 pop } ifelse } forall % f r s c i n w b { % Do create a new name. Metrics 2 index //unique_name exec % f r s c i n w nn Encoding 4 index 2 index put GlyphMap 1 index 5 -1 roll put % f r s c i w nn exch % Stack: font font-res mscale first-char index new_name width } if } if 2 copy Metrics 3 1 roll put exit } loop pop pop 1 add } forall pop pop pop exch Encoding Metrics GlyphMap end } { //null //null

} ifelse } bdef currentdict /unique_name undef currentdict /match_in_diff undef /ToUnicodeCMapReader 3 dict begin /defineresource % <name> <dict> <cat-name> defineresource <dict> { pop dup userdict exch /.lastToUnicode exch put exch pop } bind def /CIDSystemInfo { ( **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n) pdfformaterror /CIDSystemInfo } bind def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed. /CMapName { ( **** Warning: ToUnicode CMap has no CMapName.\n\ See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdff ormaterror /CMap1 % arbitrary, PDF defineresource tolerates non-unique names } bind def % A work around incorrect ToUnicode CMap generated by GS before rev . 6201. currentdict end readonly def /string2number % <string> string2number <number> { 0 exch dup 0 exch 1 exch length 1 sub { % n () i 1 index exch get % n () v 3 2 roll 256 mul add exch % v+n*256 () } for pop % N } bind def /copy&def % <key> <value> <bool> copy&def { { true } { currentdict gcheck { dup gcheck not } { false } ifelse } ifelse { currentglobal currentdict gcheck setglobal exch dup length string copy exch setglobal } if def } bind def /.convert_ToUnicode-into-g2u % <GlyphNames2Unicode> <Encoding|null> <CMap> .conv ert_ToUnicode-into-g2u { PDFDEBUG { (.convert_ToUnicode-into-g2u beg) =

} if 3 2 roll begin /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "C Map operators". 1 get % code maps { PDFDEBUG { dup == } if dup length 1 sub 0 exch 5 exch { % e [] i 2 copy get % e [] i (prefix) string2number % e [] i prefix 2 index 2 index 1 add get % e [] i prefix (key_size,?is_ran ge,value_type,value_size) dup 0 get 8 mul % e [] i prefix (key_size,?is_ran ge,value_type,value_size) key_size*8 3 2 roll exch bitshift exch % e [] i prefix<<key_size*8 (key_ size,?is_range,value_type,value_size) dup 0 get exch 3 get % e [] i offset key_size value_si ze 4 index 4 index 2 add get % e [] i offset key_size value_si ze (keys) 5 index 5 index 3 add get % e [] i offset key_size value_si ze (keys) (values) PDFDEBUG { ( offset=) print 4 index =string cvs print ( key_size=) print 3 index =string cvs print ( value_size=) print 2 index = ( keys=) print 1 index == ( values=) print dup == } if 1 index length 0 eq { % A single pair. exch pop exch pop exch pop exch % e [] i (values) offset 4 index null ne { 4 index length 1 index gt { 4 index exch get } if } if % e [] i (values) cid|name exch PDFDEBUG { ( defined single: ) print 1 index =string cvs print ( ) print dup == } if false copy&def % e [] i pop % e [] } { % A range. % e [] i offset key_size value_si ze (keys) (values) dup length string copy % protect the original string from modifications below. 0 4 index 2 mul 3 index length 1 sub { % e [] i offset key_size value_si ze (keys) (values) j 2 index 1 index 6 index getinterval string2number % e [] i offset key_size value_si ze (keys) (values) j keyL PDFDEBUG { ( keyL=) print dup =string cvs print } if 3 index 2 index 7 index add 7 index getinterval string2number % e [] i offset key_size value_si

ze (keys) (values) j keyL keyH PDFDEBUG { ( keyH=) print dup = } if 3 2 roll 6 index idiv 5 index mul % e [] i offset key_size value_si ze (keys) (values) keyL keyH J 3 index exch 6 index getinterval % e [] i offset key_size value_si ze (keys) (values) keyL keyH (valueL) 3 1 roll 1 exch { % e [] i offset key_size value_si ze (keys) (values) (value) k 9 index null ne { 9 index exch get % e [] i offset key_size value_si ze (keys) (values) (value) name } if % e [] i offset key_size value_si ze (keys) (values) (value) cid|name 1 index % e [] i offset key_size value_si ze (keys) (values) (value) cid|name (value) PDFDEBUG { ( defined from range: ) print 1 index =string cvs print ( ) print dup == } if true copy&def % e [] i offset key_size value_si ze (keys) (values) (value) % Assuming the lowest byte of 'value' changes, others don't. dup dup length 1 sub % e [] i offset key_size value_si ze (keys) (values) (value) (value) l 2 copy get % e [] i offset key_size value_si ze (keys) (values) (value) (value) l v % Modulo 256 increment prevents a rangecheck error when the result i s stored in a string. % The adjustment can happen only at the end of the loop where the st ring is discarded. Bug 688535. 1 add 255 and put % e [] i offset key_size value_si ze (keys) (values) (value') } for % e [] i offset key_size value_si ze (keys) (values) (value) } for pop pop pop pop pop pop pop % e [] } ifelse } for pop % e } forall end pop % PDFDEBUG { (.convert_ToUnicode-into-g2u end) = } if } bind def /.processToUnicode % <font-resource> <font-dict> <encoding|null> .processToUni code { % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to % generate a ToUnicode CMaps. So don't bother with other devices. currentdevice .devicename /pdfwrite eq { PDFDEBUG { (.processToUnicode beg) = } if 2 index /ToUnicode knownoget { dup type /dicttype eq { dup /File known not } { //true } ifelse {

% We undefine wrong /Length and define /File in stream dictionaries. % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect. ( **** Warning: Ignoring bad ToUnicode CMap.\n) pdfformaterror pop } { /PDFScanRules .getuserparam dup //null eq { pop //PDFScanRules_null } { 1 dict dup /PDFScanRules 4 -1 roll put } ifelse //PDFScanRules_true setuserparams PDFfile fileposition 3 -1 roll //false resolvestream //ToUnicodeCMapReader begin % Following Acrobat we ignore everything outside % begincodespacerange .. endcmap. dup 0 (begincodespacerange) /SubFileDecode filter flushfile /CIDInit /ProcSet findresource begin 12 dict begin /CMapType 2 def mark exch % emulate 'begincodespacerange' 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn endcmap userdict /.lastToUnicode currentdict put end end end PDFfile exch setfileposition setuserparams 1 index /FontInfo .knownget not { currentglobal 2 index dup gcheck setglobal /FontInfo 5 dict dup 5 1 roll .forceput setglobal } if dup /GlyphNames2Unicode .knownget not { true % No existing G2U, make one } { dup wcheck { false % Existing, writeable G2U, don't mak e new one } { pop true % Existing read only G2U, make new o ne } ifelse } ifelse { currentglobal exch dup gcheck setglobal dup /GlyphNames2Unicode 100 dict dup 4 1 roll 3 2 roll setglobal } if % font-res font-info g2u exch pop exch % font-res ull userdict /.lastToUnicode get % font-res ull CMap .convert_ToUnicode-into-g2u % font-res //null % font-res } ifelse .forceput font-dict encoding|null font-dict g2u encoding|n font-dict g2u Encoding|n font-dict font-dict null

} if PDFDEBUG { (.processToUnicode end) = } if } if pop pop pop } bind def % ---------------- Descriptors ---------------- % % Partial descriptors for the 14 built-in fonts. Note that % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor % object has undergone a subtle change in its meaning which has serious % consequences for searching with Acrobat: % In PDF 1.1, the flag meant: Font has StandardEncoding % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet /standardfontdescriptors mark /Courier mark /Flags 16#23 .dicttomark /Courier-Oblique 1 index /Courier-Bold 1 index /Courier-BoldOblique 1 index /Helvetica mark /Flags 16#20 .dicttomark /Helvetica-Oblique 1 index /Helvetica-Bold 1 index /Helvetica-BoldOblique 1 index /Times-Roman mark /Flags 16#22 .dicttomark /Times-Bold 1 index /Times-Italic mark /Flags 16#62 .dicttomark /Times-BoldItalic 1 index /Symbol mark /Flags 16#4 .dicttomark /ZapfDingbats 1 index .dicttomark readonly def % ---------------- Utilities ---------------- % /.pdforigfontcache_g 20 dict def currentglobal false setglobal systemdict /.pdforigfontcache_l 20 dict .forceput setglobal % Find an original font, using cache to prevent adjustfont to accumulate changes . /pdffindcachedfont { % <font_name> pdffindcachedfont <font> dup //.pdforigfontcache_g exch .knownget { exch pop } { dup .pdforigfontcache_l exch .knownget { exch pop } { dup findfont dup dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse % Stack : font_name font font cache 4 2 roll .growput } ifelse } ifelse } bind def % Add original font to cache to prevent adjustfont to accumulate changes. /pdfaddcachedfont { % <font_name> pdfaddcachedfont <font>

dup findfont dup dup gcheck { //.pdforigfontcache_g 4 2 roll put } bind def

% } % %

name font font {.pdforigfontcache_l} ifelse font d name font font

/.remove_font_name_prefix { % <name> .remove_font_name_prefix <name> dup .namestring (+) search { true exch { dup 65 lt exch 90 gt or { pop false exit } if } forall { pop exch pop cvn } { pop pop } ifelse } { pop } ifelse } bind def % Find a font (except for embedded ones), and adjust its encoding if necessary. /.pdfdfndict mark /defaultfontname /Helvetica .dicttomark readonly def /pdffindfont { % <font-resource> <fontname> pdffindfont <font> % If the font isn't available, synthesize one based on % its descriptor. dup /Font resourcestatus { pop pop pdffindcachedfont } { 1 index /FontDescriptor knownoget { % Stack: font-res fontname fontdesc dup /Flags oget dup 16#40 and -6 bitshift % 1, oblique/italic 1 index 16#40000 and -17 bitshift add % 2, bold exch 16#2 and 2 bitshift add % 8, serif % We should look at the fixed flag, too. % Stack: font-res fontname fontdesc properties % Even though /FontName is a required key in FontDescriptor dict % (As of the PDF 1.4 Reference Manual), In the case of missing % /FontName key, we substitue /BaseFont for the value of /FontNa me. % Yet another case of broken PDF's that Adobe Reader accepts. 1 index dup /FontName known { /FontName oget dup type /nametype ne { ( **** /FontName attribute in FontDescriptor is not a name.\n) pdfformaterror cvn } if } { ( **** FontDescriptor missing required /FontName key. BaseFont name us ed.\n) pdfformaterror pop 2 index % grab the BaseFont from the stack. } ifelse .remove_font_name_prefix

exch % Analyzes font name and extract "Bold" and "Narrow" properties % which are not described by the FontDescriptor Flags. 0 2 index .fontnameproperties 6 and or % Rebind the default font name to Helvetica so that % fonts with no properties are handled correctly. //.pdfdfndict begin .substitutefontname end % Stack: font-res fontname fontdesc substname|null Fontmap 1 index known not { % No available good substitution, use the standard one. pop 1 index .substitutefont } if dup 3 index ne QUIET not and { (Substituting font ) print dup =only ( for ) print 2 index =only (.) = flush } if pdffindcachedfont % Stack: font-res fontname fontdesc font % If this is a small-caps font, replace the CharString % entries for a..z. exch /Flags oget 16#20000 and 0 ne { true .copyfontdict dup /CharStrings 2 copy get dup length dict .copydict % stack: font-res fontname font font /CharStrings CharStringsdict 5 index /FirstChar get 97 .max 6 index /LastChar get 122 .min 1 exch { % Stack: font-res fontname font' font' /CharStrings charstrings code % Note that this only remaps a-z, not accented characters. 6 index /Widths oget 1 index 8 index /FirstChar get sub oget 1 string dup 0 5 -1 roll put % Stack: font-res font' font' /CharStrings charstrings code % width (x) 2 index exch dup cvn exch dup 0 2 copy get 32 sub put 4 -1 roll { % Stack: operand (X) width 0 setcharwidth exch pop currentfont /FontMatrix get matrix invertmatrix concat 0.7 dup scale 0 0 moveto show } /exec cvx 4 packedarray cvx put } for put } if dup /FontName get 2 index ne { true .copyfontdict 2 copy exch /FontName exch put } if exch pop .completefont } { % No descriptor available, use the default algorithm. pdffindcachedfont } ifelse } ifelse exch pop } bdef % ---------------- Type 1 fonts ---------------- % /buildType1 % <Type1-font-resource> buildType1 <font> { dup /BaseFont get pdffindfont } bdef

% Read an embedded Type 1 font. /readfontfilter { % <proc> readfontfilter <filter> 0 () /SubFileDecode filter } bdef % Adobe Acrobat doesn't skip space characters after eexec /eexec_pdf_param_dict mark .eexec_param_dict {} forall /keep_spaces true .dicttomark readonly def % When Type 1 font reading procedure is executing, a copy of this dictionary is current. % We have to do something special about embedded fonts that execute definefont % more than once -- that is the function of topFontDict. % The whole type1 stream can be executed directly. There's no need to process % Length1, 2, 3 keys. /readtype1dict 10 dict dup begin /definefont { exch pop /topFontDict where { { /FontType % in PLRM order /FontMatrix /FontName /FontInfo /WMode /Encoding /FontBBox /UniqueID /XUID /PaintType /StrokeWidth /Metrics /Metrics2 /CDevProc /CharStrings /Private /WeightVector } { 2 copy .knownget { % Stack: font topFontDict /key val 3 index 3 1 roll put dup /MisplacedKey 0 put } { pop } ifelse } forall /MisplacedKey known { ( **** Warning: Type 1 font defines some of the keys in the external s cope.\n) pdfformaterror } if } if dup /UniqueID .knownget { dup dup 0 lt exch 16#ffffff gt or { ( **** Warning: Ignoring invalid /UniqueID = ) exch =string cvs

concatstrings (\n) concatstrings pdfformaterror dup /UniqueID undef } { pop } ifelse } if .completefont } bdef /undef_proc_warning { /Repaired true store % flag that we have warnings UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put } bdef /missing-type1-procs 6 dict begin /-| { string currentfile exch readstring pop /-| executeonly bdef /RD { string currentfile exch readstring pop /RD executeonly bdef /|- { noaccess def /|- //undef_proc_warning exec /ND { noaccess def /ND //undef_proc_warning exec /| { noaccess put /| //undef_proc_warning exec /NP { noaccess put /NP //undef_proc_warning exec currentdict end readonly def //undef_proc_warning exec } //undef_proc_warning exec } } } } } executeonly executeonly executeonly executeonly bdef bdef bdef bdef

/eexec { % Assume the font dictionary is directly below the file on the stack count 0 gt { /topFontDict 2 index cvlit store } if //eexec_pdf_param_dict /eexecDecode filter //missing-type1-procs begin /userdict .systemvar begin //systemdict begin readtype1dictcopy begin cvx stopped { currentdict end //missing-type1-procs eq { exit } if } loop { stop } if } bdef /readonly-op-dict << /stringtype 0 /arraytype 0 /packedarraytype 0 /dicttype 0 >> readonly def /readonly { % bug 689617 dup type //readonly-op-dict exch known { readonly } { ( **** Warning: Type 1 font applies operator readonly to a wrong type.\n) pdfformaterror } ifelse } .bind def /prev_get /get load def /get { dup /FontName eq { % No warning, probably FontName is defined elsewhere; see definefont above .

.knownget not { /Missing } if } { dup /UniqueID eq { % We don't want fonts to check /UniqueID and do 'restore'. pop pop 16#FEDCBA98 % Arbitrary and invalid value } { prev_get } ifelse } ifelse } bdef /prev_begin /begin load def /begin { dup //systemdict eq { pop 0 dict } if prev_begin } bdef { /undef_proc_warning /missing-type1-procs /readonly-op-dict } { currentdict exch undef } forall end readonly def currentdict /eexec_pdf_param_dict .undef /readtype1 { % <font-resource> <stream-dict> readtype1 <font> 1 index exch % res res stream PDFfile fileposition 3 1 roll % res pos res stream dup /PFB known exch % res pos res pfb? stream true resolvestream % res pos res pfb? file exch { //false /PFBDecode filter } if % Some buggy embedded fonts leave extra junk on the stack, % so we have to make a closure that records the stack depth % in a fail-safe way. This code also removes the mark when % the implied cleartomark is not executed, i.e. Length3 == 0. % Also restore dictstack depth. % //systemdict begin //readtype1dict dup length 3 add dict copy begin 1 index /BaseFont oget /savedFontName exch def /topFontDict null def /readtype1dictcopy currentdict def { cvx exec } aload pop count 2 sub 3 packedarray cvx exec % clean up the dictstack { currentdict /topFontDict known not { end } { exit } ifelse } loop count exch sub { pop } repeat PDFfile 3 -1 roll setfileposition pop pop currentdict end end /topFontDict get } bdef % ---------------- Type 3 fonts ---------------- % /buildType3 { % <Type3-font-resource> buildType3 <font> 8 dict begin /FontType 3 def % If the font does not contain a Resources entry, then we use % the resources from our current context. Page 391 of the PDF

% 1.6 spec says that the Resources dict is optional and if not % present then we should use the Resources for the page. % However we have a test file (687989) which uses a Type3 font % inside a form XObject and the desired Resources are in the % XObject dict and not in the Page dict. So we are going to % the parent object to find resources instead of only going to % the page dict when a font does not specify its required % resources. /Resources 1 index /Resources knownoget { oforce } { LocalResources } ifelse def /FontBBox 1 index /FontBBox get cvx def /FontMatrix 1 index /FontMatrix oget def /CharProcs 1 index /CharProcs oget def 1 index /Widths knownoget { /Widths exch def /FirstChar 1 index /FirstChar oget def /LastChar 1 index /LastChar oget def } if /FontName 1 index /Name knownoget not { /PDFType3Untitled } if def /Encoding .notdefEncoding 2 index getencoding def % We have to define BuildChar rather than BuildGlyph: % there is no PDF equivalent of glyphshow, and we need % the character code to access the Widths. /BuildChar { % Stack: font charcode 1 index begin 3 dict begin /Font 3 -1 roll def /CharCode 1 index def Encoding exch get CharProcs exch knownoget { { //false resolvestream % Stack: filepos stream % Don't let setgcolor set the color inside the BuildGlyph % procedure, because this causes an /undefined error. q //null /FillColor gput //null /StrokeColor gput Font /Resources get exch pdfopdict .pdfruncontext Q } PDFfile fileposition 2 .execn % Keep pdfcount valid. PDFfile exch setfileposition } { % PDF Type 3 fonts don't use .notdef % d1 implementation adjusts the width as needed 0 0 0 0 0 0 pdfopdict /d1 get exec } ifelse end end } bdef dup currentdict Encoding .processToUnicode currentdict end .completefont exch pop } bdef /.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'> % Enforce the metrics, in glyph space, to the values found in the PDF Font obj ect % - force wy == 0 (assumed, and not stored in the PDF font) % Even though PDF1.3-1.7 specifications state that this must be 0, % Distiller sometimes creates Type3 fonts with non-zero wy. We set % it to 0 since this is apparently what Acrobat Reader 4 and 5 do. % PDF1.2 does not mention this restriction, it only says % "see setcharwidth/ setcachedevice in the PostScript Reference".

% - get wx from the Widths array (do nothing if not present) pop 0 /Widths where { begin CharCode FirstChar ge CharCode LastChar le and { exch pop Widths CharCode FirstChar sub get exch } if end } if } bdef % ---------------- TrueType fonts ---------------- % /TTfonts mark /Arial /Helvetica /Arial,Italic /Helvetica-Oblique /Arial,Bold /Helvetica-Bold /Arial,BoldItalic /Helvetica-BoldOblique /CourierNew /Courier /CourierNew,Bold /Courier-Bold /TimesNewRoman /Times-Roman /TimesNewRoman,Italic /Times-Italic /TimesNewRoman,Bold /Times-Bold /TimesNewRoman,BoldItalic /Times-BoldItalic .dicttomark readonly def /buildTrueType { % <TrueType-font-resource> buildTrueType <font> dup /BaseFont oget dup /Font resourcestatus dup { exch pop exch pop } if not TTfonts 2 index known and { dup TTfonts exch get QUIET not { (Substituting font ) print dup =only ( for ) print 1 index =only (.) = flush } if exch 3 1 roll pdffindfont true .copyfontdict 2 copy exch /FontName exch put exch pop .completefont } { pdffindfont } ifelse } bdef % Read an embedded TrueType font. /readtruetype { % <font-resource> <stream-dict> readtruetype <font> 1 index exch PDFfile fileposition 3 1 roll true resolvestream readfontfilter % Stack: filepos fontres stream 1 index /Subtype get /CIDFontType2 eq { 1 index /BaseFont get % Use the BaseFont name for the font. Otherwise we /PDFCIDFontName exch def % would use the name table, or a manuf actured name. .loadttcidfont % Stack: filepos fontres cidfont currentdict /PDFCIDFontName undef % Remove the name to avoid interferenc e. } { % filepos fontres stream

1 index /FontDescriptor oget % filepos fontres /Flags get 4 and 0 ne % filepos fontres dup { //null } { StandardEncoding } ifelse 3 index /Encoding known { 3 index getencoding } if % filepos fontres ncoding dup 4 index exch % filepos fontres ncoding fontres Encoding /prebuilt_encoding exch put % filepos fontres ncoding .loadpdfttfont } ifelse exch pop PDFfile 3 -1 roll setfileposition % Ignore both the Encoding and the Widths. exch pop } bdef % ---------------- Type 0 fonts ---------------- % % Predefine the known CMaps, but only create them on demand. /knownCMaps mark /Identity-H { /Identity-H 0 makeIdentityCMap } /Identity-V { /Identity-V 1 makeIdentityCMap } .dicttomark def

stream fd stream is_symbolic

stream is_symbolic E stream is_symbolic E stream is_symbolic E

/makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap .currentglobal true .setglobal 3 1 roll /CIDInit /ProcSet findresource begin 12 dict begin begincmap /WMode exch def /CMapName exch def /CIDSystemInfo 3 dict dup begin /Registry (Adobe) def /Ordering (Identity) def /Supplement 0 def end def %/CMapName (see above) /CMapVersion 1 def /CMapType 1 def %WMode (see above) % The PDF documentation says that these CMaps map CIDs % "1 to 65,536". This is a misprint for 0 to 65,535. 1 begincodespacerange % <0001> <00ff> <0100> <ffff> <0000> <ffff> endcodespacerange 1 begincidrange % <0001> <00ff> 1 <0100> <ffff> 256 <0000> <ffff> 0 endcidrange endcmap CMapName currentdict /CMap defineresource knownCMaps CMapName 2 index put end % CMap end % CIDInit ProcSet exch .setglobal } bdef

/buildType0 { % <Type0-font-resource> buildType0 <font> dup /BaseFont get % FontName 1 index /Encoding oget dup type /nametype eq { dup /CMap resourcestatus { pop pop /CMap findresource } { knownCMaps 1 index .knownget { exch pop exec } { /undefined signalerror } ifelse } ifelse } { PDFfile fileposition exch dup /CMapName get exch true resolvestream cvx exec /CMap findresource exch PDFfile exch setfileposition } ifelse % CMap [ 3 index /DescendantFonts oget { exec resourcefont } forall ] % subfonts .composefontdict % composefont must insert FontInfo dictionary - see gs_cmap. ps . % Stack: fontres name font 3 copy exch pop null .processToUnicode exch pop .completefont % Stack: fontres font 1 index /FontMatrix knownoget { dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall { 1 index exch makefont exch /FontName get exch exch pop .completefont } { pop } ifelse } if exch pop } bdef % ---------------- CIDFontType0/2 fonts ---------------- % % % % % % % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2 arrays and using a (currently very inefficient) CDevProc. For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts". It notes default DW is 0, but Acrobat Reader uses 1000 as default. If DW is 0, currentpoint does not move by default in rendering text horizontally, the result is unreadable. You can check it by Acrobat.

/.pdfDefaultDW 1000 def /.pdfDefaultDW2 [ 880 -1000 ] def /addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict> dup length 5 add dict .copydict dup /FID undef dup /UniqueID undef dup /XUID undef % Insert the widths into the font. % Stack: pdfresource newfont 1 index /DW knownoget { 1 index /DW 3 -1 roll put } { dup /DW .pdfDefaultDW put

} ifelse 1 index /W knownoget { //false 1 index { xcheck or } forall { oforce_array } if dup 2 index /W 3 -1 roll put .pdfMakeInternalW 1 index /.internalW 3 -1 roll put } if 1 index /DW2 knownoget { 1 index /DW2 3 -1 roll put } { dup /DW2 .pdfDefaultDW2 put } ifelse 1 index /W2 knownoget { //false 1 index { xcheck or } forall { oforce_array } if dup 2 index /W2 3 -1 roll put .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put } if dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put exch pop } bdef /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_ array'> % convert /W or /W2 to internal expression % % mtx_array: original /W or /W2 array % item_size: number of metrics values per CID % % for detail of the metrics list format in PDF, % refer PDF Ref. p.317 "Glyph Metrics in CIDFonts". % % format of single entry in internal expression % % [ % [cid_begin cid_end] % value_is_varied (bool) % [ [values for cid_begin...] % [values for cid_begin + 1] % ... ] % ] % 7 dict begin /itemSize exch def /M exch def % original /W or /W2 /Msize M length def /Mi { M i get } def % W[i] /Mi1 { M i 1 add get } def % W[i + 1] /putMTXEntry << /arraytype { [

[Mi Mi Mi1 length itemSize idiv add 1 sub] true [ 0 itemSize Mi1 length 1 sub { [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ] } for ] ] /i i 2 add def } /integertype { [ [Mi Mi1] false [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]] ] /i i 2 add itemSize add def } >> def /i 0 def [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ] end } def /.pdfMakeInternalW { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def /.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def /.pdfGetMTXByCID { % <internalMTXArray> <cid> % .pdfGetMTXByCID % { <MTXEntry> true | false } % get values for given CID from internal format of /W or /W2 exch { { dup 0 get {} forall % Stack: <cid> <entry> <cid_0> <cid_1> 3 index lt { pop pop false exit } if 2 index exch sub dup 0 lt { pop pop false exit } if 1 index 1 get not { pop 0 } if exch 2 get exch get true exit } loop { exit } if } forall dup type /arraytype eq { exch pop true } { pop false } ifelse } def % Apply the [D]W[2] metrics to a character before displaying. /CIDWProc { % <w0x> <w0y> <llx> <lly> <urx> <ury> % <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc % <w0x'> ... <vy'> begin % push <font> to currentdict % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now 5 1 roll pop pop pop pop { currentdict /DW .knownget not { % no DW

.pdfDefaultDW exit } if

% replace <w0x> by defaultDW

currentdict /.internalW .knownget not { % no W exit % use already-stacked DW } if dup length 0 eq { pop exit } if % W is null array % discard unusable W % use already-stacked DW

% W is finite array, try to get W_cid 2 index .pdfGetMTXByCID { % got W, discard DW exch pop {} forall exit } if exit } loop FontType 11 eq { 1000 div } if 0 % <w0x'> (normalized W) % <w0y'>

% Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'> 9 -2 roll pop pop % discard <w0x> <w0y> 7 2 roll % put <w0x'> <w0y'> % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid> 0 % <w1x'> exch % put <w1x'> % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid> { currentdict /DW2 .knownget not { % no DW2, use defaultDW2 .pdfDefaultDW2 exit } if currentdict /.internalW2 .knownget not { % has DW2, no W2 exit % use already-stacked DW2 } if dup length 0 eq { pop exit } if 2 index .pdfGetMTXByCID { exch pop exit } if % could not get W2_cid exit } loop exch pop % discard <cid> % W2 is null array % discard unusable W2 % use already-stacked DW2 % got W2_cid, discard DW2

% Stack: <w0x'> <w0y'> <llx> <lly> 1y'> <vx'> <vy'>] } dup length 2 eq { FontType 11 eq {{1000 div}} {{}} 8 index 2 div exch }{ FontType 11 eq {{1000 div}} {{}} } ifelse end } def

<urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w % this is DW2 ifelse forall exch % <vx'> = <w0x'> / 2 % assume W2 ifelse forall % recover currentdict

% <string> <match> tailmatch ==> <pre> true % ==> <string> false /tailmatch { 2 copy length 1 index length .min dup 2 index length exch sub exch getinterval 1 index eq { length 1 index length exch sub 0 exch getinterval true } { pop false } ifelse } bind def /makeboldfont { 16 dict begin /strokewidth exch def /basecidfont exch def /FontMatrix [ 1 0 0 1 0 0 ] def /CIDFontName /.boldfont def /CIDFontType 1 def /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def /CIDSystemInfo dup basecidfont exch get def /FontBBox [ basecidfont /FontBBox get cvx exec 4 2 roll basecidfont /FontMatrix get transform 4 2 roll basecidfont /FontMatrix get transform ] def /tmpstr 2 string def /BuildGlyph { gsave exch begin dup 256 idiv tmpstr exch 0 exch put 256 mod tmpstr exch 1 exch put rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse { basefont-V } { basefont-H } ifelse setfont strokewidth setlinewidth 1 setlinejoin newpath 0 0 moveto tmpstr false charpath stroke 0 0 moveto tmpstr show currentpoint setcharwidth end

grestore } bind def currentdict end dup /CIDFontName get exch /CIDFont defineresource } bind def % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font> % CIDFont-resource is not modified. /findCIDFont { { dup /CIDFont resourcestatus { pop pop /CIDFont findresource exit } if .remove_font_name_prefix dup dup length string cvs (,Bold) tailmatch { exch pop cvn findCIDFont 0.03 makeboldfont exit } if (,Italic) tailmatch { exch pop cvn findCIDFont [ 1 0 0.3 1 0 0 ] makefont exit } if (,BoldItalic) tailmatch { exch pop cvn findCIDFont 0.03 makeboldfont [ 1 0 0.3 1 0 0 ] makefont exit } if QUIET not { (Can't find CID font ") print dup =string cvs print (".) = } if pop 1 index /CIDSystemInfo oget begin Registry (-) Ordering end concatstrings concatstrings cvn QUIET not { (Substituting CID font ) print dup ==only ( for ) print 1 index ==only (, see doc/Use.htm#CIDFontSubstitution.) = } if exch pop dup /CIDFont resourcestatus { pop pop /CIDFont findresource exit } if QUIET not { (The substitute CID font ") print dup =string cvs print (" is not provided either. Will exit with error.) = } if /findresource cvx /undefined signalerror } loop } bdef /buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font>

dup /BaseFont get findCIDFont exch pop } bdef /buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font> dup /BaseFont get findCIDFont exch pop } bdef /processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfon t> 1 index /CIDToGIDMap knownoget { PDFfile fileposition 4 1 roll dup /Identity eq { pop } { true resolvestream % Stack: filepos fontres font mapstream % Can't know the length of the decompressed stream, so allocate a big bu ffer... dup 65534 string readstring { % Length exceeded max string size, use an array of two strings 1 index 65534 string readstring pop % maybe a null string - not import ant. 2 array astore % Stack: filepos fontres font mapstream array dup 1 get length 65534 add } { dup length } ifelse 2 idiv % Stack: filepos fontres font mapstream array/string CIDCount 3 index exch /CIDCount exch put exch closefile exch dup /CIDMap 4 -1 roll put } ifelse 3 2 roll PDFfile exch setfileposition } if } bdef % Adjust a CIDFontType0 DW[2] in the font resource. /adjustCIDType0 { % <font-resource> <font> adjustfont <font'> addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource } bind def % Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource. /adjustCIDType2 { % <font-resource> <font> adjustfont <font'> addCIDmetrics dup /CIDFontType get 2 eq { % OpenType CFF font converts to CIDFontType 0 processCIDToGIDMap % that ignores CIDMap. } if dup /CIDFontName get exch /CIDFont defineresource } bind def % ---------------- Other embedded fonts ---------------- % /fontloadprocs mark /Type1C /readType1C cvx /CIDFontType0C /readCIDFontType0C cvx .dicttomark readonly def

% Read an embedded compressed font. /readType1C { % <font-resource> <stream-dict> readType1C <font> 1 index exch PDFfile fileposition 3 1 roll dup true resolvestream dup readfontfilter % Stack: pos resource streamdict stream filter 3 index /FontDescriptor oget /FontName oget 1 index /FontSetInit /ProcSet findresource begin //true //false ReadData { exch pop exit } forall 7 1 roll closefile closefile pop PDFfile 3 -1 roll setfileposition pop pop } bdef % Read an embedded CFF CIDFont. /readCIDFontType0C { % <font-resource> <stream-dict> readCIDFontType0C <font> PDFfile fileposition 3 1 roll dup true resolvestream dup readfontfilter % Stack: pos resource streamdict stream filter 3 index /FontDescriptor oget /FontName oget 1 index /FontSetInit /ProcSet findresource begin //true //false ReadData pop closefile closefile pop PDFfile 3 -1 roll setfileposition % Some broken Adobe software produces PDF files in which % the FontName of the CFF font and the FontName in the % FontDescriptor don't match the BaseFont in the font. % Use the FontName, rather than the BaseFont, here. dup /FontDescriptor oget /FontName oget /CIDFont findresource addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource } bdef % Read an embedded OpenType font. /readOTTOfont { % <font-resource> <stream-dict> readOTTOfont <font> 1 index exch % res res strdict PDFfile fileposition 3 1 roll % res pos res strdict dup //true resolvestream % res pos res strdict stream dup readfontfilter % res pos res strdict stream filter 3 index /FontDescriptor oget /FontName oget % res pos res strdict stream filter /name 1 index .init_otto_font_file % res pos res strdict stream filter /name filt er' //true 6 index /CIDSystemInfo known % res pos res strdict stream filter /name filt er' bool bool ReadData % res pos res strdict stream filter fontset { exch pop exit } forall % res pos res strdict stream filter font dup /FontType get 9 eq { % OpenType may contain simple CFF font, which is accesed as a CIDFont by PDF . % The font is converted to Type 9 CIDFont resource, which ignores CIDMap att ribute. % The following code just shuffles GlyphDirectory to the same effect. 4 index /CIDToGIDMap knownoget { dup type /dicttype eq { 1 index /GlyphDirectory get exch % res pos res strdict stream filt er font dir c2g //true resolvestream % res pos res strdict stream filt

er font dir c2g_file 256 dict begin 0 2 index 0 get def % copy .notdef 0 1 16#7fffffff { 1 index read not { pop exit } if % er font dir c2g_file cid hi 256 mul % er font dir c2g_file cid hi 2 index read not { pop pop exit } if % er font dir c2g_file cid hi lo add % er font dir c2g_file cid gid dup 0 ne { dup 4 index length lt { 3 index exch get % er font dir c2g_file cid charstr def % er font dir c2g_file } { pop pop } ifelse } { pop pop } ifelse } for closefile pop % er font dup length dict copy % er font' dup /GlyphDirectory currentdict put % er font' end dup /GlyphDirectory get 0 exch { pop .max } forall 1 index exch /CIDCount exch 1 add put } { pop } ifelse } if } if 7 1 roll % font res pos closefile closefile pop pop % font res pos PDFfile exch setfileposition % font res pop % font } bdef % ---------------- Font lookup ---------------- % % % % % % %

res pos res strdict stream filt res pos res strdict stream filt res pos res strdict stream filt res pos res strdict stream filt

res pos res strdict stream filt res pos res strdict stream filt

res pos res strdict stream filt res pos res strdict stream filt res pos res strdict stream filt

res strdict stream filter

Some PDF files mis-identify font type of the embedded font streams or include raw PFB font streams. Length1, Length2, Length3 may be wrong or missing. Adobe Acrobat corrects these errors transparently to the user. We ignore the font type keys and recognize the font type by the 1st 4 bytes of the font stream. The PFB stream is recognized by the 1st 2 bytes. % <font-resource> -proc- <font>

/fonttypeprocs mark /Type0 //buildType0 /Type1 //buildType1 /MMType1 //buildType1

/Type3 //buildType3 /TrueType //buildTrueType /CIDFontType0 //buildCIDType0 /CIDFontType2 //buildCIDType2 .dicttomark readonly def /adjustfonttypes mark /Type1 //adjustfont /MMType1 //adjustfont /TrueType //adjustfont /CIDFontType0 //adjustCIDType0 /CIDFontType2 //adjustCIDType2 .dicttomark readonly def % Bind a proc and define n names % /name ... /name {proc} n bndef /bndef { exch bind exch { dup 3 1 roll def } repeat pop } bdef % Prototype for all procedures: <res> <desc> <stream> foo <font> /font_tag_dict 13 dict begin % When the font stream is absent or cannot be read we load the font by the nam e. /no_stream { pop pop dup /Subtype get % res res /subtype dup / eq { ( **** Warning: Font missing required Subtype, /Type1 assumed.\n) pdfformaterror pop /Type1 } if //fonttypeprocs exch get exec } bdef /bad_stream { ( **** Warning: Error reading font stream, loading font by the name\n) pdfformaterror //no_stream exec } bdef <8001> % PFB { dup /PFB //true put exch pop readtype1 } bdef (%!PS) (%!Fo) % Type1 { exch pop readtype1 } 2 bndef <01000401> <01000402> <01000403> <01000404> % Type 1C <01000C02> <01000C03> { exch pop dup /Subtype get fontloadprocs exch get exec } 6 bndef

<00010000> (true) (typ1) (ttcf) % TrueType OpenType { exch pop readtruetype } 4 bndef (OTTO) { exch pop readOTTOfont } bdef currentdict end readonly def currentdict /bndef undef /resourcefont % <font-resource> resourcefont <font> { dup /PSFont .knownget dup { pop /FID knownoget dup { pop type /fonttype eq } if } if { /PSFont get } { dup dup /FontDescriptor knownoget { % font-res font-res font-desc % The same font descriptor can be reused in a CID and non-CID contexts. % Store CID and non-CID fonts under different keys. Bug 689301 1 index /Subtype knownoget dup { pop dup /CIDFontType0 eq exch /CIDFontType2 eq or } if { /CIDFontObject } { /FontObject } ifelse % font-res font-res font-desc /key 2 copy .knownget { 4 1 roll pop pop pop % font-res obj } { 4 1 roll % /key font-res font-res font-desc dup /FontFile knownoget not { dup /FontFile2 knownoget not { dup /FontFile3 knownoget not { //null } if } if } if % /key res res desc stream dup //null ne { PDFfile fileposition mark { 2 index //true resolvestream dup 4 string readstring pop exch closefile } stopped { cleartomark /bad_stream } { exch pop } ifelse PDFfile 3 -1 roll setfileposition dup length 4 lt { pop /bad_stream } if } { /no_stream } ifelse % /key res res desc stream tag //font_tag_dict 1 index known not {

dup 0 2 getinterval <8001> eq { 0 2 getinterval % /key res res desc stream pfb_tag } { (12345678>\n) dup /ASCIIHexEncode filter dup 4 -1 roll writestring c losefile ( trings pdfformaterror /no_stream } ifelse } if //font_tag_dict exch get exec 1 index /FontDescriptor oget % /key res font desc 4 -1 roll 2 index % res font desc /key font put % Save pointer to the font. } ifelse } { dup /Subtype get dup / eq { ( **** Warning: Font missing required Subtype, /Type1 assumed.\n) pdfformaterror pop /Type1 } if //fonttypeprocs exch get exec } ifelse % Stack: font-res font 1 index exch 1 index /Subtype get //adjustfonttypes exch .knownget { exec } { exch pop } ifelse dup 3 1 roll /PSFont exch put } ifelse dup checkGlyphNames2Unicode } bdef currentdict /font_tag_dict .undef currentdict /fonttypeprocs .undef currentdict /adjustfonttypes .undef drawopdict begin /d0 { .adjustcharwidth setcharwidth } bdef /d1 { 2 copy % ... llx lly urx ury | urx ury 0 ne exch 0 ne % ... llx lly urx ury | ury!=0 urx!=0 3 index 6 index eq and % ... llx lly urx ury | ury!=0 (urx!=0 && l lx==urx) exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx ) || (ury!=0 && lly==ury) % The bounding box is empty and likely incorrect. Don't cache. pop pop pop pop .adjustcharwidth setcharwidth } { 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice } ifelse } bdef /Tf { 1 index Page /Font rget { resourcefont exch Tf pop % /key res res desc stream unknown_tag **** Warning: unrecognized font file starts with <) exch concats

} { % Bug 689037 ( **** Warning: Tf refers to an unknown resource name: ) pdfformaterror 1 index .namestring pdfformaterror ( Assuming it's a font name.\n) pdfformaterror Tf } ifelse } bdef end end end .setglobal % pdfdict % GS_PDF_ProcSet