1456 lines · 45.3 KB · Text
RawDownload
%    Copyright (C) 1996-2003 artofcode LLC.  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: gs_ttf.ps,v 1.48 2005/09/22 16:11:37 ray 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 {    2 index 1 index unread    % beginning with binary 0 or 't' (TrueType), or 'O' (OpenType)    dup 0 eq 1 index (O) 0 get eq or 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  } { pop closefile false } ifelse} bind def % <file> .findttfontname <fname> true% <file> .findttfontname false% Closes the file in either case./.findttfontname {  //true 0 .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 32764 def    % half the maximum length of a PostScript string,			% must be a multiple of 4 (for hmtx / loca / vmtx) /.invert_encoding   % <array> invert_encoding <dict>{ dup 256 dict exch  0 exch 1 exch length 1 sub {     % [] <> i    dup 3 index exch get           % [] <> i v    dup /.notdef ne {      exch 2 index 2 index .knownget {        dup type /arraytype eq {  	[ exch aload pop counttomark 2 add -1 roll ]        } {  	exch 2 array astore        } ifelse      } if 2 index 3 1 roll put    } {      pop pop    } ifelse  } for  exch pop} bind def % Define the Macintosh standard mapping from characters to glyph indices./MacRomanEncoding dup .findencoding def/MacGlyphEncoding dup .findencoding def % Invert the MacRomanEncoding./.romanmacdict MacRomanEncoding .invert_encoding def % Define remapping for misnamed glyphs in TrueType 'post' tables.% There are probably a lot more than this!/postremap mark  /Cdot /Cdotaccent  /Edot /Edotaccent  /Eoverdot /Edotaccent  /Gdot /Gdotaccent  /Ldot /Ldotaccent  /Zdot /Zdotaccent  /cdot /cdotaccent   /edot /edotaccent   /eoverdot /edotaccent  /gdot /gdotaccent   /ldot /ldotaccent  /zdot /zdotaccent .dicttomark readonly def % Array used for fast pre-filling of cmap array/.array1024z [ 1024 { 0 } repeat ] 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 16#ffffffff 0 gt {  % 64-bit sign extension  { /curxuid /gets32 } {    mark 1 index load aload pop { 16#80000000 xor 16#80000000 sub } aload pop    .packtomark cvx def  } bind forall} if % <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 {  TTFDEBUG { (findname: ) print dup =only  } if  false 3 1 roll  1 index length 0 gt {	% check for zero length name table     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	    3 copy add 1 index length	    le {	      pop	      getinterval exch		  % Stack: false string record		  % Check for 8- vs. 16-bit characters.	  is2byte { string2to1 } if true null 4 -1 roll exit	    } {	      pop pop pop pop	      false		  exit	    } ifelse      } if pop    } for  } if  pop pop  TTFDEBUG {    dup { ( = ) print 1 index == } { ( not found) = } ifelse  } if} 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 % 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  2 {		% Apple 16bit CJK (ShiftJIS etc)     % /sHK_sz		subHeaderKey_size	% 1 * uint16    % /sH_sz		subHeader_size		% 4 * uint16    % /sH_len		subHeader_length    % /cmapf2_tblen	total table length    % /cmapf2_lang	language code (not used)    % /sHKs		subHeaderKeys     /sHK_sz 2 def    /sH_sz 8 def    dup 2 getu16 /cmapf2_tblen exch def     dup 4 getu16 /cmapf2_lang exch def     dup 6 256 sHK_sz mul getinterval /sHKs exch def     0		% initialization value for /sH_len    0 1 255 {       sHKs exch       2 mul getu16       1 index	% get current max       1 index	% get current subHeaderKey       lt {exch} if pop    } for    /sH_len exch def     dup 6 256 sHK_sz mul add    cmapf2_tblen 1 index sub getinterval    /sH_gIA exch def     /cmapf2_glyph_array 65535 array def     /.cmapf2_putGID {        /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def        firstCode cmapf2_ch_lo le        cmapf2_ch_lo firstCode entryCount add lt        and { % true: j is inside            sH_offset idRangeOffset add		% offset to gI            cmapf2_ch_lo firstCode sub 2 mul	% rel. pos. in range            add 6 add				% offset in sH_gIA            sH_gIA exch getu16            dup 0 gt { %                idDelta add                cmapf2_glyph_array exch cmapf2_ch exch put            } {                pop                % cmapf2_glyph_array cmapf2_ch 0 put            } ifelse        } {   % false: j is outside            % cmapf2_glyph_array cmapf2_ch 0 put        } ifelse    } def     16#00 1 16#ff { % hi_byte scan        /cmapf2_ch_hi exch def        sHKs cmapf2_ch_hi sHK_sz mul getu16        /sH_offset exch def        sH_gIA sH_offset sH_sz getinterval            dup 0 getu16 /firstCode exch def            dup 2 getu16 /entryCount exch def            dup 4 gets16 /idDelta exch def            dup 6 getu16 /idRangeOffset exch def        pop        sH_offset 0 eq {           /cmapf2_ch_lo cmapf2_ch_hi def           /cmapf2_ch_hi 0 def           .cmapf2_putGID        } {           16#00 1 16#ff { % lo_byte scan               /cmapf2_ch_lo exch def               .cmapf2_putGID           } for        } ifelse     } for     pop     0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.        dup cmapf2_glyph_array exch get        null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse     } for     cmapf2_glyph_array  } 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      % the previous line is obstructive to CJK fonts, so it was removed      exch sub 0 .max ecode scode sub 1 add add      exch 1 index add exch      numcodes add /numcodes exch def    } for array def    % prefill the array with 0's faster than a { 0 putglyph } repeat    glyphs length 1024 ge {      .array1024z 0 1024 glyphs length 1023 sub { glyphs exch 2 index putinterval } for      glyphs dup length 1024 sub 3 -1 roll      putinterval    } {      0 1 glyphs length 1 sub { glyphs exch 0 put } for    } ifelse		% 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      % the previous line is obstructive to CJK fonts, so it was removed      exch sub 0 .max dup /code exch code exch add def      ecode scode sub 1 add add numcodes add /numcodes exch def      /delta iddelta i2 gets16 def      TTFDEBUG {	(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 4 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 {    TTFDEBUG {      (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  TTFDEBUG {    (cmap: length=) print dup length = dup ==  } if} bind def /get_from_stringarray % <array|string> <offset> get_from_stringarray <int>{ 1 index type /stringtype eq {    get  } {    exch {                % o ()      2 copy length gt {        length sub      } {        exch get exit      } ifelse    } forall  } ifelse} bind def /getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string>{ % May allocate a string in VM.  2 index type /stringtype eq {    getinterval  } {    string exch 0                                 % [] s o p    4 3 roll {                                    % s o p Si      dup length                                  % s o p Si lSi      dup 4 index lt {        3 index exch sub                          % s o p Si o'        exch pop 3 1 roll exch pop                % s o' p      } {                                         % s o p Si lSi        dup 3 1 roll                              % s o p lSi Si lSi        4 index sub                               % s o p lSi Si lSi-o        5 index length 4 index sub                % s o p lSi Si lSi-o ls-p        2 copy gt { exch } if pop                 % s o p lSi Si minl        dup 3 1 roll                              % s o p lSi minl Si minl        5 index exch getinterval                  % s o p lSi minl from        5 index 4 index 3 index                   % s o p lSi minl from s p minl        getinterval                               % s o p lSi minl from to        copy pop                                  % s o p lSi minl        3 1 roll                                  % s o minl p lSi        sub                                       % s o minl p'        3 1 roll add                              % s p' o'        dup 3 index length ge {          exch exit                               % s o p'        } if        exch                                      % s o' p'      } ifelse    } forall

Lines 1–500 of 1456.