font2c.ps 19 KB

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