home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / GhostScript / !GhostScr / 6_01 / lib / font2c.ps < prev    next >
Text File  |  2000-03-09  |  20KB  |  673 lines

  1. %    Copyright (C) 1992, 1993, 1994, 1995, 1999 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. % $Id: font2c.ps,v 1.1 2000/03/09 08:40:39 lpd Exp $
  16. % font2c.ps
  17. % Write out a PostScript Type 0 or Type 1 font as C code
  18. % that can be linked with the interpreter.
  19. % This even works on protected fonts, if you use the -dWRITESYSTEMDICT
  20. % switch in the command line.  The code is reentrant and location-
  21. % independent and has no external references, so it can be put into
  22. % a sharable library even on VMS.
  23.  
  24. % Define the maximum string length that all compilers will accept.
  25. % This must be approximately
  26. %    min(max line length, max string literal length) / 4 - 5.
  27.  
  28. /font2cdict 100 dict dup begin
  29.  
  30. /max_wcs 50 def
  31.  
  32. % Define a temporary file for writing out procedures.
  33. /wtempname (_.tmp) def
  34.  
  35. % ------ Protection utilities ------ %
  36.  
  37. % Protection values are represented by a mask:
  38. /a_noaccess 0 def
  39. /a_executeonly 1 def
  40. /a_readonly 3 def
  41. /a_all 7 def
  42. /prot_names
  43.  [ (0) (a_execute) null (a_readonly) null null null (a_all)
  44.  ] def
  45. /prot_opers
  46.  [ {noaccess} {executeonly} {} {readonly} {} {} {} {}
  47.  ] def
  48.  
  49. % Get the protection of an object.
  50.    /getpa
  51.     { dup wcheck
  52.        { pop a_all }
  53.        {    % Check for executeonly or noaccess objects in protected.
  54.          dup protected exch known
  55.       { protected exch get }
  56.       { pop a_readonly }
  57.      ifelse
  58.        }
  59.       ifelse
  60.     } bind def
  61.  
  62. % Get the protection appropriate for (all the) values in a dictionary.
  63.    /getva
  64.     { a_noaccess exch
  65.        { exch pop
  66.          dup type dup /stringtype eq 1 index /arraytype eq or
  67.      exch /packedarraytype eq or
  68.       { getpa a_readonly and or }
  69.       { pop pop a_all exit }
  70.      ifelse
  71.        }
  72.       forall
  73.     } bind def
  74.  
  75. % Keep track of executeonly and noaccess objects,
  76. % but don't let the protection actually take effect.
  77. .currentglobal
  78. false .setglobal    % so protected can reference local objs
  79. /protected        % do first so // will work
  80.   systemdict wcheck { 1500 dict } { 1 dict } ifelse
  81. def
  82. systemdict wcheck not
  83.  { (Warning: you will not be able to convert protected fonts.\n) print
  84.    (If you need to convert a protected font, please\n) print
  85.    (restart the program and specify the -dWRITESYSTEMDICT switch.\n) print
  86.    flush
  87.    (%end) .skipeof
  88.  }
  89. if
  90. userdict begin
  91.   /executeonly
  92.    { dup //protected exch //a_executeonly put readonly
  93.    } bind def
  94.   /noaccess
  95.    { dup //protected exch //a_noaccess put readonly
  96.    } bind def
  97. end
  98. true .setglobal
  99. systemdict begin
  100.   /executeonly
  101.    { userdict /executeonly get exec
  102.    } bind odef
  103.   /noaccess
  104.    { userdict /noaccess get exec
  105.    } bind odef
  106. end
  107. %end
  108. .setglobal
  109.  
  110. % ------ Output utilities ------ %
  111.  
  112. % By convention, the output file is named cfile.
  113.  
  114. % Define some utilities for writing the output file.
  115.    /wtstring 100 string def
  116.    /wb {cfile exch write} bind def
  117.    /ws {cfile exch writestring} bind def
  118.    /wl {ws (\n) ws} bind def
  119.    /wt {wtstring cvs ws} bind def
  120.  
  121. % Write a C string.  Some compilers have unreasonably small limits on
  122. % the length of a string literal or the length of a line, so every place
  123. % that uses wcs must either know that the string is short,
  124. % or be prepared to use wcca instead.
  125.    /wbx
  126.     { 8#1000 add 8 (0000) cvrs dup 0 (\\) 0 get put ws
  127.     } bind def
  128.    /wcst
  129.     [
  130.       32 { /wbx load } repeat
  131.       95 { /wb load } repeat
  132.       129 { /wbx load } repeat
  133.     ] def
  134.    ("\\) { wcst exch { (\\) ws wb } put } forall
  135.    /wcs
  136.     { (") ws { dup wcst exch get exec } forall (") ws
  137.     } bind def
  138.    /can_wcs    % Test if can use wcs
  139.     { length max_wcs le
  140.     } bind def
  141.    /wncs    % name -> C string
  142.     { wtstring cvs wcs
  143.     } bind def
  144. % Write a C string as an array of character values.
  145. % We only need this because of line and literal length limitations.
  146.    /wca        % <string> <prefix> <suffix> wca -
  147.     { 0 4 -2 roll exch
  148.        {    % Stack: suffix n prefix char
  149.      exch ws
  150.      exch dup 19 ge { () wl pop 0 } if 1 add
  151.      exch dup 32 ge 1 index 126 le and
  152.       { 39 wb dup 39 eq 1 index 92 eq or { 92 wb } if wb 39 wb }
  153.       { wt }
  154.      ifelse (,)
  155.        } forall
  156.       pop pop ws
  157.     } bind def
  158.    /wcca    % <string> wcca -
  159.     { ({\n) (}) wca
  160.     } bind def
  161.  
  162. % Write object protection attributes.  Note that dictionaries and arrays are
  163. % the only objects that can be writable.
  164.    /wpa
  165.     { dup xcheck { (a_executable|) ws } if
  166.       dup type dup /dicttype eq exch /arraytype eq or
  167.        { getpa }
  168.        { getpa a_readonly and }
  169.       ifelse prot_names exch get ws
  170.     } bind def
  171.    /wva
  172.     { getva prot_names exch get ws
  173.     } bind def
  174.  
  175. % ------ Object writing ------ %
  176.  
  177.    /wnstring 128 string def
  178.  
  179. % Convert an object to a string to be scanned at a later time.
  180.    /cvos        % <obj> cvos <string>
  181.     {        % We'd like to use == and write directly to a string,
  182.         % but we can't do the former because of operators,
  183.         % and we can't do the latter because we can't predict
  184.         % how long the string would have to be....
  185.      wtempname (w) file dup 3 -1 roll wproc closefile
  186.      wtempname status pop pop pop exch pop string
  187.      wtempname (r) file dup 3 -1 roll readstring pop exch closefile
  188.     } bind def
  189.  
  190. % Write a string/name or null as an element of a string/name/null array.
  191. % Convert any other kind of value to a token to be read back in.
  192.    /wsn
  193.     { dup null eq
  194.        { pop (\t255,255,) wl
  195.        }
  196.        { dup type /nametype eq { wnstring cvs } if
  197.      dup type /stringtype ne { cvos (255,) ws } if
  198.      dup length 256 idiv wt (,) ws
  199.      dup length 256 mod wt
  200.      (,) (,\n) wca
  201.        }
  202.       ifelse
  203.     } bind def
  204. % Write a packed string/name/null array.
  205.    /wsna    % <name> <(string|name|null)*> wsna -
  206.     { (\tstatic const char ) ws exch wt ([] = {) wl
  207.       { wsn } forall
  208.       (\t0\n};) wl
  209.     } bind def
  210.  
  211. % Write a number or an array of numbers, as refs.
  212. /isnumber
  213.  { type dup /integertype eq exch /realtype eq or
  214.  } bind def
  215. /wnums
  216.  { dup isnumber
  217.     { (real_v\() ws wt (\),) ws }
  218.     { { wnums } forall }
  219.    ifelse
  220.  } bind def
  221.  
  222. % Test whether a procedure or unusual array can be written (printed).
  223. /iswx 4 dict dup begin
  224.   /arraytype { { iswproc } isall } def
  225.   /nametype { pop true } def
  226.   /operatortype { pop true } def    % assume it has been bound in
  227.   /packedarraytype /arraytype load def
  228. end def
  229. /iswnx 6 dict dup begin
  230.   /arraytype { { iswproc } isall } def
  231.   /integertype { pop true } def
  232.   /nametype { pop true } def
  233.   /realtype { pop true } def
  234.   /stringtype { pop true } def
  235.   /packedarraytype /arraytype load def
  236. end def
  237. /iswproc    % <obj> iswproc <bool>
  238.  { dup xcheck { iswx } { iswnx } ifelse
  239.    1 index type .knownget { exec } { pop false } ifelse
  240.  } bind def
  241.  
  242. % Write a printable procedure (one for which iswproc returns true).
  243. /wproca 3 dict dup begin
  244.   /arraytype
  245.    { 1 index ({) writestring
  246.       { 1 index ( ) writestring 1 index exch wproc } forall
  247.      (}) writestring
  248.    } bind def
  249.   /packedarraytype /arraytype load def
  250.   /operatortype { .writecvs } bind def    % assume binding would work
  251. end def
  252. /wproc        % <file> <proc> wproc -
  253.  { dup type wproca exch .knownget { exec } { write==only } ifelse
  254.  } bind def
  255.  
  256. % Write a named object.  Return true if this was possible.
  257. % Legal types are: boolean, integer, name, real, string,
  258. % array of (integer, integer+real, name, null+string),
  259. % and certain procedures and other arrays (see iswproc above).
  260. % All other objects are either handled specially or ignored.
  261.    /isall    % <array> <proc> isall <bool>
  262.     { true 3 -1 roll
  263.        { 2 index exec not { pop false exit } if }
  264.       forall exch pop
  265.     } bind def
  266.    /wott 8 dict dup begin
  267.       /arraytype
  268.        { woatt
  269.           { aload pop 2 index 2 index exec
  270.          { exch pop exec exit }
  271.          { pop pop }
  272.         ifelse
  273.       }
  274.      forall
  275.        } bind def
  276.       /booleantype
  277.        { { (\tmake_true\(&) } { (\tmake_false\(&) } ifelse ws
  278.          wt (\);) wl true
  279.        } bind def
  280.       /integertype
  281.        { (\tmake_int\(&) ws exch wt (, ) ws
  282.          wt (\);) wl true
  283.        } bind def
  284.       /nametype
  285.        { (\tcode = (*pprocs->name_create)\(i_ctx_p, &) ws exch wt
  286.          (, ) ws wnstring cvs wcs    % OK, names are short
  287.      (\);) wl
  288.      (\tif ( code < 0 ) return code;) wl
  289.      true
  290.        } bind def
  291.       /packedarraytype
  292.     /arraytype load def
  293.       /realtype
  294.        { (\tmake_real\(&) ws exch wt (, ) ws
  295.          wt (\);) wl true
  296.        } bind def
  297.       /stringtype
  298.        { ({\tstatic const char s_[] = ) ws
  299.          dup dup can_wcs { wcs } { wcca } ifelse
  300.      (;) wl
  301.      (\tmake_const_string\(&) ws exch wt
  302.      (, a_readonly, ) ws length wt (, (const byte *)s_\);) wl
  303.      (}) wl true
  304.        } bind def
  305.    end def
  306. % Write some other kind of object, if known.
  307.    /wother
  308.     { dup otherobjs exch known
  309.        { otherobjs exch get (\t) ws exch wt ( = ) ws wt (;) wl true }
  310.        { pop pop false }
  311.       ifelse
  312.     } bind def
  313. % Top-level procedure.
  314.    /wo        % name obj -> OK
  315.     { dup type wott exch .knownget { exec } { wother } ifelse
  316.     } bind def
  317.  
  318. % Write an array (called by wo).
  319.    /wap        % <name> <array> wap -
  320.     { dup xcheck not 1 index wcheck not and 1 index rcheck and
  321.        { pop pop }
  322.        { (\tr_set_attrs\(&) ws exch wt (, ) ws wpa (\);) wl }
  323.       ifelse
  324.     } bind def
  325.    /wnuma {    % <name> <array> <element_C_type> <<type>_v> wnuma -
  326.       ({\tstatic const ref_\() ws exch ws (\) a_[] = {) wl exch
  327.         % Stack: name type_v array
  328.       dup length 0 eq {
  329.     (\t) ws 1 index ws (\(0\)) wl
  330.       } {
  331.     dup {
  332.       (\t) ws 2 index ws (\() ws wt (\),) wl
  333.     } forall
  334.       } ifelse exch pop
  335.         % Stack: name array
  336.       (\t};) wl
  337.       dup wcheck {
  338.     (\tcode = (*pprocs->scalar_array_create)\(i_ctx_p, &) ws exch wt
  339.     (, (const ref *)a_, ) ws dup length wt
  340.     (, ) ws wpa (\);) wl
  341.     (\tif ( code < 0 ) return code;) wl
  342.       } {
  343.     (\tmake_const_array\(&) ws exch wt
  344.     (, avm_foreign|) ws dup wpa (, ) ws length wt
  345.     (, (const ref *)a_\);) wl
  346.       } ifelse
  347.       (}) wl
  348.     } bind def
  349.    /woatt [
  350.     % Integers
  351.      { { { type /integertype eq } isall }
  352.        { (long) (integer_v) wnuma true }
  353.      }
  354.     % Integers + reals
  355.      { { { type dup /integertype eq exch /realtype eq or } isall }
  356.        { (float) (real_v) wnuma true }
  357.      }
  358.     % Strings + nulls
  359.      { { { type dup /nulltype eq exch /stringtype eq or } isall }
  360.        { ({) ws dup (sa_) exch wsna
  361.      (\tcode = (*pprocs->string_array_create)\(i_ctx_p, &) ws exch wt
  362.      (, sa_, ) ws dup length wt (, ) ws wpa (\);) wl
  363.      (\tif ( code < 0 ) return code;) wl
  364.      (}) wl true
  365.        }
  366.      }
  367.     % Names
  368.      { { { type /nametype eq } isall }
  369.        { ({) ws dup (na_) exch wsna
  370.      (\tcode = (*pprocs->name_array_create)\(i_ctx_p, &) ws 1 index wt
  371.      (, na_, ) ws dup length wt (\);) wl
  372.      (\tif ( code < 0 ) return code;) wl
  373.      wap (}) wl true
  374.        }
  375.      }
  376.     % Procedure
  377.      { { iswproc }
  378.        { dup cvos
  379.         % Stack: name proc string
  380.      ({\tstatic const char s_[] = ) ws
  381.          dup dup can_wcs { wcs } { wcca } ifelse
  382.      (;) wl
  383.      (\tcode = (*pprocs->ref_from_string)\(i_ctx_p, &) ws 2 index wt
  384.      (, s_, ) ws length wt (\);) wl
  385.      (\tif ( code < 0 ) return code;) wl
  386.      wap (}) wl true
  387.      wtempname deletefile
  388.        }
  389.      }
  390.     % Default
  391.      { { pop true }
  392.        { wother }
  393.      }
  394.    ] def
  395.  
  396. % Write a named dictionary.  We assume the ref is already declared.
  397.    /wd        % <name> <dict> <extra> wd -
  398.     { 3 1 roll
  399.       ({) ws
  400.       (\tref v_[) ws dup length wt (];) wl
  401.       dup [ exch
  402.        { counttomark 2 sub wtstring cvs
  403.          (v_[) exch concatstrings (]) concatstrings exch wo not
  404.           { (Skipping ) print ==only (....\n) print }
  405.      if
  406.        } forall
  407.       ]
  408.         % Stack: array of keys (names)
  409.       ({) ws dup (str_keys_) exch wsna
  410.       (\tstatic const cfont_dict_keys keys_ =) wl
  411.       (\t { 0, 0, ) ws length wt (, ) ws 3 -1 roll wt (, ) ws
  412.       dup wpa (, ) ws dup wva ( };) wl pop
  413.       (\tcode = \(*pprocs->ref_dict_create\)\(i_ctx_p, &) ws wt
  414.       (, &keys_, str_keys_, v_\);) wl
  415.       (\tif ( code < 0 ) return code;) wl
  416.       (}) wl
  417.       (}) wl
  418.     } bind def
  419.  
  420. % Write character dictionary keys.
  421. % We save a lot of space by abbreviating keys which appear in
  422. % StandardEncoding or ISOLatin1Encoding.
  423. % Writes code to declare and initialize enc_keys_, str_keys, and keys_.
  424. /wcdkeys    % <dict> wcdkeys -
  425.  {    % Write keys present in StandardEncoding or ISOLatin1Encoding,
  426.     % pushing other keys on the o-stack.
  427.    (static const charindex enc_keys_[] = {) wl
  428.    dup [ exch 0 exch
  429.     { pop decoding 1 index known
  430.        { decoding exch get ({) ws dup -8 bitshift wt
  431.      (,) ws 255 and wt (}, ) ws
  432.      1 add dup 5 mod 0 eq { (\n) ws } if
  433.        }
  434.        { exch }
  435.       ifelse
  436.     }
  437.    forall pop
  438.    ]
  439.    ({0,0}\n};) wl
  440.     % Write other keys.
  441.    (str_keys_) exch wsna
  442.     % Write the declaration for keys_.
  443.    (static const cfont_dict_keys keys_ = {) wl
  444.    (\tenc_keys_, countof\(enc_keys_\) - 1,) wl
  445.    (\t) ws dup length wt ( - \(countof\(enc_keys_\) - 1\), 0, ) ws
  446.    dup wpa (, ) ws wva () wl
  447.    (};) wl
  448.  } bind def
  449.  
  450. % Enumerate character dictionary values in the same order that
  451. % the keys appear in enc_keys_ and str_keys_.
  452. % <proc> is called with each value in turn.
  453. /cdforall    % <dict> <proc> cdforall -
  454.  { 2 copy
  455.     { decoding 3 index known
  456.        { 3 -1 roll pop exec }
  457.        { pop pop pop }
  458.       ifelse
  459.     }
  460.    /exec cvx 3 packedarray cvx
  461.    /forall cvx
  462.    5 -2 roll
  463.     { decoding 3 index known
  464.        { pop pop pop }
  465.        { 3 -1 roll pop exec }
  466.       ifelse
  467.     }
  468.    /exec cvx 3 packedarray cvx
  469.    /forall cvx
  470.    6 packedarray cvx exec
  471.  } bind def
  472.  
  473. % ------ Writers for special objects ------ %
  474.  
  475. /writespecial 10 dict dup begin
  476.  
  477.    /FontInfo { 0 wd } def
  478.  
  479.    /Private { 0 wd } def
  480.  
  481.    /CharStrings
  482.     { ({) wl
  483.       dup wcdkeys
  484.       (static const char values_[] = {) wl
  485.        { wsn } cdforall
  486.       (\t0\n};) wl
  487.       (\tcode = \(*pprocs->string_dict_create\)\(i_ctx_p, &) ws wt
  488.       (, &keys_, str_keys_, values_\);) wl
  489.       (\tif ( code < 0 ) return code;) wl
  490.       (}) wl
  491.     } bind def
  492.  
  493.    /Metrics
  494.     { ({) wl
  495.       dup wcdkeys
  496.       (static const ref_(float) values_[] = {) wl
  497.       dup { (\t) ws wnums () wl } cdforall
  498.       (\t0\n};) wl
  499.       (static const char lengths_[] = {) wl
  500.        { (\t) ws dup isnumber
  501.       { pop 0 }
  502.       { length 1 add }
  503.      ifelse wt (,) wl
  504.        } cdforall
  505.       (\t0\n};) wl
  506.       (\tcode = \(*pprocs->num_dict_create\)\(i_ctx_p, &) ws wt
  507.       (, &keys_, str_keys_, (const ref *)values_, lengths_\);) wl
  508.       (\tif ( code < 0 ) return code;) wl
  509.       (}) wl
  510.     } bind def
  511.  
  512.    /Metrics2 /Metrics load def
  513.  
  514.    /FDepVector pop    % (converted to a list of font names)
  515.  
  516. end def
  517.  
  518. % ------ The main program ------ %
  519.  
  520. % Construct an inverse dictionary of encodings.
  521. [ /StandardEncoding /ISOLatin1Encoding
  522.   /SymbolEncoding /DingbatsEncoding
  523.   /KanjiSubEncoding
  524. ]
  525. dup length dict begin
  526.  { mark exch dup { .findencoding exch def } stopped cleartomark
  527.  } forall
  528. currentdict end /encodingnames exch def
  529.  
  530. % Invert the StandardEncoding and ISOLatin1Encoding vectors.
  531. 512 dict begin
  532.   0 1 255 { dup ISOLatin1Encoding exch get exch 256 add def } for
  533.   0 1 255 { dup StandardEncoding exch get exch def } for
  534. currentdict end /decoding exch def
  535.  
  536. /writefont        % cfilename procname -> [writes the current font]
  537.  { (gsf_) exch concatstrings
  538.      /fontprocname exch def
  539.    /cfname exch def
  540.    /cfile cfname (w) file def
  541.  
  542. % Remove unwanted keys from the font.
  543.    currentfont dup length dict begin { def } forall
  544.     { /FID /MIDVector /CurMID } { currentdict exch undef } forall
  545.    /Font currentdict end def
  546.  
  547. % Replace the FDepVector with a list of font names.
  548.    Font /FDepVector .knownget
  549.     { [ exch { /FontName get } forall ]
  550.       Font /FDepVector 3 -1 roll put
  551.     }
  552.    if
  553.  
  554. % Find all the special objects we know about.
  555. % wo uses this to write out references to otherwise intractable objects.
  556.    /otherobjs writespecial length dict dup begin
  557.      writespecial
  558.       { pop Font 1 index .knownget { exch def } { pop } ifelse
  559.       }
  560.      forall
  561.    end def
  562.  
  563. % Define a dummy FontInfo, in case the font doesn't have one.
  564.    /FontInfo 0 dict def
  565.  
  566. % Write out the boilerplate.
  567.    Font begin
  568.    (/****************************************************************) wl
  569.    (   Portions of this file are subject to the following notice(s):) wl
  570.    systemdict /copyright get wl
  571.    FontInfo /Notice .knownget
  572.     { (----------------------------------------------------------------) wl wl
  573.     } if
  574.    (****************************************************************/) wl
  575.    () wl
  576.    (/* ) ws cfname ws ( */) wl
  577.    (/* This file was created by the ) ws product ws ( font2c utility. */) wl
  578.    () wl
  579.    (#undef DEBUG) wl
  580.    (#include "ccfont.h") wl
  581.    () wl
  582.  
  583. % Write the procedure prologue.
  584.    (#ifdef __PROTOTYPES__) wl
  585.    (ccfont_proc\() ws fontprocname ws (\);) wl
  586.    (int) wl
  587.    fontprocname ws ((i_ctx_t *i_ctx_p, const cfont_procs *pprocs, ref *pfont)) wl
  588.    (#else) wl
  589.    (int) wl
  590.    fontprocname ws ((i_ctx_p, pprocs, pfont) i_ctx_t *i_ctx_p; const cfont_procs *pprocs; ref *pfont;) wl
  591.    (#endif) wl
  592.    ({\tint code;) wl
  593.    (\tref Font;) wl
  594.    otherobjs
  595.     { exch pop (\tref ) ws wt (;) wl }
  596.    forall
  597.  
  598. % Write out the special objects.
  599.    otherobjs
  600.     { exch writespecial 2 index get exec
  601.     }
  602.    forall
  603.  
  604. % Write out the main font dictionary.
  605. % If possible, substitute the encoding name for the encoding;
  606. % PostScript code will fix this up.
  607.     { /Encoding /PrefEnc }
  608.     { Font 1 index .knownget
  609.        { encodingnames exch .knownget { def } { pop } ifelse }
  610.        { pop }
  611.       ifelse
  612.     }
  613.    forall
  614.    (Font) Font FontType 0 eq { 5 } { 1 } ifelse wd
  615.  
  616. % Finish the procedural initialization code.
  617.    (\t*pfont = Font;) wl
  618.    (\treturn 0;) wl
  619.    (}) wl
  620.    end                % Font
  621.  
  622.    cfile closefile
  623.  
  624.  } bind def
  625.  
  626. end def            % font2cdict
  627.  
  628. % Compute the procedure name from the font name.
  629. % Replace all non-alphanumeric characters with '_'.
  630. /makefontprocnamemap 256 string
  631.    0 1 255 { 2 copy 95 put pop } for
  632.    (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz)
  633.     { 2 copy dup put pop } forall
  634. readonly def
  635. /makefontprocname    % <fontname> makefontprocname <procnamestring>
  636.  { dup length string cvs
  637.    dup length 1 sub -1 0
  638.     {        % Stack: string index
  639.       2 copy 2 copy get //makefontprocnamemap exch get put pop
  640.     }
  641.    for 
  642.  } def
  643.  
  644. /writefont { font2cdict begin writefont end } def
  645.  
  646. % If the program was invoked from the command line, run it now.
  647. [ shellarguments
  648.  { counttomark dup 2 eq exch 3 eq or
  649.     { counttomark -1 roll cvn
  650.       (Converting ) print dup =only ( font.\n) print flush
  651.       dup FontDirectory exch known { dup FontDirectory exch undef } if
  652.       findfont setfont
  653.       (FontName is ) print currentfont /FontName get ==only (.\n) print flush
  654.       counttomark 1 eq
  655.        {    % Construct the procedure name from the file name.
  656.          currentfont /FontName get makefontprocname
  657.        }
  658.       if
  659.       writefont
  660.       (Done.\n) print flush
  661.     }
  662.     { cleartomark
  663.       (Usage: font2c fontname cfilename.c [shortname]\n) print
  664.       ( e.g.: font2c Courier cour.c\n) print flush
  665.       mark
  666.     }
  667.    ifelse
  668.  }
  669. if pop
  670.