msoffice-kern
Derive a PowerPoint / MS Office–safe legacy kern table from a font's GPOS
kerning, without touching GPOS.
PowerPoint and the GDI text paths in MS Office do not read GPOS kerning — they
only kern by the old format-0 kern table. This package reads the full GPOS
kerning of a compiled static TTF or OTF/CFF, selects a reduced set of pairs,
and writes a single format-0 kern subtable. Modern applications keep using the
untouched GPOS; Office gets a working fallback.
It is a single, well-tested, deterministic implementation of that conversion:
golden byte tests lock the produced kern table, so the same input always
yields the same bytes.
Installation
pip install msoffice-kern
Usage
from fontTools.ttLib import TTFont
from msoffice_kern import apply_legacy_kern
font = TTFont("Family-Regular.ttf") # a compiled static TTF/OTF
result = apply_legacy_kern(font) # mutates font in place; GPOS untouched
if result.applied:
font.save("Family-Regular.ttf")
print(result.summary())
apply_legacy_kern(font, *, max_pairs=10900, min_abs_value=5, profile="latin-extended-text", strict=False) returns a LegacyKernResult.
With strict=False (default) a font whose kerning cannot be derived — no
usable GPOS kern, no cmap, malformed GPOS, or a variable font — yields
applied=False instead of raising, so a batch never fails on one font; with
strict=True the typed exceptions propagate. Variable fonts are always
refused (VariableFontError): the legacy table could only encode the default
instance, so derive it from exported static instances instead. max_pairs is
validated against the format-0 hard limit of 10 920 pairs
(MAX_FORMAT0_PAIRS, the subtable's 16-bit length capacity). The low-level
primitives (kern_lookups, build_legacy_kern_pairs,
reduce_pairs_to_max_count, replace_legacy_kern, …) are exported too.
Selection algorithm
When the candidate count exceeds the MAX_LEGACY_PAIRS (10 900) cap, pairs are
chosen by:
- Frequency-weighted score —
abs(value) × P(left) × P(right) × case_factor(European-language letter/punctuation frequencies; lowercase→UPPERCASE transitions penalised). - Atomic class-pair selection — all expansions of one GPOS class×class
record (
A/Á/Â × T) are kept or dropped together. Whole groups are filled by score density (group score / group size); this is a heuristic, not a global optimum (selecting variable-size groups under a cap is a 0/1 knapsack). - UPM-relative pruning — tiny pairs below
round(min_abs_value × upm / 1000)are dropped first. - Whitelist — Latin Extended text letters plus basic punctuation; symbols, currency and unencoded alternates stay out.
Diagnostic pairs (AT AV TA VA LT LV To Vo) and the strongest left/right pair
per Latin Extended letter are always reserved.
Scope
This package does only the legacy kern derivation. Font naming/STAT/WWS
metadata, autohinting, subsetting, WOFF and verification are out of scope.
Determinism
fontTools serialises the final kern table, so its version affects the byte
output. The golden tests lock the produced bytes, and CI runs them on a matrix
of fonttools versions across the supported range (>=4.61,<5) so the output
stays byte-stable for the whole range.
Development
pip install -e ".[dev]"
pytest
ruff check src tests
mypy
Metadata
Release files for msoffice-kern 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| msoffice_kern-0.1.1.tar.gz | 25.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| msoffice_kern-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.2 kB
Release files / msoffice_kern-0.1.1.tar.gz
| Download URL | msoffice_kern-0.1.1.tar.gz |
|---|---|
| Size | 25.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d4d8253620bd4fe4d45a5c11514d47f051c1921f1ca1e49b2fe205781e46a1c3
|
|
BLAKE2b-256 checksum How to use checksums |
d330f0fae7386368d6c24083c70810050365acf65d99fd743b978a9430cd2bed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.
Transparency logRelease files / msoffice_kern-0.1.1-py3-none-any.whl
| Download URL | msoffice_kern-0.1.1-py3-none-any.whl |
|---|---|
| Size | 20.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
942ff845e74865c4f05066e26e2fe47f968ebd196eac74667b998a2c7e3230f7
|
|
BLAKE2b-256 checksum How to use checksums |
2b6ba3f1b53c98abedd6fe8c537489df5e6e73bdd3484410b8446c5f5c24a98f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.
Transparency log