home *** CD-ROM | disk | FTP | other *** search
/ Internet Magazine 2002 February / INTERNET88.ISO / pc / software / windows / bits / pdf995 / data1.cab / Program_Executable_Files / res / font2c.ps < prev    next >
Encoding:
Text File  |  2001-12-08  |  19.8 KB  |  674 lines

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