# What changed in fonttools

> 78 changes in fonttools 4 from its official release notes, upgrade guides and advisories: 13 breaking, 1 deprecations, 2 security, 6 new APIs and options. Each one cited. Sources checked 2026-10-21. HTML: https://unstale.sh/pypi/fonttools/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## fonttools 4

### Breaking changes

- Bounds-checks count and offSize on read, raising TTLibError instead of allocating huge lazy lists. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Fixes format 2 compilation edge cases, rejects glyph IDs above 65535 in formats 2 and 4, splits long format 14 default UVS ranges, and round-trips empty formats 12 and 13. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Prefers the Windows English name over the Mac name. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Raises NotImplementedError for an all-off-curve cubic contour, which the point pen protocol cannot express. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Rejects in-place union with |=. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Raises ValueError instead of IndexError for a truncated path command. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Updates the variation-store binary format; VARC fonts built with earlier fontTools versions must be rebuilt. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- When splitting a DesignSpace v5 document with makeNames=True, explicitly set family and style names take precedence over names computed from STAT labels in all languages; an instance with its own style name no longer gets a PostScript name made from… (4.66.1) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.1)
- Decompiling a format 4 subtable with an idRangeOffset outside glyphIndexArray now raises TTLibError instead of silently mapping to the wrong glyph or raising a bare AssertionError. (4.66.1) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.1)
- Entity resolution is disabled altogether on lxml 5.0 and later to prevent crafted DTDs from reading local files into parsed XML content. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Python 3.10 support is dropped; fontTools now requires Python 3.11 or later. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- When unicodedata2 is used, version 18.0.0 is required. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- The instancer rejects pinning or restricting axes referenced by VARC components. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)

### Security

- Expansion of format 4 segments and format 12/13 groups is bounded; out-of-range, inverted, overlapping, and missing-glyph groups are handled without unbounded expansion. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Escapes axis names and tags in emitted designspace snippets to prevent crafted fonts from injecting markup. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)

### Deprecations

- This module now only re-exports enum.StrEnum and is deprecated. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)

### New APIs and options

- Adds a keyword-only argument to support decreasing design-space axis mappings. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Adds support for instancing variable COLRv1 fonts. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Allows requesting an axis's original range on VARC fonts. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- A new axisCount element provides the axis count when gvar data is processed without fvar. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- The new languages attribute contains all language tags in a LanguageStatement; language remains the first tag. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Static VARC fonts can omit fvar while retaining gvar or CFF2 component-internal variation data; hidden axes are addressed by index, and gvar supports compilation, decompilation, and TTX round-tripping without fvar. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)

### Behavior and default changes

- Accepts flattened per-region vector tuples. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Supports merging fonts that both have a MATH table. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Warns when a source or instance is dropped because it lies outside the document's own axes. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Warns when a source or instance is dropped because it lies outside the document's own axes. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- feaLib supports listing multiple language tags; following rules and lookup references are registered under every listed language, and dflt cannot be combined with other tags. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- When --flavor is omitted, pyftsubset preserves the input font's WOFF or WOFF2 flavor; use --flavor=none to force uncompressed output. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)

### Tooling

- Support for Python 3.15 is explicitly tested and declared. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)

### Fixes and other changes

- Omitted range attributes on a DesignSpace v5 axis subset are taken from the parent axis. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Corrects BCP 47 tags for some Mac and Windows language IDs. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Deleting a CFF dict attribute now actually removes it. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Reads CFF font names as Latin-1, matching how they are written. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Preserves operands when a blend has zero regions. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Normalizes mapped-axis bounds and rule conditions from their original values. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Keeps glyph metrics after probing a missing attribute. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Rejects duplicate use of a mark class in one anchor list, handles value records with all-NULL devices, and pads a short OS/2 Vendor with spaces. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Invalid BASE, UnicodeRange, name, STAT location, and OS/2 Vendor inputs now raise FeatureLibError with a source location instead of a bare Python error. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Fixes size, ssXX, and cvXX FeatureParams in FeatureVariations alternate feature tables so they compile and round-trip. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Adding rvrn shifts lookup indices inside existing FeatureVariations; null offsets are handled and substitution records stay sorted after merging. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- The subsetter handles a null GDEF variation store. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- The instancer CLI raises ValueError with a missing fvar table message for a static font instead of a bare KeyError. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Folds, removes, or remaps MATH VariationIndex devices when instancing, subsetting the GDEF store, or optimizing it. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Fixes tokenizing escaped parentheses in PostScript strings. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Preserves the direction of the remaining axis when decomposing a transform whose first column is zero. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Closes owned input streams when parsing fails. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Handles empty packed deltas when this setting is enabled. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Avoids a crash on a format 2.0 table with numGlyphs set to 0. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Recursive decompilation fully decodes lazily loaded ligatures, SinglePos, and PairPos arrays, preventing corruption or assertions on lazy fonts. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Passes the all-off-curve None sentinel through. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Scales per-glyph VORG origins, fixes VARC scaling for static fonts and condition variations, and avoids mutating the shared default CFF FontMatrix. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Fixes compiling a Silf table decompiled from binary. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Returns NotImplemented for unsupported types. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Fixes cubic off-curve detection across contour starts. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Computes glyph width lazily for glyf variable fonts without HVAR, making width correct before drawing. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Fixes component conditions, implicit scaleY import, reported coordinates after axis resets, and inherited coordinates when drawing CFF2 components. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Applies VVAR vertical-origin deltas to VORG and uses OpenType rounding for instanced advances and vertical origins. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Keeps a universal FeatureVariations record when pinning removes its last condition but other axes remain. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Preserves ppem Device corrections in GDEF, BASE, GPOS, and JSTF instead of asserting on them. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Respects designspace source layers and fixes --json output with SciPy. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Raises ValueError with a missing fvar table message for a static font instead of a bare KeyError. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Recomputes numRecs and numRatios when compiling. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Preserves minorVersion when copying flavor data. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Can be called more than once. (4.67.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.67.0)
- Compiling succeeds when the lowest glyph ID in a lead-byte row is 32768 or higher, instead of failing with struct.error. (4.66.1) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.1)
- The instancer no longer culls avar2 ranges for component-internal variations that can reach outside font-level ranges. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- The VarStore is always recompiled when saving, preventing stale data when a font is modified in place after an earlier save. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Its type annotation and documentation now correctly specify that it holds a SourceDescriptor, not a source name. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- A STAT table block missing ElidedFallbackName or ElidedFallbackNameID now raises FeatureLibError instead of UnboundLocalError. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Collinear vertical lines are treated as parallel, avoiding ZeroDivisionError. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Repeated script/language pairs within a feature block no longer replace the language system's lookups with a fresh copy of the defaults. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Preserves exact endpoints when splitting a cubic curve. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Preserves exact endpoints when splitting a quadratic curve. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Inconsistent WOFF table, metadata, or private-data lengths raise TTLibError instead of AssertionError, including under python -O. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Bundled script, script extension, block, and bidi-mirroring tables are updated to Unicode 18.0.0. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Merge reports incompatible unitsPerEm values by name and includes the input values instead of raising a bare assertion. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- The instancer fixes stale VARC axis references after removing an unrelated axis. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
- Drawing VARC components with a negated condition (format 5) no longer raises AttributeError. (4.66.0) — [release notes](https://github.com/fonttools/fonttools/releases/tag/4.66.0)
