3 # mf-to-table.py -- convert spacing info in MF logs .afm and .tex
5 # source file of the GNU LilyPond music typesetter
7 # (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
17 postfixes
= ['log', 'dvi', '2602gf', 'tfm']
19 def read_log_file (fn
):
20 str = open (fn
).read ()
21 str = re
.sub ('\n', '', str)
22 str = re
.sub ('[\t ]+', ' ', str)
26 def include_func (match
, d
= deps
):
27 d
.append (match
.group (1))
30 def auto_func (match
, a
= autolines
):
31 a
.append (match
.group (1))
34 str = re
.sub ('\(([a-zA-Z_0-9-]+\.mf)', include_func
, str)
35 str = re
.sub ('@{(.*?)@}', auto_func
, str)
37 return (autolines
, deps
)
46 def tfm_checksum (fn
):
47 sys
.stderr
.write ("Reading checksum from `%s'\n" % fn
)
55 cs
= cs
+ (long (ord (b
)) << shift
)
60 ## ugh. What's font_family supposed to be? It's not an afm thing.
62 def parse_logfile (fn
):
63 (autolines
, deps
) = read_log_file (fn
)
69 tags
= string
.split(l
, '@:')
70 if tags
[0] == 'group':
72 elif tags
[0] == 'puorg':
74 elif tags
[0] == 'char':
77 name
= group
+ '-' + name
79 'description': tags
[1],
82 'code': string
.atoi (tags
[2]),
83 'breapth':string
.atof (tags
[3]),
84 'width': string
.atof (tags
[4]),
85 'depth':string
.atof (tags
[5]),
86 'height':string
.atof (tags
[6]),
87 'wx': string
.atof (tags
[7]),
88 'wy':string
.atof (tags
[8]),
90 charmetrics
.append (m
)
91 elif tags
[0] == 'font':
93 font_family
= (tags
[3])
94 # To omit 'GNU' (foundry) from font name proper:
98 tags
.append ('Regular')
101 encoding
= re
.sub (' ','-', tags
[5])
104 global_info
['DesignSize'] = string
.atof (tags
[4])
105 global_info
['FontName'] = string
.join (name
,'-')
106 global_info
['FullName'] = string
.join (name
,' ')
107 global_info
['FamilyName'] = string
.join (name
[1:-1],
110 global_info
['Weight'] = tags
[4]
112 global_info
['Weight'] = tags
[-1]
114 global_info
['FontBBox'] = '0 0 1000 1000'
115 global_info
['Ascender'] = '0'
116 global_info
['Descender'] = '0'
117 global_info
['EncodingScheme'] = encoding
119 return (global_info
, charmetrics
, deps
)
122 def write_afm_char_metric(file, charmetric
):
125 tup
= (charmetric
['code'],
127 -charmetric
['breapth'] *f
,
128 -charmetric
['depth']*f
,
129 charmetric
['width']*f
,
130 charmetric
['height']*f
,
131 charmetric
['wx'] * f
,
132 charmetric
['wy'] * f
)
134 file.write ('C %d ; N %s ; B %d %d %d %d ; W %d %d ;\n'% tup
)
136 def write_afm_header (file):
137 file.write ("StartFontMetrics 2.0\n")
138 file.write ("Comment Automatically generated by mf-to-table.py\n")
140 def write_afm_metric (file, global_info
, charmetrics
):
141 for (k
,v
) in global_info
.items():
142 file.write ("%s %s\n" % (k
,v
))
143 file.write ('StartCharMetrics %d\n' % len(charmetrics
))
144 for m
in charmetrics
:
145 write_afm_char_metric (file,m
)
146 file.write ('EndCharMetrics\n')
147 file.write ('EndFontMetrics\n')
150 def write_tex_defs (file, global_info
, charmetrics
):
151 ##nm = global_info['FontFamily']
153 for m
in charmetrics
:
154 file.write (r
'''\gdef\%s%s{\char%d}%%%s''' % (nm
, m
['tex'], m
['code'],'\n'))
155 file.write ('\\endinput\n')
157 def write_ps_encoding (name
, file, global_info
, charmetrics
):
158 encs
= ['.notdef'] * 256
159 for m
in charmetrics
:
160 encs
[m
['code']] = m
['tex']
162 file.write ('/%s [\n' % name
)
163 for m
in range(0,256):
164 file.write (' /%s %% %d\n' % (encs
[m
], m
))
165 file.write ('] def\n')
167 def write_fontlist (file, global_info
, charmetrics
):
168 ##nm = global_info['FontFamily']
172 %% LilyPond file to list all font symbols and the corresponding names
173 %% Automatically generated by mf-to-table.py
174 \score{ \new Lyrics \lyrics { \time %d/8
175 """ % (2*per_line
+1))
178 for m
in charmetrics
:
182 ## \musicglyph and \markup require "_" to be escaped differently:
185 scm_string
= re
.sub('_', r
'_', m
['name'])
186 tex_string
= re
.sub ('_', r
'\\_' , m
['name'])
188 ## prevent TeX from interpreting "--" as long dash:
189 tex_string
=re
.sub('--','-{}-', tex_string
)
191 file.write (' \\markup { \\raise #0.75 \\vcenter \\musicglyph #"%s" " %s" } 4 \n' % (scm_string
, tex_string
))
194 file.write ('\skip 8 \\break\n')
202 \override SeparationItem #'padding = #2
203 minimumVerticalExtent = ##f
207 \remove "Bar_number_engraver"
213 def write_deps (file, deps
, targets
):
217 t
= re
.sub ( '^\\./', '', t
)
218 file.write ('%s '% t
)
221 file.write ('%s ' % d
)
225 sys
.stdout
.write(r
"""Usage: mf-to-table [OPTIONS] LOGFILEs
226 Generate feta metrics table from preparated feta log.
229 -a, --afm=FILE specify .afm file
230 -d, --dep=FILE print dependency info to FILE
231 -h, --help print this help
232 -l, --ly=FILE name output table
233 -o, --outdir=DIR prefix for dependency info
234 -p, --package=DIR specify package
235 -t, --tex=FILE name output tex chardefs
243 (options
, files
) = getopt
.getopt(
244 sys
.argv
[1:], 'a:d:hl:o:p:t:',
245 ['enc=', 'afm=', 'outdir=', 'dep=', 'tex=', 'ly=', 'debug', 'help', 'package='])
258 if o
== '--dep' or o
== '-d':
260 elif o
== '--outdir' or o
== '-o':
262 elif o
== '--tex' or o
== '-t':
266 elif o
== '--ly' or o
== '-l':
268 elif o
== '--help' or o
== '-h':
270 elif o
=='--afm' or o
== '-a':
274 elif o
== '-p' or o
== '--package':
280 base
= re
.sub ('.tex$', '', texfile_nm
)
283 (g
, m
, deps
) = parse_logfile (filenm
)
284 cs
= tfm_checksum (re
.sub ('.log$', '.tfm', filenm
))
285 afm
= open (afmfile_nm
, 'w')
287 write_afm_header (afm
)
288 afm
.write ("Comment TfmCheckSum %d\n" % cs
)
289 afm
.write ("Comment DesignSize %.2f\n" % g
['DesignSize'])
293 write_afm_metric (afm
, g
, m
)
295 write_tex_defs (open (texfile_nm
, 'w'), g
, m
)
296 enc_name
= 'FetaEncoding'
297 if re
.search ('parmesan', filenm
) :
298 enc_name
= 'ParmesanEncoding'
299 elif re
.search ('feta-brace', filenm
) :
300 enc_name
= 'FetaBraceEncoding'
302 write_ps_encoding (enc_name
, open (enc_nm
, 'w'), g
, m
)
305 write_deps (open (depfile_nm
, 'wb'), deps
,
306 [base
+ '.dvi', base
+ '.pfa', base
+ '.pfb',
307 texfile_nm
, afmfile_nm
])
309 write_fontlist (open (lyfile_nm
, 'w'), g
, m
)