NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #157 most downloaded on PyPI
Tools to manipulate font files
Last release 2 days ago
29 Sep 2026
Release timing varies
gaps range from 9 days to 4 months
Nearly every release is documented
notes for 59 of the last 60 stable releases
2 versions withdrawn
withdrawn after publishing
13 years old
238 releases · first in 2013
[colorLib/otData] Updated to latest draft COLR v1 spec (#2092).
COLR v1 spec (#2092).Debg if Builder.buildLookups_ has cooperated (#2065, #2067).[varLib.instancer] Fixed TypeError exception when instantiating a VF with a GSUB table 1.1 in which FeatureVariations attribute is present but set to
TypeError exception when instantiating a VF with a GSUB table 1.1 in which FeatureVariations attribute is present but set to None -- indicating that optional FeatureVariations is missing (#2077).x and y attributes of the point element required even when validation is turned off, and raise a meaningful GlifLibError message when that happens (#2075).One column per quarter.
[removeOverlaps] Added new module and removeOverlaps function that merges overlapping contours and components in TrueType glyphs. It requires the skia
removeOverlaps function that merges overlapping contours and components in TrueType glyphs. It requires the skia-pathops module. Note that removing overlaps invalidates the TrueType hinting (#2068).--remove-overlaps command-line option.overlap option in instantiateVariableFont now takes an OverlapMode enum: 0: KEEP_AND_DONT_SET_FLAGS, 1: KEEP_AND_SET_FLAGS (default), and 2: REMOVE. The latter is equivalent to calling removeOverlaps on the generated static
instance. The option continues to accept bool value for backward compatibility.[plistlib] Added typing annotations to plistlib module. Set up mypy static typechecker to run automatically on CI (#2061).
Debg table, a reverse-DNS namespaced JSON dict.Debg table with the original lookup name (if any), feature name / script / language combination (if any), and original source filename and line location.SFNTReader (#2058).mtiLib module (#2027).[feaLib] Allow anonymous classes in LookupFlags definitions (#2037).
maxp.maxComponentDepth calculation (#2044, #2045).[feaLib/otlLib] Moved lookup subtable builders from feaLib to otlLib; refactored some common code (#2004, #2007).
[_n_a_m_e] Fixed error in addMultilingualName with one-character names. Only attempt to recover malformed UTF-16 data from a bytes string, not from un
addMultilingualName with one-character names. Only attempt to recover malformed UTF-16 data from a bytes string, not from unicode str (#1997, #1998).[_n_a_m_e] Fixed error in addMultilingualName with one-character names. Only attempt to recovered malformed UTF-16 data from a bytes string, not from unicode str (#1997, #1998).
[otlLib/varLib] Ensure that the AxisNameID in the STAT and fvar tables is grater than 255 as per OpenType spec (#1985, #1986).
AxisNameID in the STAT and fvar tables is grater than 255 as per OpenType spec (#1985, #1986).fontTools.misc package: filenames, fixedTools, intTools, loggingTools, macCreatorType, macRes, plistlib (#1981).[feaLib] Introduced includeDir parameter on Parser and IncludingLexer to explicitly specify the directory to search when include() statements are enco
includeDir parameter on Parser and IncludingLexer to
explicitly specify the directory to search when include() statements are
encountered (#1973).[sfnt] Fixed NameError: SimpleNamespace while reading TTC header. The regression was introduced with 4.10.1 after removing py23 star import.
NameError: SimpleNamespace while reading TTC header. The regression was introduced with 4.10.1 after removing py23 star import.[sfnt] Make SFNTReader pickleable even when TTFont is loaded with lazy=True option and thus keeps a reference to an external file (#1962, #1967).
SFNTReader pickleable even when TTFont is loaded with lazy=True option and thus keeps a reference to an external file (#1962, #1967).ChainContextPosStatement and ChainContextSubstStatement classes.fontTools.misc package: arrayTools, bezierTools cliTools and eexec (#1956).findMultilingualName() when name record's string is encoded as bytes sequence (#1963).[varLib] Allow feature variations to be active across the entire space (#1957).
formatVersionMinor in UFO's fontinfo.plist and for formatMinor attribute in GLIF file as discussed in unified-font-object/ufo-spec#78.OS/2 table (#1865, #1952).AttributeError while subsetting ContextSubst and ContextPos Format 3 subtable (#1879, #1944).afmLib (#1933), agl (#1934), cffLib (#1935), cu2qu (#1937), encodings (#1940), feaLib (#1941), merge (#1949).findMultilingualName() method (#1921).RTL_SCRIPTS for Unicode 13.0 (#1925).gvar XML output by glyph name, not glyph order (#1907, #1908).fonttools command line tool (#1913, #1920).[subset] Fixed subsetting of FeatureVariations table. The subsetter no longer drops FeatureVariationRecords that have empty substitutions as that will
fontTools.agl (#1895).fonttools feaLib command line. Use --traceback option to show (#1898).Transform class is now subclass of typing.NamedTuple. No change in functionality (#1904).[feaLib] Fixed AttributeError: 'NoneType' has no attribute 'getAlternateGlyphs' when aalt feature references a chain contextual substitution lookup (g
AttributeError: 'NoneType' has no attribute 'getAlternateGlyphs' when aalt feature references a chain contextual substitution lookup (googlefonts/fontmake#648, #1878).[feaLib] If Parser is initialized without a glyphNames parameter, it cannot distinguish between a glyph name containing an hyphen, or a range of glyph
glyphNames parameter, it cannot distinguish between a glyph name containing an hyphen, or a range of glyph names; instead of raising an error, it now interprets them as literal glyph names, while also outputting a logging warning to alert user about the ambiguity (#1768, #1870).COLR v1 tables as per the colr-gradients-spec draft proposal.COLR v1 are susceptible to change while the proposal is being discussed and formalized (#1822).[cu2qu] Added fontTools.cu2qu package, imported from the original cu2qu project (#1868). The cu2qu.pens module was moved to fontTools.pens.cu2quPen. T
fontTools.cu2qu package, imported from the original cu2qu project (#1868).cu2qu.pens module was moved to fontTools.pens.cu2quPen.pip downloads, unless --no-binary option is used), will continue to be pure-Python for now.[varLib] Added support for building variable BASE table version 1.1 (#1858).
BASE table version 1.1 (#1858).fromRGBA method to Color class (#1861).[designspaceLib] Added add{Axis,Source,Instance,Rule}Descriptor methods to DesignSpaceDocument class, to initialize new descriptor objects using keywo
add{Axis,Source,Instance,Rule}Descriptor methods to DesignSpaceDocument class, to initialize new descriptor objects using keyword arguments, and at the same time append them to the current document (#1860).[varLib] Always build gvar table for TrueType-flavored Variable Fonts, even if it contains no variation data. The table is required according to the O
gvar table for TrueType-flavored Variable Fonts, even if it contains no variation data.
The table is required according to the OpenType spec (#1855, #1857).[ttx] Annotate LookupFlag in XML dump with comment explaining what bits are set and what they mean (#1850).
LookupFlag in XML dump with comment explaining what bits are set and what they mean (#1850).IncludedFeaNotFound error (#1842).Nothing published for this version
[woff2] Skip normalizing glyf and loca tables if these are missing from a font (e.g. in NotoColorEmoji using CBDT/CBLC tables).
glyf and loca tables if these are missing from a font (e.g. in NotoColorEmoji using CBDT/CBLC tables).timestampFromString, to fix error when non-English LC_TIME locale is set (#1838, #1839).[colorLib] Added fontTools.colorLib.builder module, initially with buildCOLR and buildCPAL public functions. More color font formats will follow (#182
fontTools.colorLib.builder module, initially with buildCOLR and buildCPAL public functions. More color font formats will follow (#1827).setupCOLR and setupCPAL methods (#1826).GlyphComponent.transform floats to F2Dot14 to fix round-trip issue when computing bounding boxes of transformed components (#1830).firstPt and secondPt) for alignment (instead of X and Y offsets), compute the effective translation offset after having applied any transform (#1831).glyf table data as a single null byte in order to pass validation by OTS and Windows (#1829).[EBLC/CBLC] Fixed incorrect padding length calculation for Format 3 IndexSubTable (#1817, #1818).
lazy=True (#1808, #1809).CFF2 table when building VF (#1816).recalcBBoxes option work also with CFF2 table (#1816).lookupflag in lookups defined inside feature blocks. They will now inherit the current lookupflag of the feature. This is what Adobe makeotf also does in this case (#1815).[feaLib] Do not fail on duplicate multiple substitutions, only warn (#1811).
[unicodedata] Update RTL_SCRIPTS for Unicode 11 and 12.
[otTables] Fixed bug when splitting MarkBasePos subtables as offsets overflow. The mark class values in the split subtable were not being updated, lea
MarkBasePos subtables as offsets overflow.[subset] Fixed issue with subsetting FeatureVariations table when the index of features changes as features get dropped. The feature index needs to be
addFeatureVariations method to FontBuilder class. This is a shorthand for calling featureVars.addFeatureVariations on the builder's TTFont object (#1781).glyph.drawPoints() like we did for glyph.draw() (#1771, #1774).[glyf] Use the flagOnCurve bit mask in glyph.draw(), so that we ignore the overlap flag that may be set when instantiating variable fonts (#1771).
flagOnCurve bit mask in glyph.draw(), so that we ignore the overlap flag that may be set when instantiating variable fonts (#1771).[pens] Added the following pens (#1766):
roundingPen.RoundingPen: filter pen that rounds coordinates and components' offsets to integer;roundingPen.RoundingPointPen: like the above, but using PointPen protocol.filterPen.FilterPointPen: base class for filter point pens;transformPen.TransformPointPen: filter point pen to apply affine transform;recordingPen.RecordingPointPen: records and replays point-pen commands.[instancer] Implemented restricting axis ranges (level 3 partial instancing). You can now pass {axis_tag: (min, max)} tuples as input to the instantia
{axis_tag: (min, max)} tuples as input to the instantiateVariableFont function. Note that changing the default axis position is not supported yet. The command-line script also accepts axis ranges in the form of colon-separated float values, e.g. wght=400:700 (#1753, #1537).DesignAxis records, but only prune out-of-range AxisValue records.processing attribute for <rules> element, with values "first" or "last", plus other editorial changes to DesignSpace specification. Bumped format version to 4.1 (#1750).addFeatureVariations; allow said feature to already exist, in which case we append new lookup indices to existing features.<rules> attribute processing according to DesignSpace specification update in #1750. Depending on this flag, we generate either an 'rvrn' (always processed first) or a 'rclt' feature (follows lookup order, therefore last) (#1747, #1625, #1371).with statement like with TTFont (#1751).fixedToFloat to not do any rounding but simply return value / (1 << precisionBits). Added floatToFixedToStr and strToFixedToFloat functions to be used when loading from or dumping to XML. Fixed values (e.g. fvar axes and instance coordinates, avar mappings, etc.) are are now stored as un-rounded decimal floats upon decompiling (#1740, #737).LigatureCaret statements for the same glyph. Only the first rule per glyph is used, additional ones are ignored (#1733).[voltLib] Added support for ALL and NONE in PROCESS_MARKS (#1732).
ALL and NONE in PROCESS_MARKS (#1732).Silf table compilation and decompilation regarding str vs bytes in python3 (#1728).post and CFF tables (#1729).[otTables] Support fixing offset overflows in MultipleSubst lookup subtables (#1706).
MultipleSubst lookup subtables (#1706).EBDT and CBDT table data (#1698, #1633).PointToSegmentPen when last point of closed contour has same coordinates as the starting point and was incorrectly dropped (#1720).Sill table output to pass OTS (#1705).removeNames method to table__n_a_m_e class (#1719).ascender and descender in hhea table (#1715).…kept, but these are no-op. The module is now *DEPRECATED* and will removed in the future.
NOTE: This is the last scheduled release to support Python 2.7. The upcoming fonttools v4.x series is going to require Python 3.6 or greater.
NOTE: This is the last scheduled release to support Python 2.7. The upcoming fonttools v4.x series is going to require Python 3.6 or greater.
varLib.instancer module for partially instantiating variable fonts. This extends (and will eventually replace) varLib.mutator module, as it allows to create not just full static instances from a variable font, but also "partial" or "less variable" fonts where some of the axes are dropped or instantiated at a particular value.fonttools varLib.instancer --help (#1537, #1628).FDSelect format 4 (#1677).sbix (Apple bitmap color font) table.eexec section in Type1 fonts when whitespace characters are interspersed among the trailing zeros (#1676).programToCommands with CFF2 charstrings (#1669).[featureVars] Fixed region-merging code on python3 (#1659).
[subset] Fixed regression when passing --flavor=woff2 option with an input font that was already compressed as WOFF 1.0 (#1650).
--flavor=woff2 option with an input font that was already compressed as WOFF 1.0 (#1650).[woff2] Added support for compressing/decompressing WOFF2 fonts with non-transformed glyf and loca tables, as well as with transformed hmtx table. Rem
glyf and loca tables, as well as with transformed hmtx table.Snippets/woff2_compress.py and Snippets/woff2_decompress.py scripts, and replaced them with a new console entry point fonttools ttLib.woff2 that provides two sub-commands compress and decompress.PrivateDicts. The PrivateDict data from the first region font was incorrecty used for all subsequent fonts. The bug would only affect variable CFF2 fonts with hinting (#1643, #1644).LastResortLogger class.rvrn feature record in DefaultLangSys tables when calling addFeatureVariations on a font that does not already have a GSUB table (aa8a5bc).SinglePos subtables (#1621, #1641).[OS/2] Fixed sign of fsType: it should be uint16, not int16 (#1619).
fsType: it should be uint16, not int16 (#1619).DSIG table with setupDummyDSIG method (#1621).GDEF.GlyphClassDef were being dropped when generating instance via varLib.mutator (#1614).-v and -q to configure logging (#1613).unicodedata2 backport for Unicode 12.0.[cffLib] Fixed issue when importing a CFF2 variable font from XML, whereby the VarStore state was not propagated to PrivateDict (#1598).
CFF2 variable font from XML, whereby the VarStore state was not propagated to PrivateDict (#1598).post glyph names when building CFF2 variable font (#1609).[designspaceLib] Added loadSourceFonts method to load source fonts using custom opener function (#1606).
loadSourceFonts method to load source fonts using custom opener function (#1606).None in ast.ValueRecord.asFea() (#1599).AssertionError when using --desubroutinize option (#1590, #1594).Silf table's decompile method unmasked by previous typo fix (#1597). Decode languange code as UTF-8 in Sill table's decompile method (#1600).[varLib/cffLib] Added support for building CFF2 variable font from sparse masters, or masters with more than one model (multiple VarStore.VarData). In
CFF2 variable font from sparse masters, or masters with more than one model (multiple VarStore.VarData).cffLib.specializer, added support for CFF2 CharStrings with blend operators (#1547, #1591).HVAR and VVAR with --retain-gids option, and when advances mapping is null while sidebearings mappings are non-null (#1587, #1588).otlLib.maxContextCalc module to compute OS/2.usMaxContext value.--recalc-max-context to subset module (#1582).AttributeError on missing OT table fields after importing font from TTX (#1584).Silf table's decompile method (#1586).GPOS SinglePos (LookupType 1) subtables (#1539).Fixed DeprecationWarning on invalid escape sequences (#1562).
VVAR with --retain-gids option (#1552).findDefault method (#1554).calcIntBounds (used to compute bounding boxes of glyf table's glyphs) now uses otRound instead of round3 (#1566).d strings (ellipse, line, polyline), as well as support for transform attributes. Only matrix transformations are currently supported (#1564, #1564).VVAR table from vmtx and VORG tables (#1551).post table format 2 (#1557).DeprecationWarning on invalid escape sequences (#1562).[ttLib/glyf] Raise more specific error when encountering recursive component references (#1545, #1546).
public.skipExportGlyphs lib key (#1534, unified-font-object/ufo-spec#84).vmtx to compute vertical phantom points; or hhea.ascent and head.unitsPerEM if vmtx is missing (#1528).TupleVariation.toXML to improve readability of TTX dump (#1527).OVERLAP_SIMPLE and OVERLAP_COMPOUND glyf flags by default in instantiateVariableFont. Added --no-overlap cli option to disable this (#1518).VVAR table (#1516, #1517).HVAR table that has an AdvanceWidthMap when the option --retain-gids is used.forceChained in MultipleSubstStatement (#1511).subtable statement (#1512).subtable statement in more places than just PairPos lookups (#1520).load_designspace, provide a default English name for the ital axis tag.[cffLib] Fixed RecursionError when unpickling or deepcopying TTFont with CFF table (#1488, 649dc49).
The previous release accidentally changed several files from Unix to DOS line-endings. Fix that.
The previous release accidentally changed several files from Unix to DOS line-endings. Fix that.
[varLib] Temporarily revert the fix to load_masters(), which caused a crash in interpolate_layout() when deepcopy-ing OTFs.
[varLib] Temporarily revert the fix to load_masters(), which caused a crash in interpolate_layout() when deepcopy-ing OTFs.
[varLib] load_masters() now actually assigns the fonts it loads to the source.font attributes.
[varLib] load_masters() now actually assigns the fonts it loads to the source.font attributes.
[varLib] Fixed an MVAR table generation crash when sparse masters were involved.
[voltLib] parse_coverage_() returns a tuple instead of an ast.Enum.
[feaLib] A MarkClassDefinition inside a block is no longer doubly indented compared to the rest of the block.
Fixed "DeprecationWarning: invalid escape sequence" in Python 3.7.
math.isfinite.hidden=1.<NULL> for PairPos2 format A (#1459). Round-trip useExtension keyword. Implemented ValueRecord.asFea method.[ufoLib] Replace deprecated calls to getbytes and setbytes with new equivalent readbytes and writebytes calls. fs >= 2.2 is now required.
--no-recalc-timestamp option to keep the original font's head.modified timestamp (#1455, #46).END operator in .vtp file (#1453).--retain-gids option to subset font without modifying the current glyph indices (#1443, #1447).getbytes and setbytes with new equivalent readbytes and writebytes calls. fs >= 2.2 is now required.[hmtx/vmtx]: Allow to compile/decompile hmtx and vmtx tables even without the corresponding (required) metrics header tables, hhea and vhea (#1439).
hmtx and vmtx tables even without the corresponding (required) metrics header tables, hhea and vhea (#1439).labelname and named instances' stylename (#1438).[_m_a_x_p] Include maxComponentElements in maxp table's recalculation.
maxComponentElements in maxp table's recalculation.[psCharStrings] In encodeFloat function, use float's "general format" with 8 digits of precision (i.e. %8g) instead of str(). This works around a macO
encodeFloat function, use float's "general format" with 8 digits of precision (i.e. %8g) instead of str(). This works around a macOS rendering issue when real numbers in CFF table are too long, and also makes sure that floats are encoded with the same precision in python 2.7 and 3.x (#1430, googlei18n/ufo2ft#306)._n_a_m_e_table.addMultilingualName also add Macintosh (platformID=1) names by default. Added options to FontBuilder.setupNameTable method to optionally disable Macintosh or Windows names (#1359, #1431).build optionally accept a DesignSpaceDocument object, instead of a designspace file path. The caller can now set the font attribute of designspace's sources to a TTFont object, thus allowing to skip filenames manipulation altogether (#1416, #1425).[merge] Fixed AssertionError when none of the script tables in GPOS/GSUB have a DefaultLangSys record (#1408, 135a4a1).
[varLib] Work around macOS rendering issue for composites without gvar entry (#1381).
[varLib] Support generation of CFF2 variable fonts. model.reorderMasters() now supports arbitrary mapping. Fix handling of overlapping ranges for feat
model.reorderMasters() now supports arbitrary mapping. Fix handling of overlapping ranges for feature variations (#1400).FontMatrix automatically from unitsPerEm.collections.Mapping instead of the specific dict class to support custom data classes that should serialize to dictionaries.[subset] subsetter bug fix with variable fonts.
[subset] subsetter bug fix with variable fonts.
[varLib.featureVar] Improve FeatureVariations generation with many rules.
[varLib] Enable sparse masters when building variable fonts: https://github.com/fonttools/fonttools/pull/1368#issuecomment-437257368
[varLib.mutator] Add IDEF for GETVARIATION opcode, for handling hints in an instance.
[ttLib] Ignore the length of kern table subtable format 0
[ufoLib] Make UFOWriter a subclass of UFOReader, and use mixins for shared methods (#1344).
UFOWriter a subclass of UFOReader, and use mixins for shared methods (#1344).<rule> (#1346, #1347).[plot] to extras, to optionally install matplotlib, needed to use the fonTools.varLib.plot module.STAT has no AxisValue tables.FontBuilder wrapper class around TTFont that makes it easier to create a working TTF or OTF font from scratch with code. NOTE: the API is still experimental and may change in future versions.[ufoLib] Merged the ufoLib master branch into a new fontTools.ufoLib package (#1335, #1095). Moved ufoLib.pointPen module to fontTools.pens.pointPen.
fontTools.ufoLib package (#1335, #1095).ufoLib.pointPen module to fontTools.pens.pointPen.ufoLib.etree module to fontTools.misc.etree.ufoLib.plistlib module to fontTools.misc.plistlib.fontTools.ufoLib module you need to install fonttools with the [ufo] extra, or you can manually install the required additional dependencies (cf. README.rst).--no-hinting on a CFF font now also drops the optional hinting keys in Private dict: ForceBold, LanguageGroup, and ExpansionFactor (#1322).msg=None argument to CapturingLogHandler.assertRegex (0245f2c).FeatureVariations instantiation (#1244)._TTGlyph objects (#1334).[varLib] Use fontTools.designspaceLib to read DesignSpaceDocument. The fontTools.varLib.designspace module is now deprecated and will be removed in fu…
OVERLAP_SIMPLE of glyf table's contour points in the TTX dump. This is used in some implementations to specify a non-zero fill with overlapping contours (#1316).TS1C tables containing VTT sources for cvar variation table (#1310).fontTools.designspaceLib to read DesignSpaceDocument. The fontTools.varLib.designspace module is now deprecated and will be removed in future versions. The presence of an explicit axes element is now required in order to build a variable font (#1224, #1313).rules element of DesignSpace document (#1240, #713, #1314).--no-layout-closure option to not expand the subset with the glyphs produced by OpenType layout features. Instead, OpenType features will be subset to only rules that are relevant to the otherwise-specified glyph set (#43, #1121).Your coding agent can read these notes before it upgrades. Set up the MCP server →