ufo-tdkit-tools
PS hints extraction, optimization, and preserve-mode compilation for UFO fonts.
Features
- extraction -- Convert binary fonts (OTF/TTF/WOFF/WOFF2) to UFO with full PS hint preservation (multi-entry
hintSetList, counter tripletshstem3/vstem3, font-level Private dict includingStdHW/StdVW) and FEA post-processing (one feature block per tag, inlinedaaltfor spec compliance). - ps_hints -- Parse, optimize, analyze, and validate PostScript hints in UFO fonts; move hints between processedglyphs / glyph lib / default layers.
- compilation -- Compile UFO back to OTF preserving PS hints (via AFDKO
makeotf+ per-glyph charstring merge, then production glyph names +cffsubrsubroutinization). Parallel batch viaProcessPoolExecutor.
Installation
pip install ufo-tdkit-tools # core (constants, ps_hints parser)
pip install ufo-tdkit-tools[extraction] # + binary font conversion
pip install ufo-tdkit-tools[compilation] # + OTF compilation with hints
pip install ufo-tdkit-tools[all] # everything
The extraction and compilation extras pull in AFDKO (>=5,<6), whose wheels ship the tx and makeotf executables the compiler runs — nothing needs to be installed separately.
Quick start
The simplest path is the process_font pipeline — any input (binary or
UFO, hinted or not) becomes a hinted OTF + a clean UFO:
from ufo_tdkit_tools import process_font
result = process_font(
"input.otf", # OTF / TTF / WOFF / WOFF2 / UFO
"out.otf",
"out.ufo",
hint_source="auto", # priority: processed > v2 > public_ps
autohint="fill", # "fill" | "all" | "off"
optimize=False, # set True to run the ps_hints optimizer
)
assert result.success
print(result.glyphs_with_hints, "/", result.glyphs_total,
"autohinted=", result.autohinted_count,
"in otf=", result.otf_glyphs_hinted)
Glyphs the chosen source does not hint are autohinted individually with
afdko.otfautohint — a partially hinted master (base forms hinted,
composites not) comes out fully hinted, with the authored hints kept.
autohint="all" re-hints everything instead, autohint="off" leaves the
gaps alone.
For the lower-level entry points (extraction.convert_binary_to_ufo,
compilation.compile_otf_preserve_optimized, the ps_hints parser /
optimizer / validator / batch wrappers), see docs/API.md.
Legacy kern table for Word
Modern build tools emit kerning only as GPOS, which Microsoft Word ignores.
add_legacy_kern regenerates the old-style kern table from the font's own
GPOS kern feature, rewriting the binary so that nothing but kern changes:
from ufo_tdkit_tools import add_legacy_kern
pairs = add_legacy_kern("Sans-Regular.ttf") # 0 if the font has no GPOS kerning
It needs only fontTools — no extras required.
Command line
Installing the package (uv sync / pip install) provides the
ufo-tdkit-tools console script (also runnable as
python -m ufo_tdkit_tools). It wraps process_font for batch builds:
# Re-hint/optimize a batch of OTFs in place (temp UFO created & discarded)
ufo-tdkit-tools optimize-otf --in-place *.otf
# Or write fresh <stem>.otf + <stem>.ufo pairs into a directory
ufo-tdkit-tools optimize-otf -o build/ Sans-Regular.otf Sans-Bold.otf
# Skip the ps_hints optimizer (autohint + compile only)
ufo-tdkit-tools optimize-otf --in-place --no-optimize *.otf
# Keep only the authored hints, never call the autohinter
ufo-tdkit-tools optimize-otf -o build/ --autohint off Src.ufo
Every run prints one machine-parseable summary line and exits non-zero if any input failed — convenient inside a build log:
optimized=36 autohinted=0 failed=0
--in-place only rewrites .otf inputs (atomically, so a mid-pipeline
failure never corrupts the source). UFO and other binary inputs use -o DIR.
Round-trip fidelity
OTF → UFO → OTF preserves declared hstem/vstem positions and widths byte-for-byte, hint substitution between drawing operations, counter-mask grouping, and font-level Private dict scalars. The one structural exception is hint substitution that fires between subpaths (a hintmask immediately before a moveto, common on disconnected glyphs like i, j, dieresis-bearing letters): the autohint.v2 format has no anchor for these and AFDKO's own autohint produces the same flattening.
Metadata (OS/2, head, name) also round-trips: fsType, weight/width class, vendor ID, Unicode/code-page ranges, PANOSE, typo/win/hhea metrics, sub/superscript and strikeout, head.macStyle/head.flags, and all name records. The OS/2.fsSelection flags USE_TYPO_METRICS (bit 7), WWS (bit 8) and OBLIQUE (bit 9) are restored during extraction — ufo-extractor (≤ 0.8.1) drops them, so they are re-read straight from the source OS/2 table.
License
Apache-2.0
Metadata
Release files for ufo-tdkit-tools 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ufo_tdkit_tools-0.2.0.tar.gz | 104.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ufo_tdkit_tools-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 189.1 kB
Release files / ufo_tdkit_tools-0.2.0.tar.gz
| Download URL | ufo_tdkit_tools-0.2.0.tar.gz |
|---|---|
| Size | 104.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c0c88e16925206e44b21bd65d98a83aff47ac9f13e3dd6f183e6a696c9d55023
|
|
BLAKE2b-256 checksum How to use checksums |
17963e9c5f578124740d54e45fe3cef497283e0cfc4d8975793fe9047ac818f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / ufo_tdkit_tools-0.2.0-py3-none-any.whl
| Download URL | ufo_tdkit_tools-0.2.0-py3-none-any.whl |
|---|---|
| Size | 85.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4f6dd49cc2e19a0970e399aa2b61ecd99a52ae8636efdeab236810fcf974ff7
|
|
BLAKE2b-256 checksum How to use checksums |
19bde84f938ffdadeb36d1d2de3c86fed6cf4545c2918c7b12a2873a635cb4a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|