From defd7289851e96ae7cc91a41988e3e7f8303d903 Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Sat, 14 Mar 2026 01:27:42 +0100 Subject: [PATCH] Autohint for improved rendering on Kobo --- VERSION | 2 +- build.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 5625e59..7e32cd5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2 +1.3 diff --git a/build.py b/build.py index 9129c18..df35a3b 100755 --- a/build.py +++ b/build.py @@ -621,6 +621,40 @@ def fix_ttf_style_flags(ttf_path, style_suffix): print(f" Normalized style flags for {style_suffix}") +def autohint_ttf(ttf_path): + """Run ttfautohint to add proper TrueType hinting. + + Kobo uses FreeType for font rasterization. Without embedded hints, + FreeType's auto-hinter computes "blue zones" from the outlines. + When a glyph (e.g. italic 't') has a curved tail that dips just + below the baseline, the auto-hinter snaps that edge up to y=0 — + shifting the entire glyph upward relative to its neighbors. This + is most visible at small sizes. + + ttfautohint replaces FreeType's built-in auto-hinter with its own + hinting, which may handle sub-baseline overshoots more gracefully. + The resulting bytecode is baked into the font, so FreeType uses + the TrueType interpreter instead of falling back to auto-hinting. + """ + if not shutil.which("ttfautohint"): + print(" [warn] ttfautohint not found, skipping", file=sys.stderr) + return + + tmp_path = ttf_path + ".autohint.tmp" + result = subprocess.run( + ["ttfautohint", "--no-info", ttf_path, tmp_path], + capture_output=True, text=True, + ) + if result.returncode != 0: + print(f" [warn] ttfautohint failed: {result.stderr.strip()}", file=sys.stderr) + if os.path.exists(tmp_path): + os.remove(tmp_path) + return + + os.replace(tmp_path, ttf_path) + print(f" Autohinted with ttfautohint") + + # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # MAIN # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ @@ -764,6 +798,7 @@ def _build(tmp_dir, family=DEFAULT_FAMILY, old_kern=True, outline_fix=True): if outline_fix: clean_ttf_degenerate_contours(ttf_path) fix_ttf_style_flags(ttf_path, style_suffix) + autohint_ttf(ttf_path) print("\n" + "=" * 60)