home *** CD-ROM | disk | FTP | other *** search
- % Copyright (C) 1992, 1993, 1994 Aladdin Enterprises. All rights reserved.
- %
- % This file is part of Aladdin Ghostscript.
- %
- % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- % or distributor accepts any responsibility for the consequences of using it,
- % or for whether it serves any particular purpose or works at all, unless he
- % or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- % License (the "License") for full details.
- %
- % Every copy of Aladdin Ghostscript must include a copy of the License,
- % normally in a plain ASCII text file named PUBLIC. The License grants you
- % the right to copy, modify and redistribute Aladdin Ghostscript, but only
- % under certain conditions described in the License. Among other things, the
- % License requires that the copyright notice and this notice be preserved on
- % all copies.
-
- % font2c.ps
- % Write out a PostScript Type 0 or Type 1 font as C code
- % that can be linked with the interpreter.
- % This even works on protected fonts, if you use the -dWRITESYSTEMDICT
- % switch in the command line. The code is reentrant and has no
- % external references, so it can be shared.
-
- % Define the maximum string length that all compilers will accept.
- % This must be approximately
- % min(max line length, max string literal length) / 4 - 5.
-
- /font2cdict 100 dict dup begin
-
- /max_wcs 50 def
-
- % ------ Protection utilities ------ %
-
- % Protection values are represented by a mask:
- /a_noaccess 0 def
- /a_executeonly 1 def
- /a_readonly 3 def
- /a_all 7 def
- /prot_names
- [ (0) (a_execute) null (a_readonly) null null null (a_all)
- ] def
- /prot_opers
- [ {noaccess} {executeonly} {} {readonly} {} {} {} {}
- ] def
-
- % Get the protection of an object.
- /getpa
- { dup wcheck
- { pop a_all }
- { % Check for executeonly or noaccess objects in protected.
- dup protected exch known
- { protected exch get }
- { pop a_readonly }
- ifelse
- }
- ifelse
- } bind def
-
- % Get the protection appropriate for (all the) values in a dictionary.
- /getva
- { a_noaccess exch
- { exch pop
- dup type dup /stringtype eq 1 index /arraytype eq or
- exch /packedarraytype eq or
- { getpa a_readonly and or }
- { pop pop a_all exit }
- ifelse
- }
- forall
- } bind def
-
- % Keep track of executeonly and noaccess objects,
- % but don't let the protection actually take effect.
- .currentglobal
- false .setglobal % so protected can reference local objs
- /protected % do first so // will work
- systemdict wcheck { 1500 dict } { 1 dict } ifelse
- def
- systemdict wcheck not
- { (Warning: you will not be able to convert protected fonts.\n) print
- (If you need to convert a protected font, please\n) print
- (restart the program and specify the -dWRITESYSTEMDICT switch.\n) print
- flush
- (%end) .skipeof
- }
- if
- userdict begin
- /executeonly
- { dup //protected exch //a_executeonly put readonly
- } bind def
- /noaccess
- { dup //protected exch //a_noaccess put readonly
- } bind def
- end
- true .setglobal
- systemdict begin
- /executeonly
- { userdict /executeonly get exec
- } bind odef
- /noaccess
- { userdict /noaccess get exec
- } bind odef
- end
- %end
- .setglobal
-
- % ------ Output utilities ------ %
-
- % By convention, the output file is named cfile.
-
- % Define some utilities for writing the output file.
- /wtstring 100 string def
- /wb {cfile exch write} bind def
- /ws {cfile exch writestring} bind def
- /wl {ws (\n) ws} bind def
- /wt {wtstring cvs ws} bind def
-
- % Write a C string. Some compilers have unreasonably small limits on
- % the length of a string literal or the length of a line, so every place
- % that uses wcs must either know that the string is short,
- % or be prepared to use wcca instead.
- /wbx
- { 8#1000 add 8 (0000) cvrs dup 0 (\\) 0 get put ws
- } bind def
- /wcst
- [
- 32 { /wbx load } repeat
- 95 { /wb load } repeat
- 129 { /wbx load } repeat
- ] def
- ("\\) { wcst exch { (\\) ws wb } put } forall
- /wcs
- { (") ws { dup wcst exch get exec } forall (") ws
- } bind def
- /can_wcs % Test if can use wcs
- { length max_wcs le
- } bind def
- /wncs % name -> C string
- { wtstring cvs wcs
- } bind def
- % Write a C string as an array of character values.
- % We only need this because of line and literal length limitations.
- /wca % string prefix suffix ->
- { 0 4 -2 roll exch
- { exch ws
- exch dup 19 ge { () wl pop 0 } if 1 add
- exch wt (,)
- } forall
- pop pop ws
- } bind def
- /wcca
- { ({\n) (}) wca
- } bind def
-
- % Write object protection attributes. Note that dictionaries are
- % the only objects that can be writable.
- /wpa
- { dup xcheck { (a_executable|) ws } if
- dup type /dicttype eq { getpa } { getpa a_readonly and } ifelse
- prot_names exch get ws
- } bind def
- /wva
- { getva prot_names exch get ws
- } bind def
-
- % ------ Object writing ------ %
-
- /wnstring 128 string def
-
- % Write a string/name or null as an element of a string/name/null array. */
- /wsn
- { dup null eq
- { pop (\t255,255,) wl
- }
- { dup type /nametype eq { wnstring cvs } if
- dup length 256 idiv wt (,) ws
- dup length 256 mod wt
- (,) (,\n) wca
- }
- ifelse
- } bind def
- % Write a packed string/name/null array.
- /wsna % <name> <(string|name|null)*> wsna -
- { (\tstatic const char ) ws exch wt ([] = {) wl
- { wsn } forall
- (\t0\n};) wl
- } bind def
-
-
- % Write a named object. Return true if this was possible.
- % Legal types are: boolean, integer, name, real, string,
- % array of (integer, integer+real, name, null+string).
- % All other objects are either handled specially or ignored.
- /isall % array proc -> bool
- { true 3 -1 roll
- { 2 index exec not { pop false exit } if }
- forall exch pop
- } bind def
- /wott 8 dict dup begin
- /arraytype
- { woatt
- { aload pop 2 index 2 index isall
- { exch pop exec exit }
- { pop pop }
- ifelse
- }
- forall
- } bind def
- /booleantype
- { { (\tmake_true\(&) } { (\tmake_false\(&) } ifelse ws
- wt (\);) wl true
- } bind def
- /integertype
- { (\tmake_int\(&) ws exch wt (, ) ws
- wt (\);) wl true
- } bind def
- /nametype
- { (\tcode = (*pprocs->name_create)\(&) ws exch wt
- (, ) ws wnstring cvs wcs % OK, names are short
- (\);) wl
- (\tif ( code < 0 ) return code;) wl
- true
- } bind def
- /packedarraytype
- /arraytype load def
- /realtype
- { (\tmake_real\(&) ws exch wt (, ) ws
- wt (\);) wl true
- } bind def
- /stringtype
- { ({\tstatic const char s_[] = ) ws
- dup dup can_wcs { wcs } { wcca } ifelse
- (;) wl
- (\tmake_const_string\(&) ws exch wt
- (, a_readonly, ) ws length wt (, (const byte *)s_\);) wl
- (}) wl true
- } bind def
- end def
- % Write some other kind of object, if known.
- /wother
- { dup otherobjs exch known
- { otherobjs exch get (\t) ws exch wt ( = ) ws wt (;) wl true }
- { pop pop false }
- ifelse
- } bind def
- % Top-level procedure.
- /wo % name obj -> OK
- { dup type wott exch .knownget { exec } { wother } ifelse
- } bind def
-
- % Write an array (called by wo).
- /wnuma % name array C_type type_v ->
- { ({\tstatic const ref_\() ws exch ws
- (\) a_[] = {) wl exch
- dup length 0 eq
- { (\t0) wl
- }
- { dup
- { (\t) ws 2 index ws (\() ws wt (\),) wl
- } forall
- }
- ifelse
- (\t};) wl exch pop
- (\tmake_array\(&) ws exch wt
- (, a_foreign|) ws dup wpa (, ) ws length wt
- (, (ref *)a_\);) wl (}) wl
- } bind def
- /woatt [
- % Integers
- { { type /integertype eq }
- { (long) (integer_v) wnuma true }
- }
- % Integers + reals
- { { type dup /integertype eq exch /realtype eq or }
- { (float) (real_v) wnuma true }
- }
- % Strings + nulls
- { { type dup /nulltype eq exch /stringtype eq or }
- { ({) ws dup (sa_) exch wsna
- exch (\tcode = (*pprocs->string_array_create)\(&) ws wt
- (, sa_, ) ws dup length wt (, ) ws wpa (\);) wl
- (\tif ( code < 0 ) return code;) wl
- (}) wl true
- }
- }
- % Names
- { { type /nametype eq }
- { ({) ws dup (na_) exch wsna
- exch (\tcode = (*pprocs->name_array_create)\(&) ws wt
- (, na_, ) ws length wt (\);) wl
- (\tif ( code < 0 ) return code;) wl
- (}) wl true
- }
- }
- % Default
- { { pop true }
- { wother }
- }
- ] def
-
- % Write a named dictionary. We assume the ref is already declared.
- /wd % <name> <dict> <extra> wd -
- { 3 1 roll
- ({) ws
- (\tref v_[) ws dup length wt (];) wl
- dup [ exch
- { counttomark 2 sub wtstring cvs
- (v_[) exch concatstrings (]) concatstrings exch wo not
- { (Skipping ) print ==only (....\n) print }
- if
- } forall
- ]
- % Stack: array of keys (names)
- ({) ws dup (str_keys_) exch wsna
- (\tstatic const cfont_dict_keys keys_ =) wl
- (\t { 0, 0, ) ws length wt (, ) ws 3 -1 roll wt (, ) ws
- dup wpa (, ) ws dup wva ( };) wl pop
- (\tcode = \(*pprocs->ref_dict_create\)\(&) ws wt
- (, &keys_, str_keys_, &v_[0]\);) wl
- (\tif (code < 0) return code;) wl
- (}) wl
- (}) wl
- } bind def
-
- % Write a character dictionary.
- % We save a lot of space by abbreviating keys which appear in
- % StandardEncoding or ISOLatin1Encoding.
- /wcd % namestring createtype dict valuetype writevalueproc ->
- { % Keys present in StandardEncoding or ISOLatin1Encoding:
- 2 index
- (static const charindex enc_keys_[] = {) wl
- [ exch 0 exch
- { pop decoding 1 index known
- { decoding exch get ({) ws dup -8 bitshift wt
- (,) ws 255 and wt (}, ) ws
- 1 add dup 5 mod 0 eq { (\n) ws } if
- }
- { exch }
- ifelse
- }
- forall pop
- ]
- ({0,0}\n};) wl
- % Other keys:
- (str_keys_) exch wsna
- % Values, with those corresponding to stdkeys first:
- (static const ) ws 1 index ws
- ( values_[] = {) wl
- 2 index
- { decoding 2 index known
- { exch pop 1 index exec }
- { pop pop }
- ifelse
- }
- forall
- 2 index
- { decoding 2 index known
- { pop pop }
- { exch pop 1 index exec }
- ifelse
- }
- forall
- (\t0\n};) wl
- % Actual creation code:
- (static const cfont_dict_keys keys_ = {) wl
- (\tenc_keys_, countof\(enc_keys_\) - 1,) wl
- (\t) ws 2 index length wt ( - \(countof\(enc_keys_\) - 1\), 0, ) ws
- pop pop
- dup wpa (, ) ws wva () wl
- (};) wl
- (\tcode = \(*pprocs->) ws ws (_dict_create\)\(&) ws ws
- (, &keys_, str_keys_, &values_[0]\);) wl
- (\tif ( code < 0 ) return code;) wl
- } bind def
-
- % ------ Writers for special objects ------ %
-
- /writespecial 10 dict dup begin
-
- /FontInfo { 0 wd } def
-
- /Private { 0 wd } def
-
- /CharStrings
- { ({) wl
- (CharStrings) (string) 3 -1 roll (char) { wsn } wcd pop
- (}) wl
- } bind def
-
- /Metrics
- { ({) wl
- exch (num) 3 -1 roll (float) { (\t) ws wtstring cvs ws (,) wl } wcd
- (}) wl
- } bind def
-
- /Metrics2 /Metrics load def
-
- /CDevProc pop % NOT IMPLEMENTED YET
-
- /FDepVector pop % (converted to a list of font names)
-
- end def
-
- % ------ The main program ------ %
-
- % Construct an inverse dictionary of encodings.
- [ /StandardEncoding /ISOLatin1Encoding
- /SymbolEncoding /DingbatsEncoding
- /KanjiSubEncoding
- ]
- dup length dict begin
- { mark exch dup { .findencoding exch def } stopped cleartomark
- } forall
- currentdict end /encodingnames exch def
-
- % Invert the StandardEncoding and ISOLatin1Encoding vectors.
- 512 dict begin
- 0 1 255 { dup ISOLatin1Encoding exch get exch 256 add def } for
- 0 1 255 { dup StandardEncoding exch get exch def } for
- currentdict end /decoding exch def
-
- /writefont % cfilename procname -> [writes the current font]
- { (gsf_) exch concatstrings
- /fontprocname exch def
- /cfname exch def
- /cfile cfname (w) file def
-
- % Remove unwanted keys from the font.
- currentfont dup length dict begin { def } forall
- { /FID /MIDVector /CurMID } { currentdict exch undef } forall
- /Font currentdict end def
-
- % Replace the FDepVector with a list of font names.
- Font /FDepVector .knownget
- { [ exch { /FontName get } forall ]
- Font /FDepVector 3 -1 roll put
- }
- if
-
- % Find all the special objects we know about.
- % wo uses this to write out references to otherwise intractable objects.
- /otherobjs writespecial length dict dup begin
- writespecial
- { pop Font 1 index .knownget { exch def } { pop } ifelse
- }
- forall
- end def
-
- % Define a dummy FontInfo, in case the font doesn't have one.
- /FontInfo 0 dict def
-
- % Write out the boilerplate.
- Font begin
- (/* Portions of this file are subject to the following notice: */) wl
- (/*) wl
- ( * ) ws systemdict /copyright get ws
- ( * All rights reserved.) wl
- ( */) wl
- FontInfo /Notice known
- { (/* Portions of this file are also subject to the following notice: */) wl
- (/****************************************************************) wl
- FontInfo /Notice get wl
- ( ****************************************************************/) wl
- } if
- () wl
- (/* ) ws cfname ws ( */) wl
- (/* This file was created by the ) ws product ws ( font2c utility. */) wl
- () wl
- (#include "ccfont.h") wl
- () wl
-
- % Write the procedure prologue.
- (#ifdef __PROTOTYPES__) wl
- (int huge) wl
- fontprocname ws ((const cfont_procs *pprocs, ref *pfont)) wl
- (#else) wl
- (int huge) wl
- fontprocname ws ((pprocs, pfont) const cfont_procs *pprocs; ref *pfont;) wl
- (#endif) wl
- ({\tint code;) wl
- (\tref Font;) wl
- otherobjs
- { exch pop (\tref ) ws wt (;) wl }
- forall
-
- % Write out the special objects.
- otherobjs
- { exch writespecial 2 index get exec
- }
- forall
-
- % Write out the main font dictionary.
- % If possible, substitute the encoding name for the encoding;
- % PostScript code will fix this up.
- { /Encoding /PrefEnc }
- { Font 1 index .knownget
- { encodingnames exch .knownget { def } { pop } ifelse }
- { pop }
- ifelse
- }
- forall
- (Font) Font FontType 0 eq { 5 } { 1 } ifelse wd
-
- % Finish the procedural initialization code.
- (\t*pfont = Font;) wl
- (\treturn 0;) wl
- (}) wl
- end % Font
-
- cfile closefile
-
- } bind def
-
- end def % font2cdict
-
- % Compute the procedure name from the font name.
- /makefontprocname % fontname -> procname
- { =string cvs
- dup length 1 sub -1 0
- { dup =string exch get 45 eq { =string exch 95 put } { pop } ifelse
- }
- for
- } def
-
- /writefont { font2cdict begin writefont end } def
-
- % If the program was invoked from the command line, run it now.
- [ shellarguments
- { counttomark dup 2 eq exch 3 eq or
- { counttomark -1 roll cvn
- (Converting ) print dup =only ( font.\n) print flush
- dup FontDirectory exch known { dup FontDirectory exch undef } if
- findfont setfont
- (FontName is ) print currentfont /FontName get ==only (.\n) print flush
- counttomark 1 eq
- { % Construct the procedure name from the file name.
- currentfont /FontName get makefontprocname
- }
- if
- writefont
- (Done.\n) print flush
- }
- { cleartomark
- (Usage: font2c fontname cfilename.c [shortname]\n) print
- ( e.g.: font2c Courier cour.c\n) print flush
- mark
- }
- ifelse
- }
- if pop
-