home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / gs403osk.tgz / gs403osk.tar / gs_ttf.ps < prev    next >
Text File  |  1996-09-22  |  15KB  |  443 lines

  1. %    Copyright (C) 1996 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % Support code for direct use of TrueType fonts.
  16. % (Not needed for Type 42 fonts.)
  17.  
  18. % ---------------- Font loading machinery ---------------- %
  19.  
  20. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  21.  
  22. /.scanfontheaders where     % only defined if DISKFONTS is recognized
  23.  { pop
  24.    /.scanfontheaders [ .scanfontheaders aload pop (\000\001\000\000*) ] def
  25.  }
  26. if
  27. /.findnonttfontvalue /.findfontvalue load def
  28. /.findfontvalue     % <file> <key> .findfontvalue <value> true
  29.             % <file> <key> .findfontvalue false
  30.             % Closes the file in either case.
  31.  { 1 index read pop 2 index 1 index unread 0 eq
  32.     {       % If this is a font at all, it's a TrueType font.
  33.       dup /FontType eq
  34.        { pop closefile 42 true }
  35.        { dup /FontName eq
  36.       { pop .findttfontname }
  37.       { pop closefile false }
  38.      ifelse
  39.        }
  40.       ifelse
  41.     }
  42.     {       % Not a TrueType font.
  43.       .findnonttfontvalue
  44.     }
  45.    ifelse
  46.  } bind def
  47. /.findttfontname    % <file> .findttfontname <fname> true
  48.             % <file> .findttfontname false
  49.             % Closes the file in either case.
  50.  { .loadttfonttables
  51.    (name) findtableentry
  52.     { dup 8 getu32 f exch setfileposition
  53.       12 getu32 string f exch readstring pop
  54.       6 findname
  55.     }
  56.     { false
  57.     }
  58.    ifelse
  59.    f closefile end end
  60.  } bind def
  61.  
  62. % Load a font file that might be a TrueType font.
  63.  
  64. /.loadnonttfontfile /.loadfontfile load def
  65. /.loadfontfile      % <file> .loadfontfile -
  66.  { dup read pop 2 copy unread 0 eq
  67.     {       % If this is a font at all, it's a TrueType font.
  68.       .loadttfont dup /FontName get exch definefont pop
  69.     }
  70.     {       % Not a TrueType font.
  71.       .loadnonttfontfile
  72.     }
  73.    ifelse
  74.  } bind def
  75.  
  76. % ---------------- Automatic Type 42 generation ---------------- %
  77.  
  78. % Load a TrueType font from a file as a Type 42 PostScript font.
  79. % The thing that makes this really messy is the handling of encodings.
  80. % There are 3 interacting tables that affect the encoding:
  81. %   'cmap' provides multiple maps from character codes to glyph indices
  82. %   'glyf' maps glyph indices to outlines
  83. %   'post' maps glyph indices to glyph names (if present)
  84. % What we need to get out of this is:
  85. %   Encoding mapping character codes to glyph names
  86. %     (the composition of cmap and post)
  87. %   CharStrings mapping glyph names to glyph indices
  88. %     (the inverse of post)
  89. % If the post table is missing, we have to take a guess based on the cmap
  90. % table.
  91.  
  92. /.loadttfontdict mark
  93. /orgXUID 107 def    % Aladdin Enterprises organization XUID
  94. /maxstring 65500 def    % maximum length of a PostScript string
  95.  
  96. % Define the Macintosh standard mapping from characters to glyph indices.
  97. /MacRomanEncoding dup .findencoding def
  98. /MacGlyphEncoding mark
  99.     /.notdef /.null /CR
  100. MacRomanEncoding 32 95 getinterval aload pop
  101. MacRomanEncoding 128 45 getinterval aload pop
  102. % 143
  103.     /notequal /AE
  104.     /Oslash /infinity /plusinus /lessequal /greaterequal
  105.     /yen /mu1 /partialdiff /summation /product
  106.     /pi /integral /ordfeminine /ordmasculine /Ohm
  107.     /ae /oslash /questiondown /exclamdown /logicalnot
  108.     /radical /florin /approxequal /increment /guillemotleft
  109.     /guillemotright /ellipsis /nbspace
  110. MacRomanEncoding 203 12 getinterval aload pop
  111.     /lozenge
  112. MacRomanEncoding 216 24 getinterval aload pop
  113.     /applelogo
  114. MacRomanEncoding 241 7 getinterval aload pop
  115.     /overscore
  116. MacRomanEncoding 249 7 getinterval aload pop
  117. % 226
  118.     /Lslash /lslash /Scaron /scaron
  119.     /Zcaron /zcaron /brokenbar /Eth /eth
  120.     /Yacute /yacute /Thorn /thorn /minus
  121.     /multiply /onesuperior /twosuperior /threesuperior /onehalf
  122.     /onequarter /threequarters /franc /Gbreve /gbreve
  123.     /Idot /Scedilla /scedilla /Cacute /cacute
  124.     /Ccaron /ccaron /dmacron
  125. /packedarray where
  126.  { pop counttomark packedarray exch pop }
  127.  { ] readonly }
  128. ifelse def
  129.  
  130. % Procedures
  131. /getu16         % <string> <index> getu16 <integer>
  132.  { 2 copy get 8 bitshift 3 1 roll 1 add get add
  133.  } bind def
  134. /gets16         % <string> <index> gets16 <integer>
  135.  { getu16 16#8000 xor 16#8000 sub
  136.  } bind def
  137. /getu32         % <string> <index> getu32 <integer>
  138.  { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  139.  } bind def
  140. /gets32         % <string> <index> gets32 <integer>
  141.  { getu32 dup 16#7fffffff gt { 4 { 16#40000000 sub } repeat } if
  142.  } bind def
  143. /getrange       % <offset> <length> getrange <string>
  144.             % Free variables: sfnts
  145.  { () sfnts
  146.     {       % Stack: offset length () sfnt
  147.       dup length 4 index gt { exch pop exit } if
  148.       4 -1 roll exch length sub 3 1 roll
  149.     }
  150.    forall 3 1 roll getinterval
  151.  } bind def
  152. /findtableentry     % <name4> findtableentry <tableentry> true
  153.             % <name4> findtableentry false
  154.             % Free variables: tables
  155.  { false 0 16 tables length 16 sub
  156.     {       % Stack: name4 false toffset
  157.       tables 1 index 4 getinterval 3 index eq
  158.        { tables exch 16 getinterval
  159.      exch pop exch true exit
  160.        }
  161.       if pop
  162.     }
  163.    for exch pop
  164.  } bind def
  165. /findtable      % <name4> findtable <table> true
  166.             % <name4> findtable false
  167.             % Free variables: tables
  168.  { findtableentry
  169.     { dup 8 getu32 exch 12 getu32 getrange true }
  170.     { false }
  171.    ifelse
  172.  } bind def
  173. /findname       % <nametable> <nameid> findname <string> true
  174.             % <nametable> <nameid> findname false
  175.  { false 3 1 roll 0 1 3 index 2 getu16 1 sub
  176.     {       % Stack: false table id index
  177.       12 mul 6 add 2 index exch 12 getinterval
  178.       dup 6 getu16 2 index eq
  179.        {    % We found the name we want.
  180.      exch pop
  181.         % Stack: false table record
  182.      dup 10 getu16 2 index 4 getu16 add
  183.      1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch
  184.         % Stack: false string record
  185.         % Check for 8- vs. 16-bit characters.
  186.      is2byte { string2to1 } if true null 4 -1 roll exit
  187.        }
  188.       if pop
  189.     }
  190.    for pop pop
  191.  } bind def
  192. /is2byte        % <namerecord> is2byte <bool>
  193.  { dup 0 getu16
  194.     { { pop true }      % Apple Unicode
  195.       { pop false }     % Macintosh Script manager
  196.       { 1 getu16 1 eq }     % ISO
  197.       { 1 getu16 1 eq }     % Microsoft
  198.     }
  199.    exch get exec
  200.  } bind def
  201. /string2to1     % <string2> string2to1 <string>
  202.  { dup length 2 idiv string dup
  203.    0 1 3 index length 1 sub
  204.     { 3 index 1 index 2 mul 1 add get put dup }
  205.    for pop exch pop
  206.  } bind def
  207. /cmapformats mark
  208.         % Each procedure in this dictionary is called as follows:
  209.         %   -mark- encodingtable <<proc>> -mark- glyphindices...
  210.   0     % Apple standard 1-to-1 mapping.
  211.     { 6 256 getinterval { } forall
  212.     } bind
  213.   4     % Microsoft/Adobe segmented mapping.
  214.     { /etab exch def
  215.       /nseg2 etab 6 getu16 def
  216.       14 /endc etab 2 index nseg2 getinterval def
  217.         % The Apple TrueType documentation omits the 2-byte
  218.         % 'reserved pad' that follows the endCount vector!
  219.       2 add
  220.       nseg2 add /startc etab 2 index nseg2 getinterval def
  221.       nseg2 add /iddelta etab 2 index nseg2 getinterval def
  222.       nseg2 add /idroff etab 2 index nseg2 getinterval def
  223.       pop 0 2 nseg2 3 sub
  224.        { /i2 exch def
  225.          /scode startc i2 getu16 def
  226.      counttomark scode 256 min exch sub 0 max { 0 } repeat
  227.      /ecode endc i2 getu16 def
  228.      /delta iddelta i2 getu16 def
  229.      idroff i2 getu16 dup 0 eq
  230.       { pop scode 1 ecode { delta add 65535 and } for
  231.       }
  232.       { % The +2 is for the 'reserved pad'.
  233.         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  234.         0 1 ecode scode sub
  235.          { 2 mul gloff add etab exch getu16
  236.            dup 0 ne { delta add 65535 and } if
  237.          }
  238.         for
  239.       }
  240.      ifelse
  241.        }
  242.       for
  243.     } bind
  244.   6     % Single interval lookup.
  245.     { dup 6 getu16 { 0 exch } repeat
  246.       dup 8 getu16 0 exch 1 exch 1 sub
  247.        { 2 mul 10 add 2 copy getu16 exch pop exch }
  248.       repeat pop
  249.     } bind
  250. .dicttomark readonly def        % cmapformats
  251. /cmaparray      % <cmaptab> cmaparray -mark- <glyphs> ...
  252.  { mark exch dup 0 getu16 cmapformats exch .knownget
  253.     { exec }
  254.     { (Can't handle format ) print 0 getu16 = flush
  255.       0 1 255 { } for
  256.     }
  257.    ifelse
  258.  } bind def
  259. /postformats mark
  260.         % Each procedure in this dictionary is called as follows:
  261.         %   posttable <<proc>> glyphencoding
  262.   16#00020000   % Detailed map, required by Microsoft fonts.
  263.     { /postglyphs exch def
  264.       postglyphs 32 getu16 /numglyphs exch def
  265.       /glyphnames numglyphs 2 mul 34 add def
  266.       [ 0 1 numglyphs 1 sub
  267.        { 2 mul 34 add postglyphs exch getu16
  268.      dup 258 lt
  269.       { MacGlyphEncoding exch get
  270.       }
  271.       { 258 sub glyphnames exch
  272.          { postglyphs 1 index get 1 add add }
  273.         repeat
  274.         1 add postglyphs exch 2 copy 1 sub get getinterval cvn
  275.       }
  276.      ifelse
  277.        }
  278.       for ]
  279.     } bind
  280. .dicttomark readonly def        % postformats
  281. .dicttomark readonly def        % .loadttfontdict
  282. /.loadttfonttables  % <file> .loadttfonttables -
  283.             % Pushes .loadttfontdict & scratch dict on d-stack,
  284.             % defines f, offsets, tables
  285.  { .loadttfontdict begin
  286.    40 dict begin
  287.    /f exch def
  288.    /offsets f 12 string readstring pop def
  289.    /tables f offsets 4 getu16 16 mul string readstring pop def
  290.  } bind def
  291. /.makesfnts     % - .makesfnts -
  292.             % Defines head, sfnts
  293.  {      % Find the end of the last table, and also the end of
  294.         % the last table below the 64K mark.
  295.    0 8 16 tables length
  296.     {       % Stack: end toffset
  297.       DEBUG
  298.        { tables 1 index 8 sub 4 getinterval print ( ) print
  299.      tables 1 index getu32 =only ( ) print
  300.      tables 1 index 4 add getu32 =
  301.        }
  302.       if
  303.       tables 1 index getu32 exch tables exch 4 add getu32 add max
  304.     }
  305.    for
  306.         % Divide into 2+n strings: before glyf, glyfs, after glyf
  307.    (glyf) findtableentry pop
  308.    dup 8 getu32 /len0 exch def
  309.    12 getu32 /len1 exch def
  310.    len0 len1 add sub /len2 exch def
  311.    /sfnts [
  312.    len0 string
  313.      dup 0 offsets putinterval
  314.      dup offsets length tables putinterval
  315.      dup offsets length tables length add
  316.        len0 1 index sub getinterval
  317.        f exch dup length 0 ne { readstring } if pop pop
  318.    len1 dup maxstring gt
  319.     {       % Bad news: we'll have to split the glyfs.
  320.         % Right now we only provide for splitting into 2 parts,
  321.         % but we could generalize this without too much trouble.
  322.       f maxstring string readstring pop
  323.       exch maxstring sub
  324.     }
  325.    if string f exch readstring pop
  326.    len2 0 ne { f len2 string readstring pop } if
  327.    ] def
  328.    /head (head) findtable pop def
  329.    len1 maxstring gt
  330.     {       % Determine where to split the glyfs by scanning loca.
  331.         % The very last entry in loca may be bogus.
  332.         % What a nuisance!
  333.       (loca) findtable pop dup length
  334.       head 50 getu16 0 ne
  335.        {    % 32-bit loca
  336.      8 sub -4 0
  337.       { 1 index exch getu32 dup maxstring le { exch pop exit } if pop }
  338.        }
  339.        {    % 16-bit loca
  340.      4 sub -2 0
  341.       { 1 index exch getu16 1 bitshift dup maxstring le { exch pop exit } if pop }
  342.        }
  343.       ifelse for
  344.         % Now the top element of the stack is the length of
  345.         % the first glyf string.
  346.       sfnts 1 get dup 0 3 index getinterval
  347.     sfnts exch 1 exch put
  348.       exch 1 index length 1 index sub getinterval
  349.     sfnts 2 get concatstrings sfnts exch 2 exch put
  350.     }
  351.    if
  352.  } bind def
  353. /.loadttfont        % <file> .loadttfont <type42font>
  354.  { .loadttfonttables
  355.    .makesfnts
  356.    /upem head 18 getu16 def
  357.    (cmap) findtable pop
  358.         % The Apple cmap format is no help in determining the encoding.
  359.         % Look for a Microsoft table.  If we can't find one,
  360.         % just use the first table, whatever it is.
  361.    dup 4 8 getinterval exch     % the default
  362.    0 1 2 index 2 getu16 1 sub
  363.     { 8 mul 4 add 1 index exch 8 getinterval
  364.       dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
  365.     }
  366.    for
  367.         % Stack: subentry table
  368.    /cmapsub 2 index def
  369.    exch 4 getu32 1 index length 1 index sub getinterval
  370.    /cmaptab exch def
  371.         % See if we have PostScript glyph name information.
  372.    /post (post) findtable pop def
  373.    /glyphencoding postformats post 0 getu32 .knownget
  374.     { post exch exec }
  375.     { MacGlyphEncoding }
  376.    ifelse def
  377.    /checksum head 8 getu32 def
  378.    mark
  379.      /FontType 42
  380.      /FontMatrix matrix
  381.      /PaintType 0
  382.      /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  383.      (name) findtable
  384.       {     % Find the names from the 'name' table.
  385.     /names exch def
  386.     /FontName names 6 findname not { checksum 16 8 string cvrs } if
  387.     /FontInfo mark
  388.       names 0 findname { /Notice exch } if
  389.       names 1 findname { /FamilyName exch } if
  390.       names 4 findname { /FullName exch } if
  391.       names 5 findname { /Version exch } if
  392.       }
  393.       {     % No name table, fabricate a FontName.
  394.     /FontName checksum 16 8 string cvrs
  395.     /FontInfo mark
  396.       }
  397.      ifelse
  398.         % Stack: /FontInfo mark key1 value1 ...
  399.      post null ne
  400.       { /ItalicAngle post 4 gets32 65536.0 div
  401.     /isFixedPitch post 12 getu32 0 ne
  402.     /UnderlinePosition post 8 gets16 upem div
  403.     /UnderlineThickness post 10 gets16 upem div
  404.       }
  405.      if
  406.      counttomark 0 ne
  407.       { .dicttomark }
  408.       { pop pop }
  409.      ifelse
  410.      /Encoding
  411.        cmaptab cmaparray
  412.         % For some reason, the Symbol and WingDing fonts start with
  413.         % 192 unmapped character codes.
  414.        counttomark 384 ge
  415.     { counttomark 256 sub /skip exch def
  416.       counttomark skip neg roll skip { pop } repeat
  417.     }
  418.        if
  419.        counttomark array astore { glyphencoding exch get } forall
  420.        counttomark 256 sub dup 0 ge
  421.     { { pop } repeat }
  422.     { neg { /.notdef } repeat }
  423.        ifelse ]
  424.         % Until we can compute the MD5 fingerprint,
  425.         % just use the precomputed checksum.
  426.      /XUID [orgXUID 42 checksum]
  427.      /CharStrings glyphencoding dup length dict
  428.        0 1 3 index length 1 sub
  429.     {   % Stack: glyphencoding dict index
  430.       2 index 1 index get 2 index 1 index known
  431.        { pop pop }
  432.        { 2 index exch 3 -1 roll put }
  433.       ifelse
  434.     }
  435.        for exch pop readonly
  436.      /sfnts sfnts
  437.    .dicttomark
  438.    end end dup /FontName get exch definefont
  439.  } bind def
  440.