Derive a PowerPoint/MS Office-safe legacy 'kern' table from a font's GPOS kerning.
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file msoffice_kern-0.1.1.tar.gz.
File metadata
- Download URL: msoffice_kern-0.1.1.tar.gz
- Upload date:
- Size: 25.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4d8253620bd4fe4d45a5c11514d47f051c1921f1ca1e49b2fe205781e46a1c3
|
|
| MD5 |
4f1e0561e5204b4df1a45dcd65945b70
|
|
| BLAKE2b-256 |
d330f0fae7386368d6c24083c70810050365acf65d99fd743b978a9430cd2bed
|
Provenance
The following attestation bundles were made for msoffice_kern-0.1.1.tar.gz:
Publisher:
release.yml on displaay/msoffice-kern
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
msoffice_kern-0.1.1.tar.gz -
Subject digest:
d4d8253620bd4fe4d45a5c11514d47f051c1921f1ca1e49b2fe205781e46a1c3 - Sigstore transparency entry: 2138898500
- Sigstore integration time:
-
Permalink:
displaay/msoffice-kern@0c2ca358db2f7596a614d040380706e3afd6436f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/displaay
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0c2ca358db2f7596a614d040380706e3afd6436f -
Trigger Event:
push
-
Statement type:
File details
Details for the file msoffice_kern-0.1.1-py3-none-any.whl.
File metadata
- Download URL: msoffice_kern-0.1.1-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
942ff845e74865c4f05066e26e2fe47f968ebd196eac74667b998a2c7e3230f7
|
|
| MD5 |
564bb3ec620553f1b0bd8d8c4510d89e
|
|
| BLAKE2b-256 |
2b6ba3f1b53c98abedd6fe8c537489df5e6e73bdd3484410b8446c5f5c24a98f
|
Provenance
The following attestation bundles were made for msoffice_kern-0.1.1-py3-none-any.whl:
Publisher:
release.yml on displaay/msoffice-kern
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
msoffice_kern-0.1.1-py3-none-any.whl -
Subject digest:
942ff845e74865c4f05066e26e2fe47f968ebd196eac74667b998a2c7e3230f7 - Sigstore transparency entry: 2138898527
- Sigstore integration time:
-
Permalink:
displaay/msoffice-kern@0c2ca358db2f7596a614d040380706e3afd6436f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/displaay
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0c2ca358db2f7596a614d040380706e3afd6436f -
Trigger Event:
push
-
Statement type: