home *** CD-ROM | disk | FTP | other *** search
- % Copyright (C) 1996, 1997 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.
-
- % Support code for direct use of TrueType fonts.
- % (Not needed for Type 42 fonts.)
-
- % ---------------- Font loading machinery ---------------- %
-
- % Augment the FONTPATH machinery so it recognizes TrueType fonts.
-
- /.scanfontheaders where % only defined if DISKFONTS is recognized
- { pop
- /.scanfontheaders [ .scanfontheaders aload pop (\000\001\000\000*) ] def
- }
- if
- /.findnonttfontvalue /.findfontvalue load def
- /.findfontvalue % <file> <key> .findfontvalue <value> true
- % <file> <key> .findfontvalue false
- % Closes the file in either case.
- { 1 index read pop 2 index 1 index unread 0 eq
- { % 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
- /.findttfontname % <file> .findttfontname <fname> true
- % <file> .findttfontname false
- % Closes the file in either case.
- { .loadttfonttables
- (name) findtableentry
- { 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.
-
- /.loadnonttfontfile /.loadfontfile load def
- /.loadfontfile % <file> .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 3 interacting tables that affect the encoding:
- % 'cmap' provides multiple maps from character codes to glyph indices
- % 'glyf' maps glyph indices to outlines
- % '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 mark
- /orgXUID 107 def % Aladdin Enterprises organization XUID
- /maxstring 65500 def % maximum length of a PostScript string
-
- % Define the Macintosh standard mapping from characters to glyph indices.
- /MacRomanEncoding dup .findencoding def
- /MacGlyphEncoding mark
- /.notdef /.null /CR
- MacRomanEncoding 32 95 getinterval aload pop
- MacRomanEncoding 128 45 getinterval aload pop
- % 143
- /notequal /AE
- /Oslash /infinity /plusinus /lessequal /greaterequal
- /yen /mu1 /partialdiff /summation /product
- /pi /integral /ordfeminine /ordmasculine /Ohm
- /ae /oslash /questiondown /exclamdown /logicalnot
- /radical /florin /approxequal /increment /guillemotleft
- /guillemotright /ellipsis /nbspace
- MacRomanEncoding 203 12 getinterval aload pop
- /lozenge
- MacRomanEncoding 216 24 getinterval aload pop
- /applelogo
- MacRomanEncoding 241 7 getinterval aload pop
- /overscore
- MacRomanEncoding 249 7 getinterval aload pop
- % 226
- /Lslash /lslash /Scaron /scaron
- /Zcaron /zcaron /brokenbar /Eth /eth
- /Yacute /yacute /Thorn /thorn /minus
- /multiply /onesuperior /twosuperior /threesuperior /onehalf
- /onequarter /threequarters /franc /Gbreve /gbreve
- /Idot /Scedilla /scedilla /Cacute /cacute
- /Ccaron /ccaron /dmacron
- /packedarray where
- { pop counttomark packedarray exch pop }
- { ] readonly }
- ifelse def
-
- % Procedures
- /getu16 % <string> <index> getu16 <integer>
- { 2 copy get 8 bitshift 3 1 roll 1 add get add
- } bind def
- /gets16 % <string> <index> gets16 <integer>
- { getu16 16#8000 xor 16#8000 sub
- } bind def
- /getu32 % <string> <index> getu32 <integer>
- { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
- } bind def
- /gets32 % <string> <index> gets32 <integer>
- { getu32 dup 16#7fffffff gt { 4 { 16#40000000 sub } repeat } if
- } bind def
- /getrange % <offset> <length> getrange <string>
- % Free variables: sfnts
- { () sfnts
- { % Stack: offset length () sfnt
- dup length 4 index gt { exch pop exit } if
- 4 -1 roll exch length sub 3 1 roll
- }
- forall 3 1 roll getinterval
- } bind def
- /findtableentry % <name4> findtableentry <tableentry> true
- % <name4> findtableentry false
- % Free variables: tables
- { false 0 16 tables length 16 sub
- { % Stack: name4 false toffset
- tables 1 index 4 getinterval 3 index eq
- { tables exch 16 getinterval
- exch pop exch true exit
- }
- if pop
- }
- for exch pop
- } bind def
- /findtable % <name4> findtable <table> true
- % <name4> findtable false
- % Free variables: tables
- { findtableentry
- { dup 8 getu32 exch 12 getu32 getrange true }
- { false }
- ifelse
- } bind def
- /findname % <nametable> <nameid> findname <string> true
- % <nametable> <nameid> findname false
- { 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
- /is2byte % <namerecord> is2byte <bool>
- { 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
- /string2to1 % <string2> string2to1 <string>
- { 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
- /cmapformats mark
- % Each procedure in this dictionary is called as follows:
- % -mark- encodingtable <<proc>> -mark- glyphindices...
- 0 % Apple standard 1-to-1 mapping.
- { 6 256 getinterval { } forall
- } 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:
- /firstcode startc 0 getu16 16#ff00 and def
- pop 0 2 nseg2 3 sub
- { /i2 exch def
- /scode startc i2 getu16 def
- counttomark scode firstcode sub 256 min exch sub 0 max { 0 } repeat
- /ecode endc i2 getu16 def
- /delta iddelta i2 getu16 def
- idroff i2 getu16 dup 0 eq
- { pop scode 1 ecode { delta add 65535 and } 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
- }
- for
- }
- ifelse
- }
- for
- } bind
- 6 % Single interval lookup.
- { dup 6 getu16 { 0 exch } repeat
- dup 8 getu16 0 exch 1 exch 1 sub
- { 2 mul 10 add 2 copy getu16 exch pop exch }
- repeat pop
- } bind
- .dicttomark readonly def % cmapformats
- /cmaparray % <cmaptab> cmaparray -mark- <glyphs> ...
- { mark exch dup 0 getu16 cmapformats exch .knownget
- { exec }
- { (Can't handle format ) print 0 getu16 = flush
- 0 1 255 { } for
- }
- ifelse
- } bind def
- /postformats mark
- % Each procedure in this dictionary is called as follows:
- % posttable <<proc>> glyphencoding
- 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
- .dicttomark readonly def % postformats
- .dicttomark readonly def % .loadttfontdict
- /.loadttfonttables % <file> .loadttfonttables -
- % Pushes .loadttfontdict & scratch dict on d-stack,
- % defines f, offsets, tables
- { .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
- } bind def
- /.readsfnts0 { % <len0> .readsfnts0 <string>
- dup string
- dup 0 offsets putinterval
- dup offsets length tables putinterval
- dup offsets length tables length add
- % Stack: len0 str str off+tab
- 3 index 1 index sub getinterval
- f exch dup length 0 ne { readstring } if pop pop
- exch pop
- } bind def
- /.dividesfnts { % <length> .dividesfnts -
- (glyf) findtableentry pop
- dup 8 getu32 /len0 exch def
- 12 getu32 /len1 exch def
- len0 len1 add sub /len2 exch def
- /sfnts [
- len0 .readsfnts0
- len1 dup maxstring gt
- { % Bad news: we'll have to split the glyfs.
- % Right now we only provide for splitting into 2 parts,
- % but we could generalize this without too much trouble.
- f maxstring string readstring pop
- exch maxstring sub
- }
- if string f exch readstring pop
- len2 0 ne { f len2 string readstring pop } if
- ] def
- /head (head) findtable pop def
- len1 maxstring gt
- { % Determine where to split the glyfs by scanning loca.
- % The very last entry in loca may be bogus.
- % What a nuisance!
- (loca) findtable pop dup length
- head 50 getu16 0 ne
- { % 32-bit loca
- 8 sub -4 0
- { 1 index exch getu32 dup maxstring le { exch pop exit } if pop }
- }
- { % 16-bit loca
- 4 sub -2 0
- { 1 index exch getu16 1 bitshift dup maxstring le { exch pop exit } if pop }
- }
- ifelse for
- % Now the top element of the stack is the length of
- % the first glyf string.
- sfnts 1 get dup 0 3 index getinterval
- sfnts exch 1 exch put
- exch 1 index length 1 index sub getinterval
- sfnts 2 get concatstrings sfnts exch 2 exch put
- }
- if
- } bind def
- /.makesfnts % - .makesfnts -
- % Defines head, sfnts
- { % Find the end of the last table, and also the end of
- % the last table below the 64K mark.
- 0 8 16 tables length
- { % Stack: end toffset
- DEBUG
- { tables 1 index 8 sub 4 getinterval print ( ) print
- tables 1 index getu32 =only ( ) print
- tables 1 index 4 add getu32 =
- }
- if
- tables 1 index getu32 exch tables exch 4 add getu32 add max
- }
- for
- dup maxstring le {
- .readsfnts0
- % Pad to even length if necessary, per Adobe specification.
- dup length 2 mod 0 ne {
- <00> concatstrings
- } if
- 1 array astore /sfnts exch def
- /head (head) findtable pop def
- } {
- % If the total length exceeds maxstring, divide the data
- % into 2+n strings: before glyf, glyfs, after glyf
- .dividesfnts
- } ifelse
- } bind def
- /.loadttfont % <file> .loadttfont <type42font>
- { .loadttfonttables
- .makesfnts
- /upem head 18 getu16 def
- (cmap) findtable pop
- % The Apple cmap format is no help in determining the encoding.
- % Look for a Microsoft table. If we can't find one,
- % just use the first table, whatever it is.
- dup 4 8 getinterval exch % the default
- 0 1 2 index 2 getu16 1 sub
- { 8 mul 4 add 1 index exch 8 getinterval
- dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
- }
- for
- % Stack: subentry table
- /cmapsub 2 index def
- exch 4 getu32 1 index length 1 index sub getinterval
- /cmaptab exch def
- % See if we have PostScript glyph name information.
- /post (post) findtable not { null } if def
- /glyphencoding post null eq
- { MacGlyphEncoding }
- { postformats post 0 getu32 .knownget
- { post exch exec }
- { MacGlyphEncoding }
- ifelse
- }
- ifelse def
- /checksum head 8 getu32 def
- mark
- /FontType 42
- /FontMatrix matrix
- /PaintType 0
- /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
- (name) findtable
- { % Find the names from the 'name' table.
- /names exch def
- /FontName names 6 findname not { checksum 16 8 string cvrs } if
- /FontInfo mark
- names 0 findname { /Notice exch } if
- names 1 findname { /FamilyName exch } if
- names 4 findname { /FullName exch } if
- names 5 findname { /Version exch } if
- }
- { % No name table, fabricate a FontName.
- /FontName checksum 16 8 string cvrs
- /FontInfo mark
- }
- ifelse
- % Stack: /FontInfo mark key1 value1 ...
- post null ne
- { /ItalicAngle post 4 gets32 65536.0 div
- /isFixedPitch post 12 getu32 0 ne
- /UnderlinePosition post 8 gets16 upem div
- /UnderlineThickness post 10 gets16 upem div
- }
- if
- counttomark 0 ne
- { .dicttomark }
- { pop pop }
- ifelse
- /Encoding
- cmaptab cmaparray
- counttomark array astore { glyphencoding exch get } forall
- counttomark 256 sub dup 0 ge
- { { pop } repeat }
- { neg { /.notdef } repeat }
- ifelse ]
- % Until we can compute the MD5 fingerprint,
- % just use the precomputed checksum.
- /XUID [orgXUID 42 checksum]
- /CharStrings glyphencoding dup length dict
- 0 1 3 index length 1 sub
- { % Stack: glyphencoding dict index
- 2 index 1 index get 2 index 1 index known
- { pop pop }
- { 2 index exch 3 -1 roll put }
- ifelse
- }
- for exch pop readonly
- /sfnts sfnts
- .dicttomark
- end end dup /FontName get exch definefont
- } bind def
-