home *** CD-ROM | disk | FTP | other *** search
/ jppd.dyndns.org / jppd.dyndns.org.tar / jppd.dyndns.org / QUERYPRO / Impressora_PDF / converter.exe / GPLGS / font2c.ps < prev    next >
Text File  |  2003-12-13  |  20KB  |  676 lines

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