home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / inne / gs300ini / gs_fonts.ps < prev    next >
Encoding:
Text File  |  1994-08-02  |  14.4 KB  |  482 lines

  1. %    Copyright (C) 1990, 1992, 1993, 1994 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. % Font initialization and management code.
  16.  
  17. % Define the default font.
  18. /defaultfontname /Courier def
  19.  
  20. % Load the font name -> font file name map.
  21. userdict /Fontmap FontDirectory maxlength dict put
  22. /.loadFontmap        % <file> .loadFontmap -
  23.  {  { dup token not { closefile exit } if
  24.         % stack: <file> fontname
  25.       1 index token not
  26.        { (File or alias name missing in Fontmap!  Giving up.\n) print flush
  27.          {.loadFontmap} 0 get 1 .quit
  28.        } if
  29.         % stack: <file> fontname filename|aliasname
  30.         % Read and pop tokens until a semicolon.
  31.        { 2 index token not
  32.       { (Semicolon missing in Fontmap!  Giving up.\n) print flush
  33.         {.loadFontmap} 0 get 1 .quit
  34.       } if
  35.      dup /; eq { pop Fontmap 3 1 roll .growput exit } if
  36.      pop
  37.        } loop
  38.     } loop 
  39.  } bind def
  40.  
  41. % If there is no FONTPATH, get one from the environment.
  42. /FONTPATH where
  43.  { pop }
  44.  { (GS_FONTPATH) getenv { /FONTPATH exch def } if }
  45. ifelse
  46.  
  47. % If we can't find a Fontmap, try using the FONTPATH.
  48. (Fontmap) findlibfile
  49.  { exch pop .loadFontmap }
  50.  { pop /FONTPATH where
  51.     { pop }
  52.     { (Fontmap) /undefinedfilename signalerror }
  53.    ifelse
  54.  }
  55. ifelse
  56.  
  57. % Parse a font file just enough to find the FontName.
  58. /.findfontname        % <file> .findfontname <name> true
  59.             % <file> .findfontname false
  60.             % Closes the file in either case.
  61.  { dup read not { -1 } if
  62.    2 copy unread 16#80 eq
  63.     { dup (xxxxxx) readstring pop pop }        % skip .PFB header
  64.    if
  65.     { dup token not { false exit } if        % end of file
  66.       dup /eexec eq { pop false exit } if    % reached eexec section
  67.       dup /FontName eq
  68.        { xcheck not { dup token exit } if }    % found /FontName
  69.        { pop }
  70.       ifelse
  71.     } loop
  72.    dup { 3 } { 2 } ifelse -1 roll closefile
  73.  } bind def
  74.  
  75. /FONTPATH where not { (%END FONTPATH) .skipeof } if
  76. pop
  77.  
  78. % Scan directories looking for plausible fonts.  "Plausible" means that
  79. % the file begins with %!PS-AdobeFont- or %!FontType1-, or with \200\001
  80. % followed by four arbitrary bytes and then either of these strings.
  81. % To speed up the search, we skip any file whose name appears in
  82. % the Fontmap (with any extension and upper/lower case variation) already,
  83. % and any file whose extension definitely indicates it is not a font.
  84. %
  85. % NOTE: The current implementation of this procedure is Unix/DOS-
  86. % specific.  It assumes that '/' and '\' are directory separators; that
  87. % the part of a file name following the last '.' is the extension;
  88. % that ';' cannot appear in a file name; and that ':' can appear in a
  89. % file name only if the file name doesn't begin with '/', '\', or '.'.
  90. % (this is so that Unix systems can use ':' as the separator).
  91. %
  92. /.lowerstring        % <string> .lowerstring <lowerstring>
  93.  { 0 1 2 index length 1 sub
  94.     { 2 copy get dup 65 ge exch 90 le and
  95.        { 2 copy 2 copy get 32 add put }
  96.      if pop
  97.     }
  98.    for
  99.  } bind def
  100. /.splitfilename        % <dir.../base.extn> .basename <base> <extn>
  101.  {  { (/) search { true } { (\\) search } ifelse
  102.        { pop pop }
  103.        { exit }
  104.       ifelse
  105.     }
  106.    loop
  107.    dup { (.) search { pop pop } { exit } ifelse } loop
  108.    2 copy eq
  109.     { pop () }
  110.     { exch dup length 2 index length 1 add sub 0 exch getinterval exch }
  111.    ifelse
  112. % Following is debugging code.
  113. %   (*** Split => ) print 2 copy exch ==only ( ) print ==only
  114. %   ( ***\n) print flush
  115.  } bind def
  116. /.scanfontdict Fontmap maxlength dict def
  117. /.scanfontbegin
  118.  {    % Construct the table of all file names already in Fontmap.
  119.    Fontmap
  120.     { exch pop dup type /stringtype eq
  121.        { .splitfilename pop =string copy .lowerstring cvn
  122.          .scanfontdict exch true .growput
  123.        }
  124.        { pop
  125.        }
  126.       ifelse
  127.     }
  128.    forall
  129.  } bind def
  130. /.scanfontskip mark
  131.         % Strings are converted to names anyway, so....
  132.   /afm true
  133.   /bat true
  134.   /c true
  135.   /cmd true
  136.   /com true
  137.   /dll true
  138.   /doc true
  139.   /exe true
  140.   /h true
  141.   /o true
  142.   /obj true
  143.   /pfm true
  144.   /txt true
  145. .dicttomark def
  146. /.scan1fontstring 128 string def
  147. /.fontheaders [(%!PS-AdobeFont-*) (%!FontType1-*)] def
  148. 0 .fontheaders { length max } forall 6 add    % extra for PFB header
  149. /.scan1fontfirst exch string def
  150. /.scan1fontdir        % <dirname> .scan1fontdir -
  151.  { QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
  152.    (/*) concatstrings 0 0 0 4 -1 roll    % found scanned files
  153.     {        % stack: <fontcount> <scancount> <filecount> <filename>
  154.       exch 1 add exch                   % increment filecount
  155.       dup .splitfilename .lowerstring
  156.         % stack: <fontcount> <scancount> <filecount+1> <filename>
  157.         %    <BASE> <ext>
  158.       .scanfontskip exch known exch .scanfontdict exch known or
  159.        { pop
  160.         % stack: <fontcount> <scancount> <filecount+1>
  161.        }
  162.        { 3 -1 roll 1 add 3 1 roll
  163.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  164.          dup (r) { file } stopped
  165.       { pop pop null () 
  166.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  167.         %    null ()
  168.           }
  169.       { 
  170.         % On some platforms, the file operator will open directories,
  171.         % but an error will occur if we try to read from one.
  172.         % Handle this possibility here.
  173.         dup .scan1fontfirst { readstring } stopped
  174.          { pop pop () }
  175.          { pop }
  176.         ifelse 
  177.         % stack: <fontcount> <scancount+1> <filecount+1>
  178.         %    <filename> <file> <header>
  179.           }
  180.      ifelse
  181.         % Check for PFB file header.
  182.      dup (\200\001????*) .stringmatch
  183.       { dup length 6 sub 6 exch getinterval }
  184.      if
  185.         % Check for font file headers.
  186.      false .fontheaders { 2 index exch .stringmatch or } forall exch pop
  187.       {    % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  188.         %    <file>
  189.             dup 0 setfileposition .findfontname
  190.          { dup Fontmap exch known
  191.         { pop pop
  192.         }
  193.         { exch copystring exch
  194.           DEBUG { ( ) print dup =only } if
  195.           Fontmap exch 2 index .growput
  196.           .splitfilename pop true .scanfontdict 3 1 roll .growput
  197.             % Increment fontcount.
  198.           3 -1 roll 1 add 3 1 roll
  199.         }
  200.            ifelse
  201.          }
  202.         if
  203.       }
  204.         % .findfontname will have done a closefile in the above case.
  205.       { dup null eq { pop } { closefile } ifelse pop 
  206.           }
  207.      ifelse
  208.        }
  209.       ifelse
  210.     }
  211.    .scan1fontstring filenameforall
  212.    QUIET
  213.     { pop pop pop }
  214.     { ( ) print =only ( files, ) print =only ( scanned, ) print
  215.       =only ( new fonts.\n) print flush
  216.     }
  217.    ifelse
  218.  } bind def
  219. % Scan all the directories mentioned in FONTPATH (or GS_FONTPATH).
  220. /FONTPATH where
  221.  { pop .scanfontbegin
  222.     % Parsing the list of dictionaries is messy, since we have to
  223.     % handle both the Unix : and the other-system ; as separators.
  224.     % See the earlier comment for the restrictions that make this work.
  225.    FONTPATH
  226.     { dup length 0 eq { pop exit } if
  227.       (;) search
  228.        { exch pop
  229.        }
  230.        { dup 0 1 getinterval (/\\.) exch search
  231.           { pop pop pop (:) search
  232.          { exch pop }
  233.          { () exch }
  234.         ifelse
  235.       }
  236.       { pop () exch
  237.       }
  238.      ifelse
  239.        }
  240.       ifelse .scan1fontdir
  241.     }
  242.    loop
  243.  }
  244. if
  245.  
  246. %END FONTPATH
  247.  
  248. % Define definefont.  This is a procedure built on a set of operators
  249. % that do all the error checking and key insertion.
  250. mark
  251.     /.buildfont0 where { pop 0 /.buildfont0 cvx } if
  252.     /.buildfont1 where { pop 1 /.buildfont1 cvx } if
  253.     /.buildfont3 where { pop 3 /.buildfont3 cvx } if
  254. .dicttomark /.buildfontdict exch def
  255. /definefont
  256.  { 1 dict begin count /d exch def    % save stack depth in case of error
  257.     {        % Check for disabled platform fonts.
  258.       NOPLATFONTS
  259.        { dup maxlength 1 index length sub 2 lt
  260.       { dup dup wcheck
  261.          { .growdict }
  262.          { .growdictlength dict copy }
  263.         ifelse
  264.       }
  265.       { dup wcheck not { dup maxlength dict copy } if
  266.       }
  267.      ifelse
  268.      dup /ExactSize 0 put
  269.        }
  270.        {    % Hack: if the Encoding looks like it might be the
  271.         % Symbol or Dingbats encoding, load those now (for the
  272.         % benefit of platform font matching) just in case
  273.         % the font didn't actually reference them.
  274.      dup /Encoding get length 65 ge
  275.       { dup /Encoding get 64 get
  276.         dup /congruent eq { SymbolEncoding pop } if
  277.         /a9 eq { DingbatsEncoding pop } if
  278.       }
  279.      if
  280.        }
  281.       ifelse
  282.       dup /FontType get //.buildfontdict exch get exec
  283.       DISKFONTS
  284.        { FontFileDirectory 2 index known
  285.           { dup /FontFile FontFileDirectory 4 index get .growput
  286.       }
  287.      if
  288.        }
  289.       if
  290.       readonly
  291.     }
  292.    stopped
  293.     { count d sub { pop } repeat end /invalidfont signalerror
  294.     }
  295.     { end        % stack: name fontdict
  296.         % If the current allocation mode is global, also enter
  297.         % the font in GlobalFontDirectory.
  298.       .currentglobal
  299.        { /GlobalFontDirectory where
  300.       { pop GlobalFontDirectory 2 index 2 index .growput }
  301.      if
  302.        }
  303.       if
  304.       dup FontDirectory 4 -2 roll .growput
  305.     }
  306.    ifelse
  307.  } odef
  308.  
  309. % Define a procedure for defining aliased fonts.
  310. % We just copy the original font, changing the FontName.
  311. /.aliasfont        % <name> <font> .aliasfont <newFont>
  312.  { dup length 2 add dict
  313.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  314.    /FontName 3 index put
  315.    systemdict /definefont get exec    % Don't bind, since Level 2
  316.                     % redefines definefont
  317.  } odef        % so findfont will bind it
  318.  
  319. % Define .loadfont for loading a font.  If we recognize Type 1 fonts,
  320. % gs_type1.ps will redefine this.
  321. /.loadfont { cvx exec } bind def
  322.  
  323. % Find an alternate font to substitute for an unknown one.
  324. % We go to a little trouble to parse the font name and extract
  325. % properties from it.
  326. /.substituteproperties [
  327.   [(Grot) 8]
  328.   [(Condensed) 4] [(Narrow) 4]
  329.   [(Bold) 2]
  330.   [(Italic) 1] [(Oblique) 1]
  331. ] readonly def
  332. /.substitutenames {
  333.   defaultfontname /Helvetica-Oblique
  334.     /Helvetica-Bold /Helvetica-BoldOblique
  335.   /Helvetica-Narrow /Helvetica-Narrow-Oblique
  336.     /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique
  337.   /Times-Roman /Times-Italic
  338.     /Times-Bold /Times-BoldItalic
  339.   defaultfontname defaultfontname
  340.     defaultfontname defaultfontname
  341. } cvlit readonly def
  342. /.substitutefont        % <fontname> .substitutefont <altname>
  343.  {    % Look for properties in the font name.
  344.     % If we find any, use Helvetica as the base font;
  345.     % otherwise, use the default font
  346.    dup length string cvs
  347.    0 exch .substituteproperties
  348.     { 2 copy 0 get search
  349.        { pop pop pop 1 get 3 -1 roll or exch }
  350.        { pop pop }
  351.       ifelse
  352.     }
  353.    forall exch .substitutenames exch get exec
  354.     % Only accept fonts known in the Fontmap.
  355.    Fontmap 1 index known not { pop defaultfontname } if
  356.     % Don't "substitute" the same font name.
  357.    exch cvn 1 index eq { pop defaultfontname } if
  358.  } bind def
  359.  
  360. % Define findfont so it tries to load a font if it's not found.
  361. % The Red Book requires that findfont be a procedure, not an operator.
  362. /findfont
  363.  {    % Since PostScript has no concept of goto, or even blocks with
  364.     % exits, we use a loop as a way to get an exitable scope.
  365.     % The loop is never executed more than twice.
  366.     {
  367.     dup FontDirectory exch known        % Already loaded?
  368.      { FontDirectory exch get exit }
  369.     if
  370.  
  371.     dup Fontmap exch known not    % Unknown font name.
  372.      { dup defaultfontname eq
  373.         { (Default font ) print cvx =only
  374.           ( not found in Fontmap!  Giving up.\n) print flush
  375.           /findfont cvx 1 .quit
  376.         } if
  377.        QUIET not
  378.         { (Substituting ) print dup .substitutefont cvx =only
  379.           ( for unknown font ) print dup == flush
  380.         } if
  381.        dup .substitutefont findfont .aliasfont exit
  382.      }
  383.     if
  384.  
  385.     dup Fontmap exch get
  386.  
  387.     % Check for a font alias.
  388.     dup type /nametype eq
  389.      { findfont .aliasfont exit
  390.      }
  391.     if
  392.  
  393.     % If we can't open the file, substitute for the font.
  394.     findlibfile
  395.      { % Stack: fontname fontfilename fontfile
  396.        DISKFONTS
  397.         { 1 index (r) file
  398.           FontFileDirectory exch 4 index exch .growput
  399.         }
  400.        if
  401.        QUIET not
  402.         { (Loading ) print 2 index =only
  403.           ( font from ) print exch print (... ) print flush }
  404.         { exch pop }
  405.        ifelse
  406.        .loadfont
  407.        QUIET not
  408.         { vmstatus 3 { =only ( ) print } repeat
  409.           (done.\n) print flush
  410.         } if
  411.  
  412.        % Check to make sure the font was actually loaded.
  413.        dup FontDirectory exch known { findfont exit } if
  414.  
  415.        % Maybe the file had a different FontName.
  416.        % See if we can get a FontName from the file, and if so,
  417.        % whether a font by that name exists now.
  418.        dup Fontmap exch get findlibfile
  419.         { exch pop .findfontname
  420.            { dup FontDirectory exch .knownget
  421.               {    % Yes.  Stack: origfontname filefontname fontdir
  422.             exch
  423.             QUIET
  424.              { pop
  425.              }
  426.              { (Using ) print cvx =only
  427.                ( font for ) print 1 index cvx =only
  428.                (.\n) print flush
  429.              }
  430.             ifelse
  431.             .aliasfont exit
  432.           }
  433.          if pop
  434.            }
  435.           if
  436.         }
  437.        if
  438.  
  439.        % The font definitely did not load correctly.
  440.        QUIET not
  441.         { (Loading ) print dup cvx =only
  442.           ( font failed, substituting ) print dup .substitutefont cvx =only
  443.           (.\n) print flush
  444.         } if
  445.        dup .substitutefont findfont .aliasfont exit
  446.      }
  447.     if
  448.  
  449.     % findlibfile failed, substitute the default font.
  450.     % Stack: fontname fontfilename
  451.     (Can't find \(or can't open\) font file )
  452.     2 index defaultfontname eq
  453.      { print print ( for default font \() print cvx =only
  454.        (\)!  Giving up.\n) print flush /findfont cvx 1 .quit
  455.      }
  456.      { QUIET
  457.         { pop pop
  458.         }
  459.         { print print ( for font ) print dup cvx =only
  460.           (, substituting ) print dup .substitutefont cvx =only
  461.           (.\n) print flush
  462.         }
  463.        ifelse
  464.        dup .substitutefont findfont .aliasfont
  465.      }
  466.     ifelse
  467.     exit
  468.  
  469.     } loop        % end of loop
  470.  
  471.  } bind def
  472.  
  473.  
  474. % Define a procedure to load all known fonts.
  475. % This isn't likely to be very useful.
  476. /loadallfonts
  477.  { Fontmap { pop findfont pop } forall
  478.  } bind def
  479.