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_fonts.ps < prev    next >
Text File  |  1996-10-12  |  26KB  |  793 lines

  1. %    Copyright (C) 1990, 1995, 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. % Font initialization and management code.
  16.  
  17. % Define the default font.
  18. /defaultfontname /Courier def
  19.  
  20. % Define the name of the font map file.
  21. /defaultfontmap (Fontmap) def
  22.  
  23. % ------ End of editable parameters ------ %
  24.  
  25. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  26. % (This is intended primarily for machines with very small memories.)
  27. % In this case, we define another dictionary, parallel to FontDirectory,
  28. % that retains an open file for every font loaded.
  29. /FontFileDirectory 10 dict def
  30.  
  31. % Split up a search path into individual directories or files.
  32. /.pathlist      % <path> .pathlist <dir1|file1> ...
  33.  {  { dup length 0 eq { pop exit } if
  34.       .filenamelistseparator search not { exit } if
  35.       exch pop exch
  36.     }
  37.    loop
  38.  } bind def
  39.  
  40. % Load a font name -> font file name map.
  41. userdict /Fontmap FontDirectory maxlength dict put
  42. /.loadFontmap       % <file> .loadFontmap -
  43.  {      % We would like to simply execute .definefontmap as we read,
  44.         % but we have to maintain backward compatibility with an older
  45.         % specification that makes later entries override earlier.
  46.    50 dict exch
  47.     { dup token not { closefile exit } if
  48.         % stack: <file> fontname
  49.       % This is a hack to get around the absurd habit of MS-DOS editors
  50.       % of adding an EOF character at the end of the file.
  51.       dup (\032) eq { pop closefile exit } if
  52.       1 index token not
  53.        { (Fontmap entry for ) print dup =only
  54.      ( has no associated file or alias name!  Giving up.\n) print flush
  55.      {.loadFontmap} 0 get 1 .quit
  56.        } if
  57.       dup type dup /stringtype eq exch /nametype eq or not
  58.        { (Fontmap entry for ) print 1 index =only
  59.      ( has an invalid file or alias name!  Giving up.\n) print flush
  60.      {.loadFontmap} 0 get 1 .quit
  61.        } if
  62.         % stack: dict file fontname filename|aliasname
  63.         % Read and pop tokens until a semicolon.
  64.        { 2 index token not
  65.       { (Fontmap entry for ) print 1 index =only
  66.         ( ends prematurely!  Giving up.\n) print flush
  67.         {.loadFontmap} 0 get 1 .quit
  68.       } if
  69.      dup /; eq { pop 3 index 3 1 roll .growput exit } if
  70.      pop
  71.        } loop
  72.     } loop
  73.     { .definefontmap } forall
  74.  } bind def
  75. % Add an entry in Fontmap.  We redefine this if the Level 2
  76. % resource machinery is loaded.
  77. /.definefontmap         % <fontname> <file|alias> .definefontmap -
  78.  {      % Since Fontmap is global, make sure the values are storable.
  79.    .currentglobal 3 1 roll true .setglobal
  80.    dup type /stringtype eq
  81.     { dup .gcheck not { dup length string copy } if
  82.     }
  83.    if
  84.    Fontmap 3 -1 roll 2 copy .knownget
  85.     {       % Add an element to the end of the existing value,
  86.         % unless it's the same as the current last element.
  87.       mark exch aload pop counttomark 4 add -1 roll
  88.       2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse
  89.     }
  90.     {       % Make a new entry.
  91.       mark 4 -1 roll ] readonly .growput
  92.     }
  93.    ifelse .setglobal
  94.  } bind def
  95.  
  96. % Parse a font file just enough to find the FontName or FontType.
  97. /.findfontvalue     % <file> <key> .findfontvalue <value> true
  98.             % <file> <key> .findfontvalue false
  99.             % Closes the file in either case.
  100.  { exch dup read not { -1 } if
  101.    2 copy unread 16#80 eq
  102.     { dup (xxxxxx) readstring pop pop }     % skip .PFB header
  103.    if
  104.         % Stack: key file
  105.     { dup token not { false exit } if       % end of file
  106.       dup /eexec eq { pop false exit } if   % reached eexec section
  107.       dup /Subrs eq { pop false exit } if   % Subrs without eexec
  108.       dup /CharStrings eq { pop false exit } if % CharStrings without eexec
  109.       dup 3 index eq
  110.        { xcheck not { dup token exit } if } % found key
  111.        { pop }
  112.       ifelse
  113.     } loop
  114.         % Stack: key file value true   (or)
  115.         % Stack: key file false
  116.    dup { 4 } { 3 } ifelse -2 roll closefile pop
  117.  } bind def
  118. /.findfontname
  119.  { /FontName .findfontvalue
  120.  } bind def
  121.  
  122. % If there is no FONTPATH, try to get one from the environment.
  123. NOFONTPATH { /FONTPATH () def } if
  124. /FONTPATH where
  125.  { pop }
  126.  { /FONTPATH (GS_FONTPATH) getenv not { () } if def }
  127. ifelse
  128. FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
  129. /FONTPATH [ FONTPATH .pathlist ] def
  130.  
  131. % Scan directories looking for plausible fonts.  "Plausible" means that
  132. % the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001
  133. % followed by four arbitrary bytes and then either of these strings.
  134. % To speed up the search, we skip any file whose name appears in
  135. % the Fontmap (with any extension and upper/lower case variation) already,
  136. % and any file whose extension definitely indicates it is not a font.
  137. %
  138. % NOTE: The current implementation of this procedure is somewhat Unix/DOS-
  139. % specific.  It assumes that '/' and '\' are directory separators, and that
  140. % the part of a file name following the last '.' is the extension.
  141. %
  142. /.lowerstring       % <string> .lowerstring <lowerstring>
  143.  { 0 1 2 index length 1 sub
  144.     { 2 copy get dup 65 ge exch 90 le and
  145.        { 2 copy 2 copy get 32 add put }
  146.      if pop
  147.     }
  148.    for
  149.  } bind def
  150. /.splitfilename     % <dir.../base.extn> .basename <base> <extn>
  151.  {  { (/) search { true } { (\\) search } ifelse
  152.        { pop pop }
  153.        { exit }
  154.       ifelse
  155.     }
  156.    loop
  157.    dup { (.) search { pop pop } { exit } ifelse } loop
  158.    2 copy eq
  159.     { pop () }
  160.     { exch dup length 2 index length 1 add sub 0 exch getinterval exch }
  161.    ifelse
  162. % Following is debugging code.
  163. %   (*** Split => ) print 2 copy exch ==only ( ) print ==only
  164. %   ( ***\n) print flush
  165.  } bind def
  166. /.scanfontdict 1 dict def       % establish a binding
  167. /.scanfontbegin
  168.  {  % Construct the table of all file names already in Fontmap.
  169.    currentglobal true setglobal
  170.    .scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength
  171.    Fontmap
  172.     { exch pop
  173.        { dup type /stringtype eq
  174.       { .splitfilename pop =string copy .lowerstring cvn
  175.         .scanfontdict exch true put
  176.       }
  177.       { pop
  178.       }
  179.      ifelse
  180.        }
  181.       forall
  182.     }
  183.    forall
  184.    setglobal
  185.  } bind def
  186. /.scanfontskip mark
  187.         % Strings are converted to names anyway, so....
  188.   /afm true
  189.   /bat true
  190.   /c true
  191.   /cmd true
  192.   /com true
  193.   /dll true
  194.   /doc true
  195.   /drv true
  196.   /exe true
  197.   /fon true
  198.   /fot true
  199.   /h true
  200.   /o true
  201.   /obj true
  202.   /pfm true
  203.   /txt true
  204. .dicttomark def
  205. /.scan1fontstring 128 string def
  206. /.scanfontheaders [(%!PS-AdobeFont*) (%!FontType1*)] def
  207. 0 .scanfontheaders { length max } forall 6 add  % extra for PFB header
  208. /.scan1fontfirst exch string def
  209. /.scanfontdir       % <dirname> .scanfontdir -
  210.  { currentglobal exch true setglobal
  211.    QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
  212.    (*) 2 copy .filenamedirseparator
  213.    dup (\\) eq { pop (\\\\) } if    % double \ for pattern match
  214.    exch concatstrings concatstrings
  215.    0 0 0 4 -1 roll  % found scanned files
  216.     {       % stack: <fontcount> <scancount> <filecount> <filename>
  217.       exch 1 add exch                   % increment filecount
  218.       dup .splitfilename .lowerstring
  219.         % stack: <fontcount> <scancount> <filecount+1> <filename>
  220.         %   <BASE> <ext>
  221.       .scanfontskip exch known exch .scanfontdict exch known or
  222.        { pop
  223.         % stack: <fontcount> <scancount> <filecount+1>
  224.        }
  225.        { 3 -1 roll 1 add 3 1 roll
  226.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  227.      dup (r) { file } .internalstopped
  228.       { pop pop null ()
  229.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  230.         %   null ()
  231.       }
  232.       {
  233.         % On some platforms, the file operator will open directories,
  234.         % but an error will occur if we try to read from one.
  235.         % Handle this possibility here.
  236.         dup .scan1fontfirst { readstring } .internalstopped
  237.          { pop pop () }
  238.          { pop }
  239.         ifelse
  240.         % stack: <fontcount> <scancount+1> <filecount+1>
  241.         %   <filename> <file> <header>
  242.       }
  243.      ifelse
  244.         % Check for PFB file header.
  245.      dup (\200\001????*) .stringmatch
  246.       { dup length 6 sub 6 exch getinterval }
  247.      if
  248.         % Check for font file headers.
  249.      false .scanfontheaders
  250.       { 2 index exch .stringmatch or
  251.       }
  252.      forall exch pop
  253.       { % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  254.         %   <file>
  255.         dup 0 setfileposition .findfontname
  256.          { dup Fontmap exch known
  257.         { pop pop
  258.         }
  259.         { exch copystring exch
  260.           DEBUG { ( ) print dup =only } if
  261.           1 index .definefontmap
  262.           .splitfilename pop true .scanfontdict 3 1 roll .growput
  263.             % Increment fontcount.
  264.           3 -1 roll 1 add 3 1 roll
  265.         }
  266.            ifelse
  267.          }
  268.          { pop
  269.          }
  270.         ifelse
  271.       }
  272.         % .findfontname will have done a closefile in the above case.
  273.       { dup null eq { pop } { closefile } ifelse pop
  274.       }
  275.      ifelse
  276.        }
  277.       ifelse
  278.     }
  279.    .scan1fontstring filenameforall
  280.    QUIET
  281.     { pop pop pop }
  282.     { ( ) print =only ( files, ) print =only ( scanned, ) print
  283.       =only ( new fonts.\n) print flush
  284.     }
  285.    ifelse
  286.    setglobal
  287.  } bind def
  288.  
  289. %END FONTPATH
  290.  
  291. % Define definefont.  This is a procedure built on a set of operators
  292. % that do all the error checking and key insertion.
  293. mark
  294.     /.buildfont0 where { pop 0 /.buildfont0 cvx } if
  295.     /.buildfont1 where { pop 1 /.buildfont1 cvx } if
  296.     /.buildfont3 where { pop 3 /.buildfont3 cvx } if
  297.     /.buildfont4 where { pop 4 /.buildfont4 cvx } if
  298.     /.buildfont42 where { pop 42 /.buildfont42 cvx } if
  299. .dicttomark /buildfontdict exch def
  300. /.growfontdict
  301.  {  % Grow the font dictionary, if necessary, to ensure room for an
  302.     % added entry, making sure there is at least one slot left for FID.
  303.    dup maxlength 1 index length sub 2 lt
  304.     { dup dup wcheck
  305.        { .growdict }
  306.        { .growdictlength dict .copydict }
  307.       ifelse
  308.     }
  309.     { dup wcheck not { dup maxlength dict .copydict } if
  310.     }
  311.    ifelse
  312.  } bind def 
  313. /definefont
  314.  { 1 dict begin count /d exch def   % save stack depth in case of error
  315.     {       % Check for disabled platform fonts.
  316.       NOPLATFONTS
  317.        {    % Make sure we leave room for FID.
  318.      .growfontdict dup /ExactSize 0 put
  319.        }
  320.        {    % Hack: if the Encoding looks like it might be the
  321.         % Symbol or Dingbats encoding, load those now (for the
  322.         % benefit of platform font matching) just in case
  323.         % the font didn't actually reference them.
  324.      dup /Encoding get length 65 ge
  325.       { dup /Encoding get 64 get
  326.         dup /congruent eq { SymbolEncoding pop } if
  327.         /a9 eq { DingbatsEncoding pop } if
  328.       }
  329.      if
  330.        }
  331.       ifelse
  332.       dup /FontType get //buildfontdict exch get exec
  333.       DISKFONTS
  334.        { FontFileDirectory 2 index known
  335.       { dup /FontFile FontFileDirectory 4 index get .growput
  336.       }
  337.      if
  338.        }
  339.       if
  340.       readonly
  341.     }
  342.    stopped
  343.     { count d sub { pop } repeat end /invalidfont signalerror
  344.     }
  345.     { end       % stack: name fontdict
  346.         % If the current allocation mode is global, also enter
  347.         % the font in LocalFontDirectory.
  348.       .currentglobal
  349.        { //systemdict /LocalFontDirectory .knownget
  350.       { 2 index 2 index .growput }
  351.      if
  352.        }
  353.       if
  354.       dup FontDirectory 4 -2 roll .growput
  355.     }
  356.    ifelse
  357.  } odef
  358.  
  359. % Define a procedure for defining aliased fonts.
  360. % We can't just copy the font (or even use the same font unchanged),
  361. % because a significant number of PostScript files assume that
  362. % the FontName of a font is the same as the font resource name or
  363. % the key in [Shared]FontDirectory; on the other hand, some Adobe files
  364. % rely on the FontName of a substituted font *not* being the same as
  365. % the requested resource name.  We address this issue heuristically:
  366. % we substitute the new name iff the font name doesn't have MM in it.
  367. /.aliasfont     % <name> <font> .aliasfont <newFont>
  368.  { .currentglobal 3 1 roll dup .gcheck .setglobal
  369.    dup length 2 add dict
  370.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  371.         % Stack: global fontname newfont newfont.
  372.         % We might be defining a global font whose FontName
  373.         % is a local string.  This is weird, but legal,
  374.         % and doesn't cause problems anywhere else.
  375.         % To avoid any possible problems, do a cvn.
  376.    2 index =string cvs (MM) search
  377.     { pop pop pop pop
  378.     }
  379.     { /FontName exch dup type /stringtype eq { cvn } if put
  380.     }
  381.    ifelse
  382.    //systemdict /definefont get exec    % Don't bind, since Level 2
  383.                     % redefines definefont
  384.    exch .setglobal
  385.  } odef     % so findfont will bind it
  386.  
  387. % Define .loadfontfile for loading a font.  If we recognize Type 1 and/or
  388. % TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this.
  389. /.loadfontfile { cvx exec } bind def
  390. /.loadfont
  391.  {      % Some buggy fonts leave extra junk on the stack,
  392.         % so we have to make a closure that records the stack depth
  393.         % in a fail-safe way.
  394.    /.loadfontfile cvx count 1 sub 2 packedarray cvx exec
  395.    count exch sub { pop } repeat
  396.  } bind def
  397.  
  398. % Find an alternate font to substitute for an unknown one.
  399. % We go to some trouble to parse the font name and extract
  400. % properties from it.  Later entries take priority over earlier.
  401. /.substitutefaces [
  402.     % Guess at suitable substitutions for random unknown fonts.
  403.   [(Grot) /Times]
  404.   [(Roman) /Times]
  405.   [(Book) /NewCenturySchlbk]
  406.     % If the family name appears in the font name,
  407.     % use a font from that family.
  408.   [(Arial) /Helvetica]
  409.   [(Avant) /AvantGarde]
  410.   [(Bookman) /Bookman]
  411.   [(Century) /NewCenturySchlbk]
  412.   [(Cour) /Courier]
  413.   [(Geneva) /Helvetica]
  414.   [(Helv) /Helvetica]
  415.   [(NewYork) /Times]
  416.   [(Pala) /Palatino]
  417.   [(Sans) /Helvetica]
  418.   [(Schlbk) /NewCenturySchlbk]
  419.   [(Serif) /Times]
  420.   [(Swiss) /Helvetica]
  421.   [(Times) /Times]
  422.     % Substitute for Adobe Multiple Master fonts.
  423.   [(Myriad) /Times]
  424.   [(Minion) /Helvetica]
  425.     % Condensed or narrow fonts map to the only narrow family we have.
  426.   [(Cond) /Helvetica-Narrow]
  427.   [(Narrow) /Helvetica-Narrow]
  428.     % If the font wants to be monospace, use Courier.
  429.   [(Monospace) /Courier]
  430.   [(Typewriter) /Courier]
  431. ] readonly def
  432. /.substituteproperties [
  433.   [(It) 1] [(Oblique) 1]
  434.   [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2]
  435. ] readonly def
  436. /.substitutefamilies mark
  437.   /AvantGarde
  438.     {/AvantGarde-Book /AvantGarde-BookOblique
  439.      /AvantGarde-Demi /AvantGarde-DemiOblique}
  440.   /Bookman
  441.     {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic}
  442.   /Courier
  443.     {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique}
  444.   /Helvetica
  445.     {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
  446.   /Helvetica-Narrow
  447.     {/Helvetica-Narrow /Helvetica-Narrow-Oblique
  448.      /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique}
  449.   /NewCenturySchlbk
  450.     {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic
  451.      /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic}
  452.   /Palatino
  453.     {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic}
  454.   /Times
  455.     {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic}
  456. .dicttomark readonly def
  457. /.substitutefont        % <fontname> .substitutefont <altname>
  458.  {  % Look for properties and/or a face name in the font name.
  459.     % If we find any, use Helvetica as the base font;
  460.     % otherwise, use the default font.
  461.     % Note that the "substituted" font name may be the same as
  462.     % the requested one; the caller must check this.
  463.    dup length string cvs
  464.     {defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
  465.    exch 0 exch  % stack: fontname facelist properties fontname
  466.     % Look for a face name.
  467.    .substitutefaces
  468.     { 2 copy 0 get search
  469.        { pop pop pop 1 get .substitutefamilies exch get
  470.      4 -1 roll pop 3 1 roll
  471.        }
  472.        { pop pop
  473.        }
  474.       ifelse
  475.     }
  476.    forall
  477.    .substituteproperties
  478.     { 2 copy 0 get search
  479.        { pop pop pop 1 get 3 -1 roll or exch }
  480.        { pop pop }
  481.       ifelse
  482.     }
  483.    forall pop get
  484.     % If SUBSTFONT is defined, use it.
  485.    /SUBSTFONT where
  486.     { pop pop /SUBSTFONT load cvn }
  487.     { exec }
  488.    ifelse
  489.     % Only accept fonts known in the Fontmap.
  490.    Fontmap 1 index known not { pop defaultfontname } if
  491.  } bind def
  492.  
  493. % If requested, make (and recognize) fake entries in FontDirectory for fonts
  494. % present in Fontmap but not actually loaded.  Thanks to Ray Johnston for
  495. % the idea behind this code.
  496. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if
  497.  
  498. % We use the presence or absence of the FontMatrix key to indicate whether
  499. % a font is real or fake.
  500.  
  501. /definefont     % <name> <font> definefont <font>
  502.  { dup /FontMatrix known not { /FontName get findfont } if
  503.    //definefont
  504.  } bind odef
  505.  
  506. /scalefont      % <font> <scale> scalefont <font>
  507.  { exch dup /FontMatrix known not { /FontName get findfont } if
  508.    exch //scalefont
  509.  } bind odef
  510.  
  511. /makefont       % <font> <matrix> makefont <font>
  512.  { exch dup /FontMatrix known not { /FontName get findfont } if
  513.    exch //makefont
  514.  } bind def
  515.  
  516. /setfont        % <font> setfont -
  517.  { dup /FontMatrix known not { /FontName get findfont } if
  518.    //setfont
  519.  } bind odef
  520.  
  521. %END FAKEFONTS
  522.  
  523. % Define findfont so it tries to load a font if it's not found.
  524. % The Red Book requires that findfont be a procedure, not an operator.
  525. /findfont
  526.  { mark exch
  527.     { .dofindfont
  528.     } stopped
  529.     { counttomark 1 sub { pop } repeat exch pop stop
  530.     }
  531.     {   % Define any needed aliases.
  532.       counttomark 1 sub { .aliasfont } repeat
  533.       exch pop
  534.     }
  535.    ifelse
  536.  } bind def
  537. % Check whether the font name we are about to look for is already on the list
  538. % of aliases we're accumulating; if so, cause an error.
  539. /.checkalias        % -mark- <alias1> ... <name> .checkalias <<same>>
  540.  { counttomark 1 sub -1 1
  541.     { index 1 index eq
  542.        { pop QUIET not
  543.       { (Unable to substitute for font.\n) print flush
  544.       } if
  545.      /findfont cvx /invalidfont signalerror
  546.        }
  547.       if
  548.     }
  549.    for
  550.  } bind def
  551. % Get a (non-fake) font if present in a FontDirectory.
  552. /.fontknownget      % <fontdir> <fontname> .fontknownget <font> true
  553.             % <fontdir> <fontname> .fontknownget false
  554.  { .knownget
  555.     { FAKEFONTS
  556.        { dup /FontMatrix known { true } { pop false } ifelse }
  557.        { true }
  558.       ifelse
  559.     }
  560.     { false
  561.     }
  562.    ifelse
  563.  } bind def
  564. % Do the work of findfont, including substitution, defaulting, and
  565. % scanning of FONTPATH.
  566. /.dofindfont        % <fontname> .dofindfont <font>
  567.  {  { .tryfindfont { exit } if
  568.             % We didn't find the font.  If we haven't scanned
  569.             % all the directories in FONTPATH, scan the next one now,
  570.             % and look for the font again.
  571.       null 0 1 FONTPATH length 1 sub
  572.        { FONTPATH 1 index get null ne { exch pop exit } if pop
  573.        }
  574.       for dup null ne
  575.        { dup 0 eq { .scanfontbegin } if
  576.      FONTPATH 1 index get .scanfontdir
  577.      FONTPATH exch null put
  578.             % Start over with an empty alias list.
  579.      counttomark 1 sub { pop } repeat
  580.      .dofindfont exit
  581.        }
  582.       if pop
  583.             % No luck, substitute for the font.
  584.       dup defaultfontname eq
  585.        { QUIET not
  586.       { (Unable to load default font ) print
  587.         dup =only (!  Giving up.\n) print flush
  588.       }
  589.      if /findfont cvx /invalidfont signalerror
  590.        }
  591.       if dup .substitutefont
  592.       2 copy eq { pop defaultfontname } if
  593.       .checkalias
  594.       QUIET not
  595.        { (Substituting font ) print dup =only ( for ) print
  596.      1 index =only (.\n) print flush
  597.        }
  598.       if
  599.     }
  600.    loop
  601.  } bind def
  602. % Try to find a font using only the present contents of Fontmap.
  603. /.tryfindfont       % <fontname> .tryfindfont <font> true
  604.             % <fontname> .tryfindfont false
  605.  { FontDirectory 1 index .fontknownget
  606.     {           % Already loaded
  607.       exch pop true
  608.     }
  609.     { dup Fontmap exch .knownget not
  610.        {        % Unknown font name
  611.      false
  612.        }
  613.  
  614.        {        % Try each element of the Fontmap in turn.
  615.     false exch  % (in case we exhaust the list)
  616.      { exch pop
  617.        dup type /nametype eq
  618.         {           % Font alias
  619.           .checkalias .tryfindfont exit
  620.         }
  621.         { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and
  622.            {        % Font with a procedural definition
  623.          exec       % The procedure will load the font.
  624.                 % Check to make sure this really happened.
  625.          FontDirectory 1 index .knownget
  626.           { exch pop true exit }
  627.          if
  628.            }
  629.            {        % Font file name
  630.          .loadfontloop { true exit } if
  631.            }
  632.           ifelse
  633.         }
  634.        ifelse false
  635.      }
  636.     forall
  637.        }
  638.       ifelse
  639.     }
  640.    ifelse
  641.  } bind def
  642. % Attempt to load a font from a file.
  643. /.loadfontloop      % <filename> .loadfontloop <font> true
  644.             % <filename> .loadfontloop false
  645.  {          % See above regarding the use of 'loop'.
  646.  
  647.     {
  648.             % Can we open the file?
  649.     findlibfile not
  650.      { QUIET not
  651.         { (Can't find \(or can't open\) font file ) print dup print
  652.           (.\n) print flush
  653.         }
  654.        if pop false exit
  655.      }
  656.     if
  657.  
  658.             % Stack: fontname fontfilename fontfile
  659.     DISKFONTS
  660.      { .currentglobal true .setglobal
  661.        2 index (r) file
  662.        FontFileDirectory exch 5 index exch .growput
  663.        .setglobal
  664.      }
  665.     if
  666.     QUIET not
  667.      { (Loading ) print 2 index =only
  668.        ( font from ) print 1 index print (... ) print flush
  669.      }
  670.     if
  671.     % If LOCALFONTS isn't set, load the font into local or global
  672.     % VM according to FontType; if LOCALFONTS is set, load the font
  673.     % into the current VM, which is what Adobe printers (but not
  674.     % DPS or CPSI) do.
  675.     LOCALFONTS { false } { /setglobal where } ifelse
  676.      { pop /FontType .findfontvalue { 1 eq } { false } ifelse
  677.         % .setglobal, like setglobal, aliases FontDirectory to
  678.         % GlobalFontDirectory if appropriate.  However, we mustn't
  679.         % allow the current version of .setglobal to be bound in,
  680.         % because it's different depending on language level.
  681.        .currentglobal exch /.setglobal load exec
  682.         % Remove the fake definition, if any.
  683.        FontDirectory 3 index .undef
  684.        1 index (r) file .loadfont FontDirectory exch
  685.        /.setglobal load exec
  686.      }
  687.      { .loadfont FontDirectory
  688.      }
  689.     ifelse
  690.         % Stack: fontname fontfilename fontdirectory
  691.     QUIET not
  692.      { //systemdict /level2dict known
  693.         { .currentglobal false .setglobal vmstatus
  694.           true .setglobal vmstatus 3 -1 roll pop
  695.           6 -1 roll .setglobal 5
  696.         }
  697.         { vmstatus 3
  698.         }
  699.        ifelse { =only ( ) print } repeat
  700.        (done.\n) print flush
  701.      } if
  702.  
  703.         % Check to make sure the font was actually loaded.
  704.     dup 3 index .fontknownget
  705.      { 4 1 roll pop pop pop true exit } if
  706.  
  707.         % Maybe the file had a different FontName.
  708.         % See if we can get a FontName from the file, and if so,
  709.         % whether a font by that name exists now.
  710.     exch (r) file .findfontname
  711.      { 2 copy .fontknownget
  712.         {   % Yes.  Stack: origfontname fontdirectory filefontname fontdict
  713.           3 -1 roll pop exch
  714.           QUIET
  715.            { pop
  716.            }
  717.            { (Using ) print =only
  718.              ( font for ) print 1 index =only
  719.              (.\n) print flush
  720.            }
  721.           ifelse true exit
  722.         }
  723.        if pop
  724.      }
  725.     if pop
  726.  
  727.         % The font definitely did not load correctly.
  728.     QUIET not
  729.      { (Loading ) print dup =only
  730.        ( font failed.\n) print flush
  731.      } if
  732.     false exit
  733.  
  734.     } loop      % end of loop
  735.  
  736.  } bind def
  737.  
  738. % Define a procedure to load all known fonts.
  739. % This isn't likely to be very useful.
  740. /loadallfonts
  741.  { Fontmap { pop findfont pop } forall
  742.  } bind def
  743.  
  744. % If requested, load all the fonts defined in the Fontmap into FontDirectory
  745. % as "fake" fonts i.e., font dicts with only FontName defined.
  746. % We must ensure that this happens in both global and local directories.
  747. /.definefakefonts
  748.     {
  749.     }
  750.     { (gs_fonts FAKEFONTS) VMDEBUG
  751.       2
  752.     { .currentglobal not .setglobal
  753.       Fontmap
  754.        { pop dup type /stringtype eq { cvn } if
  755.          FontDirectory 1 index known not
  756.           { 1 dict dup /FontName 3 index put       
  757.             FontDirectory 3 1 roll put
  758.           }
  759.          if
  760.        }
  761.       forall
  762.        }
  763.       repeat
  764.     }
  765. FAKEFONTS { exch } if pop def       % don't bind, .current/setglobal get redefined
  766.  
  767. % Install initial fonts from Fontmap.
  768. /.loadinitialfonts
  769.  { NOFONTMAP not
  770.     { /FONTMAP where
  771.       { pop [ FONTMAP .pathlist ]
  772.          { dup VMDEBUG findlibfile
  773.         { exch pop .loadFontmap }
  774.         { /undefinedfilename signalerror }
  775.            ifelse
  776.          }
  777.       }
  778.       { LIBPATH
  779.          { defaultfontmap 2 copy .filenamedirseparator
  780.            exch concatstrings concatstrings dup VMDEBUG
  781.            (r) { file } .internalstopped
  782.         { pop pop } { .loadFontmap } ifelse
  783.          }
  784.       }
  785.      ifelse forall
  786.     }
  787.    if
  788.    .definefakefonts
  789.  } def          % don't bind, .current/setglobal get redefined
  790.