3 # ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files
5 # source file of the GNU LilyPond music typesetter
7 # (c) 1998 Jan Nieuwenhuizen <janneke@gnu.org>
9 #TODO. This could be more efficient.
26 return name
+ ' version ' + version
;
29 sys
.stdout
.write (program_id () + '\n')
32 sys
.stdout
.write ("Usage: %s [options] [files]\n"
33 "ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files\n\n"
35 + " -d, --datadir=DIR use DIR for ps header/footer\n"
36 + " -h, --help print this help\n"
37 + " -o, --output=FILE set output file to FILE.\n"
45 (options
, files
) = getopt
.getopt (
46 sys
.argv
[1:], 'o:d:', ['help', 'package', 'output='])
50 if o
== '--help' or o
== '-h':
52 elif o
== '-d' or o
== '--datadir':
54 elif o
== '-o' or o
=='--output':
62 logfile
.write ('[%s' % f
)
69 logfile
.write ('can\'t open file %s\n ' % f
)
74 logfile
.write ('gulped empty file: %s\n'% f
)
80 font_name
= os
.path
.basename (os
.path
.splitext (mf
)[0])
82 output_name
= font_name
+ '.pfa'
85 logfile
.write ('Font: %s\n'% font_name
)
88 f
.write ('%!PS-AdobeFont-3.0: ' + font_name
+ '\n')
89 f
.write ('%%%%Creator: %s-%s\n' % (name
, version
))
93 /FontType 3 def %% Required elements of font
94 /FontName /%s def""" % font_name
)
96 /FontMatrix [.083 0 0 .083 0 0] def %% 12 is default height: 1/12 = 0.083
97 /FontBBox [-1000 -1000 1000 1000] def %% does not seem to matter.
98 /Encoding 256 array def %% Trivial encoding vector
99 0 1 255 {Encoding exch /.notdef put} for
103 /BuildGlyph { % Stack contains: font charname
105 -1000 -1000 1000 1000 % Bounding Box
107 exch /CharProcs get exch % Get CharProcs dictionary
108 2 copy known not {pop /.notdef} if % See if charname is known
109 get exec % Execute character procedure
112 /BuildChar { % Level 1 compatibility
113 1 index /Encoding get exch get
114 1 index /BuildGlyph get exec
118 end % of font dictionary
122 f
.write ('/%s\n' % font_name
)
124 'exch definefont pop % Define the font\n')
126 suspect_re
= re
.compile ('closepath ((gsave )*fill( grestore stroke)*) 1 setgray newpath (.*?) closepath fill')
133 suffixes
= [".[0-9]", ".[0-9][0-9]", ".[0-9][0-9][0-9]"]
135 files
= files
+ glob
.glob(font_name
+ suf
)
138 # concat all files into charprocs.
139 charprocs
= ' /.notdef {} def\n'
143 s
= re
.sub ('%[^\n]*\n', '', s
)
145 # if you want readable stuff, look at MP output.
146 s
= re
.sub ('[\n\t ]+', ' ', s
)
147 s
= re
.sub ('showpage', '', s
)
149 # MP's implementation of unfill confuses GS.
150 # Look for "Metapost & setgray" on deja.com
151 # we do some twiddling to use eofill i.s.o. fill
152 if re
.search ('setgray',s
):
153 m
= suspect_re
.search (s
)
158 # be complicated, in case of gsave/grestore.
159 # vill as quick hack to avoid duple substitutions.
160 fill
= re
.sub ('fill', 'eovill', fill
, count
= 1)
161 s
= re
.sub (m
.group (0), ' %s %s ' % (path
, fill
), s
)
162 m
= suspect_re
.search (s
)
164 s
= re
.sub ('eovill' , 'eofill', s
)
165 s
= re
.sub ('0 setgray' ,'', s
)
168 m
= re
.match ('.*\.([0-9]+)',i
)
169 n
= atoi (m
.group (1))
171 s
= '\n /%s-%d{\n%s} bind def\n' % (font_name
, n
, s
)
172 encoding
= encoding
+ 'Encoding %d /%s-%d put\n' % (n
, font_name
, n
)
173 charprocs
= charprocs
+ s
176 '/CharProcs 3 dict def % Subsidiary dictiorary for\n'
177 'CharProcs begin % individual character definitions\n')
180 f
.write ('end % of CharProcs\n')
186 ps_file
= open (output_name
, 'w')
192 logfile
.write ('Wrote PostScript font: %s\n' % output_name
)