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--2003 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
+ (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] == 'char':
74 'description': tags
[1],
75 'name': group
+ '-' + tags
[7],
77 'code': string
.atoi (tags
[2]),
78 'breapth':string
.atof (tags
[3]),
79 'width': string
.atof (tags
[4]),
80 'depth':string
.atof (tags
[5]),
81 'height':string
.atof (tags
[6])
83 charmetrics
.append (m
)
84 elif tags
[0] == 'font':
86 font_family
= (tags
[3])
87 # To omit 'GNU' (foundry) from font name proper:
91 tags
.append ('Regular')
93 global_info
['FontName'] = string
.join (name
,'-')
94 global_info
['FullName'] = string
.join (name
,' ')
95 global_info
['FamilyName'] = string
.join (name
[1:-1],
98 global_info
['Weight'] = tags
[4]
100 global_info
['Weight'] = tags
[-1]
101 global_info
['FontBBox'] = '0 0 1000 1000'
102 global_info
['Ascender'] = '0'
103 global_info
['Descender'] = '0'
104 global_info
['EncodingScheme'] = 'FontSpecific'
106 return (global_info
, charmetrics
, deps
)
109 def write_afm_char_metric(file, charmetric
):
112 tup
= (charmetric
['code'],
113 (charmetric
['width'] + charmetric
['breapth'])*f
,
115 -charmetric
['breapth'] *f
,
116 -charmetric
['depth']*f
,
117 charmetric
['width']*f
,
118 charmetric
['height']*f
)
121 file.write ('C %d ; WX %d ; N %s ; B %d %d %d %d ;\n'% tup
)
123 def write_afm_header (file):
124 file.write ("StartFontMetrics 2.0\n")
125 file.write ("Comment Automatically generated by mf-to-table.py\n")
127 def write_afm_metric (file, global_info
, charmetrics
):
128 for (k
,v
) in global_info
.items():
129 file.write ("%s %s\n" % (k
,v
))
130 file.write ('StartCharMetrics %d\n' % len(charmetrics
))
131 for m
in charmetrics
:
132 write_afm_char_metric (file,m
)
133 file.write ('EndCharMetrics\n')
134 file.write ('EndFontMetrics\n')
137 def write_tex_defs (file, global_info
, charmetrics
):
138 ##nm = global_info['FontFamily']
140 for m
in charmetrics
:
141 file.write (r
'''\gdef\%s%s{\char%d}%%%s''' % (nm
, m
['tex'], m
['code'],'\n'))
142 file.write ('\\endinput\n')
144 def write_ps_encoding (file, global_info
, charmetrics
):
145 encs
= ['.notdef'] * 256
146 for m
in charmetrics
:
147 encs
[m
['code']] = m
['tex']
149 file.write ('/FetaEncoding [\n')
150 for m
in range(0,256):
151 file.write (' /%s %% %d\n' % (encs
[m
], m
))
152 file.write ('] def\n')
154 def write_fontlist (file, global_info
, charmetrics
):
155 ##nm = global_info['FontFamily']
159 %% LilyPond file to list all font symbols and the corresponding names
160 %% Automatically generated by mf-to-table.py
161 \score{\notes{\fatText\time %d/4
165 for m
in charmetrics
:
169 ## \musicglyph and \markup require "_" to be escaped differently:
170 musicglyphname
=re
.sub('_','\\\\_', m
['name'])
171 markupname
=re
.sub('_','\\\\_', musicglyphname
)
173 ## prevent TeX from interpreting "--" as long dash:
174 markupname
=re
.sub('--','-{}-', markupname
)
176 file.write (' s^\\markup { \\musicglyph #"%s" "%s" }\n' % (musicglyphname
, markupname
))
179 file.write (' \\break\n')
186 \remove "Bar_number_engraver"
187 TextScript \override #'extra-X-extent = #'(-1 . 1)
191 \remove "Clef_engraver"
192 \remove "Key_engraver"
193 \remove "Time_signature_engraver"
194 \remove "Staff_symbol_engraver"
195 minimumVerticalExtent = ##f
201 def write_deps (file, deps
, targets
):
205 t
= re
.sub ( '^\\./', '', t
)
206 file.write ('%s '% t
)
209 file.write ('%s ' % d
)
213 sys
.stdout
.write(r
"""Usage: mf-to-table [OPTIONS] LOGFILEs
214 Generate feta metrics table from preparated feta log.
217 -a, --afm=FILE specify .afm file
218 -d, --dep=FILE print dependency info to FILE
219 -h, --help print this help
220 -l, --ly=FILE name output table
221 -o, --outdir=DIR prefix for dependency info
222 -p, --package=DIR specify package
223 -t, --tex=FILE name output tex chardefs
231 (options
, files
) = getopt
.getopt(
232 sys
.argv
[1:], 'a:d:hl:o:p:t:',
233 ['enc=', 'afm=', 'outdir=', 'dep=', 'tex=', 'ly=', 'debug', 'help', 'package='])
246 if o
== '--dep' or o
== '-d':
248 elif o
== '--outdir' or o
== '-o':
250 elif o
== '--tex' or o
== '-t':
254 elif o
== '--ly' or o
== '-':
256 elif o
== '--help' or o
== '-h':
258 elif o
=='--afm' or o
== '-a':
262 elif o
== '-p' or o
== '--package':
268 base
= re
.sub ('.tex$', '', texfile_nm
)
271 (g
,m
, deps
) = parse_logfile (filenm
)
272 cs
= tfm_checksum (re
.sub ('.log$', '.tfm', filenm
))
273 afm
= open (afmfile_nm
, 'w')
275 write_afm_header (afm
)
276 afm
.write ("Comment TfmCheckSum %u\n" % cs
)
277 write_afm_metric (afm
, g
, m
)
279 write_tex_defs (open (texfile_nm
, 'w'), g
, m
)
280 write_ps_encoding (open (enc_nm
, 'w'), g
, m
)
282 write_deps (open (depfile_nm
, 'wb'), deps
, [base
+ '.dvi', base
+ '.pfa', base
+ '.pfb', texfile_nm
, afmfile_nm
])
284 write_fontlist(open (lyfile_nm
, 'w'), g
, m
)