extract_tfms.py (3188B)
1 #!/usr/bin/env python 2 3 import collections 4 import json 5 import parse_tfm 6 import subprocess 7 import sys 8 9 10 def find_font_path(font_name): 11 try: 12 font_path = subprocess.check_output(['kpsewhich', font_name]) 13 except OSError: 14 raise RuntimeError("Couldn't find kpsewhich program, make sure you" + 15 " have TeX installed") 16 except subprocess.CalledProcessError: 17 raise RuntimeError("Couldn't find font metrics: '%s'" % font_name) 18 return font_path.strip() 19 20 21 def main(): 22 mapping = json.load(sys.stdin) 23 24 fonts = [ 25 'cmbsy10.tfm', 26 'cmbx10.tfm', 27 'cmex10.tfm', 28 'cmmi10.tfm', 29 'cmmib10.tfm', 30 'cmr10.tfm', 31 'cmsy10.tfm', 32 'cmti10.tfm', 33 'msam10.tfm', 34 'msbm10.tfm', 35 'eufm10.tfm', 36 'cmtt10.tfm', 37 'rsfs10.tfm', 38 'cmss10.tfm', 39 ] 40 41 # Extracted by running `\font\a=<font>` and then `\showthe\skewchar\a` in 42 # TeX, where `<font>` is the name of the font listed here. The skewchar 43 # will be printed out in the output. If it outputs `-1`, that means there 44 # is no skewchar, so we use `None` here. 45 font_skewchar = { 46 'cmbsy10': None, 47 'cmbx10': None, 48 'cmex10': None, 49 'cmmi10': 127, 50 'cmmib10': None, 51 'cmr10': None, 52 'cmsy10': 48, 53 'cmti10': None, 54 'msam10': None, 55 'msbm10': None, 56 'eufm10': None, 57 'cmtt10': None, 58 'rsfs10': None, 59 'cmss10': None, 60 } 61 62 font_name_to_tfm = {} 63 64 for font_name in fonts: 65 font_basename = font_name.split('.')[0] 66 font_path = find_font_path(font_name) 67 font_name_to_tfm[font_basename] = parse_tfm.read_tfm_file(font_path) 68 69 families = collections.defaultdict(dict) 70 71 for family, chars in mapping.iteritems(): 72 for char, char_data in chars.iteritems(): 73 char_num = int(char) 74 75 font = char_data['font'] 76 tex_char_num = int(char_data['char']) 77 yshift = float(char_data['yshift']) 78 79 if family == "Script-Regular": 80 tfm_char = font_name_to_tfm[font].get_char_metrics(tex_char_num, 81 fix_rsfs=True) 82 else: 83 tfm_char = font_name_to_tfm[font].get_char_metrics(tex_char_num) 84 85 height = round(tfm_char.height + yshift / 1000.0, 5) 86 depth = round(tfm_char.depth - yshift / 1000.0, 5) 87 italic = round(tfm_char.italic_correction, 5) 88 width = round(tfm_char.width, 5) 89 90 skewkern = 0.0 91 if (font_skewchar[font] and 92 font_skewchar[font] in tfm_char.kern_table): 93 skewkern = round( 94 tfm_char.kern_table[font_skewchar[font]], 5) 95 96 families[family][char_num] = { 97 'height': height, 98 'depth': depth, 99 'italic': italic, 100 'skew': skewkern, 101 'width': width 102 } 103 104 sys.stdout.write( 105 json.dumps(families, separators=(',', ':'), sort_keys=True)) 106 107 if __name__ == '__main__': 108 main()