Merge pull request #303 from gagern/metrics
Improve font metrics creation
This commit is contained in:
commit
6357a34828
5
Makefile
5
Makefile
|
@ -79,8 +79,11 @@ test:
|
|||
./node_modules/.bin/jasmine-node test/katex-spec.js
|
||||
./node_modules/.bin/jasmine-node contrib/auto-render/auto-render-spec.js
|
||||
|
||||
PERL=perl
|
||||
PYTHON=$(shell python2 --version >/dev/null 2>&1 && echo python2 || echo python)
|
||||
|
||||
metrics:
|
||||
cd metrics && ./mapping.pl | ./extract_tfms.py | ./extract_ttfs.py | ./replace_line.py
|
||||
cd metrics && $(PERL) ./mapping.pl | $(PYTHON) ./extract_tfms.py | $(PYTHON) ./extract_ttfs.py | $(PYTHON) ./format_json.py > ../src/fontMetricsData.json
|
||||
|
||||
clean:
|
||||
rm -rf build/*
|
||||
|
|
|
@ -7,15 +7,15 @@ There are several requirements for generating the metrics used by KaTeX.
|
|||
this by running `tex --version`, and seeing if it has a line that looks like
|
||||
> kpathsea version 6.2.0
|
||||
|
||||
- You need the JSON module for perl. You can install this either from CPAN or with
|
||||
your package manager.
|
||||
- You need the JSON module for perl. You can install this either from CPAN
|
||||
(possibly using the `cpan` command line tool) or with your package manager.
|
||||
|
||||
- You need the python fontforge module. This is probably either installed with
|
||||
fontforge or can be installed from your package manager.
|
||||
- You need the python module fonttools. You can install this either from PyPi
|
||||
(using `easy_install` or `pip`) or with your package manager.
|
||||
|
||||
Once you have these things, run
|
||||
|
||||
make metrics
|
||||
|
||||
which should generate new metrics and place them into `fontMetrics.js`. You're
|
||||
done!
|
||||
which should generate new metrics and place them into `fontMetricsData.json`.
|
||||
You're done!
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import fontforge
|
||||
from fontTools.ttLib import TTFont
|
||||
import sys
|
||||
import json
|
||||
|
||||
|
@ -60,36 +60,50 @@ def main():
|
|||
start_json = json.load(sys.stdin)
|
||||
|
||||
for font, chars in metrics_to_extract.iteritems():
|
||||
fontInfo = fontforge.open("../static/fonts/KaTeX_" + font + ".ttf")
|
||||
fontInfo = TTFont("../static/fonts/KaTeX_" + font + ".ttf")
|
||||
glyf = fontInfo["glyf"]
|
||||
unitsPerEm = float(fontInfo["head"].unitsPerEm)
|
||||
|
||||
for glyph in fontInfo.glyphs():
|
||||
try:
|
||||
char = unichr(glyph.unicode)
|
||||
except ValueError:
|
||||
# We keep ALL Unicode cmaps, not just fontInfo["cmap"].getcmap(3, 1).
|
||||
# This is playing it extra safe, since it reports inconsistencies.
|
||||
# Platform 0 is Unicode, platform 3 is Windows. For platform 3,
|
||||
# encoding 1 is UCS-2 and encoding 10 is UCS-4.
|
||||
cmap = [t.cmap for t in fontInfo["cmap"].tables
|
||||
if (t.platformID == 0)
|
||||
or (t.platformID == 3 and t.platEncID in (1, 10))]
|
||||
|
||||
for char, base_char in chars.iteritems():
|
||||
code = ord(char)
|
||||
names = set(t.get(code) for t in cmap)
|
||||
if not names:
|
||||
sys.stderr.write(
|
||||
"Codepoint {} of font {} maps to no name\n"
|
||||
.format(code, font))
|
||||
continue
|
||||
if len(names) != 1:
|
||||
sys.stderr.write(
|
||||
"Codepoint {} of font {} maps to multiple names: {}\n"
|
||||
.format(code, font, ", ".join(sorted(names))))
|
||||
continue
|
||||
name = names.pop()
|
||||
|
||||
if char in chars:
|
||||
_, depth, _, height = glyph.boundingBox()
|
||||
height = depth = italic = skew = 0
|
||||
glyph = glyf[name]
|
||||
if glyph.numberOfContours:
|
||||
height = glyph.yMax
|
||||
depth = -glyph.yMin
|
||||
if base_char:
|
||||
base_char_str = str(ord(base_char))
|
||||
base_metrics = start_json[font][base_char_str]
|
||||
italic = base_metrics["italic"]
|
||||
skew = base_metrics["skew"]
|
||||
|
||||
depth = -depth
|
||||
|
||||
base_char = chars[char]
|
||||
if base_char:
|
||||
base_char_str = str(ord(base_char))
|
||||
base_metrics = start_json[font][base_char_str]
|
||||
|
||||
italic = base_metrics["italic"]
|
||||
skew = base_metrics["skew"]
|
||||
else:
|
||||
italic = 0
|
||||
skew = 0
|
||||
|
||||
start_json[font][ord(char)] = {
|
||||
"height": height / fontInfo.em,
|
||||
"depth": depth / fontInfo.em,
|
||||
"italic": italic,
|
||||
"skew": skew,
|
||||
}
|
||||
start_json[font][str(code)] = {
|
||||
"height": height / unitsPerEm,
|
||||
"depth": depth / unitsPerEm,
|
||||
"italic": italic,
|
||||
"skew": skew,
|
||||
}
|
||||
|
||||
sys.stdout.write(
|
||||
json.dumps(start_json, separators=(',', ':'), sort_keys=True))
|
||||
|
|
16
metrics/format_json.py
Normal file
16
metrics/format_json.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import json
|
||||
|
||||
data = json.load(sys.stdin)
|
||||
sep = "{\n"
|
||||
for font in sorted(data):
|
||||
sys.stdout.write(sep + json.dumps(font))
|
||||
sep = ": {\n "
|
||||
for glyph in sorted(data[font], key=int):
|
||||
sys.stdout.write(sep + json.dumps(glyph) + ": ")
|
||||
sys.stdout.write(json.dumps(data[font][glyph], sort_keys=True))
|
||||
sep = ",\n "
|
||||
sep = "\n},\n"
|
||||
sys.stdout.write("\n}}\n");
|
|
@ -135,8 +135,6 @@ $map{cmmi10} = {
|
|||
0x2E => 0x25B9, # \triangleright
|
||||
0x2F => 0x25C3, # \triangleleft
|
||||
|
||||
0x3A => 0x2E, # .
|
||||
0x3B => 0x2C, # ,
|
||||
0x3C => 0x3C, # <
|
||||
0x3D => 0x2215, # /
|
||||
0x3E => 0x3E, # >
|
||||
|
@ -148,16 +146,19 @@ $map{cmmi10} = {
|
|||
0x5F => 0x2322, # \frown
|
||||
0x60 => 0x2113, # \ell
|
||||
|
||||
0x7B => 0x131, # \imath
|
||||
0x7C => 0x237, # \jmath
|
||||
0x7D => 0x2118, # \wp
|
||||
0x7E => [0x20D7,-653,0],# \vec
|
||||
],
|
||||
|
||||
"Main-Italic" => [
|
||||
0x7B => 0x131, # \imath
|
||||
0x7C => 0x237, # \jmath
|
||||
]
|
||||
};
|
||||
|
||||
$map{cmsy10} = {
|
||||
"Main-Regular" => [
|
||||
[0,1] => 0x2212, # -
|
||||
0 => 0x2212, # -
|
||||
1 => 0x22C5, # \cdot
|
||||
2 => 0xD7, # \times
|
||||
3 => 0x2217, # \ast
|
||||
|
@ -425,8 +426,6 @@ $map{cmti10} = {
|
|||
[7,8] => 0x3A5, # \Upsilon, \Phi
|
||||
[9,0xA] => 0x3A8, # \Psi, \Omega
|
||||
|
||||
0x10 => 0x131, # \imath (roman)
|
||||
0x11 => 0x237, # \jmath (roman)
|
||||
0x12 => [0x300,-511,0], # \grave (combining)
|
||||
0x13 => [0x301,-511,0], # \acute (combining)
|
||||
0x14 => [0x30C,-511,0], # \check (combining)
|
||||
|
@ -557,8 +556,6 @@ $map{cmmib10} = {
|
|||
0x2E => 0x25B9, # \triangleright
|
||||
0x2F => 0x25C3, # \triangleleft
|
||||
|
||||
0x3A => 0x2E, # .
|
||||
0x3B => 0x2C, # ,
|
||||
0x3C => 0x3C, # <
|
||||
0x3D => 0x2215, # /
|
||||
0x3E => 0x3E, # >
|
||||
|
@ -571,8 +568,6 @@ $map{cmmib10} = {
|
|||
0x60 => 0x2113, # \ell
|
||||
0x68 => 0x210F, # \hbar (bar added below)
|
||||
|
||||
0x7B => 0x131, # \imath
|
||||
0x7C => 0x237, # \jmath
|
||||
0x7D => 0x2118, # \wp
|
||||
0x7E => [0x20D7,-729,0],# \vec
|
||||
],
|
||||
|
@ -580,7 +575,7 @@ $map{cmmib10} = {
|
|||
|
||||
$map{cmbsy10} = {
|
||||
"Main-Bold" => [
|
||||
[0,1] => 0x2212, # -
|
||||
0 => 0x2212, # -
|
||||
1 => 0x22C5, # \cdot
|
||||
2 => 0xD7, # \times
|
||||
3 => 0x2217, # \ast
|
||||
|
@ -973,6 +968,12 @@ sub add_to_output {
|
|||
"yshift" => $yshift
|
||||
};
|
||||
|
||||
if (defined($output{$mjfont}{$to})) {
|
||||
print STDERR "Duplicate mapping $to for $mjfont: " .
|
||||
$output{$mjfont}{$to}{font} . ":" .
|
||||
$output{$mjfont}{$to}{char} . " vs. $cmfont:$from\n";
|
||||
die "Duplicate mapping!"; # disable this line to see all of them
|
||||
}
|
||||
$output{$mjfont}{$to} = $data;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
import sys
|
||||
|
||||
with open("../src/fontMetrics.js", "r") as metrics:
|
||||
old_lines = file.readlines(metrics)
|
||||
|
||||
replace = sys.stdin.read()
|
||||
|
||||
with open("../src/fontMetrics.js", "w") as output:
|
||||
for line in old_lines:
|
||||
if line.startswith("var metricMap"):
|
||||
output.write("var metricMap = ")
|
||||
output.write(replace)
|
||||
output.write(";\n")
|
||||
else:
|
||||
output.write(line)
|
|
@ -14,7 +14,7 @@
|
|||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"browserify": "~2.29.1",
|
||||
"browserify": "^10.2.4",
|
||||
"clean-css": "~2.2.15",
|
||||
"express": "~3.3.3",
|
||||
"jasmine-node": "2.0.0-beta4",
|
||||
|
|
File diff suppressed because one or more lines are too long
1351
src/fontMetricsData.json
Normal file
1351
src/fontMetricsData.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user