home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / GSPMSRC / SRC / GS_FONTS.PS < prev    next >
Text File  |  1993-12-16  |  21KB  |  695 lines

  1. %    Copyright (C) 1990, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2. %
  3. % This file is part of Ghostscript.
  4. %
  5. % Ghostscript is distributed in the hope that it will be useful, but
  6. % WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. % to anyone for the consequences of using it or for whether it serves any
  8. % particular purpose or works at all, unless he says so in writing.  Refer
  9. % to the Ghostscript General Public License for full details.
  10. %
  11. % Everyone is granted permission to copy, modify and redistribute
  12. % Ghostscript, but only under the conditions described in the Ghostscript
  13. % General Public License.  A copy of this license is supposed to have been
  14. % given to you along with Ghostscript so you can know your rights and
  15. % responsibilities.  It should be in a file named COPYING.  Among other
  16. % things, the copyright notice and this notice must be preserved on all
  17. % copies.
  18.  
  19. % Font initialization and management code.
  20.  
  21. % The standard representation for PostScript compatible fonts is described
  22. % in the book "Adobe Type 1 Font Format", published by Adobe Systems Inc.
  23.  
  24. % Define the default font.
  25. /defaultfontname /Ugly def
  26.  
  27. % Load the font name -> font file name map.
  28. userdict /Fontmap FontDirectory maxlength dict put
  29. /.loadFontmap        % <filename> .loadFontmap -
  30.  { 2 dict begin
  31.      mark Fontmap
  32.      /;
  33.       { % The stack contains a mark, the dictionary, the font name,
  34.         % the file or alias name, and possibly additional information
  35.     % about the font.
  36.     counttomark 3 sub { pop } repeat .growput
  37.     Fontmap
  38.       } bind def
  39.      3 -1 roll run
  40.    end
  41.    pop pop        % pop the mark and the copy of the dictionary
  42.  } bind def
  43. (Fontmap) .loadFontmap
  44.  
  45. % Parse a font file just enough to find the FontName.
  46. /.findfontname        % <file> .findfontname <name> true
  47.             % <file> .findfontname false
  48.             % Closes the file in either case.
  49.  {  { dup token not { false exit } if        % end of file
  50.       dup /eexec eq { pop false exit } if    % reached eexec section
  51.       dup /FontName eq
  52.        { xcheck not { dup token exit } if }    % found /FontName
  53.        { pop }
  54.       ifelse
  55.     } loop
  56.    dup { 3 } { 2 } ifelse -1 roll closefile
  57.  } bind def
  58.  
  59. (GS_FONTPATH) getenv not { (%END GS_FONTPATH) .skipeof } if
  60. pop
  61.  
  62. % Scan directories looking for plausible fonts.  "Plausible" means that
  63. % the file begins either with %!PS-AdobeFont-, or with \200\001
  64. % followed by four arbitrary bytes and then "%!PS-AdobeFont-".
  65. % To speed up the search, we skip any file whose name appears in
  66. % the Fontmap (with any extension and upper/lower case variation) already.
  67. %
  68. % NOTE: The current implementation of this procedure is Unix/DOS-
  69. % specific.  It assumes that '/' and '\' are directory separators; that
  70. % the part of a file name following the last '.' is the extension;
  71. % that ';' cannot appear in a file name; and that ':' can appear in a
  72. % file name only if the file name doesn't begin with '/', '\', or '.'.
  73. % (this is so that Unix systems can use ':' as the separator).
  74. %
  75. /.lowerstring        % <string> .lowerstring <lowerstring>
  76.  { 0 1 2 index length 1 sub
  77.     { 2 copy get dup 65 ge exch 90 le and
  78.        { 2 copy 2 copy get 32 add put }
  79.      if pop
  80.     }
  81.    for
  82.  } bind def
  83. /.splitfilename        % <dir.../base.extn> .basename <base> <extn>
  84.  {  { (/) search { true } { (\\) search } ifelse
  85.        { pop pop }
  86.        { exit }
  87.       ifelse
  88.     }
  89.    loop
  90.    dup { (.) search { pop pop } { exit } ifelse } loop
  91.    2 copy eq
  92.     { pop () }
  93.     { exch dup length 2 index length 1 add sub 0 exch getinterval exch }
  94.    ifelse
  95.  } bind def
  96. /.scanfontdict Fontmap maxlength dict def
  97. /.scanfontbegin
  98.  {    % Construct the table of all file names already in Fontmap.
  99.    Fontmap
  100.     { exch pop dup type /stringtype eq
  101.        { .splitfilename pop =string copy .lowerstring cvn
  102.          .scanfontdict exch true .growput
  103.        }
  104.        { pop
  105.        }
  106.       ifelse
  107.     }
  108.    forall
  109.  } bind def
  110. /.scanfontskip 4 dict dup begin
  111.   (afm) true def
  112.   (pfm) true def
  113. end def
  114. /.scan1fontstring 128 string def
  115. /.fontheader (\200\001????%!PS-AdobeFont-*) def
  116. /.scan1fontfirst .fontheader length string def
  117. /.scan1fontdir        % <dirname> .scan1fontdir -
  118.  { QUIET not { (Scanning ) print dup print ( for fonts... ) print flush } if
  119.    0 exch (/*) concatstrings
  120.     { dup .splitfilename
  121.       .scanfontskip exch known exch .scanfontdict exch known or
  122.        { pop
  123.        }
  124.        { dup (r) file
  125.          dup .scan1fontfirst readstring pop
  126.      dup .fontheader 6 16 getinterval .stringmatch
  127.       { pop true }
  128.       { .fontheader .stringmatch }
  129.      ifelse
  130.       { dup 0 setfileposition .findfontname
  131.          { dup Fontmap exch known
  132.             { pop pop
  133.         }
  134.         { exch copystring exch
  135.           Fontmap exch 2 index .growput
  136.           .splitfilename pop true .scanfontdict 3 1 roll .growput
  137.           1 add
  138.         }
  139.            ifelse
  140.          }
  141.         if
  142.       }
  143.       { closefile pop
  144.       }
  145.      ifelse
  146.        }
  147.       ifelse
  148.     }
  149.    .scan1fontstring filenameforall
  150.    QUIET { pop } { =only ( found.\n) print flush } ifelse
  151.  } bind def
  152. % Scan all the directories mentioned in GS_FONTPATH.
  153. (GS_FONTPATH) getenv
  154.  { .scanfontbegin
  155.     % Parsing the list of dictionaries is messy, since we have to
  156.     % handle both the Unix : and the other-system ; as separators.
  157.     % See the earlier comment for the restrictions that make this work.
  158.     { dup length 0 eq { pop exit } if
  159.       (;) search
  160.        { exch pop
  161.        }
  162.        { dup 0 1 getinterval (/\\.) exch search
  163.           { pop pop pop (:) search
  164.          { exch pop }
  165.          { () exch }
  166.         ifelse
  167.       }
  168.       { pop () exch
  169.       }
  170.      ifelse
  171.        }
  172.       ifelse .scan1fontdir
  173.     }
  174.    loop
  175.  }
  176. if
  177.  
  178. %END GS_FONTPATH
  179.  
  180. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  181. % (This is intended primarily for machines with very small memories.)
  182. % In this case, we define another dictionary, parallel to FontDirectory,
  183. % that retains an open file for every font loaded.
  184. /FontFileDirectory 10 dict def
  185.  
  186. % Define an augmented version of .buildfont1 that inserts UnderlinePosition
  187. % and UnderlineThickness entries in FontInfo if they aren't there already.
  188. % (This works around the incorrect assumption, made by many word processors,
  189. % that these entries are present in the built-in fonts.)
  190. /.buildfont1x
  191.  { dup /FontInfo known not
  192.     { dup /FontInfo 2 dict .growput }
  193.    if
  194.    dup dup /FontInfo get dup dup
  195.    /UnderlinePosition known exch /UnderlineThickness known and
  196.     { pop pop        % entries already present
  197.     }
  198.     { dup length 2 add dict copy
  199.       dup /UnderlinePosition known not
  200.        { dup /UnderlinePosition 3 index /FontBBox get
  201.          1 get 2 div put        % 1/2 the font descent
  202.        }
  203.       if
  204.       dup /UnderlineThickness known not
  205.        { dup /UnderlineThickness 3 index /FontBBox get
  206.          dup 3 get exch 1 get sub 20 div put    % 1/20 the font height
  207.        }
  208.       if
  209.       1 index /FontInfo get wcheck not { readonly } if
  210.       /FontInfo exch put
  211.     }
  212.    ifelse .buildfont1
  213.  } bind def
  214. % Define definefont.  This is a procedure built on a set of operators
  215. % that do all the error checking and key insertion.
  216. mark
  217.     /.buildfont0 where { pop 0 /.buildfont0 load } if
  218.     /.buildfont1 where { pop 1 /.buildfont1x load } if
  219.     /.buildfont3 where { pop 3 /.buildfont3 load } if
  220. .dicttomark /.buildfontdict exch def
  221. /definefont
  222.  { 1 dict begin count /d exch def    % save stack depth in case of error
  223.     {        % Check for disabled platform fonts.
  224.       NOPLATFONTS
  225.        { dup maxlength 1 index length sub 2 lt { dup .growdict } if
  226.      dup /ExactSize 0 put
  227.        }
  228.        {    % Hack: if the Encoding looks like it might be the
  229.         % Symbol or Dingbats encoding, load those now (for the
  230.         % benefit of platform font matching) just in case
  231.         % the font didn't actually reference them.
  232.      dup /Encoding get length 65 ge
  233.       { dup /Encoding get 64 get
  234.         dup /congruent eq { SymbolEncoding pop } if
  235.         /a9 eq { DingbatsEncoding pop } if
  236.       }
  237.      if
  238.        }
  239.       ifelse
  240.       dup /FontType get //.buildfontdict exch get exec
  241.       DISKFONTS
  242.        { FontFileDirectory 2 index known
  243.           { dup /FontFile FontFileDirectory 4 index get .growput
  244.       }
  245.      if
  246.        }
  247.       if
  248.       readonly
  249.     }
  250.    stopped
  251.     { count d sub { pop } repeat end /invalidfont signalerror }
  252.     { end dup FontDirectory 4 2 roll .growput }
  253.    ifelse
  254.  } odef
  255.  
  256.  
  257. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  258. % (This is intended primarily for machines with very small memories.)
  259. % Initially, the character definition is the file position of the definition;
  260. % this gets replaced with the actual CharString.
  261. % Note that if we are loading characters lazily, CharStrings is writable.
  262.  
  263. % _Cstring must be long enough to hold the longest CharString for
  264. % a character defined using seac.  This is lenIV + 4 * 5 (for the operands
  265. % of sbw, assuming div is not used) + 2 (for sbw) + 3 * 5 (for the operands
  266. % of seac other than the character codes) + 2 * 2 (for the character codes)
  267. % + 2 (for seac), i.e., lenIV + 43.
  268.  
  269. /_Cstring 60 string def
  270.  
  271. % When we initially load the font, we call
  272. %    <index|charname> <length> <readproc> cskip_C
  273. % to skip over each character definition and return the file position instead.
  274. % This substitutes for the procedure
  275. %    <index|charname> <length> string currentfile exch read[hex]string pop
  276. %      [encrypt]
  277. % What we actually store is fileposition * 1000 + length,
  278. %   negated if the string is stored in binary form.
  279.  
  280. % Older fonts use skip_C rather than cskip_C.
  281. % skip_C takes /readstring or /readhexstring as its third argument,
  282. % instead of the entire reading procedure.
  283. /skipproc_C {string currentfile exch readstring pop} cvlit def
  284. /skip_C
  285.  { //skipproc_C dup 3 4 -1 roll put cvx readonly cskip_C
  286.  } bind def
  287. /cskip_C
  288.  { exch dup 1000 ge 3 index type /nametype ne or
  289.     { % This is a Subrs string, or the string is so long we can't represent
  290.       % its length.  Load it now.
  291.       exch exec
  292.     }
  293.     { % Record the position and length, and skip the string.
  294.       dup currentfile fileposition 1000 mul add
  295.       2 index 3 get /readstring cvx eq { neg } if
  296.       3 1 roll
  297.       dup _Cstring length idiv
  298.        { currentfile _Cstring 3 index 3 get exec pop pop
  299.        } repeat
  300.       _Cstring length mod _Cstring exch 0 exch getinterval
  301.       currentfile exch 3 -1 roll 3 get exec pop pop
  302.     }
  303.    ifelse
  304.  } bind def
  305.  
  306. % Type1BuildGlyph calls load_C to actually load the character definition.
  307.  
  308. /load_C        % <charname> <fileposandlength> load_C -
  309.  { dup abs 1000 idiv FontFile exch setfileposition
  310.    CharStrings 3 1 roll
  311.    dup 0 lt
  312.     { neg 1000 mod string FontFile exch readstring }
  313.     { 1000 mod string FontFile exch readhexstring }
  314.    ifelse pop
  315. % If the CharStrings aren't encrypted on the file, encrypt now.
  316.    Private /-| get 0 get
  317.    dup type /nametype ne { dup length 5 sub 5 exch getinterval exec } { pop } ifelse
  318.    dup 4 1 roll put
  319. % If the character is defined with seac, load its components now.
  320.    mark exch seac_C
  321.    counttomark
  322.     { StandardEncoding exch get dup CharStrings exch get
  323.       dup type /integertype eq { load_C } { pop pop } ifelse
  324.     } repeat
  325.    pop        % the mark
  326.  } bind def
  327.  
  328. /seac_C        % <charstring> seac_C <achar> <bchar> ..or nothing..
  329.  { dup length _Cstring length le
  330.     { 4330 exch _Cstring .type1decrypt exch pop
  331.       dup dup length 2 sub 2 getinterval <0c06> eq    % seac
  332.        { dup length
  333.          Private /lenIV known { Private /lenIV get } { 4 } ifelse
  334.      exch 1 index sub getinterval
  335. % Parse the string just enough to extract the seac information.
  336. % We assume that the only possible operators are hsbw, sbw, and seac,
  337. % and that there are no 5-byte numbers.
  338.      mark 0 3 -1 roll
  339.       { exch
  340.          { { dup 32 lt
  341.               { pop 0 }
  342.           { dup 247 lt
  343.              { 139 sub 0 }
  344.              { dup 251 lt
  345.             { 247 sub 256 mul 108 add 1 1 }
  346.             { 251 sub -256 mul -108 add -1 1 }
  347.                ifelse
  348.              }
  349.             ifelse
  350.           }
  351.          ifelse
  352.            }            % 0
  353.            { mul add 0 }        % 1
  354.          }
  355.         exch get exec
  356.       }
  357.      forall pop
  358.      counttomark 1 add 2 roll cleartomark    % pop all but achar bchar
  359.        }
  360.        { pop    % not seac
  361.        }
  362.       ifelse
  363.     }
  364.     { pop    % punt
  365.     }
  366.    ifelse
  367.  } bind def
  368.  
  369. % Define an auxiliary procedure for loading a font.
  370. % If DISKFONTS is true and the body of the font is not encrypted with eexec:
  371. %    - Prevent the CharStrings from being made read-only.
  372. %    - Substitute a different CharString-reading procedure.
  373. % (eexec disables this because the implicit 'systemdict begin' hides
  374. % the redefinitions that make the scheme work.)
  375. % We assume that:
  376. %    - The magic procedures (-|, -!, |-, and |) are defined with
  377. %    executeonly or readonly;
  378. %    - The contents of the reading procedures are as defined in bdftops.ps;
  379. %    - The font ends with
  380. %    <font> <Private> <CharStrings>
  381. %    readonly put noaccess|readonly put
  382. 4 dict begin
  383.  /dict            % leave room for FontFile
  384.   { 1 add dict
  385.   } bind def
  386.  /executeonly        % for reading procedures
  387.   { readonly
  388.   } def
  389.  /noaccess        % for Subrs strings and Private dictionary
  390.   { readonly
  391.   } def
  392.  /readonly        % for procedures and CharStrings dictionary
  393.   {    % We want to take the following non-standard actions here:
  394.       %   - If the operand is the CharStrings dictionary, do nothing;
  395.     %   - If the operand is a number (a file position replacing the
  396.     %    actual CharString), do nothing;
  397.     %   - If the operand is either of the reading procedures (-| or -!),
  398.     %    substitute a different one.
  399.     dup type /dicttype eq        % CharStrings or Private
  400.      { 1 index /CharStrings ne { readonly } if }
  401.      { dup type /arraytype eq        % procedure or data array
  402.         { dup length 5 ge 1 index xcheck and
  403.        { dup 0 get /string eq
  404.          1 index 1 get /currentfile eq and
  405.          1 index 2 get /exch eq and
  406.          1 index 3 get dup /readstring eq exch /readhexstring eq or and
  407.          1 index 4 get /pop eq and
  408.           { /cskip_C cvx 2 packedarray cvx
  409.           }
  410.           { readonly
  411.           }
  412.          ifelse
  413.        }
  414.        { readonly
  415.        }
  416.       ifelse
  417.     }
  418.     { dup type /stringtype eq    % must be a Subr string
  419.        { readonly }
  420.       if
  421.     }
  422.        ifelse
  423.      }
  424.     ifelse
  425.   } bind def
  426. currentdict end readonly /.loadfontdict exch def
  427. /.loadfont        % <file> .loadfont -
  428.  { mark exch systemdict begin
  429.    DISKFONTS { .loadfontdict begin } if
  430.    % We really would just like systemdict on the stack,
  431.    % but fonts produced by Fontographer require a writable dictionary....
  432.    8 dict begin        % garbage
  433.     % We can't just use `run', because we want to check for .PFB files.
  434.    currentpacking
  435.     { false setpacking .loadfont1 true setpacking }
  436.     { .loadfont1 }
  437.    ifelse
  438.     { handleerror } if
  439.    end
  440.    DISKFONTS { end } if
  441.    end cleartomark
  442.  } bind def
  443. /.loadfont1        % <file> .loadfont1 <errorflag>
  444.  {    % We would like to use `false /PFBDecode filter',
  445.     % but this occasionally produces a whitespace character as
  446.     % the first of an eexec section, so we can't do it.
  447.     % Also, since the interpreter doesn't currently automatically
  448.     % close an input file when the file reaches EOF (unless it's
  449.     % the interpreter's current input file), we must explicitly
  450.     % close the real file if we used a PFB filter.
  451.     { dup read not { -1 } if
  452.       2 copy unread 16#80 eq
  453.        { dup true /PFBDecode filter cvx exec closefile }
  454.        { cvx exec }
  455.       ifelse
  456.     } stopped
  457.    $error /newerror get and
  458.  } bind def
  459.  
  460. % Define a procedure for defining aliased fonts.
  461. % We just copy the original font, changing the FontName.
  462. /.aliasfont        % <name> <font> .aliasfont <newFont>
  463.  { dup length 2 add dict
  464.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  465.    /FontName 3 index put
  466.    definefont
  467.  } odef % bind def
  468.  
  469. % Define findfont so it tries to load a font if it's not found.
  470. /findfont
  471.  {    % Since PostScript has no concept of goto, or even blocks with
  472.     % exits, we use a loop as a way to get an exitable scope.
  473.     % The loop is never executed more than twice.
  474.     {
  475.     dup FontDirectory exch known        % Already loaded?
  476.      { FontDirectory exch get exit }
  477.     if
  478.  
  479.     dup Fontmap exch known not    % Unknown font name.
  480.      { dup defaultfontname eq
  481.         { (Default font ) print cvx =only
  482.           ( not found in Fontmap!  Giving up.\n) print flush
  483.           1 .quit
  484.         } if
  485.        QUIET not
  486.         { (Substituting ) print defaultfontname cvx =only
  487.           ( for unknown font ) print dup == flush
  488.         } if
  489.        defaultfontname findfont .aliasfont exit
  490.      }
  491.     if
  492.  
  493.     dup Fontmap exch get
  494.  
  495.     % Check for a font alias.
  496.     dup type /nametype eq
  497.      { findfont .aliasfont exit
  498.      }
  499.     if
  500.  
  501.     % If we can't open the file, substitute for the font.
  502.     findlibfile
  503.      { % Stack: fontname fontfilename fontfile
  504.        DISKFONTS
  505.         { 1 index (r) file
  506.           FontFileDirectory exch 4 index exch .growput
  507.         }
  508.        if
  509.        QUIET not
  510.         { (Loading ) print 2 index =only
  511.           ( font from ) print exch print (... ) print flush }
  512.         { exch pop }
  513.        ifelse
  514.        .loadfont
  515.        QUIET not
  516.         { vmstatus 3 { =only ( ) print } repeat
  517.           (done.\n) print flush
  518.         } if
  519.  
  520.        % Check to make sure the font was actually loaded.
  521.        dup FontDirectory exch known { findfont exit } if
  522.  
  523.        % Maybe the file had a different FontName.
  524.        % See if we can get a FontName from the file, and if so,
  525.        % whether a font by that name exists now.
  526.        dup Fontmap exch get findlibfile
  527.         { exch pop .findfontname
  528.            { dup FontDirectory exch .knownget
  529.               {    % Yes.  Stack: origfontname filefontname fontdir
  530.             exch
  531.             QUIET
  532.              { pop
  533.              }
  534.              { (Using ) print cvx =only
  535.                ( font for ) print 1 index cvx =only
  536.                (.\n) print flush
  537.              }
  538.             ifelse
  539.             .aliasfont exit
  540.           }
  541.          if pop
  542.            }
  543.           if
  544.         }
  545.        if
  546.  
  547.        % The font definitely did not load correctly.
  548.        QUIET not
  549.         { (Loading ) print dup cvx =only
  550.           ( font failed, substituting ) print defaultfontname cvx =only
  551.           (.\n) print flush
  552.         } if
  553.        defaultfontname findfont .aliasfont exit
  554.      }
  555.     if
  556.  
  557.     % findlibfile failed, substitute the default font.
  558.     % Stack: fontname fontfilename
  559.     (Can't find \(or can't open\) font file )
  560.     1 index defaultfontname eq
  561.      { print print ( for default font \() print cvx =only
  562.        (\)!  Giving up.\n) print flush 1 .quit
  563.      }
  564.      { QUIET
  565.         { pop
  566.         }
  567.         { print print ( for font ) print dup cvx =only
  568.           (, substituting ) print defaultfontname cvx =only
  569.           (.\n) print flush
  570.         }
  571.        ifelse
  572.        defaultfontname findfont .aliasfont
  573.      }
  574.     ifelse
  575.     exit
  576.  
  577.     } loop        % end of loop
  578.  
  579.  } odef % bind def
  580.  
  581.  
  582. % The CharStrings are a dictionary in which the key is the character name,
  583. % and the value is a compressed and encrypted representation of a path.
  584. % For detailed information, see the book "Adobe Type 1 Font Format",
  585. % published by Adobe Systems Inc.
  586.  
  587. % Here are the BuildChar and BuildGlyph implementation for Type 1 fonts.
  588. % The names Type1BuildChar and Type1BuildGlyph are known to the interpreter.
  589.  
  590. /Type1BuildChar
  591.  { 1 index /Encoding get exch get Type1BuildGlyph
  592.  } bind def
  593. /Type1BuildGlyph
  594.  { exch begin
  595.     dup CharStrings exch .knownget not
  596.      { QUIET not
  597.         { (Substituting .notdef for ) print = flush
  598.     } { pop } ifelse
  599.        /.notdef CharStrings /.notdef get
  600.      } if
  601.     % stack: charname charstring
  602.     PaintType 0 ne
  603.      { 1 setmiterlimit 1 setlinejoin 1 setlinecap
  604.        currentdict /StrokeWidth .knownget not { 0 } if
  605.        setlinewidth
  606.      } if
  607.     dup type /stringtype eq        % encoded outline
  608.      { outline_C
  609.      }
  610.      { dup type /integertype eq        % file position for lazy loading
  611.         { 1 index exch load_C dup CharStrings exch get outline_C
  612.     }
  613.     {                % PostScript procedure
  614.       currentdict end systemdict begin begin   exec   end
  615.     }
  616.        ifelse
  617.      }
  618.     ifelse
  619.    end
  620.  } bind def
  621.  
  622. % Make the call on setcachedevice a separate procedure,
  623. % so we can redefine it if the composite font extensions are present.
  624. % (We don't use the obvious
  625. %    /setcachedevice_C /setcachedevice load def
  626. % because that would bind it into outline_C.)
  627. /setcachedevice_C { setcachedevice } bind def
  628.  
  629. /outline_C        % <charname> <charstring> outline_C -
  630.  { currentdict /Metrics .knownget
  631.     { 2 index .knownget
  632.        { dup type dup /integertype eq exch /realtype eq or
  633.           {    % <wx>
  634.         exch .type1addpath 0
  635.       }
  636.       { dup length 2 eq
  637.          {    % [<wx> <sbx>]
  638.            exch 1 index 0 get 0 .type1addpath
  639.            1 get 0
  640.          }
  641.          {    % [<wx> <wy> <sbx> <sby>]
  642.            aload pop 5 -1 roll 3 1 roll .type1addpath
  643.          }
  644.         ifelse
  645.       }
  646.      ifelse
  647.        }
  648.        { .type1addpath currentpoint
  649.        }
  650.       ifelse
  651.     }
  652.     { .type1addpath currentpoint
  653.     }
  654.    ifelse        % stack: wx wy
  655.    pathbbox
  656.    PaintType 0 ne
  657.     {        % Expand the bounding box by the stroke width.
  658.         % (Actually, only half the stroke width is needed.)
  659.       4 -1 roll currentlinewidth sub
  660.       4 -1 roll currentlinewidth sub
  661.       4 -1 roll currentlinewidth add
  662.       4 -1 roll currentlinewidth add
  663.     }
  664.    if
  665.    setcachedevice_C
  666.    PaintType 0 eq { fill } { stroke } ifelse
  667.    pop
  668.  } bind def
  669.  
  670. % Find all the precompiled font operators in systemdict.
  671.    systemdict
  672.     { exch =string cvs (.font_) anchorsearch
  673.        { pop pop exec    % execute the operator, returns the font dictionary
  674.          dup begin
  675.        Encoding type /stringtype eq
  676.         { Encoding cvn cvx exec /Encoding exch def
  677.         }
  678.        if
  679.        FontName exch
  680.      end definefont pop
  681.        }
  682.        { pop pop
  683.        }
  684.       ifelse
  685.     }
  686.    forall
  687.  
  688.  
  689.  
  690. % Define a procedure to load all known fonts.
  691. % This isn't likely to be very useful.
  692. /loadallfonts
  693.  { Fontmap { pop findfont pop } forall
  694.  } bind def
  695.