
Summary: Add support for math-mode accents. This involves a couple changes. First, in order to correctly position the accents, we must know the kern between every character and the "skewchar" in that font. To do this, we improve our tfm parser to run the mini-kern-language and calculate kerns. We then export these into fontMetrics.js. Then, we add normal support for accents. In particular, we do some special handling for supsubs around accents. This involves building the supsub separately without the accent, and then replacing its base with the built accent. Finally, the character in the fonts for the \vec command is a combining unicode character, so it is shifted to the left, but none of the other characters do this. We add some special handling for \vec to account for this. Fixes #7 Test Plan: - Make sure tests pass - Make sure no huxley screenshots changed, and the new one looks good Reviewers: alpert Reviewed By: alpert Differential Revision: http://phabricator.khanacademy.org/D13157
95 lines
2.6 KiB
Python
Executable File
95 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import collections
|
|
import json
|
|
import parse_tfm
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def find_font_path(font_name):
|
|
try:
|
|
font_path = subprocess.check_output(['kpsewhich', font_name])
|
|
except OSError:
|
|
raise RuntimeError("Couldn't find kpsewhich program, make sure you" +
|
|
" have TeX installed")
|
|
except subprocess.CalledProcessError:
|
|
raise RuntimeError("Couldn't find font metrics: '%s'" % font_name)
|
|
return font_path.strip()
|
|
|
|
|
|
def main():
|
|
mapping = json.load(sys.stdin)
|
|
|
|
fonts = [
|
|
'cmbsy10.tfm',
|
|
'cmbx10.tfm',
|
|
'cmex10.tfm',
|
|
'cmmi10.tfm',
|
|
'cmmib10.tfm',
|
|
'cmr10.tfm',
|
|
'cmsy10.tfm',
|
|
'cmti10.tfm',
|
|
'msam10.tfm',
|
|
'msbm10.tfm'
|
|
]
|
|
|
|
# Extracted by running `\font\a=<font>` and then `\showthe\skewchar\a` in
|
|
# TeX, where `<font>` is the name of the font listed here. The skewchar
|
|
# will be printed out in the output. If it outputs `-1`, that means there
|
|
# is no skewchar, so we use `None` here.
|
|
font_skewchar = {
|
|
'cmbsy10': None,
|
|
'cmbx10': None,
|
|
'cmex10': None,
|
|
'cmmi10': 127,
|
|
'cmmib10': None,
|
|
'cmr10': None,
|
|
'cmsy10': 48,
|
|
'cmti10': None,
|
|
'msam10': None,
|
|
'msbm10': None
|
|
}
|
|
|
|
font_name_to_tfm = {}
|
|
|
|
for font_name in fonts:
|
|
font_basename = font_name.split('.')[0]
|
|
font_path = find_font_path(font_name)
|
|
font_name_to_tfm[font_basename] = parse_tfm.read_tfm_file(font_path)
|
|
|
|
families = collections.defaultdict(dict)
|
|
|
|
for family, chars in mapping.iteritems():
|
|
for char, char_data in chars.iteritems():
|
|
char_num = int(char)
|
|
|
|
font = char_data['font']
|
|
tex_char_num = int(char_data['char'])
|
|
yshift = float(char_data['yshift'])
|
|
|
|
tfm_char = font_name_to_tfm[font].get_char_metrics(tex_char_num)
|
|
|
|
height = round(tfm_char.height + yshift / 1000.0, 5)
|
|
depth = round(tfm_char.depth - yshift / 1000.0, 5)
|
|
italic = round(tfm_char.italic_correction, 5)
|
|
|
|
skewkern = 0.0
|
|
if (font_skewchar[font] and
|
|
font_skewchar[font] in tfm_char.kern_table):
|
|
skewkern = round(
|
|
tfm_char.kern_table[font_skewchar[font]], 5)
|
|
|
|
families[family][char_num] = {
|
|
'height': height,
|
|
'depth': depth,
|
|
'italic': italic,
|
|
'skew': skewkern,
|
|
}
|
|
|
|
sys.stdout.write(
|
|
json.dumps(families, separators=(',', ':'), sort_keys=True))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|