% Copyright (C) 1996, 2000 Aladdin Enterprises. All rights reserved.%% This file is part of Aladdin Ghostscript.%% Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author% or distributor accepts any responsibility for the consequences of using it,% or for whether it serves any particular purpose or works at all, unless he% or she says so in writing. Refer to the Aladdin Ghostscript Free Public% License (the "License") for full details.%% Every copy of Aladdin Ghostscript must include a copy of the License,% normally in a plain ASCII text file named PUBLIC. The License grants you% the right to copy, modify and redistribute Aladdin Ghostscript, but only% under certain conditions described in the License. Among other things, the% License requires that the copyright notice and this notice be preserved on% all copies. % $Id: gs_ttf.ps,v 1.3 2000/03/16 07:38:07 lpd Exp $% Support code for direct use of TrueType fonts.% (Not needed for Type 42 fonts.) % Note that if you want to use this file without including the ttfont.dev% option when you built Ghostscript, you will need to load the following% files before this one:% lib/gs_mgl_e.ps% lib/gs_mro_e.ps% lib/gs_wan_e.ps % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for% the glyf-splitting code. % ---------------- Font loading machinery ---------------- % % Augment the FONTPATH machinery so it recognizes TrueType fonts. /.scanfontheaders where { pop /.scanfontheaders [ .scanfontheaders aload pop (\000\001\000\000*) (true*) ] def} if % <file> <key> .findfontvalue <value> true% <file> <key> .findfontvalue false% Closes the file in either case./.findnonttfontvalue /.findfontvalue load def/.findfontvalue { 1 index read pop 2 index 1 index unread dup 0 eq exch (t) 0 get eq or { % If this is a font at all, it's a TrueType font. dup /FontType eq { pop closefile 42 true } { dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse } ifelse } { % Not a TrueType font. .findnonttfontvalue } ifelse} bind def % <file> .findttfontname <fname> true% <file> .findttfontname false% Closes the file in either case./.findttfontname { .loadttfonttables tabdict /name .knownget { dup 8 getu32 f exch setfileposition 12 getu32 string f exch readstring pop 6 findname } { false } ifelse f closefile end end} bind def % Load a font file that might be a TrueType font. % <file> .loadfontfile -/.loadnonttfontfile /.loadfontfile load def/.loadfontfile { dup read pop 2 copy unread 0 eq { % If this is a font at all, it's a TrueType font. .loadttfont pop } { % Not a TrueType font. .loadnonttfontfile } ifelse} bind def % ---------------- Automatic Type 42 generation ---------------- % % Load a TrueType font from a file as a Type 42 PostScript font.% The thing that makes this really messy is the handling of encodings.% There are 2 interacting tables that affect the encoding:% 'cmap' provides multiple maps from character codes to glyph indices% 'post' maps glyph indices to glyph names (if present)% What we need to get out of this is:% Encoding mapping character codes to glyph names% (the composition of cmap and post)% CharStrings mapping glyph names to glyph indices% (the inverse of post)% If the post table is missing, we have to take a guess based on the cmap% table. /.loadttfontdict 50 dict dup begin /orgXUID AladdinEnterprisesXUID def/maxstring 32000 def % half the maximum length of a PostScript string, % must be a multiple of 4 (for hmtx / loca / vmtx) % Define the Macintosh standard mapping from characters to glyph indices./MacRomanEncoding dup .findencoding def/MacGlyphEncoding dup .findencoding def % ---- Utilities ---- % % Define a serial number for creating unique XUIDs for TrueType fonts.% We used to use the checkSumAdjustment value from the font, but this is% not reliable, since some fonts don't set it correctly.% Note that we must do this in a string to make it immune to save/restore./xuidstring <80000000> def/curxuid { % - curxuid <int> 0 xuidstring { exch 8 bitshift exch add } forall} bind def/nextxuid { % - nextxuid - 3 -1 0 { xuidstring 1 index 2 copy get dup 255 ne { 1 add put pop exit } if pop 0 put pop } for} bind def % <string> <index> getu16 <integer>/getu16 { 2 copy get 8 bitshift 3 1 roll 1 add get add} bind def % <string> <index> gets16 <integer>/gets16 { getu16 16#8000 xor 16#8000 sub} bind def % <string> <index> getu32 <integer>/getu32 { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add} bind def % <string> <index> gets32 <integer>/gets32 { 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add} bind def % <string> <index> <integer> putu16 -/putu16 { 3 copy -8 bitshift put exch 1 add exch 16#ff and put} bind def % <string> <index> <integer> putu32 -/putu32 { 3 copy -16 bitshift putu16 exch 2 add exch 16#ffff and putu16} bind def % <nametable> <nameid> findname <string> true% <nametable> <nameid> findname false/findname { false 3 1 roll 0 1 3 index 2 getu16 1 sub { % Stack: false table id index 12 mul 6 add 2 index exch 12 getinterval dup 6 getu16 2 index eq { % We found the name we want. exch pop % Stack: false table record dup 10 getu16 2 index 4 getu16 add 1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch % Stack: false string record % Check for 8- vs. 16-bit characters. is2byte { string2to1 } if true null 4 -1 roll exit } if pop } for pop pop} bind def % <namerecord> is2byte <bool>/is2byte { dup 0 getu16 { { pop true } % Apple Unicode { pop false } % Macintosh Script manager { 1 getu16 1 eq } % ISO { 1 getu16 1 eq } % Microsoft } exch get exec} bind def % <string2> string2to1 <string>/string2to1 { dup length 2 idiv string dup 0 1 3 index length 1 sub { 3 index 1 index 2 mul 1 add get put dup } for pop exch pop} bind def % <array> <lt-proc> sort <array>/sort { 1 index length 1 sub -1 1 { 2 index exch 2 copy get 3 copy % arr proc arr i arr[i] arr i arr[i] 0 1 3 index 1 sub { 3 index 1 index get % arr proc arr i arr[i] arr imax amax j arr[j] 2 index 1 index 10 index exec { % ... amax < arr[j] 4 2 roll } if pop pop } for % arr proc arr i arr[i] arr imax amax 4 -1 roll exch 4 1 roll put put } for pop} def % Each procedure in this dictionary is called as follows:% <encodingtable> proc <glypharray>/cmapformats mark 0 { % Apple standard 1-to-1 mapping. 6 256 getinterval { } forall 256 packedarray } bind 4 { % Microsoft/Adobe segmented mapping. /etab exch def /nseg2 etab 6 getu16 def 14 /endc etab 2 index nseg2 getinterval def % The Apple TrueType documentation omits the 2-byte % 'reserved pad' that follows the endCount vector! 2 add nseg2 add /startc etab 2 index nseg2 getinterval def nseg2 add /iddelta etab 2 index nseg2 getinterval def nseg2 add /idroff etab 2 index nseg2 getinterval def % The following hack allows us to properly handle % idiosyncratic fonts that start at 0xf000: pop /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def /putglyph { glyphs code 3 -1 roll put /code code 1 add def } bind def % Do a first pass to compute the size of the glyphs array. /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub { % Stack: /glyphs numglyphs i2 /i2 exch def /scode startc i2 getu16 def /ecode endc i2 getu16 def numcodes scode firstcode sub % Hack for fonts that have only 0x0000 and 0xf000 ranges dup 16#e000 ge { 255 and } if exch sub 0 max ecode scode sub 1 add add exch 1 index add exch numcodes add /numcodes exch def } for array def % Now fill in the array. /numcodes 0 def /code 0 def 0 2 nseg2 3 sub { /i2 exch def /scode startc i2 getu16 def /ecode endc i2 getu16 def numcodes scode firstcode sub % Hack for fonts that have only 0x0000 and 0xf000 ranges dup 16#e000 ge { 255 and } if exch sub 0 max dup { 0 putglyph } repeat ecode scode sub 1 add add numcodes add /numcodes exch def /delta iddelta i2 gets16 def DEBUG { (scode=) print scode =only ( ecode=) print ecode =only ( delta=) print delta =only ( droff=) print idroff i2 getu16 = } if idroff i2 getu16 dup 0 eq { pop scode delta add 65535 and 1 ecode delta add 65535 and { putglyph } for } { % The +2 is for the 'reserved pad'. /gloff exch 14 nseg2 3 mul add 2 add i2 add add def 0 1 ecode scode sub { 2 mul gloff add etab exch getu16 dup 0 ne { delta add 65535 and } if putglyph } for } ifelse } for glyphs /glyphs null def % for GC } bind 6 { % Single interval lookup. dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def firstcode ng add array % Stack: tab array % Fill elements 0 .. firstcode-1 with 0 0 1 firstcode 1 sub { 2 copy 0 put pop } for dup firstcode ng getinterval % Stack: tab array subarray % Fill elements firstcode .. firstcode+nvalue-1 with glyph values 0 1 ng 1 sub { dup 2 mul 10 add 3 index exch getu16 3 copy put pop pop } for pop exch pop } bind.dicttomark readonly def % cmapformats % <cmaptab> cmaparray <glypharray>/cmaparray { dup 0 getu16 cmapformats exch .knownget { DEBUG { (cmap: format ) print 1 index 0 getu16 = flush } if exec } { (Can't handle format ) print 0 getu16 = flush 0 1 255 { } for 256 packedarray } ifelse DEBUG { (cmap: length=) print dup length = dup == } if} bind def % Each procedure in this dictionary is called as follows:% posttable <<proc>> glyphencoding/postformats mark 16#00010000 { % 258 standard Macintosh glyphs. pop MacGlyphEncoding } 16#00020000 { % Detailed map, required by Microsoft fonts. /postglyphs exch def postglyphs 32 getu16 /numglyphs exch def /glyphnames numglyphs 2 mul 34 add def [ 0 1 numglyphs 1 sub { 2 mul 34 add postglyphs exch getu16 dup 258 lt { MacGlyphEncoding exch get } { 258 sub glyphnames exch { postglyphs 1 index get 1 add add } repeat 1 add postglyphs exch 2 copy 1 sub get getinterval cvn } ifelse } for ] } bind 16#00030000 { % No map. pop [ ] } bind.dicttomark readonly def % postformats % Each procedure in this dictionary is called as follows:% <file> <length> -proc- <string|array_of_strings>% Note that each table must have an even length, because of a strange% Adobe requirement that each sfnts entry have even length./readtables mark % Ordinary tables (cmap) { .readtable } (head) 1 index (hhea) 1 index (maxp) 1 index (name) 1 index (OS/2) 1 index (post) 1 index (vhea) 1 index % Big tables (glyf) { .readbigtable } (loca) 1 index (hmtx) 1 index (vmtx) 1 index % Tables only needed for embedding in PDF files (cvt ) { .readtable } (fpgm) 1 index (prep) 1 index.dicttomark% Normally there would be a 'readonly' here, but the ttf2pf utility wants% to include the 'kern' table as well, so we leave the readtables dictionary% writable.def % readtables % Read a table as a single string.% <file> <length> .readtable <string>/.readtable { dup dup 1 and add string % Stack: f len str dup 0 4 -1 roll getinterval % Stack: f str str1 3 -1 roll exch readstring pop pop} bind def % Read a big table (one that may exceed 64K).% <file> <length> .readbigtable <string[s]>/.readbigtable { dup 65400 lt { .readtable } { currentuserparams /VMReclaim get -2 vmreclaim [ 4 2 roll { % Stack: mark ... f left dup maxstring le { exit } if 1 index maxstring string readstring pop 3 1 roll maxstring sub } loop .readtable ] exch vmreclaim } ifelse} bind def end readonly def % .loadttfontdict % <tab> .printtab -/.printtab { dup 0 4 getinterval print ( ) print dup 8 getu32 =only ( ) print 12 getu32 =} bind def % <file> .loadttfonttables -% Pushes .loadttfontdict & scratch dict on d-stack.% Defines f, offsets, tables, tabdict, tabs./.loadttfonttables { .loadttfontdict begin 40 dict begin /f exch def /offsets f 12 string readstring pop def /tables f offsets 4 getu16 16 mul string readstring pop def /tabdict tables length 16 idiv dict def % tabs = tables we want to keep, sorted by file position. /tabs [ 0 16 tables length 1 sub { tables exch 16 getinterval DEBUG { dup .printtab } if dup 0 4 getinterval readtables 1 index known { tabdict exch 2 index put } { pop pop } ifelse } for ] { exch 8 getu32 exch 8 getu32 lt } sort def % In certain malformed TrueType fonts, tables overlap. % Truncate tables if necessary. 0 1 tabs length 2 sub { dup tabs exch get exch 1 add tabs exch get 1 index 8 getu32 2 index 12 getu32 add 1 index 8 getu32 gt { (**** Warning: ) print 1 index 0 4 getinterval print ( overlaps ) print dup 0 4 getinterval print (, truncating.) = flush dup 8 getu32 2 index 8 getu32 sub 2 index 12 3 -1 roll putu32 } if pop pop } for} bind def % - .readttdata -% Read data. Updates offsets, tabs; stores data in tabdict./.readttdata { /fpos offsets length tables length add def /sfpos offsets length tabs length 16 mul add def offsets 4 tabs length putu16 tabs { dup 0 4 getinterval /tname exch def dup 8 getu32 /tpos exch def dup 12 getu32 /tlen exch def 8 sfpos putu32 % Skip data between the end of the previous table and % the beginning of this one, if any. tpos fpos gt { f tpos fpos sub () /SubFileDecode filter dup flushfile closefile /fpos tpos def } if f tlen readtables tname get exec tabdict tname 3 -1 roll put /fpos fpos tlen add def % Round up the table length to an even value. /sfpos sfpos tlen dup 1 and add add def } forall} bind def % Find the string in a list of strings that includes a given index.% <strings> <index> .findseg <string> <index'>/.findseg { exch { dup length 2 index gt { exch exit } if length sub } forall} bind def % - .makesfnts -% Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem/.makesfnts { .readttdata /head tabdict /head get def /locatable tabdict /loca get def /post tabdict /post .knownget not { null } if def /numloca locatable dup type /stringtype eq { length } { 0 exch { length add } forall } ifelse % no def yet locatable type /stringtype eq { /.indexloca {} def } { /.indexloca /.findseg load def } ifelse head 50 getu16 0 ne { /getloca { 2 bitshift locatable exch .indexloca getu32 } def 4 idiv 1 sub } { /getloca { dup add locatable exch .indexloca getu16 dup add } def 2 idiv 1 subLines 1–500 of 766. Load more
% Copyright (C) 1996, 2000 Aladdin Enterprises. All rights reserved. % % This file is part of Aladdin Ghostscript. % % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author % or distributor accepts any responsibility for the consequences of using it, % or for whether it serves any particular purpose or works at all, unless he % or she says so in writing. Refer to the Aladdin Ghostscript Free Public % License (the "License") for full details. % % Every copy of Aladdin Ghostscript must include a copy of the License, % normally in a plain ASCII text file named PUBLIC. The License grants you % the right to copy, modify and redistribute Aladdin Ghostscript, but only % under certain conditions described in the License. Among other things, the % License requires that the copyright notice and this notice be preserved on % all copies. % $Id: gs_ttf.ps,v 1.3 2000/03/16 07:38:07 lpd Exp $ % Support code for direct use of TrueType fonts. % (Not needed for Type 42 fonts.) % Note that if you want to use this file without including the ttfont.dev % option when you built Ghostscript, you will need to load the following % files before this one: % lib/gs_mgl_e.ps % lib/gs_mro_e.ps % lib/gs_wan_e.ps % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for % the glyf-splitting code. % ---------------- Font loading machinery ---------------- % % Augment the FONTPATH machinery so it recognizes TrueType fonts. /.scanfontheaders where { pop /.scanfontheaders [ .scanfontheaders aload pop (\000\001\000\000*) (true*) ] def } if % <file> <key> .findfontvalue <value> true % <file> <key> .findfontvalue false % Closes the file in either case. /.findnonttfontvalue /.findfontvalue load def /.findfontvalue { 1 index read pop 2 index 1 index unread dup 0 eq exch (t) 0 get eq or { % If this is a font at all, it's a TrueType font. dup /FontType eq { pop closefile 42 true } { dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse } ifelse } { % Not a TrueType font. .findnonttfontvalue } ifelse } bind def % <file> .findttfontname <fname> true % <file> .findttfontname false % Closes the file in either case. /.findttfontname { .loadttfonttables tabdict /name .knownget { dup 8 getu32 f exch setfileposition 12 getu32 string f exch readstring pop 6 findname } { false } ifelse f closefile end end } bind def % Load a font file that might be a TrueType font. % <file> .loadfontfile - /.loadnonttfontfile /.loadfontfile load def /.loadfontfile { dup read pop 2 copy unread 0 eq { % If this is a font at all, it's a TrueType font. .loadttfont pop } { % Not a TrueType font. .loadnonttfontfile } ifelse } bind def % ---------------- Automatic Type 42 generation ---------------- % % Load a TrueType font from a file as a Type 42 PostScript font. % The thing that makes this really messy is the handling of encodings. % There are 2 interacting tables that affect the encoding: % 'cmap' provides multiple maps from character codes to glyph indices % 'post' maps glyph indices to glyph names (if present) % What we need to get out of this is: % Encoding mapping character codes to glyph names % (the composition of cmap and post) % CharStrings mapping glyph names to glyph indices % (the inverse of post) % If the post table is missing, we have to take a guess based on the cmap % table. /.loadttfontdict 50 dict dup begin /orgXUID AladdinEnterprisesXUID def /maxstring 32000 def % half the maximum length of a PostScript string, % must be a multiple of 4 (for hmtx / loca / vmtx) % Define the Macintosh standard mapping from characters to glyph indices. /MacRomanEncoding dup .findencoding def /MacGlyphEncoding dup .findencoding def % ---- Utilities ---- % % Define a serial number for creating unique XUIDs for TrueType fonts. % We used to use the checkSumAdjustment value from the font, but this is % not reliable, since some fonts don't set it correctly. % Note that we must do this in a string to make it immune to save/restore. /xuidstring <80000000> def /curxuid { % - curxuid <int> 0 xuidstring { exch 8 bitshift exch add } forall } bind def /nextxuid { % - nextxuid - 3 -1 0 { xuidstring 1 index 2 copy get dup 255 ne { 1 add put pop exit } if pop 0 put pop } for } bind def % <string> <index> getu16 <integer> /getu16 { 2 copy get 8 bitshift 3 1 roll 1 add get add } bind def % <string> <index> gets16 <integer> /gets16 { getu16 16#8000 xor 16#8000 sub } bind def % <string> <index> getu32 <integer> /getu32 { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add } bind def % <string> <index> gets32 <integer> /gets32 { 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add } bind def % <string> <index> <integer> putu16 - /putu16 { 3 copy -8 bitshift put exch 1 add exch 16#ff and put } bind def % <string> <index> <integer> putu32 - /putu32 { 3 copy -16 bitshift putu16 exch 2 add exch 16#ffff and putu16 } bind def % <nametable> <nameid> findname <string> true % <nametable> <nameid> findname false /findname { false 3 1 roll 0 1 3 index 2 getu16 1 sub { % Stack: false table id index 12 mul 6 add 2 index exch 12 getinterval dup 6 getu16 2 index eq { % We found the name we want. exch pop % Stack: false table record dup 10 getu16 2 index 4 getu16 add 1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch % Stack: false string record % Check for 8- vs. 16-bit characters. is2byte { string2to1 } if true null 4 -1 roll exit } if pop } for pop pop } bind def % <namerecord> is2byte <bool> /is2byte { dup 0 getu16 { { pop true } % Apple Unicode { pop false } % Macintosh Script manager { 1 getu16 1 eq } % ISO { 1 getu16 1 eq } % Microsoft } exch get exec } bind def % <string2> string2to1 <string> /string2to1 { dup length 2 idiv string dup 0 1 3 index length 1 sub { 3 index 1 index 2 mul 1 add get put dup } for pop exch pop } bind def % <array> <lt-proc> sort <array> /sort { 1 index length 1 sub -1 1 { 2 index exch 2 copy get 3 copy % arr proc arr i arr[i] arr i arr[i] 0 1 3 index 1 sub { 3 index 1 index get % arr proc arr i arr[i] arr imax amax j arr[j] 2 index 1 index 10 index exec { % ... amax < arr[j] 4 2 roll } if pop pop } for % arr proc arr i arr[i] arr imax amax 4 -1 roll exch 4 1 roll put put } for pop } def % Each procedure in this dictionary is called as follows: % <encodingtable> proc <glypharray> /cmapformats mark 0 { % Apple standard 1-to-1 mapping. 6 256 getinterval { } forall 256 packedarray } bind 4 { % Microsoft/Adobe segmented mapping. /etab exch def /nseg2 etab 6 getu16 def 14 /endc etab 2 index nseg2 getinterval def % The Apple TrueType documentation omits the 2-byte % 'reserved pad' that follows the endCount vector! 2 add nseg2 add /startc etab 2 index nseg2 getinterval def nseg2 add /iddelta etab 2 index nseg2 getinterval def nseg2 add /idroff etab 2 index nseg2 getinterval def % The following hack allows us to properly handle % idiosyncratic fonts that start at 0xf000: pop /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def /putglyph { glyphs code 3 -1 roll put /code code 1 add def } bind def % Do a first pass to compute the size of the glyphs array. /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub { % Stack: /glyphs numglyphs i2 /i2 exch def /scode startc i2 getu16 def /ecode endc i2 getu16 def numcodes scode firstcode sub % Hack for fonts that have only 0x0000 and 0xf000 ranges dup 16#e000 ge { 255 and } if exch sub 0 max ecode scode sub 1 add add exch 1 index add exch numcodes add /numcodes exch def } for array def % Now fill in the array. /numcodes 0 def /code 0 def 0 2 nseg2 3 sub { /i2 exch def /scode startc i2 getu16 def /ecode endc i2 getu16 def numcodes scode firstcode sub % Hack for fonts that have only 0x0000 and 0xf000 ranges dup 16#e000 ge { 255 and } if exch sub 0 max dup { 0 putglyph } repeat ecode scode sub 1 add add numcodes add /numcodes exch def /delta iddelta i2 gets16 def DEBUG { (scode=) print scode =only ( ecode=) print ecode =only ( delta=) print delta =only ( droff=) print idroff i2 getu16 = } if idroff i2 getu16 dup 0 eq { pop scode delta add 65535 and 1 ecode delta add 65535 and { putglyph } for } { % The +2 is for the 'reserved pad'. /gloff exch 14 nseg2 3 mul add 2 add i2 add add def 0 1 ecode scode sub { 2 mul gloff add etab exch getu16 dup 0 ne { delta add 65535 and } if putglyph } for } ifelse } for glyphs /glyphs null def % for GC } bind 6 { % Single interval lookup. dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def firstcode ng add array % Stack: tab array % Fill elements 0 .. firstcode-1 with 0 0 1 firstcode 1 sub { 2 copy 0 put pop } for dup firstcode ng getinterval % Stack: tab array subarray % Fill elements firstcode .. firstcode+nvalue-1 with glyph values 0 1 ng 1 sub { dup 2 mul 10 add 3 index exch getu16 3 copy put pop pop } for pop exch pop } bind .dicttomark readonly def % cmapformats % <cmaptab> cmaparray <glypharray> /cmaparray { dup 0 getu16 cmapformats exch .knownget { DEBUG { (cmap: format ) print 1 index 0 getu16 = flush } if exec } { (Can't handle format ) print 0 getu16 = flush 0 1 255 { } for 256 packedarray } ifelse DEBUG { (cmap: length=) print dup length = dup == } if } bind def % Each procedure in this dictionary is called as follows: % posttable <<proc>> glyphencoding /postformats mark 16#00010000 { % 258 standard Macintosh glyphs. pop MacGlyphEncoding } 16#00020000 { % Detailed map, required by Microsoft fonts. /postglyphs exch def postglyphs 32 getu16 /numglyphs exch def /glyphnames numglyphs 2 mul 34 add def [ 0 1 numglyphs 1 sub { 2 mul 34 add postglyphs exch getu16 dup 258 lt { MacGlyphEncoding exch get } { 258 sub glyphnames exch { postglyphs 1 index get 1 add add } repeat 1 add postglyphs exch 2 copy 1 sub get getinterval cvn } ifelse } for ] } bind 16#00030000 { % No map. pop [ ] } bind .dicttomark readonly def % postformats % Each procedure in this dictionary is called as follows: % <file> <length> -proc- <string|array_of_strings> % Note that each table must have an even length, because of a strange % Adobe requirement that each sfnts entry have even length. /readtables mark % Ordinary tables (cmap) { .readtable } (head) 1 index (hhea) 1 index (maxp) 1 index (name) 1 index (OS/2) 1 index (post) 1 index (vhea) 1 index % Big tables (glyf) { .readbigtable } (loca) 1 index (hmtx) 1 index (vmtx) 1 index % Tables only needed for embedding in PDF files (cvt ) { .readtable } (fpgm) 1 index (prep) 1 index .dicttomark % Normally there would be a 'readonly' here, but the ttf2pf utility wants % to include the 'kern' table as well, so we leave the readtables dictionary % writable. def % readtables % Read a table as a single string. % <file> <length> .readtable <string> /.readtable { dup dup 1 and add string % Stack: f len str dup 0 4 -1 roll getinterval % Stack: f str str1 3 -1 roll exch readstring pop pop } bind def % Read a big table (one that may exceed 64K). % <file> <length> .readbigtable <string[s]> /.readbigtable { dup 65400 lt { .readtable } { currentuserparams /VMReclaim get -2 vmreclaim [ 4 2 roll { % Stack: mark ... f left dup maxstring le { exit } if 1 index maxstring string readstring pop 3 1 roll maxstring sub } loop .readtable ] exch vmreclaim } ifelse } bind def end readonly def % .loadttfontdict % <tab> .printtab - /.printtab { dup 0 4 getinterval print ( ) print dup 8 getu32 =only ( ) print 12 getu32 = } bind def % <file> .loadttfonttables - % Pushes .loadttfontdict & scratch dict on d-stack. % Defines f, offsets, tables, tabdict, tabs. /.loadttfonttables { .loadttfontdict begin 40 dict begin /f exch def /offsets f 12 string readstring pop def /tables f offsets 4 getu16 16 mul string readstring pop def /tabdict tables length 16 idiv dict def % tabs = tables we want to keep, sorted by file position. /tabs [ 0 16 tables length 1 sub { tables exch 16 getinterval DEBUG { dup .printtab } if dup 0 4 getinterval readtables 1 index known { tabdict exch 2 index put } { pop pop } ifelse } for ] { exch 8 getu32 exch 8 getu32 lt } sort def % In certain malformed TrueType fonts, tables overlap. % Truncate tables if necessary. 0 1 tabs length 2 sub { dup tabs exch get exch 1 add tabs exch get 1 index 8 getu32 2 index 12 getu32 add 1 index 8 getu32 gt { (**** Warning: ) print 1 index 0 4 getinterval print ( overlaps ) print dup 0 4 getinterval print (, truncating.) = flush dup 8 getu32 2 index 8 getu32 sub 2 index 12 3 -1 roll putu32 } if pop pop } for } bind def % - .readttdata - % Read data. Updates offsets, tabs; stores data in tabdict. /.readttdata { /fpos offsets length tables length add def /sfpos offsets length tabs length 16 mul add def offsets 4 tabs length putu16 tabs { dup 0 4 getinterval /tname exch def dup 8 getu32 /tpos exch def dup 12 getu32 /tlen exch def 8 sfpos putu32 % Skip data between the end of the previous table and % the beginning of this one, if any. tpos fpos gt { f tpos fpos sub () /SubFileDecode filter dup flushfile closefile /fpos tpos def } if f tlen readtables tname get exec tabdict tname 3 -1 roll put /fpos fpos tlen add def % Round up the table length to an even value. /sfpos sfpos tlen dup 1 and add add def } forall } bind def % Find the string in a list of strings that includes a given index. % <strings> <index> .findseg <string> <index'> /.findseg { exch { dup length 2 index gt { exch exit } if length sub } forall } bind def % - .makesfnts - % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem /.makesfnts { .readttdata /head tabdict /head get def /locatable tabdict /loca get def /post tabdict /post .knownget not { null } if def /numloca locatable dup type /stringtype eq { length } { 0 exch { length add } forall } ifelse % no def yet locatable type /stringtype eq { /.indexloca {} def } { /.indexloca /.findseg load def } ifelse head 50 getu16 0 ne { /getloca { 2 bitshift locatable exch .indexloca getu32 } def 4 idiv 1 sub } { /getloca { dup add locatable exch .indexloca getu16 dup add } def 2 idiv 1 sub