home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / Vyzkuste / gs / gs650w32.exe / gs6.50 / lib / gs_fonts.ps < prev    next >
Text File  |  2000-12-05  |  33KB  |  1,044 lines

  1. %    Copyright (C) 1990, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of AFPL Ghostscript.
  3. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  4. % distributor accepts any responsibility for the consequences of using it, or
  5. % for whether it serves any particular purpose or works at all, unless he or
  6. % she says so in writing.  Refer to the Aladdin Free Public License (the
  7. % "License") for full details.
  8. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. % in a plain ASCII text file named PUBLIC.  The License grants you the right
  10. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. % conditions described in the License.  Among other things, the License
  12. % requires that the copyright notice and this notice be preserved on all
  13. % copies.
  14.  
  15. % $Id: gs_fonts.ps,v 1.9 2000/09/19 18:29:11 lpd Exp $
  16. % Font initialization and management code.
  17.  
  18. % Define the default font.
  19. /defaultfontname /Courier def
  20.  
  21. % Define the name of the font map file.
  22. /defaultfontmap (Fontmap) def
  23.  
  24. % ------ End of editable parameters ------ %
  25.  
  26. % Define the UniqueIDs and organization XUID assigned to Aladdin.
  27. % UniqueIDs 5,066,501 - 5,066,580 are assigned as follows:
  28. %   01 and 02 for shareware Cyrillic
  29. %   33 through 67 for Type 1 versions of the Hershey fonts
  30. % UniqueIDs 5,115,501 - 5,115,600 are currently unassigned.
  31. /AladdinEnterprisesXUID 107 def
  32.  
  33. % If SUBSTFONT is defined, make it the default font.
  34. /SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if
  35.  
  36. % Define a reliable way of accessing FontDirectory in systemdict.
  37. /.FontDirectory
  38. { /FontDirectory .systemvar
  39. } .bind odef
  40.  
  41. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  42. % (This is intended primarily for machines with very small memories.)
  43. % In this case, we define another dictionary, parallel to FontDirectory,
  44. % that retains an open file for every font loaded.
  45. /FontFileDirectory 10 dict def
  46.  
  47. % Define a temporary string for local use, since using =string
  48. % interferes with some PostScript programs.
  49. /.fonttempstring 128 string def
  50.  
  51. % Split up a search path into individual directories or files.
  52. /.pathlist        % <path> .pathlist <dir1|file1> ...
  53.  {  { dup length 0 eq { pop exit } if
  54.       .filenamelistseparator search not { exit } if
  55.       exch pop exch
  56.     }
  57.    loop
  58.  } bind def
  59.  
  60. % Load a font name -> font file name map.
  61. userdict /Fontmap .FontDirectory maxlength dict put
  62. /.loadFontmap {        % <file> .loadFontmap -
  63.         % We would like to simply execute .definefontmap as we read,
  64.         % but we have to maintain backward compatibility with an older
  65.         % specification that makes later entries override earlier
  66.         % ones within the same file.
  67.    50 dict exch .readFontmap
  68.     { .definefontmap } forall
  69. } bind def
  70. /.readFontmap {        % <dict> <file> .readFontmap <dict>
  71.     { dup token not { closefile exit } if
  72.         % stack: dict file fontname
  73.       % This is a hack to get around the absurd habit of MS-DOS editors
  74.       % of adding an EOF character at the end of the file.
  75.       dup (\032) eq { pop closefile exit } if
  76.       1 index token not
  77.        { (Fontmap entry for ) print dup =only
  78.      ( has no associated file or alias name!  Giving up.) = flush
  79.      {.readFontmap} 0 get 1 .quit
  80.        } if
  81.       dup type dup /stringtype eq exch /nametype eq or not
  82.        { (Fontmap entry for ) print 1 index =only
  83.      ( has an invalid file or alias name!  Giving up.) = flush
  84.      {.readFontmap} 0 get 1 .quit
  85.        } if
  86.         % stack: dict file fontname filename|aliasname
  87.       1 index type /stringtype eq
  88.       1 index type /nametype eq and 1 index xcheck and
  89.       1 index /run eq 2 index /.runlibfile eq or and {
  90.         % This is an inclusion entry.
  91.     pop findlibfile { exch pop } { file } ifelse
  92.     2 index exch .readFontmap pop
  93.       } {
  94.         % This is a real entry.
  95.         % Read and pop tokens until a semicolon.
  96.        { 2 index token not
  97.       { (Fontmap entry for ) print 1 index =only
  98.         ( ends prematurely!  Giving up.) = flush
  99.         {.loadFontmap} 0 get 1 .quit
  100.       } if
  101.      dup /; eq { pop 3 index 3 1 roll .growput exit } if
  102.      pop
  103.        } loop
  104.       } ifelse
  105.     } loop
  106. } bind def
  107. % Add an entry in Fontmap.  We redefine this if the Level 2
  108. % resource machinery is loaded.
  109. /.definefontmap            % <fontname> <file|alias> .definefontmap -
  110.  {        % Since Fontmap is global, make sure the values are storable.
  111.    .currentglobal 3 1 roll true .setglobal
  112.    dup type /stringtype eq
  113.     { dup .gcheck not { dup length string copy } if
  114.     }
  115.    if
  116.    Fontmap 3 -1 roll 2 copy .knownget
  117.     {        % Add an element to the end of the existing value,
  118.         % unless it's the same as the current last element.
  119.       mark exch aload pop counttomark 4 add -1 roll
  120.       2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse
  121.     }
  122.     {        % Make a new entry.
  123.       mark 4 -1 roll ] readonly .growput
  124.     }
  125.    ifelse .setglobal
  126.  } bind def
  127.  
  128. % Parse a font file just enough to find the FontName or FontType.
  129. /.findfontvalue {    % <file> <key> .findfontvalue <value> true
  130.             % <file> <key> .findfontvalue false
  131.             % Closes the file in either case.
  132.   exch dup read not { -1 } if
  133.   2 copy unread 16#80 eq {
  134.     dup (xxxxxx) readstring pop pop        % skip .PFB header
  135.   } if
  136.   {        % Stack: key file
  137.         % Protect ourselves against syntax errors here.
  138.     dup { token } stopped { pop false exit } if
  139.     not { false exit } if        % end of file
  140.     dup /eexec eq { pop false exit } if        % reached eexec section
  141.     dup /Subrs eq { pop false exit } if        % Subrs without eexec
  142.     dup /CharStrings eq { pop false exit } if    % CharStrings without eexec
  143.     dup 3 index eq
  144.      { xcheck not { dup token exit } if }    % found key
  145.      { pop }
  146.     ifelse
  147.   } loop
  148.         % Stack: key file value true   (or)
  149.         % Stack: key file false
  150.   dup { 4 } { 3 } ifelse -2 roll closefile pop
  151. } bind def
  152. /.findfontname
  153.  { /FontName .findfontvalue
  154.  } bind def
  155.  
  156. % If there is no FONTPATH, try to get one from the environment.
  157. NOFONTPATH { /FONTPATH () def } if
  158. /FONTPATH where
  159.  { pop }
  160.  { /FONTPATH (GS_FONTPATH) getenv not { () } if def }
  161. ifelse
  162. FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
  163. /FONTPATH [ FONTPATH .pathlist ] def
  164.  
  165. % Scan directories looking for plausible fonts.  "Plausible" means that
  166. % the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001
  167. % followed by four arbitrary bytes and then either of these strings.
  168. % To speed up the search, we skip any file whose name appears in
  169. % the Fontmap (with any extension and upper/lower case variation) already,
  170. % and any file whose extension definitely indicates it is not a font.
  171. %
  172. % NOTE: The current implementation of this procedure is somewhat Unix/DOS-
  173. % specific.  It assumes that '/' and '\' are directory separators, and that
  174. % the part of a file name following the last '.' is the extension.
  175. %
  176. /.lowerstring        % <string> .lowerstring <lowerstring>
  177.  { 0 1 2 index length 1 sub
  178.     { 2 copy get dup 65 ge exch 90 le and
  179.        { 2 copy 2 copy get 32 add put }
  180.      if pop
  181.     }
  182.    for
  183.  } bind def
  184. /.splitfilename {    % <dir.../base.extn> .basename <base> <extn>
  185.         % Make the file name read-only to detect aliasing bugs.
  186.         % We really don't like doing this, but we've had one
  187.         % such bug already.
  188.   readonly {
  189.     (/) search { true } { (\\) search } ifelse { pop pop } { exit } ifelse
  190.   } loop
  191.   dup { (.) search { pop pop } { exit } ifelse } loop
  192.   2 copy eq {
  193.     pop ()
  194.   } {
  195.     exch dup length 2 index length 1 add sub 0 exch getinterval exch
  196.   } ifelse
  197. } bind def
  198. /.scanfontdict 1 dict def        % establish a binding
  199. /.scanfontbegin
  200.  {    % Construct the table of all file names already in Fontmap.
  201.    currentglobal true setglobal
  202.    .scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength
  203.    Fontmap
  204.     { exch pop
  205.        { dup type /stringtype eq
  206.       { .splitfilename pop .fonttempstring copy .lowerstring cvn
  207.         .scanfontdict exch true put
  208.       }
  209.       { pop
  210.       }
  211.      ifelse
  212.        }
  213.       forall
  214.     }
  215.    forall
  216.    setglobal
  217.  } bind def
  218. /.scanfontskip mark
  219.         % Strings are converted to names anyway, so....
  220.   /afm true
  221.   /bat true
  222.   /c true
  223.   /cmd true
  224.   /com true
  225.   /dir true
  226.   /dll true
  227.   /doc true
  228.   /drv true
  229.   /exe true
  230.   /fon true
  231.   /fot true
  232.   /h true
  233.   /o true
  234.   /obj true
  235.   /pfm true
  236.   /pss true        % Adobe Multiple Master font instances
  237.   /txt true
  238. .dicttomark def
  239. /.scan1fontstring 128 string def
  240. % %%BeginFont: is not per Adobe documentation, but a few fonts have it.
  241. /.scanfontheaders [(%!PS-Adobe*) (%!FontType*) (%%BeginFont:*)] def
  242. 0 .scanfontheaders { length max } forall 6 add    % extra for PFB header
  243. /.scan1fontfirst exch string def
  244. /.scanfontdir        % <dirname> .scanfontdir -
  245.  { currentglobal exch true setglobal
  246.    QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
  247.    (*) 2 copy .filenamedirseparator
  248.    dup (\\) eq { pop (\\\\) } if    % double \ for pattern match
  249.    exch concatstrings concatstrings
  250.    0 0 0 4 -1 roll    % found scanned files
  251.     {        % stack: <fontcount> <scancount> <filecount> <filename>
  252.       exch 1 add exch                   % increment filecount
  253.       dup .splitfilename .fonttempstring copy .lowerstring
  254.         % stack: <fontcount> <scancount> <filecount+1> <filename>
  255.         %    <BASE> <ext>
  256.       .scanfontskip exch known exch .scanfontdict exch known or
  257.        { pop
  258.         % stack: <fontcount> <scancount> <filecount+1>
  259.        }
  260.        { 3 -1 roll 1 add 3 1 roll
  261.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  262.      dup (r) { file } .internalstopped
  263.       { pop pop null ()
  264.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  265.         %    null ()
  266.       }
  267.       {
  268.         % On some platforms, the file operator will open directories,
  269.         % but an error will occur if we try to read from one.
  270.         % Handle this possibility here.
  271.         dup .scan1fontfirst { readstring } .internalstopped
  272.          { pop pop () }
  273.          { pop }
  274.         ifelse
  275.         % stack: <fontcount> <scancount+1> <filecount+1>
  276.         %    <filename> <file> <header>
  277.       }
  278.      ifelse
  279.         % Check for PFB file header.
  280.      dup (\200\001????*) .stringmatch
  281.       { dup length 6 sub 6 exch getinterval }
  282.      if
  283.         % Check for font file headers.
  284.      false .scanfontheaders
  285.       { 2 index exch .stringmatch or
  286.       }
  287.      forall exch pop
  288.       {    % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  289.         %    <file>
  290.         dup 0 setfileposition .findfontname
  291.          { dup Fontmap exch known
  292.         { pop pop
  293.         }
  294.         { exch copystring exch
  295.           DEBUG { ( ) print dup =only flush } if
  296.           1 index .definefontmap
  297.           .splitfilename pop true .scanfontdict 3 1 roll .growput
  298.             % Increment fontcount.
  299.           3 -1 roll 1 add 3 1 roll
  300.         }
  301.            ifelse
  302.          }
  303.          { pop
  304.          }
  305.         ifelse
  306.       }
  307.         % .findfontname will have done a closefile in the above case.
  308.       { dup null eq { pop } { closefile } ifelse pop
  309.       }
  310.      ifelse
  311.        }
  312.       ifelse
  313.     }
  314.    .scan1fontstring filenameforall
  315.    QUIET
  316.     { pop pop pop }
  317.     { ( ) print =only ( files, ) print =only ( scanned, ) print
  318.       =only ( new fonts.) = flush
  319.     }
  320.    ifelse
  321.    setglobal
  322.  } bind def
  323.  
  324. %END FONTPATH
  325.  
  326. % Create the dictionary that registers the .buildfont procedure (called by
  327. % definefont) for each FontType.
  328. /buildfontdict 20 dict def
  329.  
  330. % Register Type 3 fonts, which are always supported, for definefont.
  331. buildfontdict 3 /.buildfont3 cvx put
  332.  
  333. % Register Type 0 fonts if they are supported.  Strictly speaking,
  334. % we should do this in its own file (gs_type0.ps), but since this is
  335. % the only thing that would be in that file, it's simpler to put it here.
  336. /.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if
  337.  
  338. % Define definefont.  This is a procedure built on a set of operators
  339. % that do all the error checking and key insertion.
  340. /.growfontdict
  341.  {    % Grow the font dictionary, if necessary, to ensure room for an
  342.     % added entry, making sure there is at least one slot left for FID.
  343.    dup maxlength 1 index length sub 2 lt
  344.     { dup dup wcheck
  345.        { .growdict }
  346.        { .growdictlength dict .copydict }
  347.       ifelse
  348.     }
  349.     { dup wcheck not { dup maxlength dict .copydict } if
  350.     }
  351.    ifelse
  352.  } bind def 
  353. /.completefont {
  354.   {        % Check for disabled platform fonts.
  355.       NOPLATFONTS
  356.        {    % Make sure we leave room for FID.
  357.      .growfontdict dup /ExactSize 0 put
  358.        }
  359.        {    % Hack: if the Encoding looks like it might be the
  360.         % Symbol or Dingbats encoding, load those now (for the
  361.         % benefit of platform font matching) just in case
  362.         % the font didn't actually reference them.
  363.         % Note that some types of font don't have an Encoding.
  364.      dup /Encoding .knownget {
  365.        dup length 65 ge {
  366.          64 get
  367.          dup /congruent eq { SymbolEncoding pop } if
  368.          /a9 eq { DingbatsEncoding pop } if
  369.        } {
  370.          pop
  371.        } ifelse
  372.      } if
  373.        }
  374.       ifelse
  375.       true exch
  376.         % If this is a CIDFont, CIDFontType takes precedence
  377.         % over FontType.
  378.       dup /CIDFontType known {
  379.     /.buildcidfont where {
  380.       pop exch not exch    % true => false
  381.     } if
  382.       } if
  383.       exch {
  384.     dup /FontType get //buildfontdict exch get exec
  385.       } {
  386.     .buildcidfont
  387.       } ifelse
  388.  
  389.       DISKFONTS
  390.        { FontFileDirectory 2 index known
  391.       { dup /FontFile FontFileDirectory 4 index get .growput
  392.       }
  393.      if
  394.        }
  395.       if
  396.       readonly        % stack: name fontdict
  397.   } stopped { /invalidfont signalerror } if
  398. } bind odef
  399. /definefont
  400.  { .completefont
  401.         % If the current allocation mode is global, also enter
  402.         % the font in LocalFontDirectory.
  403.    .currentglobal
  404.     { //systemdict /LocalFontDirectory .knownget
  405.        { 2 index 2 index .growput }
  406.       if
  407.     }
  408.    if
  409.    dup .FontDirectory 4 -2 roll .growput
  410.         % If the font originated as a resource, register it.
  411.    currentfile .currentresourcefile eq { dup .registerfont } if
  412.  } odef
  413.  
  414. % Define a procedure for defining aliased fonts.
  415. % We use this only for explicitly aliased fonts, not substituted fonts:
  416. % we think this matches the observed behavior of Adobe interpreters.
  417. /.aliasfont        % <name> <font> .aliasfont <newFont>
  418.  { .currentglobal 3 1 roll dup .gcheck .setglobal
  419.    dup length 2 add dict
  420.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  421.         % Stack: global fontname newfont newfont.
  422.         % We might be defining a global font whose FontName
  423.         % is a local string.  This is weird, but legal,
  424.         % and doesn't cause problems anywhere else:
  425.         % to avoid any possible problems in this case, do a cvn.
  426.         % We might also be defining (as an alias) a global font
  427.         % whose FontName is a local non-string, if someone passed a
  428.         % garbage value to findfont.  In this case, just don't
  429.         % call definefont at all.
  430.    2 index dup type /stringtype eq exch .gcheck or 1 index .gcheck not or
  431.     { /FontName 3 index dup type /stringtype eq { cvn } if put
  432.         % Don't bind in definefont, since Level 2 redefines it.
  433.       /definefont .systemvar exec
  434.     }
  435.     { .completefont pop exch pop
  436.     }
  437.    ifelse exch .setglobal
  438.  } odef        % so findfont will bind it
  439.  
  440. % Define .loadfontfile for loading a font.  If we recognize Type 1 and/or
  441. % TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this.
  442. /.loadfontfile {
  443.         % According to Ed Taft, Adobe interpreters push userdict
  444.         % before loading a font, and pop it afterwards.
  445.   userdict begin
  446.     cvx exec
  447.   end
  448. } bind def
  449. /.loadfont
  450.  {        % Some buggy fonts leave extra junk on the stack,
  451.         % so we have to make a closure that records the stack depth
  452.         % in a fail-safe way.
  453.    {{.loadfontfile} .execasresource} count 1 sub 2 .execn
  454.    count exch sub { pop } repeat
  455.  } bind def
  456.  
  457. % Find an alternate font to substitute for an unknown one.
  458. % We go to some trouble to parse the font name and extract
  459. % properties from it.  Later entries take priority over earlier.
  460. /.substitutefaces [
  461.     % Guess at suitable substitutions for random unknown fonts.
  462.   [(Chancery) /ZapfChancery-MediumItalic 0]
  463.   [(Grot) /Times 0]
  464.   [(Roman) /Times 0]
  465.   [(Book) /NewCenturySchlbk 0]
  466.     % If the family name appears in the font name,
  467.     % use a font from that family.
  468.   [(Arial) /Helvetica 0]
  469.   [(Avant) /AvantGarde 0]
  470.   [(Bookman) /Bookman 0]
  471.   [(Century) /NewCenturySchlbk 0]
  472.   [(Cour) /Courier 0]
  473.   [(Frut) /Helvetica 0]
  474.   [(Garamond) /Palatino 0]
  475.   [(Geneva) /Helvetica 0]
  476.   [(Helv) /Helvetica 0]
  477.   [(NewYork) /Bookman 0]
  478.   [(Pala) /Palatino 0]
  479.   [(Schlbk) /NewCenturySchlbk 0]
  480.   [(Swiss) /Helvetica 0]
  481.   [(Symbol) /Symbol 0]
  482.   [(Times) /Times 0]
  483.   [(Univers) /Helvetica 0]
  484.     % Substitute for Adobe Multiple Master fonts.
  485.   [(Minion) /Times 0]
  486.   [(Myriad) /Helvetica 0]
  487.     % If the font wants to be monospace, use Courier.
  488.   [(Monospace) /Courier 0]
  489.   [(Typewriter) /Courier 0]
  490.     % Define substitutes for the other Adobe PostScript 3 fonts.
  491.     % For some of them, the substitution is pretty bad!
  492.   [(Albertus) /NewCenturySchlbk 0]
  493.   [(AntiqueOlive) /Helvetica 0]
  494.   [(Bodoni) /Palatino 0]
  495.   [(Chicago) /Helvetica 2]
  496.   [(Clarendon) /Bookman 0]
  497.   [(Cooper) /NewCenturySchlbk 0]
  498.   [(Copperplate) /AvantGarde 0]    % inappropriate, small-cap font
  499.   [(Coronet) /ZapfChancery-MediumItalic 0]
  500.   [(Eurostile) /AvantGarde 0]    % inappropriate
  501.   [(Geneva) /Courier 2]        % should be fixed-pitch sans demi
  502.   [(GillSans) /AvantGarde 2]
  503.   [(GillSans-Light) /AvantGarde 0]
  504.   [(Goudy) /Palatino 0]
  505.   [(Hoefler) /NewCenturySchlbk 0]
  506.   [(Joanna) /Times 0]
  507.   [(LetterGothic) /Courier 0]    % should be fixed-pitch sans
  508.   [(LubalinGraph-Book) /Bookman 2]
  509.   [(LubalinGraph-Demi) /Bookman 0]
  510.   [(Marigold) /ZapfChancery-MediumItalic 0]
  511.   [(MonaLisa-Recut) /Palatino 0]    % inappropriate
  512.   [(Monaco) /Courier 2]        % should be fixed-pitch sans demi
  513.   [(Optima) /Helvetica 0]
  514.   [(Oxford) /ZapfChancery-MediumItalic 0]
  515.   [(Tekton) /AvantGarde 0]
  516.   [(Univers) /AvantGarde 0]
  517. ] readonly def
  518. /.substituteproperties [
  519.   [(It) 9] [(Oblique) 1]
  520.   [(Black) 2] [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2]
  521.   [(Cn) 4] [(Cond) 4] [(Narrow) 4] [(Pkg) 4]
  522.   [(Serif) 8] [(Sans) -8]
  523. ] readonly def
  524. /.fontnameproperties {        % <int> <string|name> .fontnameproperties
  525.                 %   <int'>
  526.   .fontnamestring
  527.   .substituteproperties {
  528.     2 copy 0 get search {
  529.       pop pop pop dup length 1 sub 1 exch getinterval 3 -1 roll exch {
  530.     dup 0 ge { or } { neg not and } ifelse
  531.       } forall exch
  532.     } {
  533.       pop pop
  534.     } ifelse
  535.   } forall pop
  536. } bind def
  537. /.substitutefamilies mark
  538.   /AvantGarde
  539.     {/AvantGarde-Book /AvantGarde-BookOblique
  540.      /AvantGarde-Demi /AvantGarde-DemiOblique}
  541.   /Bookman
  542.     {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic}
  543.   /Courier
  544.     {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique}
  545.   /Helvetica
  546.     {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique
  547.      /Helvetica-Narrow /Helvetica-Narrow-Oblique
  548.      /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique}
  549.   /NewCenturySchlbk
  550.     {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic
  551.      /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic}
  552.   /Palatino
  553.     {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic}
  554.   /Symbol
  555.     {/Symbol /Symbol /Symbol /Symbol}
  556.   /Times
  557.     {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic}
  558.   /ZapfChancery-MediumItalic
  559.     {/ZapfChancery-MediumItalic}
  560. .dicttomark readonly def
  561. /.nametostring {        % <name> .nametostring <string>
  562.                 % <other> .nametostring <other>
  563.   dup type /nametype eq { .namestring } if
  564. } bind def
  565. /.fontnamestring {        % <fontname> .fontnamestring <string|name>
  566.   dup type dup /nametype eq {
  567.     pop .namestring
  568.   } {
  569.     /stringtype ne { pop () } if
  570.   } ifelse
  571. } bind def
  572. /.substitutefontname {        % <fontname> <properties> .substitutefontname
  573.                 %   <altname|null>
  574.     % Look for properties and/or a face name in the font name.
  575.     % If we find any, use Times (serif) or Helvetica (sans) as the
  576.     % base font; otherwise, use the default font.
  577.     % Note that the "substituted" font name may be the same as
  578.     % the requested one; the caller must check this.
  579.   exch .fontnamestring {
  580.     defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique
  581.     /Helvetica-Narrow /Helvetica-Narrow-Oblique
  582.     /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique
  583.     /Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic
  584.     /Helvetica-Narrow /Helvetica-Narrow-Oblique
  585.     /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique
  586.   } 3 1 roll
  587.     % Stack: facelist properties fontname
  588.     % Look for a face name.
  589.   .substitutefaces {
  590.     2 copy 0 get search {
  591.       pop pop pop
  592.     % Stack: facelist properties fontname [(pattern) family properties]
  593.       dup 2 get 4 -1 roll or 3 1 roll
  594.       1 get .substitutefamilies exch get
  595.       4 -1 roll pop 3 1 roll
  596.     } {
  597.       pop pop
  598.     } ifelse
  599.   } forall pop
  600.   1 index length mod get exec
  601. } bind def
  602. /.substitutefont {        % <fontname> .substitutefont <altname>
  603.   dup 0 exch .fontnameproperties .substitutefontname
  604.     % Only accept fonts known in the Fontmap.
  605.    Fontmap 1 index known not { pop defaultfontname } if
  606. } bind def
  607.  
  608. % If requested, make (and recognize) fake entries in FontDirectory for fonts
  609. % present in Fontmap but not actually loaded.  Thanks to Ray Johnston for
  610. % the idea behind this code.
  611. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if
  612.  
  613. % We use the presence or absence of the FontMatrix key to indicate whether
  614. % a font is real or fake.  We must pop the arguments at the very end,
  615. % so that stack protection will be effective.
  616.  
  617. /definefont {        % <name> <font> definefont <font>
  618.   dup /FontMatrix known {
  619.     //definefont
  620.   } {
  621.     2 copy /FontName get findfont //definefont exch pop exch pop
  622.   } ifelse
  623. } bind odef
  624.  
  625. /scalefont {        % <font> <scale> scalefont <font>
  626.   1 index /FontMatrix known {
  627.     //scalefont
  628.   } {
  629.     1 index /FontName get findfont 1 index //scalefont
  630.     exch pop exch pop
  631.   } ifelse
  632. } bind odef
  633.  
  634. /makefont {        % <font> <matrix> makefont <font>
  635.   1 index /FontMatrix known {
  636.     //makefont
  637.   } {
  638.     1 index /FontName get findfont 1 index //makefont
  639.     exch pop exch pop
  640.   } ifelse
  641. } bind odef
  642.  
  643. /setfont {        % <font> setfont -
  644.   dup /FontMatrix known {
  645.     //setfont
  646.   } {
  647.     dup /FontName get findfont //setfont pop
  648.   } ifelse
  649. } bind odef
  650.  
  651. %END FAKEFONTS
  652.  
  653. % Define findfont so it tries to load a font if it's not found.
  654. % The Red Book requires that findfont be a procedure, not an operator,
  655. % but it still needs to restore the stacks reliably if it fails,
  656. % so we do all the work in an operator.
  657. /.findfont {
  658.   mark 1 index
  659.   //systemdict begin .dofindfont
  660.     % Define any needed aliases.
  661.   counttomark 1 sub { .aliasfont } repeat end
  662.   exch pop exch pop
  663. } odef
  664. /findfont {
  665.   .findfont
  666. } bind def
  667. % Check whether the font name we are about to look for is already on the list
  668. % of aliases we're accumulating; if so, cause an error.
  669. /.checkalias        % -mark- <alias1> ... <name> .checkalias <<same>>
  670.  { counttomark 1 sub -1 1
  671.     { index 1 index eq
  672.        { pop QUIET not
  673.       { (Unable to substitute for font.) = flush
  674.       } if
  675.      /findfont cvx /invalidfont signalerror
  676.        }
  677.       if
  678.     }
  679.    for
  680.  } bind def
  681. % Get a (non-fake) font if present in a FontDirectory.
  682. /.fontknownget        % <fontdir> <fontname> .fontknownget <font> true
  683.             % <fontdir> <fontname> .fontknownget false
  684.  { .knownget
  685.     { FAKEFONTS
  686.        { dup /FontMatrix known { true } { pop false } ifelse }
  687.        { true }
  688.       ifelse
  689.     }
  690.     { false
  691.     }
  692.    ifelse
  693.  } bind def
  694. % This is the standard procedure for handling font substitution.
  695. % Its location is per an Adobe newsgroup posting.
  696. % It is called with the font name on the stack, standing in for findfont.
  697. /.stdsubstfont {    % mark <alias1> ... <fontname> .stdsubstfont <font>
  698.       /SUBSTFONT where {
  699.     pop QUIET not {
  700.       (Substituting for font ) print dup =only
  701.       (.) = flush
  702.     } if
  703.             % No aliasing.
  704.     cleartomark mark defaultfontname
  705.       } {
  706.     dup .substitutefont
  707.     2 copy eq { pop defaultfontname } if
  708.     .checkalias
  709.     QUIET not {
  710.       SHORTERRORS {
  711.         (%%[) print 1 index =only
  712.         ( not found, substituting ) print dup =only (]%%)
  713.       } {
  714.         (Substituting font ) print dup =only
  715.         ( for ) print 1 index =only (.)
  716.       } ifelse = flush
  717.     } if
  718.             % Remove all the accumulated aliases.
  719.     counttomark 1 add 1 roll cleartomark mark exch
  720.       } ifelse
  721.   .dofindfont
  722. } bind def
  723. $error /SubstituteFont { .stdsubstfont } put
  724. % Scan the next directory on FONTPATH.
  725. /.scannextfontdir {    % - .scannextfontdir <bool>
  726.             % If we haven't scanned all the directories in
  727.             % FONTPATH, scan the next one.
  728.   null 0 1 FONTPATH length 1 sub {
  729.     FONTPATH 1 index get null ne { exch pop exit } if pop
  730.   } for dup null ne {
  731.     dup 0 eq { .scanfontbegin } if
  732.     FONTPATH 1 index get .scanfontdir
  733.     FONTPATH exch null put true
  734.   } {
  735.     pop false
  736.   } ifelse
  737. } bind def
  738. % Do the work of findfont, including substitution, defaulting, and
  739. % scanning of FONTPATH.
  740. /.dofindfont {        % <fontname> .dofindfont <font>
  741.   .tryfindfont not {
  742.             % We didn't find the font.  If we haven't scanned
  743.             % all the directories in FONTPATH, scan the next one
  744.             % now and look for the font again.
  745.     .scannextfontdir {
  746.             % Start over with an empty alias list.
  747.       counttomark 1 sub { pop } repeat
  748.       .dofindfont
  749.     } {
  750.             % No luck.  Make sure we're not already
  751.             % looking for the default font.
  752.       dup defaultfontname eq {
  753.     QUIET not {
  754.       (Unable to load default font ) print
  755.       dup =only (!  Giving up.) = flush
  756.     } if
  757.     /findfont cvx /invalidfont signalerror
  758.       } if
  759.             % Substitute for the font.  Don't alias.
  760.       $error /SubstituteFont get exec
  761.     } ifelse
  762.   } if
  763. } bind def
  764. % Try to find a font using only the present contents of Fontmap.
  765. /.tryfindfont {        % <fontname> .tryfindfont <font> true
  766.             % <fontname> .tryfindfont false
  767.   .FontDirectory 1 index .fontknownget
  768.     {            % Already loaded
  769.       exch pop true
  770.     }
  771.     { dup Fontmap exch .knownget not
  772.        {        % Unknown font name.  Look for a file with the
  773.             % same name as the requested font.
  774.      .tryloadfont
  775.        }
  776.        {        % Try each element of the Fontmap in turn.
  777.      false exch    % (in case we exhaust the list)
  778.             % Stack: fontname false fontmaplist
  779.      { exch pop
  780.        dup type /nametype eq
  781.         {            % Font alias
  782.           .checkalias .tryfindfont exit
  783.         }
  784.         { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and
  785.            {        % Font with a procedural definition
  786.          exec        % The procedure will load the font.
  787.                 % Check to make sure this really happened.
  788.          .FontDirectory 1 index .knownget
  789.           { exch pop true exit }
  790.          if
  791.            }
  792.            {        % Font file name
  793.          .loadfontloop { true exit } if
  794.            }
  795.           ifelse
  796.         }
  797.        ifelse false
  798.      }
  799.      forall
  800.             % Stack: font true -or- fontname false
  801.      { true
  802.      }
  803.      {            % None of the Fontmap entries worked.
  804.                 % Try loading a file with the same name
  805.                 % as the requested font.
  806.        .tryloadfont
  807.      }
  808.     ifelse
  809.        }
  810.       ifelse
  811.     }
  812.    ifelse
  813.  } bind def
  814. % Attempt to load a font from a file.
  815. /.tryloadfont {        % <fontname> .tryloadfont <font> true
  816.             % <fontname> .tryloadfont false
  817.   dup .nametostring
  818.         % Hack: check for the presence of the resource machinery.
  819.   /.genericrfn where {
  820.     pop
  821.     2 copy .fonttempstring /FontResourceDir getsystemparam .genericrfn
  822.     .loadfontloop {
  823.       exch pop exch pop true
  824.     } {
  825.       dup .nametostring .loadfontloop
  826.     } ifelse
  827.   } {
  828.     .loadfontloop
  829.   } ifelse
  830. } bind def
  831. /.loadfontloop {    % <fontname> <filename> .loadfontloop
  832.             %   <font> true
  833.             % -or-
  834.             %   <fontname> false
  835.             % See above regarding the use of 'loop'.
  836.     {
  837.             % Is the font name a string?
  838.     dup type /stringtype ne
  839.      { QUIET not
  840.         { (Can't find font with non-string name: ) print dup =only (.) = flush
  841.         }
  842.        if pop false exit
  843.      }
  844.     if
  845.             % Can we open the file?
  846.     findlibfile not
  847.      { QUIET not
  848.         { (Can't find \(or can't open\) font file ) print dup print
  849.           (.) = flush
  850.         }
  851.        if pop false exit
  852.      }
  853.     if
  854.  
  855.             % Stack: fontname fontfilename fontfile
  856.     DISKFONTS
  857.      { .currentglobal true .setglobal
  858.        2 index (r) file
  859.        FontFileDirectory exch 5 index exch .growput
  860.        .setglobal
  861.      }
  862.     if
  863.     QUIET not
  864.      { (Loading ) print 2 index =only
  865.        ( font from ) print 1 index print (... ) print flush
  866.      }
  867.     if
  868.     % If LOCALFONTS isn't set, load the font into local or global
  869.     % VM according to FontType; if LOCALFONTS is set, load the font
  870.     % into the current VM, which is what Adobe printers (but not
  871.     % DPS or CPSI) do.
  872.     LOCALFONTS { false } { /setglobal where } ifelse
  873.      { pop /FontType .findfontvalue { 1 eq } { false } ifelse
  874.         % .setglobal, like setglobal, aliases FontDirectory to
  875.         % GlobalFontDirectory if appropriate.  However, we mustn't
  876.         % allow the current version of .setglobal to be bound in,
  877.         % because it's different depending on language level.
  878.        .currentglobal exch /.setglobal .systemvar exec
  879.         % Remove the fake definition, if any.
  880.        .FontDirectory 3 index .undef
  881.        1 index (r) file .loadfont .FontDirectory exch
  882.        /.setglobal .systemvar exec
  883.      }
  884.      { .loadfont .FontDirectory
  885.      }
  886.     ifelse
  887.         % Stack: fontname fontfilename fontdirectory
  888.     QUIET not
  889.      { //systemdict /level2dict known
  890.         { .currentglobal false .setglobal vmstatus
  891.           true .setglobal vmstatus 3 -1 roll pop
  892.           6 -1 roll .setglobal 5
  893.         }
  894.         { vmstatus 3
  895.         }
  896.        ifelse { =only ( ) print } repeat
  897.        (done.) = flush
  898.      } if
  899.  
  900.         % Check to make sure the font was actually loaded.
  901.     dup 3 index .fontknownget
  902.      { 4 1 roll pop pop pop true exit } if
  903.  
  904.         % Maybe the file had a different FontName.
  905.         % See if we can get a FontName from the file, and if so,
  906.         % whether a font by that name exists now.
  907.     exch (r) file .findfontname
  908.      { 2 copy .fontknownget
  909.         {    % Yes.  Stack: origfontname fontdirectory filefontname fontdict
  910.           3 -1 roll pop exch
  911.           QUIET
  912.            { pop
  913.            }
  914.            { (Using ) print =only
  915.              ( font for ) print 1 index =only
  916.              (.) = flush
  917.            }
  918.           ifelse true exit
  919.         }
  920.        if pop
  921.      }
  922.     if pop
  923.  
  924.         % The font definitely did not load correctly.
  925.     QUIET not
  926.      { (Loading ) print dup =only
  927.        ( font failed.) = flush
  928.      } if
  929.     false exit
  930.  
  931.     } loop        % end of loop
  932.  
  933.  } bind def
  934.  
  935. % Define a procedure to load all known fonts.
  936. % This isn't likely to be very useful.
  937. /loadallfonts
  938.  { Fontmap { pop findfont pop } forall
  939.  } bind def
  940.  
  941. % If requested, load all the fonts defined in the Fontmap into FontDirectory
  942. % as "fake" fonts i.e., font dicts with only FontName and FontType defined.
  943. % (We define FontType only for the sake of some questionable code in the
  944. % Apple Printer Utility 2.0 font inquiry code.)
  945. %
  946. % Note that this procedure only creates fake fonts in the FontDirectory
  947. % associated with the current VM.  This is because in multi-context systems,
  948. % creating the fake fonts in local VM leads to undesirable complications.
  949. /.definefakefonts
  950.     {
  951.     }
  952.     {
  953.       (gs_fonts FAKEFONTS) VMDEBUG
  954.       Fontmap {
  955.     pop dup type /stringtype eq { cvn } if
  956.     .FontDirectory 1 index known not {
  957.       2 dict dup /FontName 3 index put
  958.       dup /FontType 1 put
  959.       .FontDirectory 3 1 roll put
  960.     } {
  961.       pop
  962.     } ifelse
  963.       } forall
  964.     }
  965. FAKEFONTS { exch } if pop def    % don't bind, .current/setglobal get redefined
  966.  
  967. % Install initial fonts from Fontmap.
  968. /.loadinitialfonts
  969.  { NOFONTMAP not
  970.     { /FONTMAP where
  971.       { pop [ FONTMAP .pathlist ]
  972.          { dup VMDEBUG findlibfile
  973.         { exch pop .loadFontmap }
  974.         { /undefinedfilename signalerror }
  975.            ifelse
  976.          }
  977.       }
  978.       { LIBPATH
  979.          { defaultfontmap 2 copy .filenamedirseparator
  980.            exch concatstrings concatstrings dup VMDEBUG
  981.            (r) { file } .internalstopped
  982.         { pop pop } { .loadFontmap } ifelse
  983.          }
  984.       }
  985.      ifelse forall
  986.     }
  987.    if
  988.    .definefakefonts    % current VM is global
  989.  } def            % don't bind, .current/setglobal get redefined
  990.  
  991. % ---------------- Synthetic font support ---------------- %
  992.  
  993. % Create a new font by modifying an existing one.  paramdict contains
  994. % entries with the same keys as the ones found in a Type 1 font;
  995. % it should also contain enough empty entries to allow adding the
  996. % corresponding non-overridden entries from the original font dictionary,
  997. % including FID.  If paramdict includes a FontInfo entry, this will
  998. % also override the original font's FontInfo, entry by entry;
  999. % again, it must contain enough empty entries.
  1000.  
  1001. % Note that this procedure does not perform a definefont.
  1002.  
  1003. /.makemodifiedfont    % <fontdict> <paramdict> .makemodifiedfont <fontdict'>
  1004.  { exch
  1005.     {            % Stack: destdict key value
  1006.       1 index /FID ne
  1007.        { 2 index 2 index known
  1008.       {        % Skip fontdict entry supplied in paramdict, but
  1009.             % handle FontInfo specially.
  1010.         1 index /FontInfo eq
  1011.          { 2 index 2 index get        % new FontInfo
  1012.            1 index                % old FontInfo
  1013.         {    % Stack: destdict key value destinfo key value
  1014.           2 index 2 index known
  1015.            { pop pop }
  1016.            { 2 index 3 1 roll put }
  1017.           ifelse
  1018.         }
  1019.            forall pop
  1020.          }
  1021.         if
  1022.       }
  1023.       {        % No override, copy the fontdict entry.
  1024.         2 index 3 1 roll put
  1025.         dup dup    % to match pop pop below
  1026.       }
  1027.      ifelse
  1028.        }
  1029.       if
  1030.       pop pop
  1031.     } forall
  1032.  } bind def
  1033.  
  1034. % Make a modified font and define it.  Note that unlike definefont,
  1035. % this does not leave the font on the operand stack.
  1036.  
  1037. /.definemodifiedfont    % <fontdict> <paramdict> .definemodifiedfont -
  1038.  { .makemodifiedfont
  1039.    dup /FontName get exch definefont pop
  1040.  } bind def
  1041.