Font Tools

fontTools Docs

About

fontTools is a family of libraries and utilities for manipulating fonts in Python.

The project has an MIT open-source license. Among other things this means you can use it free of charge.

Installation

Note

fontTools requires Python 3.8 or later.

The package is listed in the Python Package Index (PyPI), so you can install it with pip:

pip install fonttools

See the Optional Requirements section below for details about module-specific dependencies that must be installed in select cases.

Utilities

fontTools installs four command-line utilities:

  • pyftmerge, a tool for merging fonts; see fontTools.merge

  • pyftsubset, a tool for subsetting fonts; see fontTools.subset

  • ttx, a tool for converting between OpenType binary fonts (OTF) and an XML representation (TTX); see fontTools.ttx

  • fonttools, a “meta-tool” for accessing other components of the fontTools family.

This last utility takes a subcommand, which could be one of:

  • cffLib.width: Calculate optimum defaultWidthX/nominalWidthX values

  • cu2qu: Convert a UFO font from cubic to quadratic curves

  • feaLib: Add features from a feature file (.fea) into a OTF font

  • help: Show this help

  • merge: Merge multiple fonts into one

  • mtiLib: Convert a FontDame OTL file to TTX XML

  • subset: OpenType font subsetter and optimizer

  • ttLib.woff2: Compress and decompress WOFF2 fonts

  • ttx: Convert OpenType fonts to XML and back

  • varLib: Build a variable font from a designspace file and masters

  • varLib.instancer: Partially instantiate a variable font.

  • varLib.interpolatable: Test for interpolatability issues between fonts

  • varLib.interpolate_layout: Interpolate GDEF/GPOS/GSUB tables for a point on a designspace

  • varLib.models: Normalize locations on a given designspace

  • varLib.mutator: Instantiate a variation font

  • varLib.varStore: Optimize a font’s GDEF variation store

  • voltLib.voltToFea: Convert MS VOLT to AFDKO feature files.

Libraries

The main library you will want to access when using fontTools for font engineering is likely to be fontTools.ttLib.ttFont, which is the module for handling TrueType/OpenType fonts. However, there are many other libraries in the fontTools suite:

  • fontTools.afmLib: Module for reading and writing AFM files

  • fontTools.agl: Access to the Adobe Glyph List

  • fontTools.cffLib: Read/write tools for Adobe CFF fonts

  • fontTools.colorLib: Module for handling colors in CPAL/COLR fonts

  • fontTools.config: Configure fontTools

  • fontTools.cu2qu: Module for cubic to quadratic conversion

  • fontTools.designspaceLib: Read and write designspace files

  • fontTools.encodings: Support for font-related character encodings

  • fontTools.feaLib: Read and read AFDKO feature files

  • fontTools.fontBuilder: Construct TTF/OTF fonts from scratch

  • fontTools.merge: Tools for merging font files

  • fontTools.pens: Various classes for manipulating glyph outlines

  • fontTools.subset: OpenType font subsetting and optimization

  • fontTools.svgLib.path: Library for drawing SVG paths onto glyphs

  • fontTools.t1Lib: Tools for PostScript Type 1 fonts (Python2 only)

  • fontTools.tfmLib: Module for reading TFM files

  • fontTools.ttLib: Module for reading/writing OpenType and Truetype fonts

  • fontTools.ttx: Module for converting between OTF and XML representation

  • fontTools.ufoLib: Module for reading and writing UFO files

  • fontTools.unicodedata: Convert between Unicode and OpenType script information

  • fontTools.varLib: Module for dealing with ‘gvar’-style font variations

  • fontTools.voltLib: Module for dealing with Visual OpenType Layout Tool (VOLT) files

A selection of sample Python programs using these libaries can be found in the Snippets directory of the fontTools repository.

Optional Dependencies

The fontTools package currently has no (required) external dependencies besides the modules included in the Python Standard Library. However, a few extra dependencies are required to unlock optional features in some of the library modules. See the optional requirements page for more information.

Developer information

Information for developers can be found here.

License

MIT license. See the full text of the license for details.

Table of Contents

afmLib: Read/write Adobe Font Metrics files

Module for reading and writing AFM (Adobe Font Metrics) files.

Note that this has been designed to read in AFM files generated by Fontographer and has not been tested on many other files. In particular, it does not implement the whole Adobe AFM specification [1] but, it should read most “common” AFM files.

Here is an example of using afmLib to read, modify and write an AFM file:

>>> from fontTools.afmLib import AFM
>>> f = AFM("Tests/afmLib/data/TestAFM.afm")
>>>
>>> # Accessing a pair gets you the kern value
>>> f[("V","A")]
-60
>>>
>>> # Accessing a glyph name gets you metrics
>>> f["A"]
(65, 668, (8, -25, 660, 666))
>>> # (charnum, width, bounding box)
>>>
>>> # Accessing an attribute gets you metadata
>>> f.FontName
'TestFont-Regular'
>>> f.FamilyName
'TestFont'
>>> f.Weight
'Regular'
>>> f.XHeight
500
>>> f.Ascender
750
>>>
>>> # Attributes and items can also be set
>>> f[("A","V")] = -150 # Tighten kerning
>>> f.FontName = "TestFont Squished"
>>>
>>> # And the font written out again (remove the # in front)
>>> #f.write("testfont-squished.afm")

Footnotes

exception fontTools.afmLib.error
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.afmLib.AFM(path=None)
addComment(comment)

Adds a new comment to the file.

addComposite(glyphName, components)

Specifies that the glyph glyphName is made up of the given components. The components list should be of the following form:

[
        (glyphname, xOffset, yOffset),
        ...
]
chars()

Returns a list of all glyph names in the font.

comments()

Returns all comments from the file.

has_char(char)

Returns True if the given glyph exists in the font.

has_kernpair(pair)

Returns True if the given glyph pair (specified as a tuple) exists in the kerning dictionary.

kernpairs()

Returns a list of all kern pairs in the kerning dictionary.

read(path)

Opens, reads and parses a file.

write(path, sep='\r')

Writes out an AFM font to the given path.

agl: Interface to the Adobe Glyph List

Interface to the Adobe Glyph List

This module exists to convert glyph names from the Adobe Glyph List to their Unicode equivalents. Example usage:

>>> from fontTools.agl import toUnicode
>>> toUnicode("nahiragana")
'な'

It also contains two dictionaries, UV2AGL and AGL2UV, which map from Unicode codepoints to AGL names and vice versa:

>>> import fontTools
>>> fontTools.agl.UV2AGL[ord("?")]
'question'
>>> fontTools.agl.AGL2UV["wcircumflex"]
373

This is used by fontTools when it has to construct glyph names for a font which doesn’t include any (e.g. format 3.0 post tables).

exception fontTools.agl.AGLError
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

fontTools.agl.toUnicode(glyph, isZapfDingbats=False)

Convert glyph names to Unicode, such as 'longs_t.oldstyle' –> u'ſt'

If isZapfDingbats is True, the implementation recognizes additional glyph names (as required by the AGL specification).

cffLib: read/write Adobe CFF fonts

cffLib: read/write Adobe CFF fonts

OpenType fonts with PostScript outlines contain a completely independent font file, Adobe’s Compact Font Format. So dealing with OpenType fonts requires also dealing with CFF. This module allows you to read and write fonts written in the CFF format.

In 2016, OpenType 1.8 introduced the CFF2 format which, along with other changes, extended the CFF format to deal with the demands of variable fonts. This module parses both original CFF and CFF2.

class fontTools.cffLib.CFFFontSet

A CFF font “file” can contain more than one font, although this is extremely rare (and not allowed within OpenType fonts).

This class is the entry point for parsing a CFF table. To actually manipulate the data inside the CFF font, you will want to access the CFFFontSet’s TopDict object. To do this, a CFFFontSet object can either be treated as a dictionary (with appropriate keys() and values() methods) mapping font names to TopDict objects, or as a list.

from fontTools import ttLib
tt = ttLib.TTFont("Tests/cffLib/data/LinLibertine_RBI.otf")
tt["CFF "].cff
# <fontTools.cffLib.CFFFontSet object at 0x101e24c90>
tt["CFF "].cff[0] # Here's your actual font data
# <fontTools.cffLib.TopDict object at 0x1020f1fd0>
compile(file, otFont, isCFF2=None)

Write the object back into binary representation onto the given file. file should be a file handle object. otFont is the top-level fontTools.ttLib.ttFont.TTFont object containing this CFF file.

If isCFF2 is passed and set to True or False, then the library makes an assertion that the CFF header is of the appropriate version.

convertCFFToCFF2(otFont)

Converts this object from CFF format to CFF2 format. This conversion is done ‘in-place’. The conversion cannot be reversed.

This assumes a decompiled CFF table. (i.e. that the object has been filled via decompile().)

decompile(file, otFont, isCFF2=None)

Parse a binary CFF file into an internal representation. file should be a file handle object. otFont is the top-level fontTools.ttLib.ttFont.TTFont object containing this CFF file.

If isCFF2 is passed and set to True or False, then the library makes an assertion that the CFF header is of the appropriate version.

fromXML(name, attrs, content, otFont=None)

Reads data from the XML element into the CFFFontSet object.

toXML(xmlWriter)

Write the object into XML representation onto the given fontTools.misc.xmlWriter.XMLWriter.

writer = xmlWriter.XMLWriter(sys.stdout)
tt["CFF "].cff.toXML(writer)
class fontTools.cffLib.CFFWriter(isCFF2)

Helper class for serializing CFF data to binary. Used by CFFFontSet.compile().

class fontTools.cffLib.CharStrings(file, charset, globalSubrs, private, fdSelect, fdArray, isCFF2=None, varStore=None)

The CharStrings in the font represent the instructions for drawing each glyph. This object presents a dictionary interface to the font’s CharStrings, indexed by glyph name:

tt["CFF "].cff[0].CharStrings["a"]
# <T2CharString (bytecode) at 103451e90>

See fontTools.misc.psCharStrings.T1CharString and fontTools.misc.psCharStrings.T2CharString for how to decompile, compile and interpret the glyph drawing instructions in the returned objects.

class fontTools.cffLib.CharStringsCompiler(items, strings, parent, isCFF2=None)

Helper class for writing the CharStrings INDEX to binary.

class fontTools.cffLib.FDArrayIndex(file=None, isCFF2=None)
append(item)

Add an item to an INDEX.

clear()

Empty the INDEX.

compilerClass

alias of FDArrayIndexCompiler

class fontTools.cffLib.FDArrayIndexCompiler(items, strings, parent, isCFF2=None)

Helper class for writing the Font DICT INDEX to binary.

class fontTools.cffLib.GlobalSubrsCompiler(items, strings, parent, isCFF2=None)

Helper class for writing the global subroutine INDEX to binary.

class fontTools.cffLib.GlobalSubrsIndex(file=None, globalSubrs=None, private=None, fdSelect=None, fdArray=None, isCFF2=None)

This index contains all the global subroutines in the font. A global subroutine is a set of CharString data which is accessible to any glyph in the font, and are used to store repeated instructions - for example, components may be encoded as global subroutines, but so could hinting instructions.

Remember that when interpreting a callgsubr instruction (or indeed a callsubr instruction) that you will need to add the “subroutine number bias” to number given:

tt = ttLib.TTFont("Almendra-Bold.otf")
u = tt["CFF "].cff[0].CharStrings["udieresis"]
u.decompile()

u.toXML(XMLWriter(sys.stdout))
# <some stuff>
# -64 callgsubr <-- Subroutine which implements the dieresis mark
# <other stuff>

tt["CFF "].cff[0].GlobalSubrs[-64] # <-- WRONG
# <T2CharString (bytecode) at 103451d10>

tt["CFF "].cff[0].GlobalSubrs[-64 + 107] # <-- RIGHT
# <T2CharString (source) at 103451390>

(“The bias applied depends on the number of subrs (gsubrs). If the number of subrs (gsubrs) is less than 1240, the bias is 107. Otherwise if it is less than 33900, it is 1131; otherwise it is 32768.”, Subroutine Operators <https://docs.microsoft.com/en-us/typography/opentype/otspec180/cff2charstr#section4.4>)

append(item)

Add an item to an INDEX.

clear()

Empty the INDEX.

compilerClass

alias of GlobalSubrsCompiler

toXML(xmlWriter)

Write the subroutines index into XML representation onto the given fontTools.misc.xmlWriter.XMLWriter.

writer = xmlWriter.XMLWriter(sys.stdout)
tt["CFF "].cff[0].GlobalSubrs.toXML(writer)
class fontTools.cffLib.Index(file=None, isCFF2=None)

This class represents what the CFF spec calls an INDEX (an array of variable-sized objects). Index items can be addressed and set using Python list indexing.

append(item)

Add an item to an INDEX.

clear()

Empty the INDEX.

compilerClass

alias of IndexCompiler

class fontTools.cffLib.IndexCompiler(items, strings, parent, isCFF2=None)

Base class for writing CFF INDEX data to binary.

class fontTools.cffLib.IndexedStrings(file=None)

SID -> string mapping.

class fontTools.cffLib.IndexedStringsCompiler(items, strings, parent, isCFF2=None)
exception fontTools.cffLib.StopHintCountEvent
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.cffLib.SubrsCompiler(items, strings, parent, isCFF2=None)

Helper class for writing the local subroutine INDEX to binary.

class fontTools.cffLib.SubrsIndex(file=None, globalSubrs=None, private=None, fdSelect=None, fdArray=None, isCFF2=None)

This index contains a glyph’s local subroutines. A local subroutine is a private set of CharString data which is accessible only to the glyph to which the index is attached.

append(item)

Add an item to an INDEX.

clear()

Empty the INDEX.

compilerClass

alias of SubrsCompiler

toXML(xmlWriter)

Write the subroutines index into XML representation onto the given fontTools.misc.xmlWriter.XMLWriter.

writer = xmlWriter.XMLWriter(sys.stdout)
tt["CFF "].cff[0].GlobalSubrs.toXML(writer)
class fontTools.cffLib.TopDict(strings=None, file=None, offset=None, GlobalSubrs=None, cff2GetGlyphOrder=None, isCFF2=None)

The TopDict represents the top-level dictionary holding font information. CFF2 tables contain a restricted set of top-level entries as described here, but CFF tables may contain a wider range of information. This information can be accessed through attributes or through the dictionary returned through the rawDict property:

font = tt["CFF "].cff[0]
font.FamilyName
# 'Linux Libertine O'
font.rawDict["FamilyName"]
# 'Linux Libertine O'

More information is available in the CFF file’s private dictionary, accessed via the Private property:

tt["CFF "].cff[0].Private.BlueValues
# [-15, 0, 515, 515, 666, 666]
getGlyphOrder()

Returns a list of glyph names in the CFF font.

class fontTools.cffLib.TopDictIndex(file=None, cff2GetGlyphOrder=None, topSize=0, isCFF2=None)

This index represents the array of TopDict structures in the font (again, usually only one entry is present). Hence the following calls are equivalent:

tt["CFF "].cff[0]
# <fontTools.cffLib.TopDict object at 0x102ed6e50>
tt["CFF "].cff.topDictIndex[0]
# <fontTools.cffLib.TopDict object at 0x102ed6e50>
append(item)

Add an item to an INDEX.

clear()

Empty the INDEX.

compilerClass

alias of TopDictIndexCompiler

class fontTools.cffLib.TopDictIndexCompiler(items, strings, parent, isCFF2=None)

Helper class for writing the TopDict to binary.

This package also contains two modules for manipulating CFF format glyphs:

specializer: T2CharString operator specializer and generalizer

T2CharString operator specializer and generalizer.

PostScript glyph drawing operations can be expressed in multiple different ways. For example, as well as the lineto operator, there is also a hlineto operator which draws a horizontal line, removing the need to specify a dx coordinate, and a vlineto operator which draws a vertical line, removing the need to specify a dy coordinate. As well as decompiling fontTools.misc.psCharStrings.T2CharString objects into lists of operations, this module allows for conversion between general and specific forms of the operation.

fontTools.cffLib.specializer.commandsToProgram(commands)

Takes a commands list as returned by programToCommands() and converts it back to a T2CharString program list.

fontTools.cffLib.specializer.generalizeCommands(commands, ignoreErrors=False)
fontTools.cffLib.specializer.generalizeProgram(program, getNumRegions=None, **kwargs)
fontTools.cffLib.specializer.programToCommands(program, getNumRegions=None)

Takes a T2CharString program list and returns list of commands. Each command is a two-tuple of commandname,arg-list. The commandname might be empty string if no commandname shall be emitted (used for glyph width, hintmask/cntrmask argument, as well as stray arguments at the end of the program (🤷). ‘getNumRegions’ may be None, or a callable object. It must return the number of regions. ‘getNumRegions’ takes a single argument, vsindex. If the vsindex argument is None, getNumRegions returns the default number of regions for the charstring, else it returns the numRegions for the vsindex. The Charstring may or may not start with a width value. If the first non-blend operator has an odd number of arguments, then the first argument is a width, and is popped off. This is complicated with blend operators, as there may be more than one before the first hint or moveto operator, and each one reduces several arguments to just one list argument. We have to sum the number of arguments that are not part of the blend arguments, and all the ‘numBlends’ values. We could instead have said that by definition, if there is a blend operator, there is no width value, since CFF2 Charstrings don’t have width values. I discussed this with Behdad, and we are allowing for an initial width value in this case because developers may assemble a CFF2 charstring from CFF Charstrings, which could have width values.

fontTools.cffLib.specializer.programToString(program)
fontTools.cffLib.specializer.specializeCommands(commands, ignoreErrors=False, generalizeFirst=True, preserveTopology=False, maxstack=48)
fontTools.cffLib.specializer.specializeProgram(program, getNumRegions=None, **kwargs)
fontTools.cffLib.specializer.stringToProgram(string)

width: T2CharString glyph width optimizer

T2CharString glyph width optimizer.

CFF glyphs whose width equals the CFF Private dictionary’s defaultWidthX value do not need to specify their width in their charstring, saving bytes. This module determines the optimum defaultWidthX and nominalWidthX values for a font, when provided with a list of glyph widths.

fontTools.cffLib.width.main(args=None)

Calculate optimum defaultWidthX/nominalWidthX values

class fontTools.cffLib.width.missingdict(missing_func)
clear() None.  Remove all items from D.
copy() a shallow copy of D
fromkeys(value=None, /)

Create a new dictionary with keys from iterable and values set to value.

get(key, default=None, /)

Return the value for key if key is in the dictionary, else default.

items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
pop(k[, d]) v, remove specified key and return the corresponding value.

If the key is not found, return the default if given; otherwise, raise a KeyError.

popitem()

Remove and return a (key, value) pair as a 2-tuple.

Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.

setdefault(key, default=None, /)

Insert key with a value of default if key is not in the dictionary.

Return the value for key if key is in the dictionary, else default.

update([E, ]**F) None.  Update D from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values() an object providing a view on D's values
fontTools.cffLib.width.optimizeWidths(widths)

Given a list of glyph widths, or dictionary mapping glyph width to number of glyphs having that, returns a tuple of best CFF default and nominal glyph widths.

This algorithm is linear in UPEM+numGlyphs.

fontTools.cffLib.width.optimizeWidthsBruteforce(widths)

Bruteforce version. Veeeeeeeeeeeeeeeeery slow. Only works for smallests of fonts.

colorLib.builder: Build COLR/CPAL tables from scratch

colorLib.builder: Build COLR/CPAL tables from scratch

class fontTools.colorLib.builder.ColorPaletteType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
as_integer_ratio()

Return integer ratio.

Return a pair of integers, whose ratio is exactly equal to the original int and with a positive denominator.

>>> (10).as_integer_ratio()
(10, 1)
>>> (-10).as_integer_ratio()
(-10, 1)
>>> (0).as_integer_ratio()
(0, 1)
bit_count()

Number of ones in the binary representation of the absolute value of self.

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3
bit_length()

Number of bits necessary to represent self in binary.

>>> bin(37)
'0b100101'
>>> (37).bit_length()
6
conjugate()

Returns self, the complex conjugate of any int.

denominator

the denominator of a rational number in lowest terms

from_bytes(byteorder='big', *, signed=False)

Return the integer represented by the given array of bytes.

bytes

Holds the array of bytes to convert. The argument must either support the buffer protocol or be an iterable object producing bytes. Bytes and bytearray are examples of built-in objects that support the buffer protocol.

byteorder

The byte order used to represent the integer. If byteorder is ‘big’, the most significant byte is at the beginning of the byte array. If byteorder is ‘little’, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder’ as the byte order value. Default is to use ‘big’.

signed

Indicates whether two’s complement is used to represent the integer.

imag

the imaginary part of a complex number

numerator

the numerator of a rational number in lowest terms

real

the real part of a complex number

to_bytes(length=1, byteorder='big', *, signed=False)

Return an array of bytes representing an integer.

length

Length of bytes object to use. An OverflowError is raised if the integer is not representable with the given number of bytes. Default is length 1.

byteorder

The byte order used to represent the integer. If byteorder is ‘big’, the most significant byte is at the beginning of the byte array. If byteorder is ‘little’, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder’ as the byte order value. Default is to use ‘big’.

signed

Determines whether two’s complement is used to represent the integer. If signed is False and a negative integer is given, an OverflowError is raised.

fontTools.colorLib.builder.buildCOLR(colorGlyphs: Dict[str, Sequence[int | Mapping[str, Any] | Paint | Tuple[str, int | Mapping[str, Any] | Paint | Tuple[str, _PaintInput]]] | int | Mapping[str, Any] | Paint | Tuple[str, int | Mapping[str, Any] | Paint | Tuple[str, _PaintInput]]], version: int | None = None, *, glyphMap: Mapping[str, int] | None = None, varStore: VarStore | None = None, varIndexMap: DeltaSetIndexMap | None = None, clipBoxes: Dict[str, Tuple[int, int, int, int, int] | Tuple[int, int, int, int] | ClipBox] | None = None, allowLayerReuse: bool = True) table_C_O_L_R_

Build COLR table from color layers mapping.

Parameters:
  • colorGlyphs – map of base glyph name to, either list of (layer glyph name, color palette index) tuples for COLRv0; or a single Paint (dict) or list of Paint for COLRv1.

  • version – the version of COLR table. If None, the version is determined by the presence of COLRv1 paints or variation data (varStore), which require version 1; otherwise, if all base glyphs use only simple color layers, version 0 is used.

  • glyphMap – a map from glyph names to glyph indices, as returned from TTFont.getReverseGlyphMap(), to optionally sort base records by GID.

  • varStore – Optional ItemVarationStore for deltas associated with v1 layer.

  • varIndexMap – Optional DeltaSetIndexMap for deltas associated with v1 layer.

  • clipBoxes – Optional map of base glyph name to clip box 4- or 5-tuples: (xMin, yMin, xMax, yMax) or (xMin, yMin, xMax, yMax, varIndexBase).

Returns:

A new COLR table.

fontTools.colorLib.builder.buildCPAL(palettes: Sequence[Sequence[Tuple[float, float, float, float]]], paletteTypes: Sequence[ColorPaletteType] | None = None, paletteLabels: Sequence[None | str | Dict[str, str]] | None = None, paletteEntryLabels: Sequence[None | str | Dict[str, str]] | None = None, nameTable: table__n_a_m_e | None = None) table_C_P_A_L_

Build CPAL table from list of color palettes.

Parameters:
  • palettes – list of lists of colors encoded as tuples of (R, G, B, A) floats in the range [0..1].

  • paletteTypes – optional list of ColorPaletteType, one for each palette.

  • paletteLabels – optional list of palette labels. Each lable can be either: None (no label), a string (for for default English labels), or a localized string (as a dict keyed with BCP47 language codes).

  • paletteEntryLabels – optional list of palette entry labels, one for each palette entry (see paletteLabels).

  • nameTable – optional name table where to store palette and palette entry labels. Required if either paletteLabels or paletteEntryLabels is set.

Returns:

A new CPAL v0 or v1 table, if custom palette types or labels are specified.

fontTools.colorLib.builder.populateCOLRv0(table: COLR, colorGlyphsV0: Dict[str, Sequence[Tuple[str, int]]], glyphMap: Mapping[str, int] | None = None)

Build v0 color layers and add to existing COLR table.

Parameters:
  • table – a raw otTables.COLR() object (not ttLib’s table_C_O_L_R_).

  • colorGlyphsV0 – map of base glyph names to lists of (layer glyph names, color palette index) tuples. Can be empty.

  • glyphMap – a map from glyph names to glyph indices, as returned from TTFont.getReverseGlyphMap(), to optionally sort base records by GID.

config: configure fontTools

Define all configuration options that can affect the working of fontTools modules. E.g. optimization levels of varLib IUP, otlLib GPOS compression level, etc. If this file gets too big, split it into smaller files per-module.

An instance of the Config class can be attached to a TTFont object, so that the various modules can access their configuration options from it.

class fontTools.config.Config(values: AbstractConfig | Dict[Option | str, Any] = {}, parse_values: bool = False, skip_unknown: bool = False)
clear() None.  Remove all items from D.
copy()
get(option_or_name: ~fontTools.misc.configTools.Option | str, default: ~typing.Any = <object object>) Any

Get the value of an option. The value which is returned is the first provided among:

  1. a user-provided value in the options’s self._values dict

  2. a caller-provided default value to this method call

  3. the global default for the option provided in fontTools.config

This is to provide the ability to migrate progressively from config options passed as arguments to fontTools APIs to config options read from the current TTFont, e.g.

def fontToolsAPI(font, some_option):
    value = font.cfg.get("someLib.module:SOME_OPTION", some_option)
    # use value

That way, the function will work the same for users of the API that still pass the option to the function call, but will favour the new config mechanism if the given font specifies a value for that option.

items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
options: ClassVar[Options] = Options({     'fontTools.otlLib.optimize.gpos:COMPRESSION_LEVEL': Option(default=0, ...),     'fontTools.ttLib.tables.otBase:USE_HARFBUZZ_REPACKER': Option(default=None, ...),     'fontTools.otlLib.builder:WRITE_GPOS7': Option(default=False, ...), })
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

classmethod register_option(name: str, help: str, default: Any, parse: Callable[[str], Any], validate: Callable[[Any], bool] | None = None) Option

Register an available option in this config system.

set(option_or_name: Option | str, value: Any, parse_values: bool = False, skip_unknown: bool = False)

Set the value of an option.

Parameters:
  • option_or_name (*) – an Option object or its name (str).

  • value (*) – the value to be assigned to given option.

  • parse_values (*) – parse the configuration value from a string into its proper type, as per its Option object. The default behavior is to raise ConfigValueValidationError when the value is not of the right type. Useful when reading options from a file type that doesn’t support as many types as Python.

  • skip_unknown (*) – skip unknown configuration options. The default behaviour is to raise ConfigUnknownOptionError. Useful when reading options from a configuration file that has extra entries (e.g. for a later version of fontTools)

setdefault(k[, d]) D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() an object providing a view on D's values

cu2qu: Cubic to quadratic curve conversion

Routines for converting cubic curves to quadratic splines, suitable for use in OpenType to TrueType outline conversion.

Conversion is carried out to a degree of tolerance provided by the user. While it is relatively easy to find the best single quadratic curve to represent a given cubic (see for example this method from CAGD), the best-fit method may not be sufficiently accurate for type design.

Instead, this method chops the cubic curve into multiple segments before converting each cubic segment to a quadratic, in order to ensure that the resulting spline fits within the given tolerance.

The basic curve conversion routines are implemented in the fontTools.cu2qu.cu2qu module; the fontTools.cu2qu.ufo module applies these routines to all of the curves in a UFO file or files; while the fontTools.cu2qu.cli module implements the fonttools cu2qu command for converting a UFO format font with cubic curves into one with quadratic curves.

fontTools.cu2qu.cu2qu

fontTools.cu2qu.cu2qu.curve_to_quadratic(curve, double max_err, int all_quadratic=True)

Approximate a cubic Bezier curve with a spline of n quadratics.

Parameters:
  • cubic (sequence) – Four 2D tuples representing control points of the cubic Bezier curve.

  • max_err (double) – Permitted deviation from the original curve.

  • all_quadratic (bool) – If True (default) returned value is a quadratic spline. If False, it’s either a single quadratic curve or a single cubic curve.

Returns:

A list of 2D tuples, representing control points of the quadratic spline if it fits within the given tolerance, or None if no suitable spline could be calculated.

If all_quadratic is False: Either a quadratic curve (if length of output is 3), or a cubic curve (if length of output is 4).

Return type:

If all_quadratic is True

fontTools.cu2qu.cu2qu.curves_to_quadratic(curves, max_errors, int all_quadratic=True)

Return quadratic Bezier splines approximating the input cubic Beziers.

Parameters:
  • curves – A sequence of n curves, each curve being a sequence of four 2D tuples.

  • max_errors – A sequence of n floats representing the maximum permissible deviation from each of the cubic Bezier curves.

  • all_quadratic (bool) – If True (default) returned values are a quadratic spline. If False, they are either a single quadratic curve or a single cubic curve.

Example:

>>> curves_to_quadratic( [
...   [ (50,50), (100,100), (150,100), (200,50) ],
...   [ (75,50), (120,100), (150,75),  (200,60) ]
... ], [1,1] )
[[(50.0, 50.0), (75.0, 75.0), (125.0, 91.66666666666666), (175.0, 75.0), (200.0, 50.0)], [(75.0, 50.0), (97.5, 75.0), (135.41666666666666, 82.08333333333333), (175.0, 67.5), (200.0, 60.0)]]

The returned splines have “implied oncurve points” suitable for use in TrueType glif outlines - i.e. in the first spline returned above, the first quadratic segment runs from (50,50) to ( (75 + 125)/2 , (120 + 91.666..)/2 ) = (100, 83.333…).

Returns:

If all_quadratic is True, a list of splines, each spline being a list of 2D tuples.

If all_quadratic is False, a list of curves, each curve being a quadratic (length 3), or cubic (length 4).

Raises:
  • fontTools.cu2qu.Errors.ApproxNotFoundError – if no suitable approximation

  • can be found for all curves with the given parameters.

fontTools.cu2qu.ufo

Converts cubic bezier curves to quadratic splines.

Conversion is performed such that the quadratic splines keep the same end-curve tangents as the original cubics. The approach is iterative, increasing the number of segments for a spline until the error gets below a bound.

Respective curves from multiple fonts will be converted at once to ensure that the resulting splines are interpolation-compatible.

fontTools.cu2qu.ufo.font_to_quadratic(font, **kwargs)

Convenience wrapper around fonts_to_quadratic, for just one font. Return the set of modified glyph names if any, else return empty set.

fontTools.cu2qu.ufo.fonts_to_quadratic(fonts, max_err_em=None, max_err=None, reverse_direction=False, stats=None, dump_stats=False, remember_curve_type=True, all_quadratic=True)

Convert the curves of a collection of fonts to quadratic.

All curves will be converted to quadratic at once, ensuring interpolation compatibility. If this is not required, calling fonts_to_quadratic with one font at a time may yield slightly more optimized results.

Return the set of modified glyph names if any, else return an empty set.

By default, cu2qu stores the curve type in the fonts’ lib, under a private key “com.github.googlei18n.cu2qu.curve_type”, and will not try to convert them again if the curve type is already set to “quadratic”. Setting ‘remember_curve_type’ to False disables this optimization.

Raises IncompatibleFontsError if same-named glyphs from different fonts have non-interpolatable outlines.

designspaceLib: Read, write, and edit designspace files

Implements support for reading and manipulating designspace files. Allows the users to define axes, rules, sources, variable fonts and instances, and their STAT information.

1 DesignSpaceDocument Python API

An object to read, write and edit interpolation systems for typefaces. Define sources, axes, rules, variable fonts and instances.

Get an overview of the available classes in the Class Diagram below:

UML class diagram of designspaceLib

UML class diagram of designspaceLib. Click to enlarge.

DesignSpaceDocument
class fontTools.designspaceLib.DesignSpaceDocument(readerClass=None, writerClass=None)

The DesignSpaceDocument object can read and write .designspace data. It imports the axes, sources, variable fonts and instances to very basic descriptor objects that store the data in attributes. Data is added to the document by creating such descriptor objects, filling them with data and then adding them to the document. This makes it easy to integrate this object in different contexts.

The DesignSpaceDocument object can be subclassed to work with different objects, as long as they have the same attributes. Reader and Writer objects can be subclassed as well.

Note: Python attribute names are usually camelCased, the corresponding XML attributes are usually all lowercase.

from fontTools.designspaceLib import DesignSpaceDocument
doc = DesignSpaceDocument.fromfile("some/path/to/my.designspace")
doc.formatVersion
doc.elidedFallbackName
doc.axes
doc.axisMappings
doc.locationLabels
doc.rules
doc.rulesProcessingLast
doc.sources
doc.variableFonts
doc.instances
doc.lib
asdict()
property log
path

String, optional. When the document is read from the disk, this is the full path that was given to read() or fromfile().

filename

String, optional. When the document is read from the disk, this is its original file name, i.e. the last part of its path.

When the document is produced by a Python script and still only exists in memory, the producing script can write here an indication of a possible “good” filename, in case one wants to save the file somewhere.

formatVersion: str | None

Format version for this document, as a string. E.g. “4.0”

elidedFallbackName: str | None

STAT Style Attributes Header field elidedFallbackNameID.

See: OTSpec STAT Style Attributes Header

New in version 5.0.

axes: List[AxisDescriptor | DiscreteAxisDescriptor]

List of this document’s axes.

axisMappings: List[AxisMappingDescriptor]

List of this document’s axis mappings.

locationLabels: List[LocationLabelDescriptor]

List of this document’s STAT format 4 labels.

New in version 5.0.

rules: List[RuleDescriptor]

List of this document’s rules.

rulesProcessingLast: bool

This flag indicates whether the substitution rules should be applied before or after other glyph substitution features.

  • False: before

  • True: after.

Default is False. For new projects, you probably want True. See the following issues for more information: fontTools#1371 fontTools#2050

If you want to use a different feature altogether, e.g. calt, use the lib key com.github.fonttools.varLib.featureVarsFeatureTag

<lib>
    <dict>
        <key>com.github.fonttools.varLib.featureVarsFeatureTag</key>
        <string>calt</string>
    </dict>
</lib>
sources: List[SourceDescriptor]

List of this document’s sources.

variableFonts: List[VariableFontDescriptor]

List of this document’s variable fonts.

New in version 5.0.

instances: List[InstanceDescriptor]

List of this document’s instances.

lib: Dict

User defined, custom data associated with the whole document.

Use reverse-DNS notation to identify your own data. Respect the data stored by others.

default: str | None

Name of the default master.

This attribute is updated by the findDefault()

classmethod fromfile(path, readerClass=None, writerClass=None)

Read a designspace file from path and return a new instance of :class:.

classmethod fromstring(string, readerClass=None, writerClass=None)
tostring(encoding=None)

Returns the designspace as a string. Default encoding utf-8.

read(path)

Read a designspace file from path and populates the fields of self with the data.

write(path)

Write this designspace to path.

updatePaths()

Right before we save we need to identify and respond to the following situations: In each descriptor, we have to do the right thing for the filename attribute.

case 1.
descriptor.filename == None
descriptor.path == None

-- action:
write as is, descriptors will not have a filename attr.
useless, but no reason to interfere.


case 2.
descriptor.filename == "../something"
descriptor.path == None

-- action:
write as is. The filename attr should not be touched.


case 3.
descriptor.filename == None
descriptor.path == "~/absolute/path/there"

-- action:
calculate the relative path for filename.
We're not overwriting some other value for filename, it should be fine


case 4.
descriptor.filename == '../somewhere'
descriptor.path == "~/absolute/path/there"

-- action:
there is a conflict between the given filename, and the path.
So we know where the file is relative to the document.
Can't guess why they're different, we just choose for path to be correct and update filename.
addSource(sourceDescriptor: SourceDescriptor)

Add the given sourceDescriptor to doc.sources.

addSourceDescriptor(**kwargs)

Instantiate a new SourceDescriptor using the given kwargs and add it to doc.sources.

addInstance(instanceDescriptor: InstanceDescriptor)

Add the given instanceDescriptor to instances.

addInstanceDescriptor(**kwargs)

Instantiate a new InstanceDescriptor using the given kwargs and add it to instances.

addAxis(axisDescriptor: AxisDescriptor | DiscreteAxisDescriptor)

Add the given axisDescriptor to axes.

addAxisDescriptor(**kwargs)

Instantiate a new AxisDescriptor using the given kwargs and add it to axes.

The axis will be and instance of DiscreteAxisDescriptor if the kwargs provide a value, or a AxisDescriptor otherwise.

addAxisMapping(axisMappingDescriptor: AxisMappingDescriptor)

Add the given axisMappingDescriptor to axisMappings.

addAxisMappingDescriptor(**kwargs)

Instantiate a new AxisMappingDescriptor using the given kwargs and add it to rules.

addRule(ruleDescriptor: RuleDescriptor)

Add the given ruleDescriptor to rules.

addRuleDescriptor(**kwargs)

Instantiate a new RuleDescriptor using the given kwargs and add it to rules.

addVariableFont(variableFontDescriptor: VariableFontDescriptor)

Add the given variableFontDescriptor to variableFonts.

New in version 5.0.

addVariableFontDescriptor(**kwargs)

Instantiate a new VariableFontDescriptor using the given kwargs and add it to variableFonts.

New in version 5.0.

addLocationLabel(locationLabelDescriptor: LocationLabelDescriptor)

Add the given locationLabelDescriptor to locationLabels.

New in version 5.0.

addLocationLabelDescriptor(**kwargs)

Instantiate a new LocationLabelDescriptor using the given kwargs and add it to locationLabels.

New in version 5.0.

newDefaultLocation()

Return a dict with the default location in design space coordinates.

labelForUserLocation(userLocation: Dict[str, float]) LocationLabelDescriptor | None

Return the LocationLabel that matches the given userLocation, or None if no such label exists.

New in version 5.0.

updateFilenameFromPath(masters=True, instances=True, force=False)

Set a descriptor filename attr from the path and this document path.

If the filename attribute is not None: skip it.

newAxisDescriptor()

Ask the writer class to make us a new axisDescriptor.

newSourceDescriptor()

Ask the writer class to make us a new sourceDescriptor.

newInstanceDescriptor()

Ask the writer class to make us a new instanceDescriptor.

getAxisOrder()

Return a list of axis names, in the same order as defined in the document.

getAxis(name: str) AxisDescriptor | DiscreteAxisDescriptor | None

Return the axis with the given name, or None if no such axis exists.

getAxisByTag(tag: str) AxisDescriptor | DiscreteAxisDescriptor | None

Return the axis with the given tag, or None if no such axis exists.

getLocationLabel(name: str) LocationLabelDescriptor | None

Return the top-level location label with the given name, or None if no such label exists.

New in version 5.0.

map_forward(userLocation: Dict[str, float]) Dict[str, float]

Map a user location to a design location.

Assume that missing coordinates are at the default location for that axis.

Note: the output won’t be anisotropic, only the xvalue is set.

New in version 5.0.

map_backward(designLocation: Dict[str, float | Tuple[float, float]]) Dict[str, float]

Map a design location to a user location.

Assume that missing coordinates are at the default location for that axis.

When the input has anisotropic locations, only the xvalue is used.

New in version 5.0.

findDefault()

Set and return SourceDescriptor at the default location or None.

The default location is the set of all default values in user space of all axes.

This function updates the document’s default value.

Changed in version 5.0: Allow the default source to not specify some of the axis values, and they are assumed to be the default. See SourceDescriptor.getFullDesignLocation()

normalizeLocation(location)

Return a dict with normalized axis values.

normalize()

Normalise the geometry of this designspace:

  • scale all the locations of all masters and instances to the -1 - 0 - 1 value.

  • we need the axis data to do the scaling, so we do those last.

loadSourceFonts(opener, **kwargs)

Ensure SourceDescriptor.font attributes are loaded, and return list of fonts.

Takes a callable which initializes a new font object (e.g. TTFont, or defcon.Font, etc.) from the SourceDescriptor.path, and sets the SourceDescriptor.font attribute. If the font attribute is already not None, it is not loaded again. Fonts with the same path are only loaded once and shared among SourceDescriptors.

For example, to load UFO sources using defcon:

designspace = DesignSpaceDocument.fromfile(“path/to/my.designspace”) designspace.loadSourceFonts(defcon.Font)

Or to load masters as FontTools binary fonts, including extra options:

designspace.loadSourceFonts(ttLib.TTFont, recalcBBoxes=False)

Parameters:
  • opener (Callable) – takes one required positional argument, the source.path, and an optional list of keyword arguments, and returns a new font object loaded from the path.

  • **kwargs – extra options passed on to the opener function.

Returns:

List of font objects in the order they appear in the sources list.

property formatTuple

Return the formatVersion as a tuple of (major, minor).

New in version 5.0.

getVariableFonts() List[VariableFontDescriptor]

Return all variable fonts defined in this document, or implicit variable fonts that can be built from the document’s continuous axes.

In the case of Designspace documents before version 5, the whole document was implicitly describing a variable font that covers the whole space.

In version 5 and above documents, there can be as many variable fonts as there are locations on discrete axes.

See also

splitInterpolable()

New in version 5.0.

deepcopyExceptFonts()

Allow deep-copying a DesignSpace document without deep-copying attached UFO fonts or TTFont objects. The font attribute is shared by reference between the original and the copy.

New in version 5.0.

AxisDescriptor
class fontTools.designspaceLib.AxisDescriptor(*, tag=None, name=None, labelNames=None, minimum=None, default=None, maximum=None, hidden=False, map=None, axisOrdering=None, axisLabels=None)

Simple container for the axis data.

Add more localisations?

a1 = AxisDescriptor()
a1.minimum = 1
a1.maximum = 1000
a1.default = 400
a1.name = "weight"
a1.tag = "wght"
a1.labelNames['fa-IR'] = "قطر"
a1.labelNames['en'] = "Wéíght"
a1.map = [(1.0, 10.0), (400.0, 66.0), (1000.0, 990.0)]
a1.axisOrdering = 1
a1.axisLabels = [
    AxisLabelDescriptor(name="Regular", userValue=400, elidable=True)
]
doc.addAxis(a1)
minimum

number. The minimum value for this axis in user space.

MutatorMath + varLib.

maximum

number. The maximum value for this axis in user space.

MutatorMath + varLib.

default

number. The default value for this axis, i.e. when a new location is created, this is the value this axis will get in user space.

MutatorMath + varLib.

serialize()
map_forward(v)

Maps value from axis mapping’s input (user) to output (design).

map_backward(v)

Maps value from axis mapping’s output (design) to input (user).

asdict()
compare(other)
flavor = 'axis'
tag

string. Four letter tag for this axis. Some might be registered at the OpenType specification. Privately-defined axis tags must begin with an uppercase letter and use only uppercase letters or digits.

name

string. Name of the axis as it is used in the location dicts.

MutatorMath + varLib.

labelNames

dict. When defining a non-registered axis, it will be necessary to define user-facing readable names for the axis. Keyed by xml:lang code. Values are required to be unicode strings, even if they only contain ASCII characters.

hidden

bool. Whether this axis should be hidden in user interfaces.

map

list of input / output values that can describe a warp of user space to design space coordinates. If no map values are present, it is assumed user space is the same as design space, as in [(minimum, minimum), (maximum, maximum)].

varLib.

axisOrdering

STAT table field axisOrdering.

See: OTSpec STAT Axis Record

New in version 5.0.

axisLabels: List[AxisLabelDescriptor]

STAT table entries for Axis Value Tables format 1, 2, 3.

See: OTSpec STAT Axis Value Tables

New in version 5.0.

DiscreteAxisDescriptor
class fontTools.designspaceLib.DiscreteAxisDescriptor(*, tag=None, name=None, labelNames=None, values=None, default=None, hidden=False, map=None, axisOrdering=None, axisLabels=None)

Container for discrete axis data.

Use this for axes that do not interpolate. The main difference from a continuous axis is that a continuous axis has a minimum and maximum, while a discrete axis has a list of values.

Example: an Italic axis with 2 stops, Roman and Italic, that are not compatible. The axis still allows to bind together the full font family, which is useful for the STAT table, however it can’t become a variation axis in a VF.

a2 = DiscreteAxisDescriptor()
a2.values = [0, 1]
a2.default = 0
a2.name = "Italic"
a2.tag = "ITAL"
a2.labelNames['fr'] = "Italique"
a2.map = [(0, 0), (1, -11)]
a2.axisOrdering = 2
a2.axisLabels = [
    AxisLabelDescriptor(name="Roman", userValue=0, elidable=True)
]
doc.addAxis(a2)

New in version 5.0.

flavor = 'axis'
default: float

The default value for this axis, i.e. when a new location is created, this is the value this axis will get in user space.

However, this default value is less important than in continuous axes:

  • it doesn’t define the “neutral” version of outlines from which deltas would apply, as this axis does not interpolate.

  • it doesn’t provide the reference glyph set for the designspace, as fonts at each value can have different glyph sets.

values: List[float]

List of possible values for this axis. Contrary to continuous axes, only the values in this list can be taken by the axis, nothing in-between.

map_forward(value)

Maps value from axis mapping’s input to output.

Returns value unchanged if no mapping entry is found.

Note: for discrete axes, each value must have its mapping entry, if you intend that value to be mapped.

map_backward(value)

Maps value from axis mapping’s output to input.

Returns value unchanged if no mapping entry is found.

Note: for discrete axes, each value must have its mapping entry, if you intend that value to be mapped.

asdict()
compare(other)
tag

string. Four letter tag for this axis. Some might be registered at the OpenType specification. Privately-defined axis tags must begin with an uppercase letter and use only uppercase letters or digits.

name

string. Name of the axis as it is used in the location dicts.

MutatorMath + varLib.

labelNames

dict. When defining a non-registered axis, it will be necessary to define user-facing readable names for the axis. Keyed by xml:lang code. Values are required to be unicode strings, even if they only contain ASCII characters.

hidden

bool. Whether this axis should be hidden in user interfaces.

map

list of input / output values that can describe a warp of user space to design space coordinates. If no map values are present, it is assumed user space is the same as design space, as in [(minimum, minimum), (maximum, maximum)].

varLib.

axisOrdering

STAT table field axisOrdering.

See: OTSpec STAT Axis Record

New in version 5.0.

axisLabels: List[AxisLabelDescriptor]

STAT table entries for Axis Value Tables format 1, 2, 3.

See: OTSpec STAT Axis Value Tables

New in version 5.0.

AxisLabelDescriptor
class fontTools.designspaceLib.AxisLabelDescriptor(*, name, userValue, userMinimum=None, userMaximum=None, elidable=False, olderSibling=False, linkedUserValue=None, labelNames=None)

Container for axis label data.

Analogue of OpenType’s STAT data for a single axis (formats 1, 2 and 3). All values are user values. See: OTSpec STAT Axis value table, format 1, 2, 3

The STAT format of the Axis value depends on which field are filled-in, see getFormat()

New in version 5.0.

flavor = 'label'
userMinimum: float | None

STAT field rangeMinValue (format 2).

userValue: float

STAT field value (format 1, 3) or nominalValue (format 2).

userMaximum: float | None

STAT field rangeMaxValue (format 2).

name: str

Label for this axis location, STAT field valueNameID.

elidable: bool

STAT flag ELIDABLE_AXIS_VALUE_NAME.

See: OTSpec STAT Flags

olderSibling: bool

STAT flag OLDER_SIBLING_FONT_ATTRIBUTE.

See: OTSpec STAT Flags

linkedUserValue: float | None

STAT field linkedValue (format 3).

labelNames: MutableMapping[str, str]

User-facing translations of this location’s label. Keyed by xml:lang code.

getFormat() int

Determine which format of STAT Axis value to use to encode this label.

STAT Format

userValue

userMinimum

userMaximum

linkedUserValue

1

2

3

property defaultName: str

Return the English name from labelNames or the name.

asdict()
compare(other)
LocationLabelDescriptor
class fontTools.designspaceLib.LocationLabelDescriptor(*, name, userLocation, elidable=False, olderSibling=False, labelNames=None)

Container for location label data.

Analogue of OpenType’s STAT data for a free-floating location (format 4). All values are user values.

See: OTSpec STAT Axis value table, format 4

New in version 5.0.

flavor = 'label'
name: str

Label for this named location, STAT field valueNameID.

userLocation: Dict[str, float]

Location in user coordinates along each axis.

If an axis is not mentioned, it is assumed to be at its default location.

See also

This may be only part of the full location. See: getFullUserLocation()

elidable: bool

STAT flag ELIDABLE_AXIS_VALUE_NAME.

See: OTSpec STAT Flags

olderSibling: bool

STAT flag OLDER_SIBLING_FONT_ATTRIBUTE.

See: OTSpec STAT Flags

labelNames: Dict[str, str]

User-facing translations of this location’s label. Keyed by xml:lang code.

property defaultName: str

Return the English name from labelNames or the name.

getFullUserLocation(doc: DesignSpaceDocument) Dict[str, float]

Get the complete user location of this label, by combining data from the explicit user location and default axis values.

New in version 5.0.

asdict()
compare(other)
RuleDescriptor
class fontTools.designspaceLib.RuleDescriptor(*, name=None, conditionSets=None, subs=None)

Represents the rule descriptor element: a set of glyph substitutions to trigger conditionally in some parts of the designspace.

r1 = RuleDescriptor()
r1.name = "unique.rule.name"
r1.conditionSets.append([dict(name="weight", minimum=-10, maximum=10), dict(...)])
r1.conditionSets.append([dict(...), dict(...)])
r1.subs.append(("a", "a.alt"))
<!-- optional: list of substitution rules -->
<rules>
    <rule name="vertical.bars">
        <conditionset>
            <condition minimum="250.000000" maximum="750.000000" name="weight"/>
            <condition minimum="100" name="width"/>
            <condition minimum="10" maximum="40" name="optical"/>
        </conditionset>
        <sub name="cent" with="cent.alt"/>
        <sub name="dollar" with="dollar.alt"/>
    </rule>
</rules>
name

string. Unique name for this rule. Can be used to reference this rule data.

conditionSets

a list of conditionsets.

  • Each conditionset is a list of conditions.

  • Each condition is a dict with name, minimum and maximum keys.

subs

list of substitutions.

  • Each substitution is stored as tuples of glyphnames, e.g. (“a”, “a.alt”).

  • Note: By default, rules are applied first, before other text shaping/OpenType layout, as they are part of the Required Variation Alternates OpenType feature. See ref:rules-element § Attributes.

asdict()
compare(other)
Evaluating rules
fontTools.designspaceLib.evaluateRule(rule, location)

Return True if any of the rule’s conditionsets matches the given location.

fontTools.designspaceLib.evaluateConditions(conditions, location)

Return True if all the conditions matches the given location.

  • If a condition has no minimum, check for < maximum.

  • If a condition has no maximum, check for > minimum.

fontTools.designspaceLib.processRules(rules, location, glyphNames)

Apply these rules at this location to these glyphnames.

Return a new list of glyphNames with substitutions applied.

  • rule order matters

SourceDescriptor
class fontTools.designspaceLib.SourceDescriptor(*, filename=None, path=None, font=None, name=None, location=None, designLocation=None, layerName=None, familyName=None, styleName=None, localisedFamilyName=None, copyLib=False, copyInfo=False, copyGroups=False, copyFeatures=False, muteKerning=False, muteInfo=False, mutedGlyphNames=None)

Simple container for data related to the source

doc = DesignSpaceDocument()
s1 = SourceDescriptor()
s1.path = masterPath1
s1.name = "master.ufo1"
s1.font = defcon.Font("master.ufo1")
s1.location = dict(weight=0)
s1.familyName = "MasterFamilyName"
s1.styleName = "MasterStyleNameOne"
s1.localisedFamilyName = dict(fr="Caractère")
s1.mutedGlyphNames.append("A")
s1.mutedGlyphNames.append("Z")
doc.addSource(s1)
flavor = 'source'
property filename

string. A relative path to the source file, as it is in the document.

MutatorMath + VarLib.

property path

The absolute path, calculated from filename.

font

Any Python object. Optional. Points to a representation of this source font that is loaded in memory, as a Python object (e.g. a defcon.Font or a fontTools.ttFont.TTFont).

The default document reader will not fill-in this attribute, and the default writer will not use this attribute. It is up to the user of designspaceLib to either load the resource identified by filename and store it in this field, or write the contents of this field to the disk and make `filename point to that.

name

string. Optional. Unique identifier name for this source.

MutatorMath + varLib.

designLocation

dict. Axis values for this source, in design space coordinates.

MutatorMath + varLib.

This may be only part of the full design location. See getFullDesignLocation()

New in version 5.0.

layerName

string. The name of the layer in the source to look for outline data. Default None which means foreground.

familyName

string. Family name of this source. Though this data can be extracted from the font, it can be efficient to have it right here.

varLib.

styleName

string. Style name of this source. Though this data can be extracted from the font, it can be efficient to have it right here.

varLib.

localisedFamilyName

dict. A dictionary of localised family name strings, keyed by language code.

If present, will be used to build localized names for all instances.

New in version 5.0.

copyLib

bool. Indicates if the contents of the font.lib need to be copied to the instances.

MutatorMath.

Deprecated since version 5.0.

copyInfo

bool. Indicates if the non-interpolating font.info needs to be copied to the instances.

MutatorMath.

Deprecated since version 5.0.

copyGroups

bool. Indicates if the groups need to be copied to the instances.

MutatorMath.

Deprecated since version 5.0.

copyFeatures

bool. Indicates if the feature text needs to be copied to the instances.

MutatorMath.

Deprecated since version 5.0.

muteKerning

bool. Indicates if the kerning data from this source needs to be muted (i.e. not be part of the calculations).

MutatorMath only.

muteInfo

bool. Indicated if the interpolating font.info data for this source needs to be muted.

MutatorMath only.

mutedGlyphNames

list. Glyphnames that need to be muted in the instances.

MutatorMath only.

property location

dict. Axis values for this source, in design space coordinates.

MutatorMath + varLib.

Deprecated since version 5.0: Use the more explicit alias for this property designLocation.

setFamilyName(familyName, languageCode='en')

Setter for localisedFamilyName

New in version 5.0.

getFamilyName(languageCode='en')

Getter for localisedFamilyName

New in version 5.0.

getFullDesignLocation(doc: DesignSpaceDocument) Dict[str, float]

Get the complete design location of this source, from its designLocation and the document’s axis defaults.

New in version 5.0.

asdict()
compare(other)
VariableFontDescriptor
class fontTools.designspaceLib.VariableFontDescriptor(*, name, filename=None, axisSubsets=None, lib=None)

Container for variable fonts, sub-spaces of the Designspace.

Use-cases:

  • From a single DesignSpace with discrete axes, define 1 variable font per value on the discrete axes. Before version 5, you would have needed 1 DesignSpace per such variable font, and a lot of data duplication.

  • From a big variable font with many axes, define subsets of that variable font that only include some axes and freeze other axes at a given location.

New in version 5.0.

flavor = 'variable-font'
name: str

string, required. Name of this variable to identify it during the build process and from other parts of the document, and also as a filename in case the filename property is empty.

VarLib.

property filename

string, optional. Relative path to the variable font file, as it is in the document. The file may or may not exist.

If not specified, the name will be used as a basename for the file.

axisSubsets: List[RangeAxisSubsetDescriptor | ValueAxisSubsetDescriptor]

Axis subsets to include in this variable font.

If an axis is not mentioned, assume that we only want the default location of that axis (same as a ValueAxisSubsetDescriptor).

lib: MutableMapping[str, Any]

Custom data associated with this variable font.

asdict()
compare(other)
RangeAxisSubsetDescriptor
class fontTools.designspaceLib.RangeAxisSubsetDescriptor(*, name, userMinimum=-inf, userDefault=None, userMaximum=inf)

Subset of a continuous axis to include in a variable font.

New in version 5.0.

flavor = 'axis-subset'
name: str

Name of the AxisDescriptor to subset.

userMinimum: float

New minimum value of the axis in the target variable font. If not specified, assume the same minimum value as the full axis. (default = -math.inf)

userDefault: float | None

New default value of the axis in the target variable font. If not specified, assume the same default value as the full axis. (default = None)

userMaximum: float

New maximum value of the axis in the target variable font. If not specified, assume the same maximum value as the full axis. (default = math.inf)

asdict()
compare(other)
ValueAxisSubsetDescriptor
class fontTools.designspaceLib.ValueAxisSubsetDescriptor(*, name, userValue)

Single value of a discrete or continuous axis to use in a variable font.

New in version 5.0.

flavor = 'axis-subset'
name: str

Name of the AxisDescriptor or DiscreteAxisDescriptor to “snapshot” or “freeze”.

userValue: float

Value in user coordinates at which to freeze the given axis.

asdict()
compare(other)
InstanceDescriptor
class fontTools.designspaceLib.InstanceDescriptor(*, filename=None, path=None, font=None, name=None, location=None, locationLabel=None, designLocation=None, userLocation=None, familyName=None, styleName=None, postScriptFontName=None, styleMapFamilyName=None, styleMapStyleName=None, localisedFamilyName=None, localisedStyleName=None, localisedStyleMapFamilyName=None, localisedStyleMapStyleName=None, glyphs=None, kerning=True, info=True, lib=None)

Simple container for data related to the instance

i2 = InstanceDescriptor()
i2.path = instancePath2
i2.familyName = "InstanceFamilyName"
i2.styleName = "InstanceStyleName"
i2.name = "instance.ufo2"
# anisotropic location
i2.designLocation = dict(weight=500, width=(400,300))
i2.postScriptFontName = "InstancePostscriptName"
i2.styleMapFamilyName = "InstanceStyleMapFamilyName"
i2.styleMapStyleName = "InstanceStyleMapStyleName"
i2.lib['com.coolDesignspaceApp.specimenText'] = 'Hamburgerwhatever'
doc.addInstance(i2)
flavor = 'instance'
property filename

string. Relative path to the instance file, as it is in the document. The file may or may not exist.

MutatorMath + VarLib.

property path

string. Absolute path to the instance file, calculated from the document path and the string in the filename attr. The file may or may not exist.

MutatorMath.

font

Same as SourceDescriptor.font

name

string. Unique identifier name of the instance, used to identify it if it needs to be referenced from elsewhere in the document.

locationLabel

Name of a LocationLabelDescriptor. If provided, the instance should have the same location as the LocationLabel.

New in version 5.0.

designLocation: Dict[str, float | Tuple[float, float]]

dict. Axis values for this instance, in design space coordinates.

MutatorMath + varLib.

See also

This may be only part of the full location. See: getFullDesignLocation() getFullUserLocation()

New in version 5.0.

userLocation: Dict[str, float]

dict. Axis values for this instance, in user space coordinates.

MutatorMath + varLib.

See also

This may be only part of the full location. See: getFullDesignLocation() getFullUserLocation()

New in version 5.0.

familyName

string. Family name of this instance.

MutatorMath + varLib.

styleName

string. Style name of this instance.

MutatorMath + varLib.

postScriptFontName

string. Postscript fontname for this instance.

MutatorMath + varLib.

styleMapFamilyName

string. StyleMap familyname for this instance.

MutatorMath + varLib.

styleMapStyleName

string. StyleMap stylename for this instance.

MutatorMath + varLib.

localisedFamilyName

dict. A dictionary of localised family name strings, keyed by language code.

localisedStyleName

dict. A dictionary of localised stylename strings, keyed by language code.

localisedStyleMapFamilyName

A dictionary of localised style map familyname strings, keyed by language code.

localisedStyleMapStyleName

A dictionary of localised style map stylename strings, keyed by language code.

glyphs

dict for special master definitions for glyphs. If glyphs need special masters (to record the results of executed rules for example).

MutatorMath.

Deprecated since version 5.0: Use rules or sparse sources instead.

kerning

bool. Indicates if this instance needs its kerning calculated.

MutatorMath.

Deprecated since version 5.0.

info

bool. Indicated if this instance needs the interpolating font.info calculated.

Deprecated since version 5.0.

lib

Custom data associated with this instance.

property location

dict. Axis values for this instance.

MutatorMath + varLib.

Deprecated since version 5.0: Use the more explicit alias for this property designLocation.

setStyleName(styleName, languageCode='en')

These methods give easier access to the localised names.

getStyleName(languageCode='en')
setFamilyName(familyName, languageCode='en')
getFamilyName(languageCode='en')
setStyleMapStyleName(styleMapStyleName, languageCode='en')
getStyleMapStyleName(languageCode='en')
setStyleMapFamilyName(styleMapFamilyName, languageCode='en')
getStyleMapFamilyName(languageCode='en')
clearLocation(axisName: str | None = None)

Clear all location-related fields. Ensures that :attr:designLocation and :attr:userLocation are dictionaries (possibly empty if clearing everything).

In order to update the location of this instance wholesale, a user should first clear all the fields, then change the field(s) for which they have data.

instance.clearLocation()
instance.designLocation = {'Weight': (34, 36.5), 'Width': 100}
instance.userLocation = {'Opsz': 16}

In order to update a single axis location, the user should only clear that axis, then edit the values:

instance.clearLocation('Weight')
instance.designLocation['Weight'] = (34, 36.5)
Parameters:

axisName – if provided, only clear the location for that axis.

New in version 5.0.

getLocationLabelDescriptor(doc: DesignSpaceDocument) LocationLabelDescriptor | None

Get the LocationLabelDescriptor instance that matches this instances’s locationLabel.

Raises if the named label can’t be found.

New in version 5.0.

getFullDesignLocation(doc: DesignSpaceDocument) Dict[str, float | Tuple[float, float]]

Get the complete design location of this instance, by combining data from the various location fields, default axis values and mappings, and top-level location labels.

The source of truth for this instance’s location is determined for each axis independently by taking the first not-None field in this list:

  • locationLabel: the location along this axis is the same as the matching STAT format 4 label. No anisotropy.

  • designLocation[axisName]: the explicit design location along this axis, possibly anisotropic.

  • userLocation[axisName]: the explicit user location along this axis. No anisotropy.

  • axis.default: default axis value. No anisotropy.

New in version 5.0.

getFullUserLocation(doc: DesignSpaceDocument) Dict[str, float]

Get the complete user location for this instance.

New in version 5.0.

asdict()
compare(other)
Subclassing descriptors

The DesignSpaceDocument can take subclassed Reader and Writer objects. This allows you to work with your own descriptors. You could subclass the descriptors. But as long as they have the basic attributes the descriptor does not need to be a subclass.

class MyDocReader(BaseDocReader):
    axisDescriptorClass = MyAxisDescriptor
    discreteAxisDescriptorClass = MyDiscreteAxisDescriptor
    axisLabelDescriptorClass = MyAxisLabelDescriptor
    locationLabelDescriptorClass = MyLocationLabelDescriptor
    ruleDescriptorClass = MyRuleDescriptor
    sourceDescriptorClass = MySourceDescriptor
    variableFontsDescriptorClass = MyVariableFontDescriptor
    valueAxisSubsetDescriptorClass = MyValueAxisSubsetDescriptor
    rangeAxisSubsetDescriptorClass = MyRangeAxisSubsetDescriptor
    instanceDescriptorClass = MyInstanceDescriptor

class MyDocWriter(BaseDocWriter):
    axisDescriptorClass = MyAxisDescriptor
    discreteAxisDescriptorClass = MyDiscreteAxisDescriptor
    axisLabelDescriptorClass = MyAxisLabelDescriptor
    locationLabelDescriptorClass = MyLocationLabelDescriptor
    ruleDescriptorClass = MyRuleDescriptor
    sourceDescriptorClass = MySourceDescriptor
    variableFontsDescriptorClass = MyVariableFontDescriptor
    valueAxisSubsetDescriptorClass = MyValueAxisSubsetDescriptor
    rangeAxisSubsetDescriptorClass = MyRangeAxisSubsetDescriptor
    instanceDescriptorClass = MyInstanceDescriptor

myDoc = DesignSpaceDocument(MyDocReader, MyDocWriter)
Helper modules
fontTools.designspaceLib.split

See Scripting > Working with DesignSpace version 5 for more information.

Allows building all the variable fonts of a DesignSpace version 5 by splitting the document into interpolable sub-space, then into each VF.

fontTools.designspaceLib.split.convert5to4(doc: DesignSpaceDocument) Dict[str, DesignSpaceDocument]

Convert each variable font listed in this document into a standalone format 4 designspace. This can be used to compile all the variable fonts from a format 5 designspace using tools that only know about format 4.

New in version 5.0.

fontTools.designspaceLib.split.defaultMakeInstanceFilename(doc: DesignSpaceDocument, instance: InstanceDescriptor, statNames: StatNames) str

Default callable to synthesize an instance filename when makeNames=True, for instances that don’t specify an instance name in the designspace. This part of the name generation can be overriden because it’s not specified by the STAT table.

fontTools.designspaceLib.split.splitInterpolable(doc: ~fontTools.designspaceLib.DesignSpaceDocument, makeNames: bool = True, expandLocations: bool = True, makeInstanceFilename: ~typing.Callable[[~fontTools.designspaceLib.DesignSpaceDocument, ~fontTools.designspaceLib.InstanceDescriptor, ~fontTools.designspaceLib.statNames.StatNames], str] = <function defaultMakeInstanceFilename>) Iterator[Tuple[Dict[str, float], DesignSpaceDocument]]

Split the given DS5 into several interpolable sub-designspaces. There are as many interpolable sub-spaces as there are combinations of discrete axis values.

E.g. with axes:
  • italic (discrete) Upright or Italic

  • style (discrete) Sans or Serif

  • weight (continuous) 100 to 900

There are 4 sub-spaces in which the Weight axis should interpolate: (Upright, Sans), (Upright, Serif), (Italic, Sans) and (Italic, Serif).

The sub-designspaces still include the full axis definitions and STAT data, but the rules, sources, variable fonts, instances are trimmed down to only keep what falls within the interpolable sub-space.

Parameters:
  • makeNames (-) – Whether to compute the instance family and style names using the STAT data.

  • expandLocations (-) – Whether to turn all locations into “full” locations, including implicit default axis values where missing.

  • makeInstanceFilename (-) – Callable to synthesize an instance filename when makeNames=True, for instances that don’t specify an instance name in the designspace. This part of the name generation can be overridden because it’s not specified by the STAT table.

New in version 5.0.

fontTools.designspaceLib.split.splitVariableFonts(doc: ~fontTools.designspaceLib.DesignSpaceDocument, makeNames: bool = False, expandLocations: bool = False, makeInstanceFilename: ~typing.Callable[[~fontTools.designspaceLib.DesignSpaceDocument, ~fontTools.designspaceLib.InstanceDescriptor, ~fontTools.designspaceLib.statNames.StatNames], str] = <function defaultMakeInstanceFilename>) Iterator[Tuple[str, DesignSpaceDocument]]

Convert each variable font listed in this document into a standalone designspace. This can be used to compile all the variable fonts from a format 5 designspace using tools that can only deal with 1 VF at a time.

Parameters:
  • makeNames (-) – Whether to compute the instance family and style names using the STAT data.

  • expandLocations (-) – Whether to turn all locations into “full” locations, including implicit default axis values where missing.

  • makeInstanceFilename (-) – Callable to synthesize an instance filename when makeNames=True, for instances that don’t specify an instance name in the designspace. This part of the name generation can be overridden because it’s not specified by the STAT table.

New in version 5.0.

fontTools.varLib.stat

Extra methods for DesignSpaceDocument to generate its STAT table data.

fontTools.varLib.stat.buildVFStatTable(ttFont: TTFont, doc: DesignSpaceDocument, vfName: str) None

Build the STAT table for the variable font identified by its name in the given document.

Knowing which variable we’re building STAT data for is needed to subset the STAT locations to only include what the variable font actually ships.

New in version 5.0.

fontTools.varLib.stat.getStatAxes(doc: DesignSpaceDocument, userRegion: Dict[str, Range | float]) List[Dict]

Return a list of axis dicts suitable for use as the axes argument to fontTools.otlLib.builder.buildStatTable().

New in version 5.0.

fontTools.varLib.stat.getStatLocations(doc: DesignSpaceDocument, userRegion: Dict[str, Range | float]) List[Dict]

Return a list of location dicts suitable for use as the locations argument to fontTools.otlLib.builder.buildStatTable().

New in version 5.0.

fontTools.designspaceLib.statNames

Compute name information for a given location in user-space coordinates using STAT data. This can be used to fill-in automatically the names of an instance:

instance = doc.instances[0]
names = getStatNames(doc, instance.getFullUserLocation(doc))
print(names.styleNames)
class fontTools.designspaceLib.statNames.StatNames(familyNames: Dict[str, str], styleNames: Dict[str, str], postScriptFontName: str | None, styleMapFamilyNames: Dict[str, str], styleMapStyleName: str | None)

Name data generated from the STAT table information.

fontTools.designspaceLib.statNames.getStatNames(doc: DesignSpaceDocument, userLocation: Dict[str, float]) StatNames

Compute the family, style, PostScript names of the given userLocation using the document’s STAT information.

Also computes localizations.

If not enough STAT data is available for a given name, either its dict of localized names will be empty (family and style names), or the name will be None (PostScript name).

New in version 5.0.

2 Document XML structure

2.1 Overview
<?xml version='1.0' encoding='utf-8'?>
<designspace format="5.1">
    <axes>
        <!-- define axes here -->
        <axis... />
        <mappings>
            <!-- define axis mappings here -->
            <!-- New in version 5.1 -->
            <mapping... />
        </mappings>
    </axes>
    <labels>
        <!-- define STAT format 4 labels here -->
        <!-- New in version 5.0 -->
        <label... />
    </labels>
    <sources>
        <!-- define masters here -->
        <source... />
    </sources>
    <variable-fonts>
        <!-- define variable fonts here -->
        <!-- New in version 5.0 -->
        <variable-font... />
    </variable-fonts>
    <instances>
        <!-- define instances here -->
        <instance... />
    </instances>
    <rules>
        <!-- define rules here -->
        <rule... />
    </rules>
    <lib>
        <dict>
            <!-- store custom data here -->
        </dict>
    </lib>
</designspace>
2.2 <axes> element

The <axes> element contains one or more <axis> elements.

Attributes

2.2.1 <axis> element
  • Define a single axis

  • Child element of axes

  • The axis can be either continuous (as in version 4.0) or discrete (new in version 5.0). Discrete axes have a list of values instead of a range minimum and maximum.

Attributes

  • name: required, string. Name of the axis that is used in the location elements.

  • tag: required, string, 4 letters. Some axis tags are registered in the OpenType Specification.

  • default: required, number. The default value for this axis, in user space coordinates.

  • hidden: optional, 0 or 1. Records whether this axis needs to be hidden in interfaces.

For a continuous axis:
  • minimum: required, number. The minimum value for this axis, in user space coordinates.

  • maximum: required, number. The maximum value for this axis, in user space coordinates.

For a discrete axis:
  • values: required, space-separated numbers. The exhaustive list of possible values along this axis.

New in version 5.0.

Example

<axis name="weight" tag="wght" minimum="1" maximum="1000" default="400">

<!--
  Discrete axes provide a list of discrete values.
  No interpolation is allowed between these.
-->
<axis name="Italic" tag="ital" default="0" values="0 1">
2.2.1.1 <labelname> element (axis)
  • Defines a human readable name for UI use.

  • Optional for non-registered axis names.

  • Can be localised with xml:lang

  • Child element of <axis> or <label>

Attributes

Value

  • The natural language name of this axis or STAT label.

Example

<labelname xml:lang="fa-IR">قطر</labelname>
<labelname xml:lang="en">Wéíght</labelname>
2.2.1.2 <map> element
  • Defines a single node in a series of input value (user space coordinate) to output value (designspace coordinate) pairs.

  • Together these values transform the designspace.

  • Child of <axis> element.

Example

<map input="1.0" output="10.0" />
<map input="400.0" output="66.0" />
<map input="1000.0" output="990.0" />
2.2.1.3 <labels> element (axis)

The <labels> element contains one or more <label> elements, and can indicate this axis’ STAT ordering.

New in version 5.0.

Attributes

  • ordering: optional, int, default: natural position of this axis in the list of axes. STAT table field axisOrdering for this axis.

    See: OTSpec STAT Axis Record

2.2.1.3.1 <label> element (axis)
  • Define STAT format 1, 2, 3 labels for the locations on this axis.

  • The axis can have several child <label> elements, one for each STAT entry.

  • This <label> element can have several <labelname> child elements, to provide translations of its name attribute.

New in version 5.0.

Attributes

  • name: required, string. the name of this label

  • elidable: optional, boolean, default: false. STAT flag ELIDABLE_AXIS_VALUE_NAME.

  • oldersibling: optional, boolean, default: false. STAT flag OLDER_SIBLING_FONT_ATTRIBUTE.

    See: OTSpec STAT Flags

Depending on the intended target STAT format, use a combination of the following field, all in user coordinates. Check the following table for the format correspondences.

  • uservalue: (required) STAT field value (format 1, 3) or nominalValue (format 2).

  • userminimum: STAT field rangeMinValue (format 2).

  • usermaximum: STAT field rangeMaxValue (format 2).

  • linkeduservalue: STAT field linkedValue (format 3).

STAT Format

uservalue

userminimum

usermaximum

linkeduservalue

1

2

3

Example

<label userminimum="200" uservalue="200" usermaximum="250" name="Extra Light">
    <labelname xml:lang="de">Extraleicht</labelname>
    <labelname xml:lang="fr">Extra léger</labelname>
</label>
<label userminimum="350" uservalue="400" usermaximum="450" name="Regular" elidable="true" />
2.2.1.3.1.1 <labelname> element (axis STAT label)

User-facing translations of this STAT label. Keyed by xml:lang code.

New in version 5.0.

Same attribute and value as the axis’ <labelname> element.

2.2.2 Example of all axis elements together
<axes elidedfallbackname="Regular">
    <axis default="1" maximum="1000" minimum="0" name="weight" tag="wght">
        <labelname xml:lang="fa-IR">قطر</labelname>
        <labelname xml:lang="en">Wéíght</labelname>
        <labels>
            <label userminimum="200" uservalue="200" usermaximum="250" name="Extra Light">
                <labelname xml:lang="de">Extraleicht</labelname>
                <labelname xml:lang="fr">Extra léger</labelname>
            </label>
            <label userminimum="350" uservalue="400" usermaximum="450" name="Regular" elidable="true" />
        </labels>
    </axis>
    <axis default="100" maximum="200" minimum="50" name="width" tag="wdth">
        <map input="50.0" output="10.0" />
        <map input="100.0" output="66.0" />
        <map input="200.0" output="990.0" />
    </axis>
</axes>
2.2.3 <mappings> element
  • Define an axis mappings group.

  • Child element of axes

Attributes

  • description: optional, string. the description of this mappings group

New in version 5.2.

2.2.3.1 <mapping> element
  • Defines an axis mapping.

  • Child element of <mappings>

Attributes

  • description: optional, string. the description of this mapping

New in version 5.2.

2.2.3.1.1 <input> element
  • Defines the input location of an axis mapping.

  • Child element of <mapping>

  • Contains one or more <dimension> elements with designspace locations.

New in version 5.1.

2.2.3.1.2 <output> element
  • Defines the output location of an axis mapping.

  • Child element of <mapping>

  • Contains one or more <dimension> elements with designspace locations.

New in version 5.1.

2.2.4 Example of all mappings elements together
<mappings>
    <mapping>
        <input>
            <dimension name="weight" xvalue="900"/>
            <dimension name="width" xvalue="150"/>
        </input>
        <output>
            <dimension name="weight" xvalue="870"/>
        </output>
    </mapping>
</mappings>
2.3 <labels> element (top-level)

The <labels> element contains one or more <label> elements.

New in version 5.0.

2.3.1 <label> element (top-level)
  • Define STAT format 4 labels for a free-standing location.

  • The designspace can have several top-level <label> elements, one for each STAT format 4 entry.

  • This <label> element must have a child <location> element that represents the location to which the label applies.

  • This <label> element may have several child <labelname> elements to provide translations of its name attribute.

See: OTSpec STAT Axis value table, format 4

New in version 5.0.

Attributes

  • name: required, string. the name of this label

  • elidable: optional, boolean, default: false. STAT flag ELIDABLE_AXIS_VALUE_NAME.

  • oldersibling: optional, boolean, default: false. STAT flag OLDER_SIBLING_FONT_ATTRIBUTE.

    See: OTSpec STAT Flags

2.3.1.1 <location> element (top-level STAT label)
  • Defines a coordinate in either user or design space.

  • Encodes a dictionary of { axisname: axisvalue }.

  • Also used in <source>, <instance> and <glyph> elements.

  • This <location> element must have one or more child <dimension> elements.

2.3.1.1.1 <dimension> element
  • Child element of <location>, input, or output elements

Attributes

  • name: required, string. Name of the axis.

Depending on whether you’re representing a location in user or design coordinates, provide one of the attributes below.

For user-space coordinates:

  • uservalue: required, number. The value on this axis in user coordinates.

    New in version 5.0.

For design-space coordinates:

  • xvalue: required, number. The value on this axis in design coordinates.

  • yvalue: optional, number. Separate value for anisotropic interpolations.

Example

<location>
    <dimension name="Width" uservalue="125" />
    <dimension name="Weight" xvalue="10" yvalue="20.5" />
</location>
2.3.1.2 <labelname> element (top-level STAT label)

User-facing translations of this STAT label. Keyed by xml:lang code.

New in version 5.0.

Same attribute and value as the axis’ <labelname> element.

2.4 <rules> element

The <rules> element contains one or more <rule> elements.

The rules are evaluated in this order.

Rules describe designspace areas in which one glyph should be replaced by another. A rule has a name and a number of conditionsets. The rule also contains a list of glyphname pairs: the glyphs that need to be substituted. For a rule to be triggered only one of the conditionsets needs to be true, OR. Within a conditionset all conditions need to be true, AND.

Attributes

  • processing: flag, optional. Valid values are [first, last]. This flag indicates whether the substitution rules should be applied before or after other glyph substitution features.

    • If no processing attribute is given, interpret as first, and put the substitution rule in the rvrn feature.

    • If processing is last, put it in rclt.

    • The default is first. For new projects, you probably want last. See the following issues for more information: fontTools#1371 fontTools#2050

    • If you want to use a different feature(s) altogether, e.g. calt, use the lib key com.github.fonttools.varLib.featureVarsFeatureTag.

      <lib>
          <dict>
              <key>com.github.fonttools.varLib.featureVarsFeatureTag</key>
              <string>calt</string>
          </dict>
      </lib>
      

      This can also take a comma-separated list of feature tags, e.g. salt,ss01, if you wish the same rules to be applied with several features.

2.4.1 <rule> element
  • Defines a named rule.

  • Each <rule> element contains one or more <conditionset> elements.

  • Only one <conditionset> needs to be true to trigger the rule (logical OR). An empty condition set is considered to be true, as in, the rule will be always-on.

  • All conditions in a <conditionset> must be true to make the <conditionset> true. (logical AND)

  • For backwards compatibility a <rule> can contain <condition> elements outside of a conditionset. These are then understood to be part of a single, implied, <conditionset>. Note: these conditions should be written wrapped in a conditionset.

  • A rule element needs to contain one or more <sub> elements in order to be compiled to a variable font.

  • Rules without sub elements should be ignored when compiling a font.

  • For authoring tools it might be necessary to save designspace files without <sub> elements just because the work is incomplete.

Attributes

  • name: optional, string. A unique name that can be used to identify this rule if it needs to be referenced elsewhere. The name is not important for compiling variable fonts.

2.4.1.1 <conditionset> element
  • Child element of <rule>

  • Contains zero or more <condition> elements.

2.4.1.1.1 <condition> element
  • Child element of <conditionset>

  • Between the minimum and maximum this condition is True.

  • minimum and maximum are in designspace coordinates.

  • If minimum is not available, assume it is axis.minimum, mapped to designspace coordinates.

  • If maximum is not available, assume it is axis.maximum, mapped to designspace coordinates.

  • The condition must contain at least a minimum or maximum or both.

Attributes

  • name: string, required. Must match one of the defined axis name attributes.

  • minimum: number, required*. The low value, in design coordinates.

  • maximum: number, required*. The high value, in design coordinates.

2.4.1.2 <sub> element
  • Child element of <rule>.

  • Defines which glyph to replace when the rule evaluates to True.

  • The <sub> element contains a pair of glyphnames. The name attribute is the glyph that should be visible when the rule evaluates to False. The with attribute is the glyph that should be visible when the rule evaluates to True.

Attributes

  • name: string, required. The name of the glyph this rule looks for.

  • with: string, required. The name of the glyph it is replaced with.

Example

Example with an implied <conditionset>. Here the conditions are not contained in a conditionset.

<rules processing="last">
    <rule name="named.rule.1">
        <condition minimum="250" maximum="750" name="weight" />
        <condition minimum="50" maximum="100" name="width" />
        <sub name="dollar" with="dollar.alt"/>
    </rule>
</rules>

Example with <conditionsets>. All conditions in a conditionset must be true.

<rules>
    <rule name="named.rule.2">
        <conditionset>
            <condition minimum="250" maximum="750" name="weight" />
            <condition minimum="50" maximum="100" name="width" />
        </conditionset>
        <conditionset>
            <condition... />
            <condition... />
        </conditionset>
        <sub name="dollar" with="dollar.alt"/>
    </rule>
</rules>
2.5 <sources> element

The <sources> element contains one or more <source> elements.

2.5.1 <source> element
  • Defines a single font or layer that contributes to the designspace.

  • Child element of <sources>

  • Location in designspace coordinates.

Attributes

  • familyname: optional, string. The family name of the source font. While this could be extracted from the font data itself, it can be more efficient to add it here.

  • stylename: optional, string. The style name of the source font.

  • name: optional, string. A unique name that can be used to identify this font if it needs to be referenced elsewhere.

  • filename: required, string. A path to the source file, relative to the root path of this document. The path can be at the same level as the document or lower.

  • layer: optional, string. The name of the layer in the source file. If no layer attribute is given assume the foreground layer should be used.

2.5.1.1 <familyname> element: localised names for sources

Localised family names for sources can be included with this <familyname> element with an xml:lang attribute: XML language definition

New in version 5.0.

Example

<familyname xml:lang="fr">Montserrat</familyname>
<familyname xml:lang="ja">モンセラート</familyname>
2.5.1.2 <location> element (source)

Defines the coordinates of this source in the design space.

2.5.1.2.1 <dimension> element (source)
2.5.1.3 <lib> element (source)
  • Example: <lib copy="1" />

  • Child element of <source>

  • Defines if the instances can inherit the data in the lib of this source.

  • MutatorMath only.

Deprecated since version 5.0.

Note

Don’t confuse with other <lib> elements which allow storing arbitrary data. Sources don’t have such a <lib> because usually the backing UFO file has one itself.

2.5.1.4 <info> element
  • Example: <info copy="1" />

  • Child element of <source>

  • Defines if the instances can inherit the non-interpolating font info from this source.

  • MutatorMath only.

Deprecated since version 5.0.

2.5.1.5 <features> element
  • Example: <features copy="1" />

  • Defines if the instances can inherit opentype feature text from this source.

  • Child element of <source>

  • MutatorMath only.

Deprecated since version 5.0.

2.5.1.6 <glyph> element (source)
  • Example: <glyph mute="1" name="A"/>

  • In a <source> element this states if a glyph is to be excluded from the calculation.

  • MutatorMath only.

Attributes

  • mute: optional attribute, number 1 or 0. Indicate if this glyph should be ignored as a master.

Note

Do not confuse with the <glyph> element in instances, which achieves something different.

2.5.1.7 <kerning> element (source)
  • Example: <kerning mute="1" />

  • Can appear in <source> as well as in <instance> elements.

  • MutatorMath only.

Attributes

  • mute: required attribute, number 1 or 0. Indicate if the kerning data from this source is to be excluded from the calculation.

    • If the kerning element is not present, assume mute=0, yes, include the kerning of this source in the calculation.

Example

<source familyname="MasterFamilyName" filename="masters/masterTest1.ufo" name="master.ufo1" stylename="MasterStyleNameOne">
    <location>
        <dimension name="width" xvalue="0.000000" />
        <dimension name="weight" xvalue="0.000000" />
    </location>
    <glyph mute="1" name="A" />
    <glyph mute="1" name="Z" />
</source>
2.6 <variable-fonts> element

The <variable-fonts> element contains one or more <variable-font> elements.

New in version 5.0.

2.6.1 <variable-font> element
  • Child of <variable-fonts>

  • Describe a variable font that can be built from an interpolating subset of the design space.

  • The document may have zero to many variable fonts.

    • If no variable fonts are defined, and all the axes are continuous, then we assume, as in version 4 of the format, that the whole document describes one variable font covering the whole space.

  • Each variable font covers a subset of the whole designspace, defined using <axis-subset> elements.

  • Each variable font can have custom associated data using a <lib> element.

New in version 5.0.

Attributes

  • name: string, required. Each variable font has a name, that can be used by build tools to refer to the font that gets built from this element.

  • filename: string, optional. This filename will be used by tools to decide where to store the built font on the disk. If not given, a filename can be computed from the name. The filename may include an extension (e.g. .ttf) and the build tools can replace that extension with another (e.g. .otf or .woff2) as needed.

Example

<variable-font name="MyFontVF_Italic">
  <axis-subsets>
    <axis-subset name="Weight"/>
    <axis-subset name="Italic" uservalue="1"/>
  </axis-subsets>
</variable-font>
2.6.1.1 <axis-subsets> element
  • Child of <variable-font>

  • Defines the portion of the design space that this variable font covers.

  • Each axis that you want to include in the VF needs to be mentioned here.

  • Not mentioning an axis is equivalent to slicing the space at the default value of that axis.

New in version 5.0.

2.6.1.1.1 <axis-subset> element
  • Child of <axis-subsets>

  • Defines the subset of one axis, by name="", that the variable font covers.

  • If this axis is continuous, the VF can either cover:

    1. the whole axis

      <axis-subset name="Weight"/>
      
    2. a sub-range of the full axis

      <axis-subset name="Weight" userminimum="400" usermaximum="500" userdefault="400"/>
      
    3. a specific value along that axis; then the axis is not functional in the VF but the design space is sliced at the given location. Note: While valid to have a specific value that doesn’t have a matching <source> at that value, currently there isn’t an implentation that supports this. See this fontmake issue.

      <!-- Make a bold VF -->
      <axis-subset name="Weight" uservalue="700"/>
      
  • If this axis is discrete, then only the third option above is possible: give one value along the axis.

    <!-- Make an italic VF -->
    <axis-subset name="Italic" uservalue="1"/>
    

New in version 5.0.

Attributes

  • name: required, string. Name of the axis to subset.

When defining a range:

  • userminimum: optional, number. Lower end of the range, in user coordinates. If not mentioned, assume the axis’s minimum.

  • usermaximum: optional, number. Upper end of the range, in user coordinates. If not mentioned, assume the axis’s maximum.

  • userdefault: optional, number. New default value of subset axis, in user coordinates. If not mentioned, assume the axis’s default. If the axis’s default falls outside of the subset range, then the new default will be the extremum that is closest to the full axis’s default.

When defining a single value:

  • uservalue: required, number. Single value, in user coordinates, at which to snapshot the design space while building this VF.

2.6.1.2 <lib> element (variable font)

Arbitrary data about this variable font.

New in version 5.0.

Here is an example of using the public.fontInfo lib key to gain more granular control over the font info of a variable font, in this case setting some names to reflect the fact that this is a Narrow variable font subset from the larger designspace. This lib key allows font info in variable fonts to be more specific than the font info of the sources.

Example

<variable-font name="MyFontNarrVF">
  <axis-subsets>
    <axis-subset name="Weight"/>
    <axis-subset name="Width" uservalue="75"/>
  </axis-subsets>
  <lib>
    <dict>
      <key>public.fontInfo</key>
      <dict>
        <key>familyName</key>
        <string>My Font Narrow VF</string>
        <key>styleName</key>
        <string>Regular</string>
        <key>postscriptFontName</key>
        <string>MyFontNarrVF-Regular</string>
        <key>trademark</key>
        <string>My Font Narrow VF is a registered trademark...</string>
      </dict>
    </dict>
  </lib>
</variable-font>
2.6.1.3 Instances included in the variable font
A designspace version 5 lists many instances and variable fonts. Each variable font gets in its fvar table whichever instances fall within the bounds of the variable font's subset axes.

Illustration of instances included in a variable font.

2.7 <instances> element

The <instances> element contains one or more <instance> elements.

2.7.1 <instance> element
  • Defines a single font that can be calculated with the designspace.

  • Child element of <instances>

  • For use in varLib the instance element really only needs the names and the location. The <glyphs> element is not required.

  • MutatorMath uses the <glyphs> element to describe how certain glyphs need different masters, mainly to describe the effects of conditional rules in Superpolator.

  • Location in designspace coordinates.

Attributes

  • familyname: required, string. The family name of the instance font. Corresponds with font.info.familyName

  • stylename: required, string. The style name of the instance font. Corresponds with font.info.styleName

  • name: required, string. A unique name that can be used to identify this font if it needs to be referenced elsewhere.

  • filename: string. Required for MutatorMath. A path to the instance file, relative to the root path of this document. The path can be at the same level as the document or lower.

  • postscriptfontname: string. Optional for MutatorMath. Corresponds with font.info.postscriptFontName

  • stylemapfamilyname: string. Optional for MutatorMath. Corresponds with styleMapFamilyName

  • stylemapstylename: string. Optional for MutatorMath. Corresponds with styleMapStyleName

  • location: string. Optional. Describes the location of this instance, taking it from the root level <labels> (STAT format 4) element with the same name as the string.

    New in version 5.0.

2.7.1.1 <location> element (instance)

Defines the coordinates of this instance in the design space.

2.7.1.1.1 <dimension> element (instance)
2.7.1.2 <lib> element (instance)

Arbitrary data about this instance.

2.7.1.3 <stylename>, <familyname>, <stylemapstylename>, <stylemapfamilyname> elements: localised names for instances

Localised names for instances can be included with these simple elements with an xml:lang attribute: XML language definition

  • <stylename>

  • <familyname>

  • <stylemapstylename>

  • <stylemapfamilyname>

Example

<stylename xml:lang="fr">Demigras</stylename>
<stylename xml:lang="ja">半ば</stylename>
<familyname xml:lang="fr">Montserrat</familyname>
<familyname xml:lang="ja">モンセラート</familyname>
<stylemapstylename xml:lang="de">Standard</stylemapstylename>
<stylemapfamilyname xml:lang="de">Montserrat Halbfett</stylemapfamilyname>
<stylemapfamilyname xml:lang="ja">モンセラート SemiBold</stylemapfamilyname>
2.7.1.4 Example for varLib
<instance familyname="InstanceFamilyName" filename="instances/instanceTest2.ufo" name="instance.ufo2" postscriptfontname="InstancePostscriptName" stylemapfamilyname="InstanceStyleMapFamilyName" stylemapstylename="InstanceStyleMapStyleName" stylename="InstanceStyleName">
<location>
    <dimension name="width" xvalue="400" yvalue="300" />
    <dimension name="weight" xvalue="66" />
</location>
<lib>
    <dict>
        <key>com.coolDesignspaceApp.specimenText</key>
        <string>Hamburgerwhatever</string>
    </dict>
</lib>
</instance>

Here is an example using STAT format 4 labels to define the location of the instance directly.

<?xml version='1.0' encoding='utf-8'?>
<designspace format="5.0">
    <!-- ... -->
    <labels>
        <!-- define STAT format 4 labels here -->
        <!-- New in version 5.0 -->
        <label name="Extra Light">
            <location>
                <dimension name="weight" uservalue="123" />
            </location>
        </label>
    </labels>
    <!-- ... -->
    <instances>
        <instance filename="instances/labelled.ufo" location="Extra Light" />
    </instances>
</designspace>

Here is an example of using the public.fontInfo lib key to gain more granular control over the font info of the instances.

openTypeNameWWSFamilyName and openTypeNameWWSSubfamilyName are not able to be set by attributes on the <instance> element. The openTypeOS2WeightClass key is superseding the value that would have been set by the weight axis value. The trademark key is superseding the value that would have been set by UFO source at the origin. If the designer wishes to set name records for other encodings, platforms or laguages, they should do so using the openTypeNameRecords key, like they would in a UFO source.

See UFO3 fontinfo.plist specification.

<instance familyname="My Font" stylename="Text Light" filename="instances/MyFont-TextLight.ufo" postscriptfontname="MyFont-TextLight" stylemapfamilyname="My Font Text Light" stylemapstylename="regular">
    <location>
        <dimension name="optical" xvalue="6"/>
        <dimension name="weight" xvalue="325"/>
    </location>
    <lib>
        <dict>
            <key>public.fontInfo</key>
            <dict>
                <key>openTypeNameWWSFamilyName</key>
                <string>My Font Text</string>
                <key>openTypeNameWWSSubfamilyName</key>
                <string>Light</string>
                <key>openTypeOS2WeightClass</key>
                <integer>300</integer>
                <key>trademark</key>
                <string>My Font Text Light is a registered trademark...</string>
                <key>openTypeNameRecords</key>
                <array>
                    <dict>
                        <key>encodingID</key>
                        <integer>1</integer>
                        <key>languageID</key>
                        <integer>1031</integer>
                        <key>nameID</key>
                        <integer>7</integer>
                        <key>platformID</key>
                        <integer>3</integer>
                        <key>string</key>
                        <string>Meine Schrift Text Leicht ist eine registrierte Marke...</string>
                    </dict>
                </array>
            </dict>
        </dict>
    </lib>
</instance>
2.7.1.5 <glyphs> element (instance)
  • Container for <glyph> elements.

  • Optional

  • MutatorMath only.

Deprecated since version 5.0.

2.7.1.5.1 <glyph> element (instance)
  • Child element of <glyphs>

  • May contain a <location> element.

Deprecated since version 5.0.

Attributes

  • name: string. The name of the glyph.

  • unicode: string. Unicode values for this glyph, in hexadecimal. Multiple values should be separated with a space.

  • mute: optional attribute, number 1 or 0. Indicate if this glyph should be supressed in the output.

2.7.1.5.1.1 <note> element
  • String. The value corresponds to glyph.note in UFO.

Deprecated since version 5.0.

2.7.1.5.1.2 <masters> element
  • Container for <master> elements

  • These <master> elements define an alternative set of glyph masters for this glyph.

Deprecated since version 5.0.

2.7.1.5.1.2.1 <master> element
  • Defines a single alternative master for this glyph.

Deprecated since version 5.0.

Attributes

  • glyphname: the name of the alternate master glyph.

  • source: the identifier name of the source this master glyph needs to be loaded from

2.7.1.5.2 Example for MutatorMath
<instance familyname="InstanceFamilyName" filename="instances/instanceTest2.ufo" name="instance.ufo2" postscriptfontname="InstancePostscriptName" stylemapfamilyname="InstanceStyleMapFamilyName" stylemapstylename="InstanceStyleMapStyleName" stylename="InstanceStyleName">
<location>
    <dimension name="width" xvalue="400" yvalue="300" />
    <dimension name="weight" xvalue="66" />
</location>
<glyphs>
    <glyph name="arrow2" />
    <glyph name="arrow" unicode="0x4d2 0x4d3">
    <location>
        <dimension name="width" xvalue="100" />
        <dimension name="weight" xvalue="120" />
    </location>
    <note>A note about this glyph</note>
    <masters>
        <master glyphname="BB" source="master.ufo1">
        <location>
            <dimension name="width" xvalue="20" />
            <dimension name="weight" xvalue="20" />
        </location>
        </master>
    </masters>
    </glyph>
</glyphs>
<kerning />
<info />
<lib>
    <dict>
        <key>com.coolDesignspaceApp.specimenText</key>
        <string>Hamburgerwhatever</string>
    </dict>
</lib>
</instance>
2.8 <lib> element (top-level)

The <lib> element contains arbitrary data.

Example:

<lib>
    <dict>
        <key>com.company.fontEditor.myString</key>
        <string>The contents use the PLIST format.</string>
    </dict>
</lib>

3 Scripting a designspace

It can be useful to build a designspace with a script rather than construct one with an interface like Superpolator or DesignSpaceEditor.

fontTools.designspaceLib offers a some tools for building designspaces in Python. This document shows an example.

Filling-in a DesignSpaceDocument

So, suppose you installed the fontTools package through your favorite git client.

The DesignSpaceDocument object represents the document, whether it already exists or not. Make a new one:

from fontTools.designspaceLib import (DesignSpaceDocument, AxisDescriptor,
                                      SourceDescriptor, InstanceDescriptor)
doc = DesignSpaceDocument()

We want to create definitions for axes, sources and instances. That means there are a lot of attributes to set. The DesignSpaceDocument object uses objects to describe the axes, sources and instances. These are relatively simple objects, think of these as collections of attributes.

Make an axis object

Make a descriptor object and add it to the document.

a1 = AxisDescriptor()
a1.maximum = 1000
a1.minimum = 0
a1.default = 0
a1.name = "weight"
a1.tag = "wght"
doc.addAxis(a1)
  • You can add as many axes as you need. OpenType has a maximum of around 64K. DesignSpaceEditor has a maximum of 5.

  • The name attribute is the name you’ll be using as the axis name in the locations.

  • The tag attribute is the one of the registered OpenType Variation Axis Tags

  • The default master is expected at the intersection of all default values of all axes.

Option: add label names

The labelnames attribute is intended to store localisable, human readable names for this axis if this is not an axis that is registered by OpenType. Think “The label next to the slider”. The attribute is a dictionary. The key is the xml language tag, the value is a unicode string with the name. Whether or not this attribute is used depends on the font building tool, the operating system and the authoring software. This, at least, is the place to record it.

a1.labelNames['fa-IR'] = u"قطر"
a1.labelNames['en'] = u"Wéíght"
Option: add a map

The map attribute is a list of (input, output) mapping values intended for axis variations table of OpenType.

# (user space, design space), (user space, design space)...
a1.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
Make a source object

A source is an object that points to a UFO file. It provides the outline geometry, kerning and font.info that we want to work with.

s0 = SourceDescriptor()
s0.path = "my/path/to/thin.ufo"
s0.name = "master.thin"
s0.location = dict(weight=0)
doc.addSource(s0)
  • You’ll need to have at least 2 sources in your document, so go ahead and add another one.

  • The location attribute is a dictionary with the designspace location for this master.

  • The axis names in the location have to match one of the axis.name values you defined before.

  • The path attribute is the absolute path to an existing UFO.

  • The name attribute is a unique name for this source used to keep track it.

  • The layerName attribute is the name of the UFO3 layer. Default None for foreground.

So go ahead and add another master:

s1 = SourceDescriptor()
s1.path = "my/path/to/bold.ufo"
s1.name = "master.bold"
s1.location = dict(weight=1000)
doc.addSource(s1)
Option: exclude glyphs

By default all glyphs in a source will be processed. If you want to exclude certain glyphs, add their names to the mutedGlyphNames list.

s1.mutedGlyphNames = ["A.test", "A.old"]
Make an instance object

An instance is description of a UFO that you want to generate with the designspace. For an instance you can define more things. If you want to generate UFO instances with MutatorMath then you can define different names and set flags for if you want to generate kerning and font info and so on. You can also set a path where to generate the instance.

i0 = InstanceDescriptor()
i0.familyName = "MyVariableFontPrototype"
i0.styleName = "Medium"
i0.path = os.path.join(root, "instances","MyVariableFontPrototype-Medium.ufo")
i0.location = dict(weight=500)
i0.kerning = True
i0.info = True
doc.addInstance(i0)
  • The path attribute needs to be the absolute (real or intended) path for the instance. When the document is saved this path will written as relative to the path of the document.

  • instance paths should be on the same level as the document, or in a level below.

  • Instances for MutatorMath will generate to UFO.

  • Instances for variable fonts become named instances.

Option: add more names

If you want you can add a PostScript font name, a stylemap familyName and a stylemap styleName.

i0.postScriptFontName = "MyVariableFontPrototype-Medium"
i0.styleMapFamilyName = "MyVarProtoMedium"
i0.styleMapStyleName = "regular"
Option: add glyph specific masters

This bit is not supported by OpenType variable fonts, but it is needed for some designspaces intended for generating instances with MutatorMath. The code becomes a bit verbose, so you’re invited to wrap this into something clever.

# we're making a dict with all sorts of
#(optional) settings for a glyph.
#In this example: the dollar.
glyphData = dict(name="dollar", unicodeValue=0x24)

# you can specify a different location for a glyph
glyphData['instanceLocation'] = dict(weight=500)

# You can specify different masters
# for this specific glyph.
# You can also give those masters new
# locations. It's a miniature designspace.
# Remember the "name" attribute we assigned to the sources?
glyphData['masters'] = [
    dict(font="master.thin",
        glyphName="dollar.nostroke",
        location=dict(weight=0)),
    dict(font="master.bold",
        glyphName="dollar.nostroke",
        location=dict(weight=1000)),
    ]

# With all of that set up, store it in the instance.
i4.glyphs['dollar'] = glyphData
Saving
path = "myprototype.designspace"
doc.write(path)
Generating?

You can generate the UFOs with MutatorMath:

from mutatorMath.ufo import build
build("whatevs/myprototype.designspace")
  • Assuming the outline data in the masters is compatible.

Or you can use the file in making a variable font with varLib.

Working with DesignSpace version 5

The new version 5 allows “discrete” axes, which do not interpolate across their values. This is useful to store in one place family-wide data such as the STAT information, however it prevents the usual things done on designspaces that interpolate everywhere:

  • checking that all sources are compatible for interpolation

  • building variable fonts

In order to allow the above in tools that want to handle designspace v5, the fontTools.designspaceLib.split module provides two methods to split a designspace into interpolable sub-spaces, splitInterpolable() and then splitVariableFonts().

Example process diagram to check and build DesignSpace 5

Example process process to check and build Designspace 5.

Also, for older tools that don’t know about the other version 5 additions such as the STAT data fields, the function convert5to4() allows to strip new information from a designspace version 5 to downgrade it to a collection of version 4 documents, one per variable font.

Notes

Paths and filenames

A designspace file needs to store many references to UFO files.

  • designspace files can be part of versioning systems and appear on different computers. This means it is not possible to store absolute paths.

  • So, all paths are relative to the designspace document path.

  • Using relative paths allows designspace files and UFO files to be near each other, and that they can be found without enforcing one particular structure.

  • The filename attribute in the SourceDescriptor and InstanceDescriptor classes stores the preferred relative path.

  • The path attribute in these objects stores the absolute path. It is calculated from the document path and the relative path in the filename attribute when the object is created.

  • Only the filename attribute is written to file.

  • Both filename and path must use forward slashes (/) as path separators, even on Windows.

Right before we save we need to identify and respond to the following situations:

In each descriptor, we have to do the right thing for the filename attribute. Before writing to file, the documentObject.updatePaths() method prepares the paths as follows:

Case 1

descriptor.filename == None
descriptor.path == None

Action

  • write as is, descriptors will not have a filename attr. Useless, but no reason to interfere.

Case 2

descriptor.filename == "../something"
descriptor.path == None

Action

  • write as is. The filename attr should not be touched.

Case 3

descriptor.filename == None
descriptor.path == "~/absolute/path/there"

Action

  • calculate the relative path for filename. We’re not overwriting some other value for filename, it should be fine.

Case 4

descriptor.filename == '../somewhere'
descriptor.path == "~/absolute/path/there"

Action

  • There is a conflict between the given filename, and the path. The difference could have happened for any number of reasons. Assuming the values were not in conflict when the object was created, either could have changed. We can’t guess.

  • Assume the path attribute is more up to date. Calculate a new value for filename based on the path and the document path.

Recommendation for editors
  • If you want to explicitly set the filename attribute, leave the path attribute empty.

  • If you want to explicitly set the path attribute, leave the filename attribute empty. It will be recalculated.

  • Use documentObject.updateFilenameFromPath() to explicitly set the filename attributes for all instance and source descriptors.

Common Lib Key Registry

public.skipExportGlyphs

This lib key works the same as the UFO lib key with the same name. The difference is that applications using a Designspace as the corner stone of the font compilation process should use the lib key in that Designspace instead of any of the UFOs. If the lib key is empty or not present in the Designspace, all glyphs should be exported, regardless of what the same lib key in any of the UFOs says.

public.fontInfo

This lib key, when included in the <lib> element inside an <instance> or <variable-font> tag, or the <lib> element at the root of a designspace document, allows for direct manipulation of font info data in instances and variable fonts. The lib value must follow the UFO3 fontinfo.plist specification, and should functionally appear to be a property list dictionary with the same structure as the fontinfo.plist file in a UFO.

All font info items in the UFO fontinfo.plist specification should be able to be defined in the public.fontInfo lib. Checking validity of the data using fontTools.ufoLib.validators is recommended but not required.

All font info items for a variable font or an instance must be inherited using the following order, in order of descending priority:

  1. The public.fontInfo key in the <lib> element of the <variable-font> or <instance> elements.

  2. XML attributes for names (i.e. familyname, stylename, etc.), if the target is an <instance> element.

  3. The public.fontInfo key found in the <lib> element of the designspace document’s root.

  4. The fontinfo.plist in the UFO source at the origin of the interpolation space.

Absence of a font info key from the value of a public.fontInfo lib does not mean a that piece of font info should be interpreted as being undefined. A tool generating the variable font or instance should recursively continue on to the next level of the inheritence order and apply the value found there, if any. If the tool makes it to the end of the inheritence order without finding a valid value for a given font info key, it should then be considered undefined. In the case of any conflicting values for a font info key, the value highest in the inheritance order must be chosen over the others.

Implementation and differences

The designspace format has gone through considerable development.

  • the format was originally written for MutatorMath.

  • the format is now also used in fontTools.varLib.

  • not all values are be required by all implementations.

varLib vs. MutatorMath

There are some differences between the way MutatorMath and fontTools.varLib handle designspaces.

  • varLib does not support anisotropic interpolations.

  • MutatorMath will extrapolate over the boundaries of the axes. varLib can not (at the moment).

  • varLib requires much less data to define an instance than MutatorMath.

  • The goals of varLib and MutatorMath are different, so not all attributes are always needed.

Rules and generating static UFO instances

When making instances as UFOs from a designspace with rules, it can be useful to evaluate the rules so that the characterset of the UFO reflects, as much as possible, the state of a variable font when seen at the same location. This can be done by some swapping and renaming of glyphs.

While useful for proofing or development work, it should be noted that swapping and renaming leaves the UFOs with glyphnames that are no longer descriptive. For instance, after a swap dollar.bar could contain a shape without a bar. Also, when the swapped glyphs are part of other GSUB variations it can become complex very quickly. So proceed with caution.

  • Assuming rulesProcessingLast = True:

  • We need to swap the glyphs so that the original shape is still available. For instance, if a rule swaps a for a.alt, a glyph that references a in a component would then show the new a.alt.

  • But that can lead to unexpected results, the two glyphs may have different widths or height. So, glyphs that are not specifically referenced in a rule should not change appearance. That means that the implementation that swaps a and a.alt also swap all components that reference these glyphs in order to preserve their appearance.

  • The swap function also needs to take care of swapping the names in kerning data and any GPOS code.

Version history

Version 5.1

The format was extended to support arbitrary mapping between input and output designspace locations. The <axes> elements now can have a <mappings> element that specifies such mappings, which when present carries data that is used to compile to an avar version 2 table.

Version 5.0

The format was extended to describe the entire design space of a reasonably regular font family in one file, with global data about the family to reduce repetition in sub-sections. “Reasonably regular” means that the sources and instances across the previously multiple Designspace files are positioned on a grid and derive their metadata (like style name) in a way that’s compatible with the STAT model, based on their axis positions. Axis mappings must be the same across the entire space.

  1. Each axis can have labels attached to stops within the axis range, analogous to the OpenType STAT table. Free-standing labels for locations are also allowed. The data is intended to be compiled into a STAT table.

  2. The axes can be discrete, to say that they do not interpolate, like a distinctly constructed upright and italic variant of a family.

  3. The data can be used to derive style and PostScript names for instances.

  4. A new variable-fonts element can subdivide the Designspace into multiple subsets that mix and match the globally available axes. It is possible for these sub-spaces to have a different default location from the global default location. It is required if the Designspace contains a discrete axis and you want to produce a variable font.

What is currently not supported is e.g.

  1. A setup where different sources sit at the same logical location in the design space, think “MyFont Regular” and “MyFont SmallCaps Regular”. (this situation could be encoded by adding a “SmallCaps” discrete axis, if that makes sense).

  2. Anisotropic locations for axis labels.

Older versions
  • In some implementations that preceed Variable Fonts, the copyInfo flag in a source indicated the source was to be treated as the default. This is no longer compatible with the assumption that the default font is located on the default value of each axis.

  • Older implementations did not require axis records to be present in the designspace file. The axis extremes for instance were generated from the locations used in the sources. This is no longer possible.

encodings: Support for OpenType-specific encodings

fontTools includes support for some character encodings found in legacy Mac TrueType fonts. Many of these legacy encodings have found their way into the standard Python encodings library, but others still remain unimplemented. Importing fontTools.encodings.codecs will therefore add string encode and decode support for the following encodings:

  • x_mac_japanese_ttx

  • x_mac_trad_chinese_ttx

  • x_mac_korean_ttx

  • x_mac_simp_chinese_ttx

fontTools also includes a package (fontTools.encodings.MacRoman) which contains a mapping of glyph IDs to glyph names in the MacRoman character set:

>>> from fontTools.encodings.MacRoman import MacRoman
>>> MacRoman[26]
'twosuperior'

feaLib: Read/write OpenType feature files

fontTools’ feaLib allows for the creation and parsing of Adobe Font Development Kit for OpenType feature (.fea) files. The syntax of these files is described here.

The fontTools.feaLib.parser.Parser class can be used to parse files into an abstract syntax tree, and from there the fontTools.feaLib.builder.Builder class can add features to an existing font file. You can inspect the parsed syntax tree, walk the tree and do clever things with it, and also generate your own feature files programmatically, by using the classes in the fontTools.feaLib.ast module.

Parsing

class fontTools.feaLib.parser.Parser(featurefile, glyphNames=(), followIncludes=True, includeDir=None, **kwargs)

Initializes a Parser object.

Example

from fontTools.feaLib.parser import Parser
parser = Parser(file, font.getReverseGlyphMap())
parsetree = parser.parse()

Note: the glyphNames iterable serves a double role to help distinguish glyph names from ranges in the presence of hyphens and to ensure that glyph names referenced in a feature file are actually part of a font’s glyph set. If the iterable is left empty, no glyph name in glyph set checking takes place, and all glyph tokens containing hyphens are treated as literal glyph names, not as ranges. (Adding a space around the hyphen can, in any case, help to disambiguate ranges from glyph names containing hyphens.)

By default, the parser will follow include() statements in the feature file. To turn this off, pass followIncludes=False. Pass a directory string as includeDir to explicitly declare a directory to search included feature files in.

parse()

Parse the file, and return a fontTools.feaLib.ast.FeatureFile object representing the root of the abstract syntax tree containing the parsed contents of the file.

parse_name_()

Parses a name record. See section 9.e.

parse_featureNames_(tag)

Parses a featureNames statement found in stylistic set features. See section 8.c.

check_glyph_name_in_glyph_set(*names)

Adds a glyph name (just start) or glyph names of a range (start and end) which are not in the glyph set to the “missing list” for future error reporting.

If no glyph set is present, does nothing.

static reverse_string_(s)

‘abc’ –> ‘cba’

make_cid_range_(location, start, limit)

(location, 999, 1001) –> [“cid00999”, “cid01000”, “cid01001”]

make_glyph_range_(location, start, limit)

(location, “a.sc”, “d.sc”) –> [“a.sc”, “b.sc”, “c.sc”, “d.sc”]

Building

fontTools.feaLib.builder.addOpenTypeFeatures(font, featurefile, tables=None, debug=False)

Add features from a file to a font. Note that this replaces any features currently present.

Parameters:
  • font (feaLib.ttLib.TTFont) – The font object.

  • featurefile – Either a path or file object (in which case we parse it into an AST), or a pre-parsed AST instance.

  • tables – If passed, restrict the set of affected tables to those in the list.

  • debug – Whether to add source debugging information to the font in the Debg table

fontTools.feaLib.builder.addOpenTypeFeaturesFromString(font, features, filename=None, tables=None, debug=False)

Add features from a string to a font. Note that this replaces any features currently present.

Parameters:
  • font (feaLib.ttLib.TTFont) – The font object.

  • features – A string containing feature code.

  • filename – The directory containing filename is used as the root of relative include() paths; if None is provided, the current directory is assumed.

  • tables – If passed, restrict the set of affected tables to those in the list.

  • debug – Whether to add source debugging information to the font in the Debg table

Generation/Interrogation

In the below, a glyph-containing object is an object of one of the following classes: GlyphName, GlyphClass, GlyphClassName.

class fontTools.feaLib.ast.Element(location=None)

A base class representing “something” in a feature file.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.FeatureFile

The top-level element of the syntax tree, containing the whole feature file in its statements attribute.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

build(builder)

When handed a ‘builder’ object of comparable interface to fontTools.feaLib.builder, walks the statements in this block, calling the builder callbacks.

statements

Statements contained in the block

class fontTools.feaLib.ast.Comment(text, location=None)

A comment in a feature file.

text

Text of the comment

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.GlyphName(glyph, location=None)

A single glyph name, such as cedilla.

glyph

The name itself as a string

glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.GlyphClass(glyphs=None, location=None)

A glyph class, such as [acute cedilla grave].

glyphs

The list of glyphs in this class, as GlyphName objects.

glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

extend(glyphs)

Add a list of GlyphName objects to the class.

append(glyph)

Add a single GlyphName object to the class.

add_range(start, end, glyphs)

Add a range (e.g. A-Z) to the class. start and end are either GlyphName objects or strings representing the start and end glyphs in the class, and glyphs is the full list of GlyphName objects in the range.

add_cid_range(start, end, glyphs)

Add a range to the class by glyph ID. start and end are the initial and final IDs, and glyphs is the full list of GlyphName objects in the range.

add_class(gc)

Add glyphs from the given GlyphClassName object to the class.

class fontTools.feaLib.ast.GlyphClassName(glyphclass, location=None)

A glyph class name, such as @FRENCH_MARKS. This must be instantiated with a GlyphClassDefinition object.

glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.MarkClassName(markClass, location=None)

A mark class name, such as @FRENCH_MARKS defined with markClass. This must be instantiated with a MarkClass object.

glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.AnonymousBlock(tag, content, location=None)

An anonymous data block.

tag

string containing the block’s “tag”

content

block data as string

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.Block(location=None)

A block of statements: feature, lookup, etc.

statements

Statements contained in the block

build(builder)

When handed a ‘builder’ object of comparable interface to fontTools.feaLib.builder, walks the statements in this block, calling the builder callbacks.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.FeatureBlock(name, use_extension=False, location=None)

A named feature block.

build(builder)

Call the start_feature callback on the builder object, visit all the statements in this feature, and then call end_feature.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

statements

Statements contained in the block

class fontTools.feaLib.ast.NestedBlock(tag, block_name, location=None)

A block inside another block, for example when found inside a cvParameters block.

build(builder)

When handed a ‘builder’ object of comparable interface to fontTools.feaLib.builder, walks the statements in this block, calling the builder callbacks.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

statements

Statements contained in the block

class fontTools.feaLib.ast.LookupBlock(name, use_extension=False, location=None)

A named lookup, containing statements.

build(builder)

When handed a ‘builder’ object of comparable interface to fontTools.feaLib.builder, walks the statements in this block, calling the builder callbacks.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

statements

Statements contained in the block

class fontTools.feaLib.ast.GlyphClassDefinition(name, glyphs, location=None)

Example: @UPPERCASE = [A-Z];.

name

class name as a string, without initial @

glyphs

a GlyphClass object

glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.GlyphClassDefStatement(baseGlyphs, markGlyphs, ligatureGlyphs, componentGlyphs, location=None)

Example: GlyphClassDef @UPPERCASE, [B], [C], [D];. The parameters must be either GlyphClass or GlyphClassName objects, or None.

build(builder)

Calls the builder’s add_glyphClassDef callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.MarkClass(name)

One or more markClass statements for the same mark class.

While glyph classes can be defined only once, the feature file format allows expanding mark classes with multiple definitions, each using different glyphs and anchors. The following are two MarkClassDefinitions for the same MarkClass:

markClass [acute grave] <anchor 350 800> @FRENCH_ACCENTS;
markClass [cedilla] <anchor 350 -200> @FRENCH_ACCENTS;

The MarkClass object is therefore just a container for a list of MarkClassDefinition statements.

addDefinition(definition)

Add a MarkClassDefinition statement to this mark class.

glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

class fontTools.feaLib.ast.MarkClassDefinition(markClass, anchor, glyphs, location=None)

A single markClass statement. The markClass should be a MarkClass object, the anchor an Anchor object, and the glyphs parameter should be a glyph-containing object .

Example

mc = MarkClass("FRENCH_ACCENTS")
mc.addDefinition( MarkClassDefinition(mc, Anchor(350, 800),
    GlyphClass([ GlyphName("acute"), GlyphName("grave") ])
) )
mc.addDefinition( MarkClassDefinition(mc, Anchor(350, -200),
    GlyphClass([ GlyphName("cedilla") ])
) )

mc.asFea()
# markClass [acute grave] <anchor 350 800> @FRENCH_ACCENTS;
# markClass [cedilla] <anchor 350 -200> @FRENCH_ACCENTS;
glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.AlternateSubstStatement(prefix, glyph, suffix, replacement, location=None)

A sub ... from ... statement.

prefix, glyph, suffix and replacement should be lists of glyph-containing objects. glyph should be a one element list.

build(builder)

Calls the builder’s add_alternate_subst callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.Anchor(x, y, name=None, contourpoint=None, xDeviceTable=None, yDeviceTable=None, location=None)

An Anchor element, used inside a pos rule.

If a name is given, this will be used in preference to the coordinates. Other values should be integer.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.AnchorDefinition(name, x, y, contourpoint=None, location=None)

A named anchor definition. (2.e.viii). name should be a string.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.AttachStatement(glyphs, contourPoints, location=None)

A GDEF table Attach statement.

glyphs

A glyph-containing object

contourPoints

A list of integer contour points

build(builder)

Calls the builder’s add_attach_points callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.AxisValueLocationStatement(tag, values, location=None)

A STAT table Axis Value Location

Parameters:
  • tag (str) – a 4 letter axis tag

  • values (list) – a list of ints and/or floats

asFea(res='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.BaseAxis(bases, scripts, vertical, location=None)

An axis definition, being either a VertAxis.BaseTagList/BaseScriptList pair or a HorizAxis.BaseTagList/BaseScriptList pair.

bases

A list of baseline tag names as strings

scripts

A list of script record tuplets (script tag, default baseline tag, base coordinate)

vertical

Boolean; VertAxis if True, HorizAxis if False

build(builder)

Calls the builder object’s set_base_axis callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.CVParametersNameStatement(nameID, platformID, platEncID, langID, string, block_name, location=None)

Represent a name statement inside a cvParameters block.

build(builder)

Calls the builder object’s add_cv_parameter callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

nameID

Name ID as integer (e.g. 9 for designer’s name)

platformID

Platform ID as integer

platEncID

Platform encoding ID as integer

langID

Language ID as integer

string

Name record value

class fontTools.feaLib.ast.ChainContextPosStatement(prefix, glyphs, suffix, lookups, location=None)

A chained contextual positioning statement.

prefix, glyphs, and suffix should be lists of glyph-containing objects .

lookups should be a list of elements representing what lookups to apply at each glyph position. Each element should be a LookupBlock to apply a single chaining lookup at the given position, a list of LookupBlocks to apply multiple lookups, or None to apply no lookup. The length of the outer list should equal the length of glyphs; the inner lists can be of variable length.

build(builder)

Calls the builder’s add_chain_context_pos callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ChainContextSubstStatement(prefix, glyphs, suffix, lookups, location=None)

A chained contextual substitution statement.

prefix, glyphs, and suffix should be lists of glyph-containing objects .

lookups should be a list of elements representing what lookups to apply at each glyph position. Each element should be a LookupBlock to apply a single chaining lookup at the given position, a list of LookupBlocks to apply multiple lookups, or None to apply no lookup. The length of the outer list should equal the length of glyphs; the inner lists can be of variable length.

build(builder)

Calls the builder’s add_chain_context_subst callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.CharacterStatement(character, tag, location=None)

Statement used in cvParameters blocks of Character Variant features (cvXX). The Unicode value may be written with either decimal or hexadecimal notation. The value must be preceded by ‘0x’ if it is a hexadecimal value. The largest Unicode value allowed is 0xFFFFFF.

build(builder)

Calls the builder object’s add_cv_character callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ConditionsetStatement(name, conditions, location=None)

A variable layout conditionset

Parameters:
  • name (str) – the name of this conditionset

  • conditions (dict) – a dictionary mapping axis tags to a tuple of (min,max) userspace coordinates.

asFea(res='', indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.CursivePosStatement(glyphclass, entryAnchor, exitAnchor, location=None)

A cursive positioning statement. Entry and exit anchors can either be Anchor objects or None.

build(builder)

Calls the builder object’s add_cursive_pos callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ElidedFallbackName(names, location=None)

STAT table ElidedFallbackName

Parameters:

names – a list of STATNameStatement objects

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ElidedFallbackNameID(value, location=None)

STAT table ElidedFallbackNameID

Parameters:

value – an int pointing to an existing name table name ID

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.Expression(location=None)
asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.FeatureNameStatement(nameID, platformID, platEncID, langID, string, location=None)

Represents a sizemenuname or name statement.

build(builder)

Calls the builder object’s add_featureName callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

nameID

Name ID as integer (e.g. 9 for designer’s name)

platformID

Platform ID as integer

platEncID

Platform encoding ID as integer

langID

Language ID as integer

string

Name record value

class fontTools.feaLib.ast.FeatureReferenceStatement(featureName, location=None)

Example: feature salt;

build(builder)

Calls the builder object’s add_feature_reference callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.FontRevisionStatement(revision, location=None)

A head table FontRevision statement. revision should be a number, and will be formatted to three significant decimal places.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.HheaField(key, value, location=None)

An entry in the hhea table.

build(builder)

Calls the builder object’s add_hhea_field callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.IgnorePosStatement(chainContexts, location=None)

An ignore pos statement, containing one or more contexts to ignore.

chainContexts should be a list of (prefix, glyphs, suffix) tuples, with each of prefix, glyphs and suffix being glyph-containing objects .

build(builder)

Calls the builder object’s add_chain_context_pos callback on each rule context.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.IgnoreSubstStatement(chainContexts, location=None)

An ignore sub statement, containing one or more contexts to ignore.

chainContexts should be a list of (prefix, glyphs, suffix) tuples, with each of prefix, glyphs and suffix being glyph-containing objects .

build(builder)

Calls the builder object’s add_chain_context_subst callback on each rule context.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.IncludeStatement(filename, location=None)

An include() statement.

filename

String containing name of file to include

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LanguageStatement(language, include_default=True, required=False, location=None)

A language statement within a feature.

language

A four-character language tag

include_default

If false, “exclude_dflt”

build(builder)

Call the builder object’s set_language callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LanguageSystemStatement(script, language, location=None)

A top-level languagesystem statement.

build(builder)

Calls the builder object’s add_language_system callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LigatureCaretByIndexStatement(glyphs, carets, location=None)

A GDEF table LigatureCaretByIndex statement. glyphs should be a glyph-containing object, and carets should be a list of integers.

build(builder)

Calls the builder object’s add_ligatureCaretByIndex_ callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LigatureCaretByPosStatement(glyphs, carets, location=None)

A GDEF table LigatureCaretByPos statement. glyphs should be a glyph-containing object, and carets should be a list of integers.

build(builder)

Calls the builder object’s add_ligatureCaretByPos_ callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LigatureSubstStatement(prefix, glyphs, suffix, replacement, forceChain, location=None)

A chained contextual substitution statement.

prefix, glyphs, and suffix should be lists of glyph-containing objects; replacement should be a single glyph-containing object.

If forceChain is True, this is expressed as a chaining rule (e.g. sub f' i' by f_i) even when no context is given.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LookupFlagStatement(value=0, markAttachment=None, markFilteringSet=None, location=None)

A lookupflag statement. The value should be an integer value representing the flags in use, but not including the markAttachment class and markFilteringSet values, which must be specified as glyph-containing objects.

build(builder)

Calls the builder object’s set_lookup_flag callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.LookupReferenceStatement(lookup, location=None)

Represents a lookup ...; statement to include a lookup in a feature.

The lookup should be a LookupBlock object.

build(builder)

Calls the builder object’s add_lookup_call callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.MarkBasePosStatement(base, marks, location=None)

A mark-to-base positioning rule. The base should be a glyph-containing object. The marks should be a list of (Anchor, MarkClass) tuples.

build(builder)

Calls the builder object’s add_mark_base_pos callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.MarkLigPosStatement(ligatures, marks, location=None)

A mark-to-ligature positioning rule. The ligatures must be a glyph-containing object. The marks should be a list of lists: each element in the top-level list represents a component glyph, and is made up of a list of (Anchor, MarkClass) tuples representing mark attachment points for that position.

Example:

m1 = MarkClass("TOP_MARKS")
m2 = MarkClass("BOTTOM_MARKS")
# ... add definitions to mark classes...

glyph = GlyphName("lam_meem_jeem")
marks = [
    [ (Anchor(625,1800), m1) ], # Attachments on 1st component (lam)
    [ (Anchor(376,-378), m2) ], # Attachments on 2nd component (meem)
    [ ]                         # No attachments on the jeem
]
mlp = MarkLigPosStatement(glyph, marks)

mlp.asFea()
# pos ligature lam_meem_jeem <anchor 625 1800> mark @TOP_MARKS
# ligComponent <anchor 376 -378> mark @BOTTOM_MARKS;
build(builder)

Calls the builder object’s add_mark_lig_pos callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.MarkMarkPosStatement(baseMarks, marks, location=None)

A mark-to-mark positioning rule. The baseMarks must be a glyph-containing object. The marks should be a list of (Anchor, MarkClass) tuples.

build(builder)

Calls the builder object’s add_mark_mark_pos callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.MultipleSubstStatement(prefix, glyph, suffix, replacement, forceChain=False, location=None)

A multiple substitution statement.

Parameters:
  • prefix – a list of glyph-containing objects.

  • glyph – a single glyph-containing object.

  • suffix – a list of glyph-containing objects.

  • replacement – a list of glyph-containing objects.

  • forceChain – If true, the statement is expressed as a chaining rule (e.g. sub f' i' by f_i) even when no context is given.

build(builder)

Calls the builder object’s add_multiple_subst callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.NameRecord(nameID, platformID, platEncID, langID, string, location=None)

Represents a name record. (Section 9.e.)

nameID

Name ID as integer (e.g. 9 for designer’s name)

platformID

Platform ID as integer

platEncID

Platform encoding ID as integer

langID

Language ID as integer

string

Name record value

build(builder)

Calls the builder object’s add_name_record callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.OS2Field(key, value, location=None)

An entry in the OS/2 table. Most values should be numbers or strings, apart from when the key is UnicodeRange, CodePageRange or Panose, in which case it should be an array of integers.

build(builder)

Calls the builder object’s add_os2_field callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.PairPosStatement(glyphs1, valuerecord1, glyphs2, valuerecord2, enumerated=False, location=None)

A pair positioning statement.

glyphs1 and glyphs2 should be glyph-containing objects. valuerecord1 should be a ValueRecord object; valuerecord2 should be either a ValueRecord object or None. If enumerated is true, then this is expressed as an enumerated pair.

build(builder)

Calls a callback on the builder object:

  • If the rule is enumerated, calls add_specific_pair_pos on each combination of first and second glyphs.

  • If the glyphs are both single GlyphName objects, calls add_specific_pair_pos.

  • Else, calls add_class_pair_pos.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ReverseChainSingleSubstStatement(old_prefix, old_suffix, glyphs, replacements, location=None)

A reverse chaining substitution statement. You don’t see those every day.

Note the unusual argument order: suffix comes before glyphs. old_prefix, old_suffix, glyphs and replacements should be lists of glyph-containing objects. glyphs and replacements should be one-item lists.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ScriptStatement(script, location=None)

A script statement.

script

the script code

build(builder)

Calls the builder’s set_script callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.SinglePosStatement(pos, prefix, suffix, forceChain, location=None)

A single position statement. prefix and suffix should be lists of glyph-containing objects.

pos should be a one-element list containing a (glyph-containing object, ValueRecord) tuple.

build(builder)

Calls the builder object’s add_single_pos callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.SingleSubstStatement(glyphs, replace, prefix, suffix, forceChain, location=None)

A single substitution statement.

Note the unusual argument order: prefix and suffix come after the replacement glyphs. prefix, suffix, glyphs and replace should be lists of glyph-containing objects. glyphs and replace should be one-item lists.

build(builder)

Calls the builder object’s add_single_subst callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.SizeParameters(DesignSize, SubfamilyID, RangeStart, RangeEnd, location=None)

A parameters statement.

build(builder)

Calls the builder object’s set_size_parameters callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.Statement(location=None)
asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.STATAxisValueStatement(names, locations, flags, location=None)

A STAT table Axis Value Record

Parameters:
asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.STATDesignAxisStatement(tag, axisOrder, names, location=None)

A STAT table Design Axis

Parameters:
  • tag (str) – a 4 letter axis tag

  • axisOrder (int) – an int

  • names (list) – a list of STATNameStatement objects

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.STATNameStatement(nameID, platformID, platEncID, langID, string, location=None)

Represents a STAT table name statement.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

build(builder)

Calls the builder object’s add_name_record callback.

nameID

Name ID as integer (e.g. 9 for designer’s name)

platformID

Platform ID as integer

platEncID

Platform encoding ID as integer

langID

Language ID as integer

string

Name record value

class fontTools.feaLib.ast.SubtableStatement(location=None)

Represents a subtable break.

build(builder)

Calls the builder objects’s add_subtable_break callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.TableBlock(name, location=None)

A table ... { } block.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

build(builder)

When handed a ‘builder’ object of comparable interface to fontTools.feaLib.builder, walks the statements in this block, calling the builder callbacks.

statements

Statements contained in the block

class fontTools.feaLib.ast.ValueRecord(xPlacement=None, yPlacement=None, xAdvance=None, yAdvance=None, xPlaDevice=None, yPlaDevice=None, xAdvDevice=None, yAdvDevice=None, vertical=False, location=None)

Represents a value record.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.ValueRecordDefinition(name, value, location=None)

Represents a named value record definition.

name

Value record name as string

value

ValueRecord object

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

class fontTools.feaLib.ast.VheaField(key, value, location=None)

An entry in the vhea table.

build(builder)

Calls the builder object’s add_vhea_field callback.

asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

merge: Merge multiple fonts into one

fontTools.merge provides both a library and a command line interface (fonttools merge) for merging multiple fonts together.

class fontTools.merge.Merger(options=None)

Font merger.

This class merges multiple files into a single OpenType font, taking into account complexities such as OpenType layout (GSUB/GPOS) tables and cross-font metrics (e.g. hhea.ascent is set to the maximum value across all the fonts).

If multiple glyphs map to the same Unicode value, and the glyphs are considered sufficiently different (that is, they differ in any of paths, widths, or height), then subsequent glyphs are renamed and a lookup in the locl feature will be created to disambiguate them. For example, if the arguments are an Arabic font and a Latin font and both contain a set of parentheses, the Latin glyphs will be renamed to parenleft#1 and parenright#1, and a lookup will be inserted into the to locl feature (creating it if necessary) under the latn script to substitute parenleft with parenleft#1 etc.

Restrictions:

  • All fonts must have the same units per em.

  • If duplicate glyph disambiguation takes place as described above then the

    fonts must have a GSUB table.

options

Currently unused.

merge(fontfiles)

Merges fonts together.

Parameters:

fontfiles – A list of file names to be merged

Returns:

A fontTools.ttLib.TTFont object. Call the save method on this to write it out to an OTF file.

misc: Miscellaneous libraries helpful for font engineering

This is a collection of packages, most of which are used as internal support utilities by fontTools, but some of which may be more generally useful.

arrayTools: Various array and rectangle tools

Routines for calculating bounding boxes, point in rectangle calculations and so on.

fontTools.misc.arrayTools.calcBounds(array)

Calculate the bounding rectangle of a 2D points array.

Parameters:

array – A sequence of 2D tuples.

Returns:

A four-item tuple representing the bounding rectangle (xMin, yMin, xMax, yMax).

fontTools.misc.arrayTools.calcIntBounds(array, round=<function otRound>)

Calculate the integer bounding rectangle of a 2D points array.

Values are rounded to closest integer towards +Infinity using the fontTools.misc.fixedTools.otRound() function by default, unless an optional round function is passed.

Parameters:
  • array – A sequence of 2D tuples.

  • round – A rounding function of type f(x: float) -> int.

Returns:

(xMin, yMin, xMax, yMax).

Return type:

A four-item tuple of integers representing the bounding rectangle

fontTools.misc.arrayTools.updateBounds(bounds, p, min=<built-in function min>, max=<built-in function max>)

Add a point to a bounding rectangle.

Parameters:
  • bounds – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax), or None.

  • p – A 2D tuple representing a point.

  • min – functions to compute the minimum and maximum.

  • max – functions to compute the minimum and maximum.

Returns:

The updated bounding rectangle (xMin, yMin, xMax, yMax).

fontTools.misc.arrayTools.pointInRect(p, rect)

Test if a point is inside a bounding rectangle.

Parameters:
  • p – A 2D tuple representing a point.

  • rect – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax).

Returns:

True if the point is inside the rectangle, False otherwise.

fontTools.misc.arrayTools.pointsInRect(array, rect)

Determine which points are inside a bounding rectangle.

Parameters:
  • array – A sequence of 2D tuples.

  • rect – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax).

Returns:

A list containing the points inside the rectangle.

fontTools.misc.arrayTools.vectorLength(vector)

Calculate the length of the given vector.

Parameters:

vector – A 2D tuple.

Returns:

The Euclidean length of the vector.

fontTools.misc.arrayTools.asInt16(array)

Round a list of floats to 16-bit signed integers.

Parameters:

array – List of float values.

Returns:

A list of rounded integers.

fontTools.misc.arrayTools.normRect(rect)

Normalize a bounding box rectangle.

This function “turns the rectangle the right way up”, so that the following holds:

xMin <= xMax and yMin <= yMax
Parameters:

rect – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax).

Returns:

A normalized bounding rectangle.

fontTools.misc.arrayTools.scaleRect(rect, x, y)

Scale a bounding box rectangle.

Parameters:
  • rect – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax).

  • x – Factor to scale the rectangle along the X axis.

  • Y – Factor to scale the rectangle along the Y axis.

Returns:

A scaled bounding rectangle.

fontTools.misc.arrayTools.offsetRect(rect, dx, dy)

Offset a bounding box rectangle.

Parameters:
  • rect – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax).

  • dx – Amount to offset the rectangle along the X axis.

  • dY – Amount to offset the rectangle along the Y axis.

Returns:

An offset bounding rectangle.

fontTools.misc.arrayTools.insetRect(rect, dx, dy)

Inset a bounding box rectangle on all sides.

Parameters:
  • rect – A bounding rectangle expressed as a tuple (xMin, yMin, xMax, yMax).

  • dx – Amount to inset the rectangle along the X axis.

  • dY – Amount to inset the rectangle along the Y axis.

Returns:

An inset bounding rectangle.

fontTools.misc.arrayTools.sectRect(rect1, rect2)

Test for rectangle-rectangle intersection.

Parameters:
  • rect1 – First bounding rectangle, expressed as tuples (xMin, yMin, xMax, yMax).

  • rect2 – Second bounding rectangle.

Returns:

A boolean and a rectangle. If the input rectangles intersect, returns True and the intersecting rectangle. Returns False and (0, 0, 0, 0) if the input rectangles don’t intersect.

fontTools.misc.arrayTools.unionRect(rect1, rect2)

Determine union of bounding rectangles.

Parameters:
  • rect1 – First bounding rectangle, expressed as tuples (xMin, yMin, xMax, yMax).

  • rect2 – Second bounding rectangle.

Returns:

The smallest rectangle in which both input rectangles are fully enclosed.

fontTools.misc.arrayTools.rectCenter(rect)

Determine rectangle center.

Parameters:

rect – Bounding rectangle, expressed as tuples (xMin, yMin, xMax, yMax).

Returns:

A 2D tuple representing the point at the center of the rectangle.

fontTools.misc.arrayTools.rectArea(rect)

Determine rectangle area.

Parameters:

rect – Bounding rectangle, expressed as tuples (xMin, yMin, xMax, yMax).

Returns:

The area of the rectangle.

fontTools.misc.arrayTools.intRect(rect)

Round a rectangle to integer values.

Guarantees that the resulting rectangle is NOT smaller than the original.

Parameters:

rect – Bounding rectangle, expressed as tuples (xMin, yMin, xMax, yMax).

Returns:

A rounded bounding rectangle.

fontTools.misc.arrayTools.quantizeRect(rect, factor=1)
>>> bounds = (72.3, -218.4, 1201.3, 919.1)
>>> quantizeRect(bounds)
(72, -219, 1202, 920)
>>> quantizeRect(bounds, factor=10)
(70, -220, 1210, 920)
>>> quantizeRect(bounds, factor=100)
(0, -300, 1300, 1000)
class fontTools.misc.arrayTools.Vector(values, keep=False)
count(value, /)

Return number of occurrences of value.

dot(other)

Performs vector dot product, returning the sum of a[0] * b[0], a[1] * b[1], ...

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

isclose(other: Vector, **kwargs) bool

Return True if the vector is close to another Vector.

length()

Return the length of the vector. Equivalent to abs(vector).

normalized()

Return the normalized vector of the vector.

toInt()
property values
fontTools.misc.arrayTools.pairwise(iterable, reverse=False)

Iterate over current and next items in iterable.

Parameters:
  • iterable – An iterable

  • reverse – If true, iterate in reverse order.

Returns:

A iterable yielding two elements per iteration.

Example

>>> tuple(pairwise([]))
()
>>> tuple(pairwise([], reverse=True))
()
>>> tuple(pairwise([0]))
((0, 0),)
>>> tuple(pairwise([0], reverse=True))
((0, 0),)
>>> tuple(pairwise([0, 1]))
((0, 1), (1, 0))
>>> tuple(pairwise([0, 1], reverse=True))
((1, 0), (0, 1))
>>> tuple(pairwise([0, 1, 2]))
((0, 1), (1, 2), (2, 0))
>>> tuple(pairwise([0, 1, 2], reverse=True))
((2, 1), (1, 0), (0, 2))
>>> tuple(pairwise(['a', 'b', 'c', 'd']))
(('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a'))
>>> tuple(pairwise(['a', 'b', 'c', 'd'], reverse=True))
(('d', 'c'), ('c', 'b'), ('b', 'a'), ('a', 'd'))

bezierTools: Routines for working with Bezier curves

fontTools.misc.bezierTools.py – tools for working with Bezier path segments.

fontTools.misc.bezierTools.approximateCubicArcLength(pt1, pt2, pt3, pt4)

Approximates the arc length for a cubic Bezier segment.

Uses Gauss-Lobatto quadrature with n=5 points to approximate arc length. See calcCubicArcLength() for a slower but more accurate result.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • pt4 – Control points of the Bezier as 2D tuples.

Returns:

Arc length value.

Example:

>>> approximateCubicArcLength((0, 0), (25, 100), (75, 100), (100, 0))
190.04332968932817
>>> approximateCubicArcLength((0, 0), (50, 0), (100, 50), (100, 100))
154.8852074945903
>>> approximateCubicArcLength((0, 0), (50, 0), (100, 0), (150, 0)) # line; exact result should be 150.
149.99999999999991
>>> approximateCubicArcLength((0, 0), (50, 0), (100, 0), (-50, 0)) # cusp; exact result should be 150.
136.9267662156362
>>> approximateCubicArcLength((0, 0), (50, 0), (100, -50), (-50, 0)) # cusp
154.80848416537057
fontTools.misc.bezierTools.approximateCubicArcLengthC(double complex pt1, double complex pt2, double complex pt3, double complex pt4)

Approximates the arc length for a cubic Bezier segment.

Parameters:
  • pt1 – Control points of the Bezier as complex numbers.

  • pt2 – Control points of the Bezier as complex numbers.

  • pt3 – Control points of the Bezier as complex numbers.

  • pt4 – Control points of the Bezier as complex numbers.

Returns:

Arc length value.

fontTools.misc.bezierTools.approximateQuadraticArcLength(pt1, pt2, pt3)

Calculates the arc length for a quadratic Bezier segment.

Uses Gauss-Legendre quadrature for a branch-free approximation. See calcQuadraticArcLength() for a slower but more accurate result.

Parameters:
  • pt1 – Start point of the Bezier as 2D tuple.

  • pt2 – Handle point of the Bezier as 2D tuple.

  • pt3 – End point of the Bezier as 2D tuple.

Returns:

Approximate arc length value.

fontTools.misc.bezierTools.approximateQuadraticArcLengthC(double complex pt1, double complex pt2, double complex pt3)

Calculates the arc length for a quadratic Bezier segment.

Uses Gauss-Legendre quadrature for a branch-free approximation. See calcQuadraticArcLength() for a slower but more accurate result.

Parameters:
  • pt1 – Start point of the Bezier as a complex number.

  • pt2 – Handle point of the Bezier as a complex number.

  • pt3 – End point of the Bezier as a complex number.

Returns:

Approximate arc length value.

fontTools.misc.bezierTools.calcCubicArcLength(pt1, pt2, pt3, pt4, tolerance=0.005)

Calculates the arc length for a cubic Bezier segment.

Whereas approximateCubicArcLength() approximates the length, this function calculates it by “measuring”, recursively dividing the curve until the divided segments are shorter than tolerance.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • pt4 – Control points of the Bezier as 2D tuples.

  • tolerance – Controls the precision of the calcuation.

Returns:

Arc length value.

fontTools.misc.bezierTools.calcCubicArcLengthC(double complex pt1, double complex pt2, double complex pt3, double complex pt4, double tolerance=0.005)

Calculates the arc length for a cubic Bezier segment.

Parameters:
  • pt1 – Control points of the Bezier as complex numbers.

  • pt2 – Control points of the Bezier as complex numbers.

  • pt3 – Control points of the Bezier as complex numbers.

  • pt4 – Control points of the Bezier as complex numbers.

  • tolerance – Controls the precision of the calcuation.

Returns:

Arc length value.

fontTools.misc.bezierTools.calcCubicBounds(pt1, pt2, pt3, pt4)

Calculates the bounding rectangle for a quadratic Bezier segment.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • pt4 – Control points of the Bezier as 2D tuples.

Returns:

A four-item tuple representing the bounding rectangle (xMin, yMin, xMax, yMax).

Example:

>>> calcCubicBounds((0, 0), (25, 100), (75, 100), (100, 0))
(0, 0, 100, 75.0)
>>> calcCubicBounds((0, 0), (50, 0), (100, 50), (100, 100))
(0.0, 0.0, 100, 100)
>>> print("%f %f %f %f" % calcCubicBounds((50, 0), (0, 100), (100, 100), (50, 0)))
35.566243 0.000000 64.433757 75.000000
fontTools.misc.bezierTools.calcQuadraticArcLength(pt1, pt2, pt3)

Calculates the arc length for a quadratic Bezier segment.

Parameters:
  • pt1 – Start point of the Bezier as 2D tuple.

  • pt2 – Handle point of the Bezier as 2D tuple.

  • pt3 – End point of the Bezier as 2D tuple.

Returns:

Arc length value.

Example:

>>> calcQuadraticArcLength((0, 0), (0, 0), (0, 0)) # empty segment
0.0
>>> calcQuadraticArcLength((0, 0), (50, 0), (80, 0)) # collinear points
80.0
>>> calcQuadraticArcLength((0, 0), (0, 50), (0, 80)) # collinear points vertical
80.0
>>> calcQuadraticArcLength((0, 0), (50, 20), (100, 40)) # collinear points
107.70329614269008
>>> calcQuadraticArcLength((0, 0), (0, 100), (100, 0))
154.02976155645263
>>> calcQuadraticArcLength((0, 0), (0, 50), (100, 0))
120.21581243984076
>>> calcQuadraticArcLength((0, 0), (50, -10), (80, 50))
102.53273816445825
>>> calcQuadraticArcLength((0, 0), (40, 0), (-40, 0)) # collinear points, control point outside
66.66666666666667
>>> calcQuadraticArcLength((0, 0), (40, 0), (0, 0)) # collinear points, looping back
40.0
fontTools.misc.bezierTools.calcQuadraticArcLengthC(double complex pt1, double complex pt2, double complex pt3)

Calculates the arc length for a quadratic Bezier segment.

Parameters:
  • pt1 – Start point of the Bezier as a complex number.

  • pt2 – Handle point of the Bezier as a complex number.

  • pt3 – End point of the Bezier as a complex number.

Returns:

Arc length value.

fontTools.misc.bezierTools.calcQuadraticBounds(pt1, pt2, pt3)

Calculates the bounding rectangle for a quadratic Bezier segment.

Parameters:
  • pt1 – Start point of the Bezier as a 2D tuple.

  • pt2 – Handle point of the Bezier as a 2D tuple.

  • pt3 – End point of the Bezier as a 2D tuple.

Returns:

A four-item tuple representing the bounding rectangle (xMin, yMin, xMax, yMax).

Example:

>>> calcQuadraticBounds((0, 0), (50, 100), (100, 0))
(0, 0, 100, 50.0)
>>> calcQuadraticBounds((0, 0), (100, 0), (100, 100))
(0.0, 0.0, 100, 100)
fontTools.misc.bezierTools.cubicPointAtT(pt1, pt2, pt3, pt4, t)

Finds the point at time t on a cubic curve.

Parameters:
  • pt1 – Coordinates of the curve as 2D tuples.

  • pt2 – Coordinates of the curve as 2D tuples.

  • pt3 – Coordinates of the curve as 2D tuples.

  • pt4 – Coordinates of the curve as 2D tuples.

  • t – The time along the curve.

Returns:

A 2D tuple with the coordinates of the point.

fontTools.misc.bezierTools.cubicPointAtTC(double complex pt1, double complex pt2, double complex pt3, double complex pt4, double t)

Finds the point at time t on a cubic curve.

Parameters:
  • pt1 – Coordinates of the curve as complex numbers.

  • pt2 – Coordinates of the curve as complex numbers.

  • pt3 – Coordinates of the curve as complex numbers.

  • pt4 – Coordinates of the curve as complex numbers.

  • t – The time along the curve.

Returns:

A complex number with the coordinates of the point.

fontTools.misc.bezierTools.curveCurveIntersections(curve1, curve2)

Finds intersections between a curve and a curve.

Parameters:
  • curve1 – List of coordinates of the first curve segment as 2D tuples.

  • curve2 – List of coordinates of the second curve segment as 2D tuples.

Returns:

A list of Intersection objects, each object having pt, t1 and t2 attributes containing the intersection point, time on first segment and time on second segment respectively.

Examples::
>>> curve1 = [ (10,100), (90,30), (40,140), (220,220) ]
>>> curve2 = [ (5,150), (180,20), (80,250), (210,190) ]
>>> intersections = curveCurveIntersections(curve1, curve2)
>>> len(intersections)
3
>>> intersections[0].pt
(81.7831487395506, 109.88904552375288)
fontTools.misc.bezierTools.curveLineIntersections(curve, line)

Finds intersections between a curve and a line.

Parameters:
  • curve – List of coordinates of the curve segment as 2D tuples.

  • line – List of coordinates of the line segment as 2D tuples.

Returns:

A list of Intersection objects, each object having pt, t1 and t2 attributes containing the intersection point, time on first segment and time on second segment respectively.

Examples::
>>> curve = [ (100, 240), (30, 60), (210, 230), (160, 30) ]
>>> line  = [ (25, 260), (230, 20) ]
>>> intersections = curveLineIntersections(curve, line)
>>> len(intersections)
3
>>> intersections[0].pt
(84.9000930760723, 189.87306176459828)
fontTools.misc.bezierTools.lineLineIntersections(s1, e1, s2, e2)

Finds intersections between two line segments.

Parameters:
  • s1 – Coordinates of the first line as 2D tuples.

  • e1 – Coordinates of the first line as 2D tuples.

  • s2 – Coordinates of the second line as 2D tuples.

  • e2 – Coordinates of the second line as 2D tuples.

Returns:

A list of Intersection objects, each object having pt, t1 and t2 attributes containing the intersection point, time on first segment and time on second segment respectively.

Examples:

>>> a = lineLineIntersections( (310,389), (453, 222), (289, 251), (447, 367))
>>> len(a)
1
>>> intersection = a[0]
>>> intersection.pt
(374.44882952482897, 313.73458370177315)
>>> (intersection.t1, intersection.t2)
(0.45069111555824465, 0.5408153767394238)
fontTools.misc.bezierTools.linePointAtT(pt1, pt2, t)

Finds the point at time t on a line.

Parameters:
  • pt1 – Coordinates of the line as 2D tuples.

  • pt2 – Coordinates of the line as 2D tuples.

  • t – The time along the line.

Returns:

A 2D tuple with the coordinates of the point.

fontTools.misc.bezierTools.quadraticPointAtT(pt1, pt2, pt3, t)

Finds the point at time t on a quadratic curve.

Parameters:
  • pt1 – Coordinates of the curve as 2D tuples.

  • pt2 – Coordinates of the curve as 2D tuples.

  • pt3 – Coordinates of the curve as 2D tuples.

  • t – The time along the curve.

Returns:

A 2D tuple with the coordinates of the point.

fontTools.misc.bezierTools.segmentPointAtT(seg, t)
fontTools.misc.bezierTools.segmentSegmentIntersections(seg1, seg2)

Finds intersections between two segments.

Parameters:
  • seg1 – List of coordinates of the first segment as 2D tuples.

  • seg2 – List of coordinates of the second segment as 2D tuples.

Returns:

A list of Intersection objects, each object having pt, t1 and t2 attributes containing the intersection point, time on first segment and time on second segment respectively.

Examples::
>>> curve1 = [ (10,100), (90,30), (40,140), (220,220) ]
>>> curve2 = [ (5,150), (180,20), (80,250), (210,190) ]
>>> intersections = segmentSegmentIntersections(curve1, curve2)
>>> len(intersections)
3
>>> intersections[0].pt
(81.7831487395506, 109.88904552375288)
>>> curve3 = [ (100, 240), (30, 60), (210, 230), (160, 30) ]
>>> line  = [ (25, 260), (230, 20) ]
>>> intersections = segmentSegmentIntersections(curve3, line)
>>> len(intersections)
3
>>> intersections[0].pt
(84.9000930760723, 189.87306176459828)
fontTools.misc.bezierTools.solveCubic(a, b, c, d)

Solve a cubic equation.

Solves a*x*x*x + b*x*x + c*x + d = 0 where a, b, c and d are real.

Parameters:
  • a – coefficient of

  • b – coefficient of

  • c – coefficient of x

  • d – constant term

Returns:

A list of roots. Note that the returned list is neither guaranteed to be sorted nor to contain unique values!

Examples:

>>> solveCubic(1, 1, -6, 0)
[-3.0, -0.0, 2.0]
>>> solveCubic(-10.0, -9.0, 48.0, -29.0)
[-2.9, 1.0, 1.0]
>>> solveCubic(-9.875, -9.0, 47.625, -28.75)
[-2.911392, 1.0, 1.0]
>>> solveCubic(1.0, -4.5, 6.75, -3.375)
[1.5, 1.5, 1.5]
>>> solveCubic(-12.0, 18.0, -9.0, 1.50023651123)
[0.5, 0.5, 0.5]
>>> solveCubic(
...     9.0, 0.0, 0.0, -7.62939453125e-05
... ) == [-0.0, -0.0, -0.0]
True
fontTools.misc.bezierTools.solveQuadratic(a, b, c, sqrt=sqrt)

Solve a quadratic equation.

Solves a*x*x + b*x + c = 0 where a, b and c are real.

Parameters:
  • a – coefficient of

  • b – coefficient of x

  • c – constant term

Returns:

A list of roots. Note that the returned list is neither guaranteed to be sorted nor to contain unique values!

fontTools.misc.bezierTools.splitCubic(pt1, pt2, pt3, pt4, where, isHorizontal)

Split a cubic Bezier curve at a given coordinate.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • pt4 – Control points of the Bezier as 2D tuples.

  • where – Position at which to split the curve.

  • isHorizontal – Direction of the ray splitting the curve. If true, where is interpreted as a Y coordinate; if false, then where is interpreted as an X coordinate.

Returns:

A list of two curve segments (each curve segment being four 2D tuples) if the curve was successfully split, or a list containing the original curve.

Example:

>>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 150, False))
((0, 0), (25, 100), (75, 100), (100, 0))
>>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 50, False))
((0, 0), (12.5, 50), (31.25, 75), (50, 75))
((50, 75), (68.75, 75), (87.5, 50), (100, 0))
>>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 25, True))
((0, 0), (2.29379, 9.17517), (4.79804, 17.5085), (7.47414, 25))
((7.47414, 25), (31.2886, 91.6667), (68.7114, 91.6667), (92.5259, 25))
((92.5259, 25), (95.202, 17.5085), (97.7062, 9.17517), (100, 1.77636e-15))
fontTools.misc.bezierTools.splitCubicAtT(pt1, pt2, pt3, pt4, *ts)

Split a cubic Bezier curve at one or more values of t.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • pt4 – Control points of the Bezier as 2D tuples.

  • *ts – Positions at which to split the curve.

Returns:

A list of curve segments (each curve segment being four 2D tuples).

Examples:

>>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5))
((0, 0), (12.5, 50), (31.25, 75), (50, 75))
((50, 75), (68.75, 75), (87.5, 50), (100, 0))
>>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5, 0.75))
((0, 0), (12.5, 50), (31.25, 75), (50, 75))
((50, 75), (59.375, 75), (68.75, 68.75), (77.3438, 56.25))
((77.3438, 56.25), (85.9375, 43.75), (93.75, 25), (100, 0))
fontTools.misc.bezierTools.splitCubicAtTC(double complex pt1, double complex pt2, double complex pt3, double complex pt4, *ts)

Split a cubic Bezier curve at one or more values of t.

Parameters:
  • pt1 – Control points of the Bezier as complex numbers..

  • pt2 – Control points of the Bezier as complex numbers..

  • pt3 – Control points of the Bezier as complex numbers..

  • pt4 – Control points of the Bezier as complex numbers..

  • *ts – Positions at which to split the curve.

Yields:

Curve segments (each curve segment being four complex numbers).

fontTools.misc.bezierTools.splitCubicIntoTwoAtTC(double complex pt1, double complex pt2, double complex pt3, double complex pt4, double t)

Split a cubic Bezier curve at t.

Parameters:
  • pt1 – Control points of the Bezier as complex numbers.

  • pt2 – Control points of the Bezier as complex numbers.

  • pt3 – Control points of the Bezier as complex numbers.

  • pt4 – Control points of the Bezier as complex numbers.

  • t – Position at which to split the curve.

Returns:

A tuple of two curve segments (each curve segment being four complex numbers).

fontTools.misc.bezierTools.splitLine(pt1, pt2, where, isHorizontal)

Split a line at a given coordinate.

Parameters:
  • pt1 – Start point of line as 2D tuple.

  • pt2 – End point of line as 2D tuple.

  • where – Position at which to split the line.

  • isHorizontal – Direction of the ray splitting the line. If true, where is interpreted as a Y coordinate; if false, then where is interpreted as an X coordinate.

Returns:

A list of two line segments (each line segment being two 2D tuples) if the line was successfully split, or a list containing the original line.

Example:

>>> printSegments(splitLine((0, 0), (100, 100), 50, True))
((0, 0), (50, 50))
((50, 50), (100, 100))
>>> printSegments(splitLine((0, 0), (100, 100), 100, True))
((0, 0), (100, 100))
>>> printSegments(splitLine((0, 0), (100, 100), 0, True))
((0, 0), (0, 0))
((0, 0), (100, 100))
>>> printSegments(splitLine((0, 0), (100, 100), 0, False))
((0, 0), (0, 0))
((0, 0), (100, 100))
>>> printSegments(splitLine((100, 0), (0, 0), 50, False))
((100, 0), (50, 0))
((50, 0), (0, 0))
>>> printSegments(splitLine((0, 100), (0, 0), 50, True))
((0, 100), (0, 50))
((0, 50), (0, 0))
fontTools.misc.bezierTools.splitQuadratic(pt1, pt2, pt3, where, isHorizontal)

Split a quadratic Bezier curve at a given coordinate.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • where – Position at which to split the curve.

  • isHorizontal – Direction of the ray splitting the curve. If true, where is interpreted as a Y coordinate; if false, then where is interpreted as an X coordinate.

Returns:

A list of two curve segments (each curve segment being three 2D tuples) if the curve was successfully split, or a list containing the original curve.

Example:

>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 150, False))
((0, 0), (50, 100), (100, 0))
>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, False))
((0, 0), (25, 50), (50, 50))
((50, 50), (75, 50), (100, 0))
>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, False))
((0, 0), (12.5, 25), (25, 37.5))
((25, 37.5), (62.5, 75), (100, 0))
>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, True))
((0, 0), (7.32233, 14.6447), (14.6447, 25))
((14.6447, 25), (50, 75), (85.3553, 25))
((85.3553, 25), (92.6777, 14.6447), (100, -7.10543e-15))
>>> # XXX I'm not at all sure if the following behavior is desirable:
>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, True))
((0, 0), (25, 50), (50, 50))
((50, 50), (50, 50), (50, 50))
((50, 50), (75, 50), (100, 0))
fontTools.misc.bezierTools.splitQuadraticAtT(pt1, pt2, pt3, *ts)

Split a quadratic Bezier curve at one or more values of t.

Parameters:
  • pt1 – Control points of the Bezier as 2D tuples.

  • pt2 – Control points of the Bezier as 2D tuples.

  • pt3 – Control points of the Bezier as 2D tuples.

  • *ts – Positions at which to split the curve.

Returns:

A list of curve segments (each curve segment being three 2D tuples).

Examples:

>>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5))
((0, 0), (25, 50), (50, 50))
((50, 50), (75, 50), (100, 0))
>>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5, 0.75))
((0, 0), (25, 50), (50, 50))
((50, 50), (62.5, 50), (75, 37.5))
((75, 37.5), (87.5, 25), (100, 0))

classifyTools

fontTools.misc.classifyTools.py – tools for classifying things.

class fontTools.misc.classifyTools.Classifier(sort=True)

Main Classifier object, used to classify things into similar sets.

add(set_of_things)

Add a set to the classifier. Any iterable is accepted.

getClasses()

Returns the list of class sets.

The return value belongs to the Classifier object and should NOT be modified while the classifier is still in use.

getMapping()

Returns the mapping from things to their class set.

The return value belongs to the Classifier object and should NOT be modified while the classifier is still in use.

getThings()

Returns the set of all things known so far.

The return value belongs to the Classifier object and should NOT be modified while the classifier is still in use.

update(list_of_sets)

Add a a list of sets to the classifier. Any iterable of iterables is accepted.

fontTools.misc.classifyTools.classify(list_of_sets, sort=True)

Takes a iterable of iterables (list of sets from here on; but any iterable works.), and returns the smallest list of sets such that each set, is either a subset, or is disjoint from, each of the input sets.

In other words, this function classifies all the things present in any of the input sets, into similar classes, based on which sets things are a member of.

If sort=True, return class sets are sorted by decreasing size and their natural sort order within each class size. Otherwise, class sets are returned in the order that they were identified, which is generally not significant.

>>> classify([]) == ([], {})
True
>>> classify([[]]) == ([], {})
True
>>> classify([[], []]) == ([], {})
True
>>> classify([[1]]) == ([{1}], {1: {1}})
True
>>> classify([[1,2]]) == ([{1, 2}], {1: {1, 2}, 2: {1, 2}})
True
>>> classify([[1],[2]]) == ([{1}, {2}], {1: {1}, 2: {2}})
True
>>> classify([[1,2],[2]]) == ([{1}, {2}], {1: {1}, 2: {2}})
True
>>> classify([[1,2],[2,4]]) == ([{1}, {2}, {4}], {1: {1}, 2: {2}, 4: {4}})
True
>>> classify([[1,2],[2,4,5]]) == (
...     [{4, 5}, {1}, {2}], {1: {1}, 2: {2}, 4: {4, 5}, 5: {4, 5}})
True
>>> classify([[1,2],[2,4,5]], sort=False) == (
...     [{1}, {4, 5}, {2}], {1: {1}, 2: {2}, 4: {4, 5}, 5: {4, 5}})
True
>>> classify([[1,2,9],[2,4,5]], sort=False) == (
...     [{1, 9}, {4, 5}, {2}], {1: {1, 9}, 2: {2}, 4: {4, 5}, 5: {4, 5},
...     9: {1, 9}})
True
>>> classify([[1,2,9,15],[2,4,5]], sort=False) == (
...     [{1, 9, 15}, {4, 5}, {2}], {1: {1, 9, 15}, 2: {2}, 4: {4, 5},
...     5: {4, 5}, 9: {1, 9, 15}, 15: {1, 9, 15}})
True
>>> classes, mapping = classify([[1,2,9,15],[2,4,5],[15,5]], sort=False)
>>> set([frozenset(c) for c in classes]) == set(
...     [frozenset(s) for s in ({1, 9}, {4}, {2}, {5}, {15})])
True
>>> mapping == {1: {1, 9}, 2: {2}, 4: {4}, 5: {5}, 9: {1, 9}, 15: {15}}
True

cliTools: Utilities for command-line interfaces and console scripts

Collection of utilities for command-line interfaces and console scripts.

fontTools.misc.cliTools.makeOutputFileName(input, outputDir=None, extension=None, overWrite=False, suffix='')

Generates a suitable file name for writing output.

Often tools will want to take a file, do some kind of transformation to it, and write it out again. This function determines an appropriate name for the output file, through one or more of the following steps:

  • changing the output directory

  • appending suffix before file extension

  • replacing the file extension

  • suffixing the filename with a number (#1, #2, etc.) to avoid overwriting an existing file.

Parameters:
  • input – Name of input file.

  • outputDir – Optionally, a new directory to write the file into.

  • suffix – Optionally, a string suffix is appended to file name before the extension.

  • extension – Optionally, a replacement for the current file extension.

  • overWrite – Overwriting an existing file is permitted if true; if false and the proposed filename exists, a new name will be generated by adding an appropriate number suffix.

Returns:

Suitable output filename

Return type:

str

configTools

Code of the config system; not related to fontTools or fonts in particular.

The options that are specific to fontTools are in fontTools.config.

To create your own config system, you need to create an instance of Options, and a subclass of AbstractConfig with its options class variable set to your instance of Options.

class fontTools.misc.configTools.AbstractConfig(values: AbstractConfig | Dict[Option | str, Any] = {}, parse_values: bool = False, skip_unknown: bool = False)

Create a set of config values, optionally pre-filled with values from the given dictionary or pre-existing config object.

The class implements the MutableMapping protocol keyed by option name (str). For convenience its methods accept either Option or str as the key parameter.

See also

set()

This config class is abstract because it needs its options class var to be set to an instance of Options before it can be instanciated and used.

class MyConfig(AbstractConfig):
    options = Options()

MyConfig.register_option( "test:option_name", "This is an option", 0, int, lambda v: isinstance(v, int))

cfg = MyConfig({"test:option_name": 10})
clear() None.  Remove all items from D.
copy()
get(option_or_name: ~fontTools.misc.configTools.Option | str, default: ~typing.Any = <object object>) Any

Get the value of an option. The value which is returned is the first provided among:

  1. a user-provided value in the options’s self._values dict

  2. a caller-provided default value to this method call

  3. the global default for the option provided in fontTools.config

This is to provide the ability to migrate progressively from config options passed as arguments to fontTools APIs to config options read from the current TTFont, e.g.

def fontToolsAPI(font, some_option):
    value = font.cfg.get("someLib.module:SOME_OPTION", some_option)
    # use value

That way, the function will work the same for users of the API that still pass the option to the function call, but will favour the new config mechanism if the given font specifies a value for that option.

items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
options: ClassVar[Options]
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

classmethod register_option(name: str, help: str, default: Any, parse: Callable[[str], Any], validate: Callable[[Any], bool] | None = None) Option

Register an available option in this config system.

set(option_or_name: Option | str, value: Any, parse_values: bool = False, skip_unknown: bool = False)

Set the value of an option.

Parameters:
  • option_or_name (*) – an Option object or its name (str).

  • value (*) – the value to be assigned to given option.

  • parse_values (*) – parse the configuration value from a string into its proper type, as per its Option object. The default behavior is to raise ConfigValueValidationError when the value is not of the right type. Useful when reading options from a file type that doesn’t support as many types as Python.

  • skip_unknown (*) – skip unknown configuration options. The default behaviour is to raise ConfigUnknownOptionError. Useful when reading options from a configuration file that has extra entries (e.g. for a later version of fontTools)

setdefault(k[, d]) D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() an object providing a view on D's values
exception fontTools.misc.configTools.ConfigAlreadyRegisteredError(name)

Raised when a module tries to register a configuration option that already exists.

Should not be raised too much really, only when developing new fontTools modules.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.misc.configTools.ConfigError

Base exception for the config module.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.misc.configTools.ConfigUnknownOptionError(option_or_name)

Raised when a configuration option is unknown.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.misc.configTools.ConfigValueParsingError(name, value)

Raised when a configuration value cannot be parsed.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.misc.configTools.ConfigValueValidationError(name, value)

Raised when a configuration value cannot be validated.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.misc.configTools.Option(name: 'str', help: 'str', default: 'Any', parse: 'Callable[[str], Any]', validate: 'Optional[Callable[[Any], bool]]' = None)
default: Any

Default value for this option.

help: str

Help text for this option.

name: str

MY_OPTION).

Type:

Unique name identifying the option (e.g. package.module

parse: Callable[[str], Any]

Turn input (e.g. string) into proper type. Only when reading from file.

static parse_optional_bool(v: str) bool | None
validate: Callable[[Any], bool] | None = None

Return true if the given value is an acceptable value.

static validate_optional_bool(v: Any) bool
class fontTools.misc.configTools.Options(other: Options = None)

Registry of available options for a given config system.

Define new options using the register() method.

Access existing options using the Mapping interface.

get(k[, d]) D[k] if k in D, else d.  d defaults to None.
is_registered(option: Option) bool

Return True if the same option object is already registered.

items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
register(name: str, help: str, default: Any, parse: Callable[[str], Any], validate: Callable[[Any], bool] | None = None) Option

Create and register a new option.

register_option(option: Option) Option

Register a new option.

values() an object providing a view on D's values

eexec: PostScript charstring encryption and decryption routines

PostScript Type 1 fonts make use of two types of encryption: charstring encryption and eexec encryption. Charstring encryption is used for the charstrings themselves, while eexec is used to encrypt larger sections of the font program, such as the Private and CharStrings dictionaries. Despite the different names, the algorithm is the same, although eexec encryption uses a fixed initial key R=55665.

The algorithm uses cipher feedback, meaning that the ciphertext is used to modify the key. Because of this, the routines in this module return the new key at the end of the operation.

fontTools.misc.eexec.deHexString(h)
fontTools.misc.eexec.decrypt(cipherstring, R)

Decrypts a string using the Type 1 encryption algorithm.

Parameters:
  • cipherstring – String of ciphertext.

  • R – Initial key.

Returns:

Plaintext string. R: Output key for subsequent decryptions.

Return type:

decryptedStr

Examples:

>>> testStr = b"\0\0asdadads asds\265"
>>> decryptedStr, R = decrypt(testStr, 12321)
>>> decryptedStr == b'0d\nh\x15\xe8\xc4\xb2\x15\x1d\x108\x1a<6\xa1'
True
>>> R == 36142
True
fontTools.misc.eexec.encrypt(plainstring, R)

Encrypts a string using the Type 1 encryption algorithm.

Note that the algorithm as described in the Type 1 specification requires the plaintext to be prefixed with a number of random bytes. (For eexec the number of random bytes is set to 4.) This routine does not add the random prefix to its input.

Parameters:
  • plainstring – String of plaintext.

  • R – Initial key.

Returns:

Ciphertext string. R: Output key for subsequent encryptions.

Return type:

cipherstring

Examples:

>>> testStr = b"\0\0asdadads asds\265"
>>> decryptedStr, R = decrypt(testStr, 12321)
>>> decryptedStr == b'0d\nh\x15\xe8\xc4\xb2\x15\x1d\x108\x1a<6\xa1'
True
>>> R == 36142
True
>>> testStr = b'0d\nh\x15\xe8\xc4\xb2\x15\x1d\x108\x1a<6\xa1'
>>> encryptedStr, R = encrypt(testStr, 12321)
>>> encryptedStr == b"\0\0asdadads asds\265"
True
>>> R == 36142
True
fontTools.misc.eexec.hexString(s)

encodingTools

fontTools.misc.encodingTools.py – tools for working with OpenType encodings.

fontTools.misc.encodingTools.getEncoding(platformID, platEncID, langID, default=None)

Returns the Python encoding name for OpenType platformID/encodingID/langID triplet. If encoding for these values is not known, by default None is returned. That can be overriden by passing a value to the default argument.

etree

Shim module exporting the same ElementTree API for lxml and xml.etree backends.

When lxml is installed, it is automatically preferred over the built-in xml.etree module. On Python 2.7, the cElementTree module is preferred over the pure-python ElementTree module.

Besides exporting a unified interface, this also defines extra functions or subclasses built-in ElementTree classes to add features that are only availble in lxml, like OrderedDict for attributes, pretty_print and iterwalk.

fontTools.misc.etree.Comment(text=None)

Comment element factory. This factory function creates a special element that will be serialized as an XML comment.

fontTools.misc.etree.Element(_tag, attrib=None, nsmap=None, **_extra)

Element factory. This function returns an object implementing the Element interface.

Also look at the _Element.makeelement() and _BaseParser.makeelement() methods, which provide a faster way to create an Element within a specific document or parser context.

fontTools.misc.etree.ElementTree(element=None, file=None, parser=None)

ElementTree wrapper class.

fontTools.misc.etree.PI(target, text=None)

ProcessingInstruction(target, text=None)

ProcessingInstruction element factory. This factory function creates a special element that will be serialized as an XML processing instruction.

exception fontTools.misc.etree.ParseError(message, code, line, column, filename=None)

Syntax error while parsing an XML document.

For compatibility with ElementTree 1.3 and later.

add_note()

Exception.add_note(note) – add a note to the exception

args
end_lineno

exception end lineno

end_offset

exception end offset

filename

exception filename

lineno

exception lineno

msg

exception msg

offset

exception offset

property position
print_file_and_line

exception print_file_and_line

text

exception text

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

fontTools.misc.etree.ProcessingInstruction(target, text=None)

ProcessingInstruction element factory. This factory function creates a special element that will be serialized as an XML processing instruction.

class fontTools.misc.etree.QName(text_or_uri_or_element, tag=None)

QName wrapper for qualified XML names.

Pass a tag name by itself or a namespace URI and a tag name to create a qualified name. Alternatively, pass an Element to extract its tag name. None as first argument is ignored in order to allow for generic 2-argument usage.

The text property holds the qualified name in {namespace}tagname notation. The namespace and localname properties hold the respective parts of the tag name.

You can pass QName objects wherever a tag name is expected. Also, setting Element text from a QName will resolve the namespace prefix on assignment and set a qualified text value. This is helpful in XML languages like SOAP or XML-Schema that use prefixed tag names in their text content.

localname
namespace
text
fontTools.misc.etree.SubElement(_parent, _tag, attrib=None, nsmap=None, **_extra)

Subelement factory. This function creates an element instance, and appends it to an existing element.

class fontTools.misc.etree.TreeBuilder
TreeBuilder(self, element_factory=None, parser=None,

comment_factory=None, pi_factory=None, insert_comments=True, insert_pis=True)

Parser target that builds a tree from parse event callbacks.

The factory arguments can be used to influence the creation of elements, comments and processing instructions.

By default, comments and processing instructions are inserted into the tree, but they can be ignored by passing the respective flags.

The final tree is returned by the close() method.

close(self)

Flushes the builder buffers, and returns the toplevel document element. Raises XMLSyntaxError on inconsistencies.

comment(self, comment)

Creates a comment using the factory, appends it (unless disabled) and returns it.

data(self, data)

Adds text to the current element. The value should be either an 8-bit string containing ASCII text, or a Unicode string.

end(self, tag)

Closes the current element.

pi(self, target, data=None)

Creates a processing instruction using the factory, appends it (unless disabled) and returns it.

start(self, tag, attrs, nsmap=None)

Opens a new element.

fontTools.misc.etree.XML(text, parser=None, base_url=None)

Parses an XML document or fragment from a string constant. Returns the root node (or the result returned by a parser target). This function can be used to embed “XML literals” in Python code, like in

>>> root = XML("<root><test/></root>")
>>> print(root.tag)
root

To override the parser with a different XMLParser you can pass it to the parser keyword argument.

The base_url keyword argument allows to set the original base URL of the document to support relative Paths when looking up external entities (DTD, XInclude, …).

class fontTools.misc.etree.XMLParser(self, encoding=None, attribute_defaults=False, dtd_validation=False, load_dtd=False, no_network=True, ns_clean=False, recover=False, schema: XMLSchema = None, huge_tree=False, remove_blank_text=False, resolve_entities=True, remove_comments=False, remove_pis=False, strip_cdata=True, collect_ids=True, target=None, compact=True)

The XML parser.

Parsers can be supplied as additional argument to various parse functions of the lxml API. A default parser is always available and can be replaced by a call to the global function ‘set_default_parser’. New parsers can be created at any time without a major run-time overhead.

The keyword arguments in the constructor are mainly based on the libxml2 parser configuration. A DTD will also be loaded if DTD validation or attribute default values are requested (unless you additionally provide an XMLSchema from which the default attributes can be read).

Available boolean keyword arguments:

  • attribute_defaults - inject default attributes from DTD or XMLSchema

  • dtd_validation - validate against a DTD referenced by the document

  • load_dtd - use DTD for parsing

  • no_network - prevent network access for related files (default: True)

  • ns_clean - clean up redundant namespace declarations

  • recover - try hard to parse through broken XML

  • remove_blank_text - discard blank text nodes that appear ignorable

  • remove_comments - discard comments

  • remove_pis - discard processing instructions

  • strip_cdata - replace CDATA sections by normal text content (default: True)

  • compact - save memory for short text content (default: True)

  • collect_ids - use a hash table of XML IDs for fast access (default: True, always True with DTD validation)

  • huge_tree - disable security restrictions and support very deep trees

    and very long text content (only affects libxml2 2.7+)

Other keyword arguments:

  • resolve_entities - replace entities by their text value: False for keeping the

    entity references, True for resolving them, and ‘internal’ for resolving internal definitions only (no external file/URL access). The default used to be True and was changed to ‘internal’ in lxml 5.0.

  • encoding - override the document encoding (note: libiconv encoding name)

  • target - a parser target object that will receive the parse events

  • schema - an XMLSchema to validate against

Note that you should avoid sharing parsers between threads. While this is not harmful, it is more efficient to use separate parsers. This does not apply to the default parser.

close(self)

Terminates feeding data to this parser. This tells the parser to process any remaining data in the feed buffer, and then returns the root Element of the tree that was parsed.

This method must be called after passing the last chunk of data into the feed() method. It should only be called when using the feed parser interface, all other usage is undefined.

copy(self)

Create a new parser with the same configuration.

error_log

The error log of the last parser run.

feed(self, data)

Feeds data to the parser. The argument should be an 8-bit string buffer containing encoded data, although Unicode is supported as long as both string types are not mixed.

This is the main entry point to the consumer interface of a parser. The parser will parse as much of the XML stream as it can on each call. To finish parsing or to reset the parser, call the close() method. Both methods may raise ParseError if errors occur in the input data. If an error is raised, there is no longer a need to call close().

The feed parser interface is independent of the normal parser usage. You can use the same parser as a feed parser and in the parse() function concurrently.

feed_error_log

The error log of the last (or current) run of the feed parser.

Note that this is local to the feed parser and thus is different from what the error_log property returns.

makeelement(self, _tag, attrib=None, nsmap=None, **_extra)

Creates a new element associated with this parser.

resolvers

The custom resolver registry of this parser.

set_element_class_lookup(self, lookup=None)

Set a lookup scheme for element classes generated from this parser.

Reset it by passing None or nothing.

target
version

The version of the underlying XML parser.

fontTools.misc.etree.dump(elem, pretty_print=True, with_tail=True)

Writes an element tree or element structure to sys.stdout. This function should be used for debugging only.

fontTools.misc.etree.fromstring(text, parser=None, base_url=None)

Parses an XML document or fragment from a string. Returns the root node (or the result returned by a parser target).

To override the default parser with a different parser you can pass it to the parser keyword argument.

The base_url keyword argument allows to set the original base URL of the document to support relative Paths when looking up external entities (DTD, XInclude, …).

fontTools.misc.etree.fromstringlist(strings, parser=None)

Parses an XML document from a sequence of strings. Returns the root node (or the result returned by a parser target).

To override the default parser with a different parser you can pass it to the parser keyword argument.

fontTools.misc.etree.iselement(element)

Checks if an object appears to be a valid element object.

class fontTools.misc.etree.iterparse(self, source, events=('end',), tag=None, attribute_defaults=False, dtd_validation=False, load_dtd=False, no_network=True, remove_blank_text=False, remove_comments=False, remove_pis=False, encoding=None, html=False, recover=None, huge_tree=False, schema=None)

Incremental parser.

Parses XML into a tree and generates tuples (event, element) in a SAX-like fashion. event is any of ‘start’, ‘end’, ‘start-ns’, ‘end-ns’.

For ‘start’ and ‘end’, element is the Element that the parser just found opening or closing. For ‘start-ns’, it is a tuple (prefix, URI) of a new namespace declaration. For ‘end-ns’, it is simply None. Note that all start and end events are guaranteed to be properly nested.

The keyword argument events specifies a sequence of event type names that should be generated. By default, only ‘end’ events will be generated.

The additional tag argument restricts the ‘start’ and ‘end’ events to those elements that match the given tag. The tag argument can also be a sequence of tags to allow matching more than one tag. By default, events are generated for all elements. Note that the ‘start-ns’ and ‘end-ns’ events are not impacted by this restriction.

The other keyword arguments in the constructor are mainly based on the libxml2 parser configuration. A DTD will also be loaded if validation or attribute default values are requested.

Available boolean keyword arguments:
  • attribute_defaults: read default attributes from DTD

  • dtd_validation: validate (if DTD is available)

  • load_dtd: use DTD for parsing

  • no_network: prevent network access for related files

  • remove_blank_text: discard blank text nodes

  • remove_comments: discard comments

  • remove_pis: discard processing instructions

  • strip_cdata: replace CDATA sections by normal text content (default: True)

  • compact: safe memory for short text content (default: True)

  • resolve_entities: replace entities by their text value (default: True)

  • huge_tree: disable security restrictions and support very deep trees

    and very long text content (only affects libxml2 2.7+)

  • html: parse input as HTML (default: XML)

  • recover: try hard to parse through broken input (default: True for HTML,

    False otherwise)

Other keyword arguments:
  • encoding: override the document encoding

  • schema: an XMLSchema to validate against

error_log

The error log of the last (or current) parser run.

makeelement(self, _tag, attrib=None, nsmap=None, **_extra)

Creates a new element associated with this parser.

resolvers

The custom resolver registry of the last (or current) parser run.

root
set_element_class_lookup(self, lookup=None)

Set a lookup scheme for element classes generated from this parser.

Reset it by passing None or nothing.

version

The version of the underlying XML parser.

fontTools.misc.etree.parse(source, parser=None, base_url=None)

Return an ElementTree object loaded with source elements. If no parser is provided as second argument, the default parser is used.

The source can be any of the following:

  • a file name/path

  • a file object

  • a file-like object

  • a URL using the HTTP or FTP protocol

To parse from a string, use the fromstring() function instead.

Note that it is generally faster to parse from a file path or URL than from an open file object or file-like object. Transparent decompression from gzip compressed sources is supported (unless explicitly disabled in libxml2).

The base_url keyword allows setting a URL for the document when parsing from a file-like object. This is needed when looking up external entities (DTD, XInclude, …) with relative paths.

fontTools.misc.etree.register_namespace(prefix, uri)

Registers a namespace prefix that newly created Elements in that namespace will use. The registry is global, and any existing mapping for either the given prefix or the namespace URI will be removed.

fontTools.misc.etree.tostring(element_or_tree, *, encoding=None, method='xml', xml_declaration=None, pretty_print=False, with_tail=True, standalone=None, doctype=None, exclusive=False, inclusive_ns_prefixes=None, with_comments=True, strip_text=False)
tostring(element_or_tree, encoding=None, method=”xml”,

xml_declaration=None, pretty_print=False, with_tail=True, standalone=None, doctype=None, exclusive=False, inclusive_ns_prefixes=None, with_comments=True, strip_text=False, )

Serialize an element to an encoded string representation of its XML tree.

Defaults to ASCII encoding without XML declaration. This behaviour can be configured with the keyword arguments ‘encoding’ (string) and ‘xml_declaration’ (bool). Note that changing the encoding to a non UTF-8 compatible encoding will enable a declaration by default.

You can also serialise to a Unicode string without declaration by passing the name 'unicode' as encoding (or the str function in Py3 or unicode in Py2). This changes the return value from a byte string to an unencoded unicode string.

The keyword argument ‘pretty_print’ (bool) enables formatted XML.

The keyword argument ‘method’ selects the output method: ‘xml’, ‘html’, plain ‘text’ (text content without tags), ‘c14n’ or ‘c14n2’. Default is ‘xml’.

With method="c14n" (C14N version 1), the options exclusive, with_comments and inclusive_ns_prefixes request exclusive C14N, include comments, and list the inclusive prefixes respectively.

With method="c14n2" (C14N version 2), the with_comments and strip_text options control the output of comments and text space according to C14N 2.0.

Passing a boolean value to the standalone option will output an XML declaration with the corresponding standalone flag.

The doctype option allows passing in a plain string that will be serialised before the XML tree. Note that passing in non well-formed content here will make the XML output non well-formed. Also, an existing doctype in the document tree will not be removed when serialising an ElementTree instance.

You can prevent the tail text of the element from being serialised by passing the boolean with_tail option. This has no impact on the tail text of children, which will always be serialised.

fontTools.misc.etree.tostringlist(element_or_tree, *args, **kwargs)

Serialize an element to an encoded string representation of its XML tree, stored in a list of partial strings.

This is purely for ElementTree 1.3 compatibility. The result is a single string wrapped in a list.

filenames: Implements UFO User Name to File Name Algorithm

This module implements the algorithm for converting between a “user name” - something that a user can choose arbitrarily inside a font editor - and a file name suitable for use in a wide range of operating systems and filesystems.

The UFO 3 specification provides an example of an algorithm for such conversion, which avoids illegal characters, reserved file names, ambiguity between upper- and lower-case characters, and clashes with existing files.

This code was originally copied from ufoLib by Tal Leming and is copyright (c) 2005-2016, The RoboFab Developers:

  • Erik van Blokland

  • Tal Leming

  • Just van Rossum

exception fontTools.misc.filenames.NameTranslationError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

fontTools.misc.filenames.handleClash1(userName, existing=[], prefix='', suffix='')

existing should be a case-insensitive list of all existing file names.

>>> prefix = ("0" * 5) + "."
>>> suffix = "." + ("0" * 10)
>>> existing = ["a" * 5]
>>> e = list(existing)
>>> handleClash1(userName="A" * 5, existing=e,
...         prefix=prefix, suffix=suffix) == (
...         '00000.AAAAA000000000000001.0000000000')
True
>>> e = list(existing)
>>> e.append(prefix + "aaaaa" + "1".zfill(15) + suffix)
>>> handleClash1(userName="A" * 5, existing=e,
...         prefix=prefix, suffix=suffix) == (
...         '00000.AAAAA000000000000002.0000000000')
True
>>> e = list(existing)
>>> e.append(prefix + "AAAAA" + "2".zfill(15) + suffix)
>>> handleClash1(userName="A" * 5, existing=e,
...         prefix=prefix, suffix=suffix) == (
...         '00000.AAAAA000000000000001.0000000000')
True
fontTools.misc.filenames.handleClash2(existing=[], prefix='', suffix='')

existing should be a case-insensitive list of all existing file names.

>>> prefix = ("0" * 5) + "."
>>> suffix = "." + ("0" * 10)
>>> existing = [prefix + str(i) + suffix for i in range(100)]
>>> e = list(existing)
>>> handleClash2(existing=e, prefix=prefix, suffix=suffix) == (
...         '00000.100.0000000000')
True
>>> e = list(existing)
>>> e.remove(prefix + "1" + suffix)
>>> handleClash2(existing=e, prefix=prefix, suffix=suffix) == (
...         '00000.1.0000000000')
True
>>> e = list(existing)
>>> e.remove(prefix + "2" + suffix)
>>> handleClash2(existing=e, prefix=prefix, suffix=suffix) == (
...         '00000.2.0000000000')
True
fontTools.misc.filenames.userNameToFileName(userName, existing=[], prefix='', suffix='')

Converts from a user name to a file name.

Takes care to avoid illegal characters, reserved file names, ambiguity between upper- and lower-case characters, and clashes with existing files.

Parameters:
  • userName (str) – The input file name.

  • existing – A case-insensitive list of all existing file names.

  • prefix – Prefix to be prepended to the file name.

  • suffix – Suffix to be appended to the file name.

Returns:

A suitable filename.

Raises:

NameTranslationError – If no suitable name could be generated.

Examples:

>>> userNameToFileName("a") == "a"
True
>>> userNameToFileName("A") == "A_"
True
>>> userNameToFileName("AE") == "A_E_"
True
>>> userNameToFileName("Ae") == "A_e"
True
>>> userNameToFileName("ae") == "ae"
True
>>> userNameToFileName("aE") == "aE_"
True
>>> userNameToFileName("a.alt") == "a.alt"
True
>>> userNameToFileName("A.alt") == "A_.alt"
True
>>> userNameToFileName("A.Alt") == "A_.A_lt"
True
>>> userNameToFileName("A.aLt") == "A_.aL_t"
True
>>> userNameToFileName(u"A.alT") == "A_.alT_"
True
>>> userNameToFileName("T_H") == "T__H_"
True
>>> userNameToFileName("T_h") == "T__h"
True
>>> userNameToFileName("t_h") == "t_h"
True
>>> userNameToFileName("F_F_I") == "F__F__I_"
True
>>> userNameToFileName("f_f_i") == "f_f_i"
True
>>> userNameToFileName("Aacute_V.swash") == "A_acute_V_.swash"
True
>>> userNameToFileName(".notdef") == "_notdef"
True
>>> userNameToFileName("con") == "_con"
True
>>> userNameToFileName("CON") == "C_O_N_"
True
>>> userNameToFileName("con.alt") == "_con.alt"
True
>>> userNameToFileName("alt.con") == "alt._con"
True

fixedTools: Tools for working with fixed-point numbers

The OpenType specification defines two fixed-point data types:

Fixed

A 32-bit signed fixed-point number with a 16 bit twos-complement magnitude component and 16 fractional bits.

F2DOT14

A 16-bit signed fixed-point number with a 2 bit twos-complement magnitude component and 14 fractional bits.

To support reading and writing data with these data types, this module provides functions for converting between fixed-point, float and string representations.

fontTools.misc.fixedTools.MAX_F2DOT14

The maximum value that can still fit in an F2Dot14. (1.99993896484375)

fontTools.misc.fixedTools.ensureVersionIsLong(value)

Ensure a table version is an unsigned long.

OpenType table version numbers are expressed as a single unsigned long comprising of an unsigned short major version and unsigned short minor version. This function detects if the value to be used as a version number looks too small (i.e. is less than 0x10000), and converts it to fixed-point using floatToFixed() if so.

Parameters:

value (Number) – a candidate table version number.

Returns:

A table version number, possibly corrected to fixed-point.

Return type:

int

fontTools.misc.fixedTools.fixedToFloat(value, precisionBits)

Converts a fixed-point number to a float given the number of precision bits.

Parameters:
  • value (int) – Number in fixed-point format.

  • precisionBits (int) – Number of precision bits.

Returns:

Floating point value.

Examples:

>>> import math
>>> f = fixedToFloat(-10139, precisionBits=14)
>>> math.isclose(f, -0.61883544921875)
True
fontTools.misc.fixedTools.fixedToStr(value, precisionBits)

Converts a fixed-point number to a string representing a decimal float.

This chooses the float that has the shortest decimal representation (the least number of fractional decimal digits).

For example, to convert a fixed-point number in a 2.14 format, use precisionBits=14:

>>> fixedToStr(-10139, precisionBits=14)
'-0.61884'

This is pretty slow compared to the simple division used in fixedToFloat. Use sporadically when you need to serialize or print the fixed-point number in a human-readable form. It uses nearestMultipleShortestRepr under the hood.

Parameters:
  • value (int) – The fixed-point value to convert.

  • precisionBits (int) – Number of precision bits, up to a maximum of 16.

Returns:

A string representation of the value.

Return type:

str

fontTools.misc.fixedTools.floatToFixed(value, precisionBits)

Converts a float to a fixed-point number given the number of precision bits.

Parameters:
  • value (float) – Floating point value.

  • precisionBits (int) – Number of precision bits.

Returns:

Fixed-point representation.

Return type:

int

Examples:

>>> floatToFixed(-0.61883544921875, precisionBits=14)
-10139
>>> floatToFixed(-0.61884, precisionBits=14)
-10139
fontTools.misc.fixedTools.floatToFixedToFloat(value, precisionBits)

Converts a float to a fixed-point number and back again.

By converting the float to fixed, rounding it, and converting it back to float again, this returns a floating point values which is exactly representable in fixed-point format.

Note: this is equivalent to fixedToFloat(floatToFixed(value)).

Parameters:
  • value (float) – The input floating point value.

  • precisionBits (int) – Number of precision bits.

Returns:

The transformed and rounded value.

Return type:

float

Examples::
>>> import math
>>> f1 = -0.61884
>>> f2 = floatToFixedToFloat(-0.61884, precisionBits=14)
>>> f1 != f2
True
>>> math.isclose(f2, -0.61883544921875)
True
fontTools.misc.fixedTools.floatToFixedToStr(value, precisionBits)

Convert float to string with fixed-point rounding.

This uses the shortest decimal representation (ie. the least number of fractional decimal digits) to represent the equivalent fixed-point number with precisionBits fractional binary digits. It uses nearestMultipleShortestRepr under the hood.

>>> floatToFixedToStr(-0.61883544921875, precisionBits=14)
'-0.61884'
Parameters:
  • value (float) – The float value to convert.

  • precisionBits (int) – Number of precision bits, up to a maximum of 16.

Returns:

A string representation of the value.

Return type:

str

fontTools.misc.fixedTools.strToFixed(string, precisionBits)

Converts a string representing a decimal float to a fixed-point number.

Parameters:
  • string (str) – A string representing a decimal float.

  • precisionBits (int) – Number of precision bits, up to a maximum of 16.

Returns:

Fixed-point representation.

Return type:

int

Examples:

>>> ## to convert a float string to a 2.14 fixed-point number:
>>> strToFixed('-0.61884', precisionBits=14)
-10139
fontTools.misc.fixedTools.strToFixedToFloat(string, precisionBits)

Convert a string to a decimal float with fixed-point rounding.

This first converts string to a float, then turns it into a fixed-point number with precisionBits fractional binary digits, then back to a float again.

This is simply a shorthand for fixedToFloat(floatToFixed(float(s))).

Parameters:
  • string (str) – A string representing a decimal float.

  • precisionBits (int) – Number of precision bits.

Returns:

The transformed and rounded value.

Return type:

float

Examples:

>>> import math
>>> s = '-0.61884'
>>> bits = 14
>>> f = strToFixedToFloat(s, precisionBits=bits)
>>> math.isclose(f, -0.61883544921875)
True
>>> f == fixedToFloat(floatToFixed(float(s), precisionBits=bits), precisionBits=bits)
True
fontTools.misc.fixedTools.versionToFixed(value)

Ensure a table version number is fixed-point.

Parameters:

value (str) – a candidate table version number.

Returns:

A table version number, possibly corrected to fixed-point.

Return type:

int

intTools: Tools for working with integer values

fontTools.misc.intTools.bit_count(self, /)

Number of ones in the binary representation of the absolute value of self.

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3
fontTools.misc.intTools.bit_indices(v)

Return list of indices where bits are set, 0 being the index of the least significant bit.

>>> bit_indices(0b101)
[0, 2]
fontTools.misc.intTools.popCount(self, /)

Number of ones in the binary representation of the absolute value of self.

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3

loggingTools: tools for interfacing with the Python logging package

class fontTools.misc.loggingTools.CapturingLogHandler(logger, level)
acquire()

Acquire the I/O thread lock.

addFilter(filter)

Add the specified filter to this handler.

assertRegex(regexp, msg=None)
close()

Tidy up any resources used by the handler.

This version removes the handler from an internal map of handlers, _handlers, which is used for handler lookup by name. Subclasses should ensure that this gets called from overridden close() methods.

createLock()

Acquire a thread lock for serializing access to the underlying I/O.

emit(record)

Do whatever it takes to actually log the specified logging record.

This version is intended to be implemented by subclasses and so raises a NotImplementedError.

filter(record)

Determine if a record is loggable by consulting all the filters.

The default is to allow the record to be logged; any filter can veto this and the record is then dropped. Returns a zero value if a record is to be dropped, else non-zero.

Changed in version 3.2: Allow filters to be just callables.

flush()

Ensure all logging output has been flushed.

This version does nothing and is intended to be implemented by subclasses.

format(record)

Format the specified record.

If a formatter is set, use it. Otherwise, use the default formatter for the module.

get_name()
handle(record)

Conditionally emit the specified logging record.

Emission depends on filters which may have been added to the handler. Wrap the actual emission of the record with acquisition/release of the I/O thread lock. Returns whether the filter passed the record for emission.

handleError(record)

Handle errors which occur during an emit() call.

This method should be called from handlers when an exception is encountered during an emit() call. If raiseExceptions is false, exceptions get silently ignored. This is what is mostly wanted for a logging system - most users will not care about errors in the logging system, they are more interested in application errors. You could, however, replace this with a custom handler if you wish. The record which was being processed is passed in to this method.

property name
release()

Release the I/O thread lock.

removeFilter(filter)

Remove the specified filter from this handler.

setFormatter(fmt)

Set the formatter for this handler.

setLevel(level)

Set the logging level of this handler. level must be an int or a str.

set_name(name)
class fontTools.misc.loggingTools.ChannelsFilter(*names)

Provides a hierarchical filter for log entries based on channel names.

Filters out records emitted from a list of enabled channel names, including their children. It works the same as the logging.Filter class, but allows the user to specify multiple channel names.

>>> import sys
>>> handler = logging.StreamHandler(sys.stdout)
>>> handler.setFormatter(logging.Formatter("%(message)s"))
>>> filter = ChannelsFilter("A.B", "C.D")
>>> handler.addFilter(filter)
>>> root = logging.getLogger()
>>> root.addHandler(handler)
>>> root.setLevel(level=logging.DEBUG)
>>> logging.getLogger('A.B').debug('this record passes through')
this record passes through
>>> logging.getLogger('A.B.C').debug('records from children also pass')
records from children also pass
>>> logging.getLogger('C.D').debug('this one as well')
this one as well
>>> logging.getLogger('A.B.').debug('also this one')
also this one
>>> logging.getLogger('A.F').debug('but this one does not!')
>>> logging.getLogger('C.DE').debug('neither this one!')
filter(record)

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

class fontTools.misc.loggingTools.LevelFormatter(fmt=None, datefmt=None, style='%')

Log formatter with level-specific formatting.

Formatter class which optionally takes a dict of logging levels to format strings, allowing to customise the log records appearance for specific levels.

fmt

A dictionary mapping logging levels to format strings. The * key identifies the default format string.

datefmt

As per py:class:logging.Formatter

style

As per py:class:logging.Formatter

>>> import sys
>>> handler = logging.StreamHandler(sys.stdout)
>>> formatter = LevelFormatter(
...     fmt={
...         '*':     '[%(levelname)s] %(message)s',
...         'DEBUG': '%(name)s [%(levelname)s] %(message)s',
...         'INFO':  '%(message)s',
...     })
>>> handler.setFormatter(formatter)
>>> log = logging.getLogger('test')
>>> log.setLevel(logging.DEBUG)
>>> log.addHandler(handler)
>>> log.debug('this uses a custom format string')
test [DEBUG] this uses a custom format string
>>> log.info('this also uses a custom format string')
this also uses a custom format string
>>> log.warning("this one uses the default format string")
[WARNING] this one uses the default format string
converter()
localtime([seconds]) -> (tm_year,tm_mon,tm_mday,tm_hour,tm_min,

tm_sec,tm_wday,tm_yday,tm_isdst)

Convert seconds since the Epoch to a time tuple expressing local time. When ‘seconds’ is not passed in, convert the current time instead.

default_msec_format = '%s,%03d'
default_time_format = '%Y-%m-%d %H:%M:%S'
format(record)

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

formatException(ei)

Format and return the specified exception information as a string.

This default implementation just uses traceback.print_exception()

formatMessage(record)
formatStack(stack_info)

This method is provided as an extension point for specialized formatting of stack information.

The input data is a string as returned from a call to traceback.print_stack(), but with the last trailing newline removed.

The base implementation just returns the value passed in.

formatTime(record, datefmt=None)

Return the creation time of the specified LogRecord as formatted text.

This method should be called from format() by a formatter which wants to make use of a formatted time. This method can be overridden in formatters to provide for any specific requirement, but the basic behaviour is as follows: if datefmt (a string) is specified, it is used with time.strftime() to format the creation time of the record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used. The resulting string is returned. This function uses a user-configurable function to convert the creation time to a tuple. By default, time.localtime() is used; to change this for a particular formatter instance, set the ‘converter’ attribute to a function with the same signature as time.localtime() or time.gmtime(). To change it for all formatters, for example if you want all logging times to be shown in GMT, set the ‘converter’ attribute in the Formatter class.

usesTime()

Check if the format uses the creation time of the record.

class fontTools.misc.loggingTools.LogMixin

Mixin class that adds logging functionality to another class.

You can define a new class that subclasses from LogMixin as well as other base classes through multiple inheritance. All instances of that class will have a log property that returns a logging.Logger named after their respective <module>.<class>.

For example:

>>> class BaseClass(object):
...     pass
>>> class MyClass(LogMixin, BaseClass):
...     pass
>>> a = MyClass()
>>> isinstance(a.log, logging.Logger)
True
>>> print(a.log.name)
fontTools.misc.loggingTools.MyClass
>>> class AnotherClass(MyClass):
...     pass
>>> b = AnotherClass()
>>> isinstance(b.log, logging.Logger)
True
>>> print(b.log.name)
fontTools.misc.loggingTools.AnotherClass
property log
class fontTools.misc.loggingTools.Timer(logger=None, msg=None, level=None, start=None)

Keeps track of overall time and split/lap times.

>>> import time
>>> timer = Timer()
>>> time.sleep(0.01)
>>> print("First lap:", timer.split())
First lap: ...
>>> time.sleep(0.02)
>>> print("Second lap:", timer.split())
Second lap: ...
>>> print("Overall time:", timer.time())
Overall time: ...

Can be used as a context manager inside with-statements.

>>> with Timer() as t:
...     time.sleep(0.01)
>>> print("%0.3f seconds" % t.elapsed)
0... seconds

If initialised with a logger, it can log the elapsed time automatically upon exiting the with-statement.

>>> import logging
>>> log = logging.getLogger("my-fancy-timer-logger")
>>> configLogger(logger=log, level="DEBUG", format="%(message)s", stream=sys.stdout)
>>> with Timer(log, 'do something'):
...     time.sleep(0.01)
Took ... to do something

The same Timer instance, holding a reference to a logger, can be reused in multiple with-statements, optionally with different messages or levels.

>>> timer = Timer(log)
>>> with timer():
...     time.sleep(0.01)
elapsed time: ...s
>>> with timer('redo it', level=logging.INFO):
...     time.sleep(0.02)
Took ... to redo it

It can also be used as a function decorator to log the time elapsed to run the decorated function.

>>> @timer()
... def test1():
...    time.sleep(0.01)
>>> @timer('run test 2', level=logging.INFO)
... def test2():
...    time.sleep(0.02)
>>> test1()
Took ... to run 'test1'
>>> test2()
Took ... to run test 2
default_format = 'Took %(time).3fs to %(msg)s'
default_msg = 'elapsed time: %(time).3fs'
formatTime(msg, time)

Format ‘time’ value in ‘msg’ and return formatted string. If ‘msg’ contains a ‘%(time)’ format string, try to use that. Otherwise, use the predefined ‘default_format’. If ‘msg’ is empty or None, fall back to ‘default_msg’.

reset(start=None)

Reset timer to ‘start_time’ or the current time.

split()

Split and return the lap time (in seconds) in between splits.

time()

Return the overall time (in seconds) since the timer started.

fontTools.misc.loggingTools.configLogger(**kwargs)

A more sophisticated logging system configuation manager.

This is more or less the same as logging.basicConfig(), with some additional options and defaults.

The default behaviour is to create a StreamHandler which writes to sys.stderr, set a formatter using the DEFAULT_FORMATS strings, and add the handler to the top-level library logger (“fontTools”).

A number of optional keyword arguments may be specified, which can alter the default behaviour.

Parameters:
  • logger – Specifies the logger name or a Logger instance to be configured. (Defaults to “fontTools” logger). Unlike basicConfig, this function can be called multiple times to reconfigure a logger. If the logger or any of its children already exists before the call is made, they will be reset before the new configuration is applied.

  • filename – Specifies that a FileHandler be created, using the specified filename, rather than a StreamHandler.

  • filemode – Specifies the mode to open the file, if filename is specified. (If filemode is unspecified, it defaults to a).

  • format – Use the specified format string for the handler. This argument also accepts a dictionary of format strings keyed by level name, to allow customising the records appearance for specific levels. The special '*' key is for ‘any other’ level.

  • datefmt – Use the specified date/time format.

  • level – Set the logger level to the specified level.

  • stream – Use the specified stream to initialize the StreamHandler. Note that this argument is incompatible with filename - if both are present, stream is ignored.

  • handlers – If specified, this should be an iterable of already created handlers, which will be added to the logger. Any handler in the list which does not have a formatter assigned will be assigned the formatter created in this function.

  • filters – If specified, this should be an iterable of already created filters. If the handlers do not already have filters assigned, these filters will be added to them.

  • propagate – All loggers have a propagate attribute which determines whether to continue searching for handlers up the logging hierarchy. If not provided, the “propagate” attribute will be set to False.

fontTools.misc.loggingTools.deprecateArgument(name, msg, category=<class 'UserWarning'>)

Raise a warning about deprecated function argument ‘name’.

fontTools.misc.loggingTools.deprecateFunction(msg, category=<class 'UserWarning'>)

Decorator to raise a warning when a deprecated function is called.

macCreatorType: Functions for working with Mac file attributes

This module requires the xattr module to be installed in order to function correctly.

fontTools.misc.macCreatorType.getMacCreatorAndType(path)

Returns file creator and file type codes for a path.

Parameters:

path (str) – A file path.

Returns:

A tuple of two fontTools.textTools.Tag objects, the first representing the file creator and the second representing the file type.

fontTools.misc.macCreatorType.setMacCreatorAndType(path, fileCreator, fileType)

Set file creator and file type codes for a path.

Note that if the xattr module is not installed, no action is taken but no error is raised.

Parameters:
  • path (str) – A file path.

  • fileCreator – A four-character file creator tag.

  • fileType – A four-character file type tag.

macRes: Tools for reading Mac resource forks

Classic Mac OS files are made up of two parts - the “data fork” which contains the file contents proper, and the “resource fork” which contains a number of structured data items called “resources”. Some fonts, such as Mac “font suitcases” and Type 1 LWFN fonts, still use the resource fork for this kind of structured data, and so to read them, fontTools needs to have access to resource forks.

The Inside Macintosh volume More Macintosh Toolbox explains the structure of resource and data forks.

exception fontTools.misc.macRes.ResourceError
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.misc.macRes.ResourceReader(fileOrPath)

Reader for Mac OS resource forks.

Parses a resource fork and returns resources according to their type. If run on OS X, this will open the resource fork in the filesystem. Otherwise, it will open the file itself and attempt to read it as though it were a resource fork.

The returned object can be indexed by type and iterated over, returning in each case a list of py:class:Resource objects representing all the resources of a certain type.

keys() a set-like object providing a view on D's keys
property types

A list of the types of resources in the resource fork.

countResources(resType)

Return the number of resources of a given type.

getIndices(resType)

Returns a list of indices of resources of a given type.

getNames(resType)

Return list of names of all resources of a given type.

getIndResource(resType, index)

Return resource of given type located at an index ranging from 1 to the number of resources for that type, or None if not found.

getNamedResource(resType, name)

Return the named resource of given type, else return None.

clear() None.  Remove all items from D.
get(k[, d]) D[k] if k in D, else d.  d defaults to None.
items() a set-like object providing a view on D's items
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() an object providing a view on D's values
class fontTools.misc.macRes.Resource(resType=None, resData=None, resID=None, resName=None, resAttr=None)

Represents a resource stored within a resource fork.

type

resource type.

data

resource data.

id

ID.

name

resource name.

attr

attributes.

plistlib: Tools for handling .plist files

class fontTools.misc.plistlib.Data(data: bytes)

Represents binary data when use_builtin_types=False.

This class wraps binary data loaded from a plist file when the use_builtin_types argument to the loading function (fromtree(), load(), loads()) is false.

The actual binary data is retrieved using the data attribute.

class fontTools.misc.plistlib.PlistTarget(use_builtin_types: bool | None = None, dict_type: ~typing.Type[~typing.MutableMapping[str, ~typing.Any]] = <class 'dict'>)

Event handler using the ElementTree Target API that can be passed to a XMLParser to produce property list objects from XML. It is based on the CPython plistlib module’s _PlistParser class, but does not use the expat parser.

>>> from fontTools.misc import etree
>>> parser = etree.XMLParser(target=PlistTarget())
>>> result = etree.XML(
...     "<dict>"
...     "    <key>something</key>"
...     "    <string>blah</string>"
...     "</dict>",
...     parser=parser)
>>> result == {"something": "blah"}
True

Links: https://github.com/python/cpython/blob/main/Lib/plistlib.py http://lxml.de/parsing.html#the-target-parser-interface

fontTools.misc.plistlib.dump(value: bool | bytes | Data | datetime | float | Integral | Mapping[str, Any] | Sequence[Any] | str, fp: IO[bytes], sort_keys: bool = True, skipkeys: bool = False, use_builtin_types: bool | None = None, pretty_print: bool = True) None

Write a Python object to a plist file.

Parameters:
  • value – An object to write.

  • fp – A file opened for writing.

  • sort_keys (bool) – Whether keys of dictionaries should be sorted.

  • skipkeys (bool) – Whether to silently skip non-string dictionary keys.

  • use_builtin_types (bool) – If true, byte strings will be encoded in Base-64 and wrapped in a data tag; if false, they will be either stored as ASCII strings or an exception raised if they cannot be represented. Defaults

  • pretty_print (bool) – Whether to indent the output.

  • indent_level (int) – Level of indentation when serializing.

Raises:
  • TypeError – if non-string dictionary keys are serialized and skipkeys is false.

  • ValueError – if non-representable binary data is present and use_builtin_types is false.

fontTools.misc.plistlib.dumps(value: bool | bytes | Data | datetime | float | Integral | Mapping[str, Any] | Sequence[Any] | str, sort_keys: bool = True, skipkeys: bool = False, use_builtin_types: bool | None = None, pretty_print: bool = True) bytes

Write a Python object to a string in plist format.

Parameters:
  • value – An object to write.

  • sort_keys (bool) – Whether keys of dictionaries should be sorted.

  • skipkeys (bool) – Whether to silently skip non-string dictionary keys.

  • use_builtin_types (bool) – If true, byte strings will be encoded in Base-64 and wrapped in a data tag; if false, they will be either stored as strings or an exception raised if they cannot be represented. Defaults

  • pretty_print (bool) – Whether to indent the output.

  • indent_level (int) – Level of indentation when serializing.

Returns:

A plist representation of the Python object.

Return type:

string

Raises:
  • TypeError – if non-string dictionary keys are serialized and skipkeys is false.

  • ValueError – if non-representable binary data is present and use_builtin_types is false.

fontTools.misc.plistlib.fromtree(tree: ~lxml.etree.Element, use_builtin_types: bool | None = None, dict_type: ~typing.Type[~typing.MutableMapping[str, ~typing.Any]] = <class 'dict'>) Any

Convert an XML tree to a plist structure.

Parameters:
  • tree – An etree Element.

  • use_builtin_types – If True, binary data is deserialized to bytes strings. If False, it is wrapped in Data objects. Defaults to True if not provided. Deprecated.

  • dict_type – What type to use for dictionaries.

Returns: An object (usually a dictionary).

fontTools.misc.plistlib.load(fp: ~typing.IO[bytes], use_builtin_types: bool | None = None, dict_type: ~typing.Type[~typing.MutableMapping[str, ~typing.Any]] = <class 'dict'>) Any

Load a plist file into an object.

Parameters:
  • fp – An opened file.

  • use_builtin_types – If True, binary data is deserialized to bytes strings. If False, it is wrapped in Data objects. Defaults to True if not provided. Deprecated.

  • dict_type – What type to use for dictionaries.

Returns:

An object (usually a dictionary) representing the top level of the plist file.

fontTools.misc.plistlib.loads(value: bytes, use_builtin_types: bool | None = None, dict_type: ~typing.Type[~typing.MutableMapping[str, ~typing.Any]] = <class 'dict'>) Any

Load a plist file from a string into an object.

Parameters:
  • value – A bytes string containing a plist.

  • use_builtin_types – If True, binary data is deserialized to bytes strings. If False, it is wrapped in Data objects. Defaults to True if not provided. Deprecated.

  • dict_type – What type to use for dictionaries.

Returns:

An object (usually a dictionary) representing the top level of the plist file.

fontTools.misc.plistlib.totree(value: bool | bytes | Data | datetime | float | Integral | Mapping[str, Any] | Sequence[Any] | str, sort_keys: bool = True, skipkeys: bool = False, use_builtin_types: bool | None = None, pretty_print: bool = True, indent_level: int = 1) Element

Convert a value derived from a plist into an XML tree.

Parameters:
  • value – Any kind of value to be serialized to XML.

  • sort_keys – Whether keys of dictionaries should be sorted.

  • skipkeys (bool) – Whether to silently skip non-string dictionary keys.

  • use_builtin_types (bool) – If true, byte strings will be encoded in Base-64 and wrapped in a data tag; if false, they will be either stored as ASCII strings or an exception raised if they cannot be decoded as such. Defaults to True if not present. Deprecated.

  • pretty_print (bool) – Whether to indent the output.

  • indent_level (int) – Level of indentation when serializing.

Returns: an etree Element object.

Raises:
  • TypeError – if non-string dictionary keys are serialized and skipkeys is false.

  • ValueError – if non-ASCII binary data is present and use_builtin_types is false.

psCharStrings

psCharStrings.py – module implementing various kinds of CharStrings: CFF dictionary data and Type1/Type2 CharStrings.

exception fontTools.misc.psCharStrings.CharStringCompileError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.misc.psCharStrings.DictDecompiler(strings, parent=None)
arg_SID(name)
arg_array(name)
arg_blendList(name)

There may be non-blend args at the top of the stack. We first calculate where the blend args start in the stack. These are the last numMasters*numBlends) +1 args. The blend args starts with numMasters relative coordinate values, the BlueValues in the list from the default master font. This is followed by numBlends list of values. Each of value in one of these lists is the Variable Font delta for the matching region.

We re-arrange this to be a list of numMaster entries. Each entry starts with the corresponding default font relative value, and is followed by the delta values. We then convert the default values, the first item in each entry, to an absolute value.

arg_blend_number(name)
arg_delta(name)
arg_number(name)
decompile(data)
getDict()
handle_operator(operator)
operandEncoding = [<function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_shortInt>, <function read_longInt>, <function read_realNumber>, <function read_operator>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt2>, <function read_smallInt2>, <function read_smallInt2>, <function read_smallInt2>, <function read_reserved>]
pop()
popall()
class fontTools.misc.psCharStrings.SimpleT2Decompiler(localSubrs, globalSubrs, private=None, blender=None)
countHints()
execute(charString)
op_abs(index)
op_add(index)
op_and(index)
op_blend(index)
op_callgsubr(index)
op_callsubr(index)
op_cntrmask(index)
op_div(index)
op_drop(index)
op_dup(index)
op_endchar(index)
op_eq(index)
op_exch(index)
op_get(index)
op_hintmask(index)
op_hstem(index)
op_hstemhm(index)
op_ifelse(index)
op_ignore(index)
op_index(index)
op_load(index)
op_mul(index)
op_neg(index)
op_not(index)
op_or(index)
op_put(index)
op_random(index)
op_return(index)
op_roll(index)
op_sqrt(index)
op_store(index)
op_sub(index)
op_vsindex(index)
op_vstem(index)
op_vstemhm(index)
pop()
popall()
push(value)
reset()
class fontTools.misc.psCharStrings.T1CharString(bytecode=None, program=None, subrs=None)
calcBounds(glyphSet)
compile(isCFF2=False)
decompile()
decompilerClass

alias of SimpleT2Decompiler

draw(pen)
fromXML(name, attrs, content)
getBytes(index, nBytes)
getFixedEncoder()
getIntEncoder()
getNumRegions(vsindex=None)
getToken(index, len=<built-in function len>, byteord=<function byteord>, isinstance=<built-in function isinstance>)
handle_operator(operator)
needsDecompilation()
opcodes = {'callothersubr': (12, 16), 'callsubr': (10,), 'closepath': (9,), 'div': (12, 12), 'dotsection': (12, 0), 'endchar': (14,), 'hlineto': (6,), 'hmoveto': (22,), 'hsbw': (13,), 'hstem': (1,), 'hstem3': (12, 2), 'hvcurveto': (31,), 'pop': (12, 17), 'return': (11,), 'rlineto': (5,), 'rmoveto': (21,), 'rrcurveto': (8,), 'sbw': (12, 7), 'seac': (12, 6), 'setcurrentpoint': (12, 33), 'vhcurveto': (30,), 'vlineto': (7,), 'vmoveto': (4,), 'vstem': (3,), 'vstem3': (12, 1)}
operandEncoding = [<function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt2>, <function read_smallInt2>, <function read_smallInt2>, <function read_smallInt2>, <function read_longInt>]
operators = {(12, 0): 'dotsection', (12, 1): 'vstem3', (12, 12): 'div', (12, 16): 'callothersubr', (12, 17): 'pop', (12, 2): 'hstem3', (12, 33): 'setcurrentpoint', (12, 6): 'seac', (12, 7): 'sbw', 1: 'hstem', 10: 'callsubr', 11: 'return', 13: 'hsbw', 14: 'endchar', 21: 'rmoveto', 22: 'hmoveto', 3: 'vstem', 30: 'vhcurveto', 31: 'hvcurveto', 4: 'vmoveto', 5: 'rlineto', 6: 'hlineto', 7: 'vlineto', 8: 'rrcurveto', 9: 'closepath'}
outlineExtractor

alias of T2OutlineExtractor

setBytecode(bytecode)
setProgram(program)
toXML(xmlWriter, ttFont=None)
class fontTools.misc.psCharStrings.T1OutlineExtractor(pen, subrs)
alternatingLineto(isHorizontal)
closePath()
countHints()
doFlex()
endPath()
exch()
execute(charString)
hcurveto(args)
op_abs(index)
op_add(index)
op_and(index)
op_blend(index)
op_callgsubr(index)
op_callothersubr(index)
op_callsubr(index)
op_closepath(index)
op_cntrmask(index)
op_div(index)
op_dotsection(index)
op_drop(index)
op_dup(index)
op_endchar(index)
op_eq(index)
op_exch(index)
op_flex(index)
op_flex1(index)
op_get(index)
op_hflex(index)
op_hflex1(index)
op_hhcurveto(index)

dy1? {dxa dxb dyb dxc}+ hhcurveto

op_hintmask(index)
op_hlineto(index)
op_hmoveto(index)
op_hsbw(index)
op_hstem(index)
op_hstem3(index)
op_hstemhm(index)
op_hvcurveto(index)

dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?

op_ifelse(index)
op_ignore(index)
op_index(index)
op_load(index)
op_mul(index)
op_neg(index)
op_not(index)
op_or(index)
op_pop(index)
op_put(index)
op_random(index)
op_rcurveline(index)

{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline

op_return(index)
op_rlinecurve(index)

{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve

op_rlineto(index)
op_rmoveto(index)
op_roll(index)
op_rrcurveto(index)

{dxa dya dxb dyb dxc dyc}+ rrcurveto

op_sbw(index)
op_seac(index)

asb adx ady bchar achar seac

op_setcurrentpoint(index)
op_sqrt(index)
op_store(index)
op_sub(index)
op_vhcurveto(index)

dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30) {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto

op_vlineto(index)
op_vmoveto(index)
op_vsindex(index)
op_vstem(index)
op_vstem3(index)
op_vstemhm(index)
op_vvcurveto(index)

dx1? {dya dxb dyb dyc}+ vvcurveto

pop()
popall()
popallWidth(evenOdd=0)
push(value)
rCurveTo(pt1, pt2, pt3)
rLineTo(point)
rMoveTo(point)
reset()
vcurveto(args)
class fontTools.misc.psCharStrings.T2CharString(bytecode=None, program=None, private=None, globalSubrs=None)
calcBounds(glyphSet)
compile(isCFF2=False)
decompile()
decompilerClass

alias of SimpleT2Decompiler

draw(pen, blender=None)
fromXML(name, attrs, content)
getBytes(index, nBytes)
getFixedEncoder()
getIntEncoder()
getNumRegions(vsindex=None)
getToken(index, len=<built-in function len>, byteord=<function byteord>, isinstance=<built-in function isinstance>)
handle_operator(operator)
needsDecompilation()
opcodes = {'abs': (12, 9), 'add': (12, 10), 'and': (12, 3), 'blend': (16,), 'callgsubr': (29,), 'callsubr': (10,), 'cntrmask': (20,), 'div': (12, 12), 'drop': (12, 18), 'dup': (12, 27), 'endchar': (14,), 'eq': (12, 15), 'exch': (12, 28), 'flex': (12, 35), 'flex1': (12, 37), 'get': (12, 21), 'hflex': (12, 34), 'hflex1': (12, 36), 'hhcurveto': (27,), 'hintmask': (19,), 'hlineto': (6,), 'hmoveto': (22,), 'hstem': (1,), 'hstemhm': (18,), 'hvcurveto': (31,), 'ifelse': (12, 22), 'ignore': (12, 0), 'index': (12, 29), 'load': (12, 13), 'mul': (12, 24), 'neg': (12, 14), 'not': (12, 5), 'or': (12, 4), 'put': (12, 20), 'random': (12, 23), 'rcurveline': (24,), 'return': (11,), 'rlinecurve': (25,), 'rlineto': (5,), 'rmoveto': (21,), 'roll': (12, 30), 'rrcurveto': (8,), 'sqrt': (12, 26), 'store': (12, 8), 'sub': (12, 11), 'vhcurveto': (30,), 'vlineto': (7,), 'vmoveto': (4,), 'vsindex': (15,), 'vstem': (3,), 'vstemhm': (23,), 'vvcurveto': (26,)}
operandEncoding = [<function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_shortInt>, <function read_operator>, <function read_operator>, <function read_operator>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_byte>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt1>, <function read_smallInt2>, <function read_smallInt2>, <function read_smallInt2>, <function read_smallInt2>, <function read_fixed1616>]
operators = {(12, 0): 'ignore', (12, 10): 'add', (12, 11): 'sub', (12, 12): 'div', (12, 13): 'load', (12, 14): 'neg', (12, 15): 'eq', (12, 18): 'drop', (12, 20): 'put', (12, 21): 'get', (12, 22): 'ifelse', (12, 23): 'random', (12, 24): 'mul', (12, 26): 'sqrt', (12, 27): 'dup', (12, 28): 'exch', (12, 29): 'index', (12, 3): 'and', (12, 30): 'roll', (12, 34): 'hflex', (12, 35): 'flex', (12, 36): 'hflex1', (12, 37): 'flex1', (12, 4): 'or', (12, 5): 'not', (12, 8): 'store', (12, 9): 'abs', 1: 'hstem', 10: 'callsubr', 11: 'return', 14: 'endchar', 15: 'vsindex', 16: 'blend', 18: 'hstemhm', 19: 'hintmask', 20: 'cntrmask', 21: 'rmoveto', 22: 'hmoveto', 23: 'vstemhm', 24: 'rcurveline', 25: 'rlinecurve', 26: 'vvcurveto', 27: 'hhcurveto', 29: 'callgsubr', 3: 'vstem', 30: 'vhcurveto', 31: 'hvcurveto', 4: 'vmoveto', 5: 'rlineto', 6: 'hlineto', 7: 'vlineto', 8: 'rrcurveto'}
outlineExtractor

alias of T2OutlineExtractor

setBytecode(bytecode)
setProgram(program)
toXML(xmlWriter, ttFont=None)
class fontTools.misc.psCharStrings.T2OutlineExtractor(pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None, blender=None)
alternatingLineto(isHorizontal)
closePath()
countHints()
endPath()
execute(charString)
hcurveto(args)
op_abs(index)
op_add(index)
op_and(index)
op_blend(index)
op_callgsubr(index)
op_callsubr(index)
op_cntrmask(index)
op_div(index)
op_drop(index)
op_dup(index)
op_endchar(index)
op_eq(index)
op_exch(index)
op_flex(index)
op_flex1(index)
op_get(index)
op_hflex(index)
op_hflex1(index)
op_hhcurveto(index)

dy1? {dxa dxb dyb dxc}+ hhcurveto

op_hintmask(index)
op_hlineto(index)
op_hmoveto(index)
op_hstem(index)
op_hstemhm(index)
op_hvcurveto(index)

dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?

op_ifelse(index)
op_ignore(index)
op_index(index)
op_load(index)
op_mul(index)
op_neg(index)
op_not(index)
op_or(index)
op_put(index)
op_random(index)
op_rcurveline(index)

{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline

op_return(index)
op_rlinecurve(index)

{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve

op_rlineto(index)
op_rmoveto(index)
op_roll(index)
op_rrcurveto(index)

{dxa dya dxb dyb dxc dyc}+ rrcurveto

op_sqrt(index)
op_store(index)
op_sub(index)
op_vhcurveto(index)

dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30) {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto

op_vlineto(index)
op_vmoveto(index)
op_vsindex(index)
op_vstem(index)
op_vstemhm(index)
op_vvcurveto(index)

dx1? {dya dxb dyb dyc}+ vvcurveto

pop()
popall()
popallWidth(evenOdd=0)
push(value)
rCurveTo(pt1, pt2, pt3)
rLineTo(point)
rMoveTo(point)
reset()
vcurveto(args)
class fontTools.misc.psCharStrings.T2WidthExtractor(localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None, blender=None)
countHints()
execute(charString)
op_abs(index)
op_add(index)
op_and(index)
op_blend(index)
op_callgsubr(index)
op_callsubr(index)
op_cntrmask(index)
op_div(index)
op_drop(index)
op_dup(index)
op_endchar(index)
op_eq(index)
op_exch(index)
op_get(index)
op_hintmask(index)
op_hmoveto(index)
op_hstem(index)
op_hstemhm(index)
op_ifelse(index)
op_ignore(index)
op_index(index)
op_load(index)
op_mul(index)
op_neg(index)
op_not(index)
op_or(index)
op_put(index)
op_random(index)
op_return(index)
op_rmoveto(index)
op_roll(index)
op_sqrt(index)
op_store(index)
op_sub(index)
op_vmoveto(index)
op_vsindex(index)
op_vstem(index)
op_vstemhm(index)
pop()
popall()
popallWidth(evenOdd=0)
push(value)
reset()
fontTools.misc.psCharStrings.buildOperatorDict(operatorList)
fontTools.misc.psCharStrings.calcSubrBias(subrs)
fontTools.misc.psCharStrings.encodeFixed(f, pack=<built-in function pack>)

For T2 only

fontTools.misc.psCharStrings.encodeFloat(f)
fontTools.misc.psCharStrings.encodeIntCFF(value, fourByteOp=b'\x1d', bytechr=<function bytechr>, pack=<built-in function pack>, unpack=<built-in function unpack>, twoByteOp=b'\x1c')
fontTools.misc.psCharStrings.encodeIntT1(value, fourByteOp=b'\xff', bytechr=<function bytechr>, pack=<built-in function pack>, unpack=<built-in function unpack>, twoByteOp=None)
fontTools.misc.psCharStrings.encodeIntT2(value, fourByteOp=None, bytechr=<function bytechr>, pack=<built-in function pack>, unpack=<built-in function unpack>, twoByteOp=b'\x1c')
fontTools.misc.psCharStrings.getIntEncoder(format)
fontTools.misc.psCharStrings.read_byte(self, b0, data, index)
fontTools.misc.psCharStrings.read_fixed1616(self, b0, data, index)
fontTools.misc.psCharStrings.read_longInt(self, b0, data, index)
fontTools.misc.psCharStrings.read_operator(self, b0, data, index)
fontTools.misc.psCharStrings.read_realNumber(self, b0, data, index)
fontTools.misc.psCharStrings.read_reserved(self, b0, data, index)
fontTools.misc.psCharStrings.read_shortInt(self, b0, data, index)
fontTools.misc.psCharStrings.read_smallInt1(self, b0, data, index)
fontTools.misc.psCharStrings.read_smallInt2(self, b0, data, index)

psLib

exception fontTools.misc.psLib.PSError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.misc.psLib.PSInterpreter(encoding='ascii')
call_procedure(proc)
close()

Remove circular references.

do_comment(token)
do_hexstring(token)
do_literal(token)
do_makearray()
do_special(token)
do_string(token)
do_token(token, int=<class 'int'>, float=<class 'float'>, ps_name=<class 'fontTools.misc.psOperators.ps_name'>, ps_integer=<class 'fontTools.misc.psOperators.ps_integer'>, ps_real=<class 'fontTools.misc.psOperators.ps_real'>)
fillsystemdict()
handle_object(object)
interpret(data, getattr=<built-in function getattr>)
pop(*types)
proc_bind(proc)
ps_anchorsearch()
ps_array()
ps_astore()
ps_begin()
ps_bind()
ps_cleartomark()
ps_closefile()
ps_count()
ps_currentdict()
ps_currentfile()
ps_cvn()
ps_cvx()
ps_def()
ps_definefont()
ps_dict()
ps_dup()
ps_eexec()
ps_end()
ps_eq()
ps_exch()
ps_exec()
ps_executeonly()
ps_findfont()
ps_for()
ps_forall()
ps_get()
ps_getinterval()
ps_if()
ps_ifelse()
ps_index()
ps_known()
ps_load()
ps_matrix()
ps_ne()
ps_noaccess()
ps_not()
ps_pop()
ps_print()
ps_put()
ps_putinterval()
ps_readonly()
ps_readstring(ps_boolean=<class 'fontTools.misc.psOperators.ps_boolean'>, len=<built-in function len>)
ps_store()
ps_string()
ps_systemdict()
ps_type()
ps_userdict()
ps_where()
push(object)
resolve_name(name)
suckoperators(systemdict, klass)
exception fontTools.misc.psLib.PSTokenError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.misc.psLib.PSTokenizer(buf=b'', encoding='ascii')
close()
getnexttoken(len=<built-in function len>, ps_special=b'()<>[]{}%', stringmatch=<built-in method match of re.Pattern object>, hexstringmatch=<built-in method match of re.Pattern object>, commentmatch=<built-in method match of re.Pattern object>, endmatch=<built-in method match of re.Pattern object>)
read(n=-1)

Read at most ‘n’ bytes from the buffer, or less if the read hits EOF before obtaining ‘n’ bytes. If ‘n’ is negative or omitted, read all data until EOF is reached.

skipwhite(whitematch=<built-in method match of re.Pattern object>)
starteexec()
stopeexec()
fontTools.misc.psLib.suckfont(data, encoding='ascii')
fontTools.misc.psLib.unpack_item(item)

psOperators

class fontTools.misc.psOperators.PSOperators
proc_bind(proc)
ps_anchorsearch()
ps_array()
ps_astore()
ps_begin()
ps_bind()
ps_cleartomark()
ps_closefile()
ps_count()
ps_currentdict()
ps_currentfile()
ps_cvn()
ps_cvx()
ps_def()
ps_definefont()
ps_dict()
ps_dup()
ps_eexec()
ps_end()
ps_eq()
ps_exch()
ps_exec()
ps_executeonly()
ps_findfont()
ps_for()
ps_forall()
ps_get()
ps_getinterval()
ps_if()
ps_ifelse()
ps_index()
ps_known()
ps_load()
ps_matrix()
ps_ne()
ps_noaccess()
ps_not()
ps_pop()
ps_print()
ps_put()
ps_putinterval()
ps_readonly()
ps_readstring(ps_boolean=<class 'fontTools.misc.psOperators.ps_boolean'>, len=<built-in function len>)
ps_store()
ps_string()
ps_systemdict()
ps_type()
ps_userdict()
ps_where()
class fontTools.misc.psOperators.ps_array(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_boolean(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_dict(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_file(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_font(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_integer(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_literal(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_mark
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_name(value)
access = 0
literal = 0
value = None
class fontTools.misc.psOperators.ps_null
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_object(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_operator(name, function)
access = 0
literal = 0
value = None
class fontTools.misc.psOperators.ps_procedure(value)
access = 0
literal = 0
value = None
class fontTools.misc.psOperators.ps_procmark
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_real(value)
access = 0
literal = 1
value = None
class fontTools.misc.psOperators.ps_string(value)
access = 0
literal = 1
value = None

sstruct

sstruct.py – SuperStruct

Higher level layer on top of the struct module, enabling to bind names to struct elements. The interface is similar to struct, except the objects passed and returned are not tuples (or argument lists), but dictionaries or instances.

Just like struct, we use fmt strings to describe a data structure, except we use one line per element. Lines are separated by newlines or semi-colons. Each line contains either one of the special struct characters (‘@’, ‘=’, ‘<’, ‘>’ or ‘!’) or a ‘name:formatchar’ combo (eg. ‘myFloat:f’). Repetitions, like the struct module offers them are not useful in this context, except for fixed length strings (eg. ‘myInt:5h’ is not allowed but ‘myString:5s’ is). The ‘x’ fmt character (pad byte) is treated as ‘special’, since it is by definition anonymous. Extra whitespace is allowed everywhere.

The sstruct module offers one feature that the “normal” struct module doesn’t: support for fixed point numbers. These are spelled as “n.mF”, where n is the number of bits before the point, and m the number of bits after the point. Fixed point numbers get converted to floats.

pack(fmt, object):

‘object’ is either a dictionary or an instance (or actually anything that has a __dict__ attribute). If it is a dictionary, its keys are used for names. If it is an instance, it’s attributes are used to grab struct elements from. Returns a string containing the data.

unpack(fmt, data, object=None)

If ‘object’ is omitted (or None), a new dictionary will be returned. If ‘object’ is a dictionary, it will be used to add struct elements to. If it is an instance (or in fact anything that has a __dict__ attribute), an attribute will be added for each struct element. In the latter two cases, ‘object’ itself is returned.

unpack2(fmt, data, object=None)

Convenience function. Same as unpack, except data may be longer than needed. The returned value is a tuple: (object, leftoverdata).

calcsize(fmt)

like struct.calcsize(), but uses our own fmt strings: it returns the size of the data in bytes.

exception fontTools.misc.sstruct.Error
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

fontTools.misc.sstruct.calcsize(fmt)
fontTools.misc.sstruct.getformat(fmt, keep_pad_byte=False)
fontTools.misc.sstruct.pack(fmt, obj)
fontTools.misc.sstruct.unpack(fmt, data, obj=None)
fontTools.misc.sstruct.unpack2(fmt, data, obj=None)

symfont

testTools

Helpers for writing unit tests.

class fontTools.misc.testTools.DataFilesHandler(methodName)
classmethod addClassCleanup(function, /, *args, **kwargs)

Same as addCleanup, except the cleanup items are called even if setUpClass fails (unlike tearDownClass).

addCleanup(function, /, *args, **kwargs)

Add a function, with arguments, to be called when the test is completed. Functions added are called on a LIFO basis and are called after tearDown on test failure or success.

Cleanup items are called even if setUp fails (unlike tearDown).

addTypeEqualityFunc(typeobj, function)

Add a type specific assertEqual style function to compare a type.

This method is for use by TestCase subclasses that need to register their own type equality functions to provide nicer error messages.

Parameters:
  • typeobj – The data type to call this function on when both values are of the same type in assertEqual().

  • function – The callable taking two arguments and an optional msg= argument that raises self.failureException with a useful error message when the two arguments are not equal.

assertAlmostEqual(first, second, places=None, msg=None, delta=None)

Fail if the two objects are unequal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero, or by comparing that the difference between the two objects is more than the given delta.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most significant digit).

If the two objects compare equal then they will automatically compare almost equal.

assertAlmostEquals(**kwargs)
assertCountEqual(first, second, msg=None)

Asserts that two iterables have the same elements, the same number of times, without regard to order.

self.assertEqual(Counter(list(first)),

Counter(list(second)))

Example:
  • [0, 1, 1] and [1, 0, 1] compare equal.

  • [0, 0, 1] and [0, 1] compare unequal.

assertDictContainsSubset(subset, dictionary, msg=None)

Checks whether dictionary is a superset of subset.

assertDictEqual(d1, d2, msg=None)
assertEqual(first, second, msg=None)

Fail if the two objects are unequal as determined by the ‘==’ operator.

assertEquals(**kwargs)
assertFalse(expr, msg=None)

Check that the expression is false.

assertGreater(a, b, msg=None)

Just like self.assertTrue(a > b), but with a nicer default message.

assertGreaterEqual(a, b, msg=None)

Just like self.assertTrue(a >= b), but with a nicer default message.

assertIn(member, container, msg=None)

Just like self.assertTrue(a in b), but with a nicer default message.

assertIs(expr1, expr2, msg=None)

Just like self.assertTrue(a is b), but with a nicer default message.

assertIsInstance(obj, cls, msg=None)

Same as self.assertTrue(isinstance(obj, cls)), with a nicer default message.

assertIsNone(obj, msg=None)

Same as self.assertTrue(obj is None), with a nicer default message.

assertIsNot(expr1, expr2, msg=None)

Just like self.assertTrue(a is not b), but with a nicer default message.

assertIsNotNone(obj, msg=None)

Included for symmetry with assertIsNone.

assertLess(a, b, msg=None)

Just like self.assertTrue(a < b), but with a nicer default message.

assertLessEqual(a, b, msg=None)

Just like self.assertTrue(a <= b), but with a nicer default message.

assertListEqual(list1, list2, msg=None)

A list-specific equality assertion.

Parameters:
  • list1 – The first list to compare.

  • list2 – The second list to compare.

  • msg – Optional message to use on failure instead of a list of differences.

assertLogs(logger=None, level=None)

Fail unless a log message of level level or higher is emitted on logger_name or its children. If omitted, level defaults to INFO and logger defaults to the root logger.

This method must be used as a context manager, and will yield a recording object with two attributes: output and records. At the end of the context manager, the output attribute will be a list of the matching formatted log messages and the records attribute will be a list of the corresponding LogRecord objects.

Example:

with self.assertLogs('foo', level='INFO') as cm:
    logging.getLogger('foo').info('first message')
    logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
                             'ERROR:foo.bar:second message'])
assertMultiLineEqual(first, second, msg=None)

Assert that two multi-line strings are equal.

assertNoLogs(logger=None, level=None)

Fail unless no log messages of level level or higher are emitted on logger_name or its children.

This method must be used as a context manager.

assertNotAlmostEqual(first, second, places=None, msg=None, delta=None)

Fail if the two objects are equal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero, or by comparing that the difference between the two objects is less than the given delta.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most significant digit).

Objects that are equal automatically fail.

assertNotAlmostEquals(**kwargs)
assertNotEqual(first, second, msg=None)

Fail if the two objects are equal as determined by the ‘!=’ operator.

assertNotEquals(**kwargs)
assertNotIn(member, container, msg=None)

Just like self.assertTrue(a not in b), but with a nicer default message.

assertNotIsInstance(obj, cls, msg=None)

Included for symmetry with assertIsInstance.

assertNotRegex(text, unexpected_regex, msg=None)

Fail the test if the text matches the regular expression.

assertNotRegexpMatches(**kwargs)
assertRaises(expected_exception, *args, **kwargs)

Fail unless an exception of class expected_exception is raised by the callable when invoked with specified positional and keyword arguments. If a different type of exception is raised, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception.

If called with the callable and arguments omitted, will return a context object used like this:

with self.assertRaises(SomeException):
    do_something()

An optional keyword argument ‘msg’ can be provided when assertRaises is used as a context object.

The context manager keeps a reference to the exception as the ‘exception’ attribute. This allows you to inspect the exception after the assertion:

with self.assertRaises(SomeException) as cm:
    do_something()
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)
assertRaisesRegex(expected_exception, expected_regex, *args, **kwargs)

Asserts that the message in a raised exception matches a regex.

Parameters:
  • expected_exception – Exception class expected to be raised.

  • expected_regex – Regex (re.Pattern object or string) expected to be found in error message.

  • args – Function to be called and extra positional args.

  • kwargs – Extra kwargs.

  • msg – Optional message used in case of failure. Can only be used when assertRaisesRegex is used as a context manager.

assertRaisesRegexp(**kwargs)
assertRegex(text, expected_regex, msg=None)

Fail the test unless the text matches the regular expression.

assertRegexpMatches(**kwargs)
assertSequenceEqual(seq1, seq2, msg=None, seq_type=None)

An equality assertion for ordered sequences (like lists and tuples).

For the purposes of this function, a valid ordered sequence type is one which can be indexed, has a length, and has an equality operator.

Parameters:
  • seq1 – The first sequence to compare.

  • seq2 – The second sequence to compare.

  • seq_type – The expected datatype of the sequences, or None if no datatype should be enforced.

  • msg – Optional message to use on failure instead of a list of differences.

assertSetEqual(set1, set2, msg=None)

A set-specific equality assertion.

Parameters:
  • set1 – The first set to compare.

  • set2 – The second set to compare.

  • msg – Optional message to use on failure instead of a list of differences.

assertSetEqual uses ducktyping to support different types of sets, and is optimized for sets specifically (parameters must support a difference method).

assertTrue(expr, msg=None)

Check that the expression is true.

assertTupleEqual(tuple1, tuple2, msg=None)

A tuple-specific equality assertion.

Parameters:
  • tuple1 – The first tuple to compare.

  • tuple2 – The second tuple to compare.

  • msg – Optional message to use on failure instead of a list of differences.

assertWarns(expected_warning, *args, **kwargs)

Fail unless a warning of class warnClass is triggered by the callable when invoked with specified positional and keyword arguments. If a different type of warning is triggered, it will not be handled: depending on the other warning filtering rules in effect, it might be silenced, printed out, or raised as an exception.

If called with the callable and arguments omitted, will return a context object used like this:

with self.assertWarns(SomeWarning):
    do_something()

An optional keyword argument ‘msg’ can be provided when assertWarns is used as a context object.

The context manager keeps a reference to the first matching warning as the ‘warning’ attribute; similarly, the ‘filename’ and ‘lineno’ attributes give you information about the line of Python code from which the warning was triggered. This allows you to inspect the warning after the assertion:

with self.assertWarns(SomeWarning) as cm:
    do_something()
the_warning = cm.warning
self.assertEqual(the_warning.some_attribute, 147)
assertWarnsRegex(expected_warning, expected_regex, *args, **kwargs)

Asserts that the message in a triggered warning matches a regexp. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression are considered successful matches.

Parameters:
  • expected_warning – Warning class expected to be triggered.

  • expected_regex – Regex (re.Pattern object or string) expected to be found in error message.

  • args – Function to be called and extra positional args.

  • kwargs – Extra kwargs.

  • msg – Optional message used in case of failure. Can only be used when assertWarnsRegex is used as a context manager.

assert_(**kwargs)
countTestCases()
debug()

Run the test without collecting errors in a TestResult

defaultTestResult()
classmethod doClassCleanups()

Execute all class cleanup functions. Normally called for you after tearDownClass.

doCleanups()

Execute all cleanup functions. Normally called for you after tearDown.

classmethod enterClassContext(cm)

Same as enterContext, but class-wide.

enterContext(cm)

Enters the supplied context manager.

If successful, also adds its __exit__ method as a cleanup function and returns the result of the __enter__ method.

fail(msg=None)

Fail immediately, with the given message.

failIf(**kwargs)
failIfAlmostEqual(**kwargs)
failIfEqual(**kwargs)
failUnless(**kwargs)
failUnlessAlmostEqual(**kwargs)
failUnlessEqual(**kwargs)
failUnlessRaises(**kwargs)
failureException

alias of AssertionError

getpath(testfile)
id()
longMessage = True
maxDiff = 640
run(result=None)
setUp()

Hook method for setting up the test fixture before exercising it.

classmethod setUpClass()

Hook method for setting up class fixture before running tests in the class.

shortDescription()

Returns a one-line description of the test, or None if no description has been provided.

The default implementation of this method returns the first line of the specified test method’s docstring.

skipTest(reason)

Skip this test.

subTest(msg=<object object>, **params)

Return a context manager that will return the enclosed block of code in a subtest identified by the optional message and keyword parameters. A failure in the subtest marks the test case as failed but resumes execution at the end of the enclosed block, allowing further test code to be executed.

tearDown()

Hook method for deconstructing the test fixture after testing it.

classmethod tearDownClass()

Hook method for deconstructing the class fixture after running all tests in the class.

temp_dir()
temp_font(font_path, file_name)
class fontTools.misc.testTools.FakeFont(glyphs)
get(tag, default=None)
getGlyphID(name)
getGlyphIDMany(lst)
getGlyphName(glyphID)
getGlyphNameMany(lst)
getGlyphNames()
getGlyphOrder()
getReverseGlyphMap()
class fontTools.misc.testTools.MockFont

A font-like object that automatically adds any looked up glyphname to its glyphOrder.

getGlyphID(glyph)
getGlyphName(gid)
getGlyphOrder()
getReverseGlyphMap()
class fontTools.misc.testTools.TestCase(methodName)
classmethod addClassCleanup(function, /, *args, **kwargs)

Same as addCleanup, except the cleanup items are called even if setUpClass fails (unlike tearDownClass).

addCleanup(function, /, *args, **kwargs)

Add a function, with arguments, to be called when the test is completed. Functions added are called on a LIFO basis and are called after tearDown on test failure or success.

Cleanup items are called even if setUp fails (unlike tearDown).

addTypeEqualityFunc(typeobj, function)

Add a type specific assertEqual style function to compare a type.

This method is for use by TestCase subclasses that need to register their own type equality functions to provide nicer error messages.

Parameters:
  • typeobj – The data type to call this function on when both values are of the same type in assertEqual().

  • function – The callable taking two arguments and an optional msg= argument that raises self.failureException with a useful error message when the two arguments are not equal.

assertAlmostEqual(first, second, places=None, msg=None, delta=None)

Fail if the two objects are unequal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero, or by comparing that the difference between the two objects is more than the given delta.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most significant digit).

If the two objects compare equal then they will automatically compare almost equal.

assertAlmostEquals(**kwargs)
assertCountEqual(first, second, msg=None)

Asserts that two iterables have the same elements, the same number of times, without regard to order.

self.assertEqual(Counter(list(first)),

Counter(list(second)))

Example:
  • [0, 1, 1] and [1, 0, 1] compare equal.

  • [0, 0, 1] and [0, 1] compare unequal.

assertDictContainsSubset(subset, dictionary, msg=None)

Checks whether dictionary is a superset of subset.

assertDictEqual(d1, d2, msg=None)
assertEqual(first, second, msg=None)

Fail if the two objects are unequal as determined by the ‘==’ operator.

assertEquals(**kwargs)
assertFalse(expr, msg=None)

Check that the expression is false.

assertGreater(a, b, msg=None)

Just like self.assertTrue(a > b), but with a nicer default message.

assertGreaterEqual(a, b, msg=None)

Just like self.assertTrue(a >= b), but with a nicer default message.

assertIn(member, container, msg=None)

Just like self.assertTrue(a in b), but with a nicer default message.

assertIs(expr1, expr2, msg=None)

Just like self.assertTrue(a is b), but with a nicer default message.

assertIsInstance(obj, cls, msg=None)

Same as self.assertTrue(isinstance(obj, cls)), with a nicer default message.

assertIsNone(obj, msg=None)

Same as self.assertTrue(obj is None), with a nicer default message.

assertIsNot(expr1, expr2, msg=None)

Just like self.assertTrue(a is not b), but with a nicer default message.

assertIsNotNone(obj, msg=None)

Included for symmetry with assertIsNone.

assertLess(a, b, msg=None)

Just like self.assertTrue(a < b), but with a nicer default message.

assertLessEqual(a, b, msg=None)

Just like self.assertTrue(a <= b), but with a nicer default message.

assertListEqual(list1, list2, msg=None)

A list-specific equality assertion.

Parameters:
  • list1 – The first list to compare.

  • list2 – The second list to compare.

  • msg – Optional message to use on failure instead of a list of differences.

assertLogs(logger=None, level=None)

Fail unless a log message of level level or higher is emitted on logger_name or its children. If omitted, level defaults to INFO and logger defaults to the root logger.

This method must be used as a context manager, and will yield a recording object with two attributes: output and records. At the end of the context manager, the output attribute will be a list of the matching formatted log messages and the records attribute will be a list of the corresponding LogRecord objects.

Example:

with self.assertLogs('foo', level='INFO') as cm:
    logging.getLogger('foo').info('first message')
    logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
                             'ERROR:foo.bar:second message'])
assertMultiLineEqual(first, second, msg=None)

Assert that two multi-line strings are equal.

assertNoLogs(logger=None, level=None)

Fail unless no log messages of level level or higher are emitted on logger_name or its children.

This method must be used as a context manager.

assertNotAlmostEqual(first, second, places=None, msg=None, delta=None)

Fail if the two objects are equal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero, or by comparing that the difference between the two objects is less than the given delta.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most significant digit).

Objects that are equal automatically fail.

assertNotAlmostEquals(**kwargs)
assertNotEqual(first, second, msg=None)

Fail if the two objects are equal as determined by the ‘!=’ operator.

assertNotEquals(**kwargs)
assertNotIn(member, container, msg=None)

Just like self.assertTrue(a not in b), but with a nicer default message.

assertNotIsInstance(obj, cls, msg=None)

Included for symmetry with assertIsInstance.

assertNotRegex(text, unexpected_regex, msg=None)

Fail the test if the text matches the regular expression.

assertNotRegexpMatches(**kwargs)
assertRaises(expected_exception, *args, **kwargs)

Fail unless an exception of class expected_exception is raised by the callable when invoked with specified positional and keyword arguments. If a different type of exception is raised, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception.

If called with the callable and arguments omitted, will return a context object used like this:

with self.assertRaises(SomeException):
    do_something()

An optional keyword argument ‘msg’ can be provided when assertRaises is used as a context object.

The context manager keeps a reference to the exception as the ‘exception’ attribute. This allows you to inspect the exception after the assertion:

with self.assertRaises(SomeException) as cm:
    do_something()
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)
assertRaisesRegex(expected_exception, expected_regex, *args, **kwargs)

Asserts that the message in a raised exception matches a regex.

Parameters:
  • expected_exception – Exception class expected to be raised.

  • expected_regex – Regex (re.Pattern object or string) expected to be found in error message.

  • args – Function to be called and extra positional args.

  • kwargs – Extra kwargs.

  • msg – Optional message used in case of failure. Can only be used when assertRaisesRegex is used as a context manager.

assertRaisesRegexp(**kwargs)
assertRegex(text, expected_regex, msg=None)

Fail the test unless the text matches the regular expression.

assertRegexpMatches(**kwargs)
assertSequenceEqual(seq1, seq2, msg=None, seq_type=None)

An equality assertion for ordered sequences (like lists and tuples).

For the purposes of this function, a valid ordered sequence type is one which can be indexed, has a length, and has an equality operator.

Parameters:
  • seq1 – The first sequence to compare.

  • seq2 – The second sequence to compare.

  • seq_type – The expected datatype of the sequences, or None if no datatype should be enforced.

  • msg – Optional message to use on failure instead of a list of differences.

assertSetEqual(set1, set2, msg=None)

A set-specific equality assertion.

Parameters:
  • set1 – The first set to compare.

  • set2 – The second set to compare.

  • msg – Optional message to use on failure instead of a list of differences.

assertSetEqual uses ducktyping to support different types of sets, and is optimized for sets specifically (parameters must support a difference method).

assertTrue(expr, msg=None)

Check that the expression is true.

assertTupleEqual(tuple1, tuple2, msg=None)

A tuple-specific equality assertion.

Parameters:
  • tuple1 – The first tuple to compare.

  • tuple2 – The second tuple to compare.

  • msg – Optional message to use on failure instead of a list of differences.

assertWarns(expected_warning, *args, **kwargs)

Fail unless a warning of class warnClass is triggered by the callable when invoked with specified positional and keyword arguments. If a different type of warning is triggered, it will not be handled: depending on the other warning filtering rules in effect, it might be silenced, printed out, or raised as an exception.

If called with the callable and arguments omitted, will return a context object used like this:

with self.assertWarns(SomeWarning):
    do_something()

An optional keyword argument ‘msg’ can be provided when assertWarns is used as a context object.

The context manager keeps a reference to the first matching warning as the ‘warning’ attribute; similarly, the ‘filename’ and ‘lineno’ attributes give you information about the line of Python code from which the warning was triggered. This allows you to inspect the warning after the assertion:

with self.assertWarns(SomeWarning) as cm:
    do_something()
the_warning = cm.warning
self.assertEqual(the_warning.some_attribute, 147)
assertWarnsRegex(expected_warning, expected_regex, *args, **kwargs)

Asserts that the message in a triggered warning matches a regexp. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression are considered successful matches.

Parameters:
  • expected_warning – Warning class expected to be triggered.

  • expected_regex – Regex (re.Pattern object or string) expected to be found in error message.

  • args – Function to be called and extra positional args.

  • kwargs – Extra kwargs.

  • msg – Optional message used in case of failure. Can only be used when assertWarnsRegex is used as a context manager.

assert_(**kwargs)
countTestCases()
debug()

Run the test without collecting errors in a TestResult

defaultTestResult()
classmethod doClassCleanups()

Execute all class cleanup functions. Normally called for you after tearDownClass.

doCleanups()

Execute all cleanup functions. Normally called for you after tearDown.

classmethod enterClassContext(cm)

Same as enterContext, but class-wide.

enterContext(cm)

Enters the supplied context manager.

If successful, also adds its __exit__ method as a cleanup function and returns the result of the __enter__ method.

fail(msg=None)

Fail immediately, with the given message.

failIf(**kwargs)
failIfAlmostEqual(**kwargs)
failIfEqual(**kwargs)
failUnless(**kwargs)
failUnlessAlmostEqual(**kwargs)
failUnlessEqual(**kwargs)
failUnlessRaises(**kwargs)
failureException

alias of AssertionError

id()
longMessage = True
maxDiff = 640
run(result=None)
setUp()

Hook method for setting up the test fixture before exercising it.

classmethod setUpClass()

Hook method for setting up class fixture before running tests in the class.

shortDescription()

Returns a one-line description of the test, or None if no description has been provided.

The default implementation of this method returns the first line of the specified test method’s docstring.

skipTest(reason)

Skip this test.

subTest(msg=<object object>, **params)

Return a context manager that will return the enclosed block of code in a subtest identified by the optional message and keyword parameters. A failure in the subtest marks the test case as failed but resumes execution at the end of the enclosed block, allowing further test code to be executed.

tearDown()

Hook method for deconstructing the test fixture after testing it.

classmethod tearDownClass()

Hook method for deconstructing the class fixture after running all tests in the class.

class fontTools.misc.testTools.TestXMLReader_
addCharacterData_(data)
endElement_(name)
startElement_(name, attrs)
fontTools.misc.testTools.getXML(func, ttFont=None)

Call the passed toXML function and return the written content as a list of lines (unicode strings). Result is stripped of XML declaration and OS-specific newline characters.

fontTools.misc.testTools.makeXMLWriter(newlinestr='\n')
fontTools.misc.testTools.parseXML(xmlSnippet)

Parses a snippet of XML.

Input can be either a single string (unicode or UTF-8 bytes), or a a sequence of strings.

The result is in the same format that would be returned by XMLReader, but the parser imposes no constraints on the root element so it can be called on small snippets of TTX files.

fontTools.misc.testTools.parseXmlInto(font, parseInto, xmlSnippet)
fontTools.misc.testTools.stripVariableItemsFromTTX(string: str, ttLibVersion: bool = True, checkSumAdjustment: bool = True, modified: bool = True, created: bool = True, sfntVersion: bool = False) str

Strip stuff like ttLibVersion, checksums, timestamps, etc. from TTX dumps.

textTools

fontTools.misc.textTools.py – miscellaneous routines.

class fontTools.misc.textTools.Tag(content)
capitalize()

Return a capitalized version of the string.

More specifically, make the first character have upper case and the rest lower case.

casefold()

Return a version of the string suitable for caseless comparisons.

center(width, fillchar=' ', /)

Return a centered string of length width.

Padding is done using the specified fill character (default is a space).

count(sub[, start[, end]]) int

Return the number of non-overlapping occurrences of substring sub in string S[start:end]. Optional arguments start and end are interpreted as in slice notation.

encode(encoding='utf-8', errors='strict')

Encode the string using the codec registered for encoding.

encoding

The encoding in which to encode the string.

errors

The error handling scheme to use for encoding errors. The default is ‘strict’ meaning that encoding errors raise a UnicodeEncodeError. Other possible values are ‘ignore’, ‘replace’ and ‘xmlcharrefreplace’ as well as any other name registered with codecs.register_error that can handle UnicodeEncodeErrors.

endswith(suffix[, start[, end]]) bool

Return True if S ends with the specified suffix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. suffix can also be a tuple of strings to try.

expandtabs(tabsize=8)

Return a copy where all tab characters are expanded using spaces.

If tabsize is not given, a tab size of 8 characters is assumed.

find(sub[, start[, end]]) int

Return the lowest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.

Return -1 on failure.

format(*args, **kwargs) str

Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces (‘{’ and ‘}’).

format_map(mapping) str

Return a formatted version of S, using substitutions from mapping. The substitutions are identified by braces (‘{’ and ‘}’).

index(sub[, start[, end]]) int

Return the lowest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.

Raises ValueError when the substring is not found.

isalnum()

Return True if the string is an alpha-numeric string, False otherwise.

A string is alpha-numeric if all characters in the string are alpha-numeric and there is at least one character in the string.

isalpha()

Return True if the string is an alphabetic string, False otherwise.

A string is alphabetic if all characters in the string are alphabetic and there is at least one character in the string.

isascii()

Return True if all characters in the string are ASCII, False otherwise.

ASCII characters have code points in the range U+0000-U+007F. Empty string is ASCII too.

isdecimal()

Return True if the string is a decimal string, False otherwise.

A string is a decimal string if all characters in the string are decimal and there is at least one character in the string.

isdigit()

Return True if the string is a digit string, False otherwise.

A string is a digit string if all characters in the string are digits and there is at least one character in the string.

isidentifier()

Return True if the string is a valid Python identifier, False otherwise.

Call keyword.iskeyword(s) to test whether string s is a reserved identifier, such as “def” or “class”.

islower()

Return True if the string is a lowercase string, False otherwise.

A string is lowercase if all cased characters in the string are lowercase and there is at least one cased character in the string.

isnumeric()

Return True if the string is a numeric string, False otherwise.

A string is numeric if all characters in the string are numeric and there is at least one character in the string.

isprintable()

Return True if the string is printable, False otherwise.

A string is printable if all of its characters are considered printable in repr() or if it is empty.

isspace()

Return True if the string is a whitespace string, False otherwise.

A string is whitespace if all characters in the string are whitespace and there is at least one character in the string.

istitle()

Return True if the string is a title-cased string, False otherwise.

In a title-cased string, upper- and title-case characters may only follow uncased characters and lowercase characters only cased ones.

isupper()

Return True if the string is an uppercase string, False otherwise.

A string is uppercase if all cased characters in the string are uppercase and there is at least one cased character in the string.

join(iterable, /)

Concatenate any number of strings.

The string whose method is called is inserted in between each given string. The result is returned as a new string.

Example: ‘.’.join([‘ab’, ‘pq’, ‘rs’]) -> ‘ab.pq.rs’

ljust(width, fillchar=' ', /)

Return a left-justified string of length width.

Padding is done using the specified fill character (default is a space).

lower()

Return a copy of the string converted to lowercase.

lstrip(chars=None, /)

Return a copy of the string with leading whitespace removed.

If chars is given and not None, remove characters in chars instead.

static maketrans()

Return a translation table usable for str.translate().

If there is only one argument, it must be a dictionary mapping Unicode ordinals (integers) or characters to Unicode ordinals, strings or None. Character keys will be then converted to ordinals. If there are two arguments, they must be strings of equal length, and in the resulting dictionary, each character in x will be mapped to the character at the same position in y. If there is a third argument, it must be a string, whose characters will be mapped to None in the result.

partition(sep, /)

Partition the string into three parts using the given separator.

This will search for the separator in the string. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it.

If the separator is not found, returns a 3-tuple containing the original string and two empty strings.

removeprefix(prefix, /)

Return a str with the given prefix string removed if present.

If the string starts with the prefix string, return string[len(prefix):]. Otherwise, return a copy of the original string.

removesuffix(suffix, /)

Return a str with the given suffix string removed if present.

If the string ends with the suffix string and that suffix is not empty, return string[:-len(suffix)]. Otherwise, return a copy of the original string.

replace(old, new, count=-1, /)

Return a copy with all occurrences of substring old replaced by new.

count

Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences.

If the optional argument count is given, only the first count occurrences are replaced.

rfind(sub[, start[, end]]) int

Return the highest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.

Return -1 on failure.

rindex(sub[, start[, end]]) int

Return the highest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.

Raises ValueError when the substring is not found.

rjust(width, fillchar=' ', /)

Return a right-justified string of length width.

Padding is done using the specified fill character (default is a space).

rpartition(sep, /)

Partition the string into three parts using the given separator.

This will search for the separator in the string, starting at the end. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it.

If the separator is not found, returns a 3-tuple containing two empty strings and the original string.

rsplit(sep=None, maxsplit=-1)

Return a list of the substrings in the string, using sep as the separator string.

sep

The separator used to split the string.

When set to None (the default value), will split on any whitespace character (including n r t f and spaces) and will discard empty strings from the result.

maxsplit

Maximum number of splits. -1 (the default value) means no limit.

Splitting starts at the end of the string and works to the front.

rstrip(chars=None, /)

Return a copy of the string with trailing whitespace removed.

If chars is given and not None, remove characters in chars instead.

split(sep=None, maxsplit=-1)

Return a list of the substrings in the string, using sep as the separator string.

sep

The separator used to split the string.

When set to None (the default value), will split on any whitespace character (including n r t f and spaces) and will discard empty strings from the result.

maxsplit

Maximum number of splits. -1 (the default value) means no limit.

Splitting starts at the front of the string and works to the end.

Note, str.split() is mainly useful for data that has been intentionally delimited. With natural text that includes punctuation, consider using the regular expression module.

splitlines(keepends=False)

Return a list of the lines in the string, breaking at line boundaries.

Line breaks are not included in the resulting list unless keepends is given and true.

startswith(prefix[, start[, end]]) bool

Return True if S starts with the specified prefix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. prefix can also be a tuple of strings to try.

strip(chars=None, /)

Return a copy of the string with leading and trailing whitespace removed.

If chars is given and not None, remove characters in chars instead.

swapcase()

Convert uppercase characters to lowercase and lowercase characters to uppercase.

title()

Return a version of the string where each word is titlecased.

More specifically, words start with uppercased characters and all remaining cased characters have lower case.

tobytes()
static transcode(blob)
translate(table, /)

Replace each character in the string using the given translation table.

table

Translation table, which must be a mapping of Unicode ordinals to Unicode ordinals, strings, or None.

The table must implement lookup/indexing via __getitem__, for instance a dictionary or list. If this operation raises LookupError, the character is left untouched. Characters mapped to None are deleted.

upper()

Return a copy of the string converted to uppercase.

zfill(width, /)

Pad a numeric string with zeros on the left, to fill a field of the given width.

The string is never truncated.

fontTools.misc.textTools.binary2num(bin)
fontTools.misc.textTools.bytechr(n)
fontTools.misc.textTools.byteord(c)
fontTools.misc.textTools.bytesjoin(iterable, joiner=b'')
fontTools.misc.textTools.caselessSort(alist)

Return a sorted copy of a list. If there are only strings in the list, it will not consider case.

fontTools.misc.textTools.deHexStr(hexdata)

Convert a hex string to binary data.

fontTools.misc.textTools.hexStr(data)

Convert binary data to a hex string.

fontTools.misc.textTools.num2binary(l, bits=32)
fontTools.misc.textTools.pad(data, size)

Pad byte string ‘data’ with null bytes until its length is a multiple of ‘size’.

>>> len(pad(b'abcd', 4))
4
>>> len(pad(b'abcde', 2))
6
>>> len(pad(b'abcde', 4))
8
>>> pad(b'abcdef', 4) == b'abcdef\x00\x00'
True
fontTools.misc.textTools.readHex(content)

Convert a list of hex strings to binary data.

fontTools.misc.textTools.strjoin(iterable, joiner='')
fontTools.misc.textTools.tobytes(s, encoding='ascii', errors='strict')
fontTools.misc.textTools.tostr(s, encoding='ascii', errors='strict')

timeTools

fontTools.misc.timeTools.py – tools for working with OpenType timestamps.

fontTools.misc.timeTools.asctime(t=None)

Convert a tuple or struct_time representing a time as returned by gmtime() or localtime() to a 24-character string of the following form:

>>> asctime(time.gmtime(0))
'Thu Jan  1 00:00:00 1970'

If t is not provided, the current time as returned by localtime() is used. Locale information is not used by asctime().

This is meant to normalise the output of the built-in time.asctime() across different platforms and Python versions. In Python 3.x, the day of the month is right-justified, whereas on Windows Python 2.7 it is padded with zeros.

See https://github.com/fonttools/fonttools/issues/455

fontTools.misc.timeTools.timestampFromString(value)
fontTools.misc.timeTools.timestampNow()
fontTools.misc.timeTools.timestampSinceEpoch(value)
fontTools.misc.timeTools.timestampToString(value)

transform

Affine 2D transformation matrix class.

The Transform class implements various transformation matrix operations, both on the matrix itself, as well as on 2D coordinates.

Transform instances are effectively immutable: all methods that operate on the transformation itself always return a new instance. This has as the interesting side effect that Transform instances are hashable, ie. they can be used as dictionary keys.

This module exports the following symbols:

Transform

this is the main class

Identity

Transform instance set to the identity transformation

Offset

Convenience function that returns a translating transformation

Scale

Convenience function that returns a scaling transformation

The DecomposedTransform class implements a transformation with separate translate, rotation, scale, skew, and transformation-center components.

Example:
>>> t = Transform(2, 0, 0, 3, 0, 0)
>>> t.transformPoint((100, 100))
(200, 300)
>>> t = Scale(2, 3)
>>> t.transformPoint((100, 100))
(200, 300)
>>> t.transformPoint((0, 0))
(0, 0)
>>> t = Offset(2, 3)
>>> t.transformPoint((100, 100))
(102, 103)
>>> t.transformPoint((0, 0))
(2, 3)
>>> t2 = t.scale(0.5)
>>> t2.transformPoint((100, 100))
(52.0, 53.0)
>>> import math
>>> t3 = t2.rotate(math.pi / 2)
>>> t3.transformPoint((0, 0))
(2.0, 3.0)
>>> t3.transformPoint((100, 100))
(-48.0, 53.0)
>>> t = Identity.scale(0.5).translate(100, 200).skew(0.1, 0.2)
>>> t.transformPoints([(0, 0), (1, 1), (100, 100)])
[(50.0, 100.0), (50.550167336042726, 100.60135501775433), (105.01673360427253, 160.13550177543362)]
>>>
class fontTools.misc.transform.DecomposedTransform(translateX: float = 0, translateY: float = 0, rotation: float = 0, scaleX: float = 1, scaleY: float = 1, skewX: float = 0, skewY: float = 0, tCenterX: float = 0, tCenterY: float = 0)

The DecomposedTransform class implements a transformation with separate translate, rotation, scale, skew, and transformation-center components.

classmethod fromTransform(transform)
rotation: float = 0
scaleX: float = 1
scaleY: float = 1
skewX: float = 0
skewY: float = 0
tCenterX: float = 0
tCenterY: float = 0
toTransform()

Return the Transform() equivalent of this transformation.

Example:
>>> DecomposedTransform(scaleX=2, scaleY=2).toTransform()
<Transform [2 0 0 2 0 0]>
>>>
translateX: float = 0
translateY: float = 0
fontTools.misc.transform.Offset(x=0, y=0)

Return the identity transformation offset by x, y.

Example:
>>> Offset(2, 3)
<Transform [1 0 0 1 2 3]>
>>>
fontTools.misc.transform.Scale(x, y=None)

Return the identity transformation scaled by x, y. The ‘y’ argument may be None, which implies to use the x value for y as well.

Example:
>>> Scale(2, 3)
<Transform [2 0 0 3 0 0]>
>>>
class fontTools.misc.transform.Transform(xx: float = 1, xy: float = 0, yx: float = 0, yy: float = 1, dx: float = 0, dy: float = 0)

2x2 transformation matrix plus offset, a.k.a. Affine transform. Transform instances are immutable: all transforming methods, eg. rotate(), return a new Transform instance.

Example:
>>> t = Transform()
>>> t
<Transform [1 0 0 1 0 0]>
>>> t.scale(2)
<Transform [2 0 0 2 0 0]>
>>> t.scale(2.5, 5.5)
<Transform [2.5 0 0 5.5 0 0]>
>>>
>>> t.scale(2, 3).transformPoint((100, 100))
(200, 300)

Transform’s constructor takes six arguments, all of which are optional, and can be used as keyword arguments:

>>> Transform(12)
<Transform [12 0 0 1 0 0]>
>>> Transform(dx=12)
<Transform [1 0 0 1 12 0]>
>>> Transform(yx=12)
<Transform [1 0 12 1 0 0]>

Transform instances also behave like sequences of length 6:

>>> len(Identity)
6
>>> list(Identity)
[1, 0, 0, 1, 0, 0]
>>> tuple(Identity)
(1, 0, 0, 1, 0, 0)

Transform instances are comparable:

>>> t1 = Identity.scale(2, 3).translate(4, 6)
>>> t2 = Identity.translate(8, 18).scale(2, 3)
>>> t1 == t2
1

But beware of floating point rounding errors:

>>> t1 = Identity.scale(0.2, 0.3).translate(0.4, 0.6)
>>> t2 = Identity.translate(0.08, 0.18).scale(0.2, 0.3)
>>> t1
<Transform [0.2 0 0 0.3 0.08 0.18]>
>>> t2
<Transform [0.2 0 0 0.3 0.08 0.18]>
>>> t1 == t2
0

Transform instances are hashable, meaning you can use them as keys in dictionaries:

>>> d = {Scale(12, 13): None}
>>> d
{<Transform [12 0 0 13 0 0]>: None}

But again, beware of floating point rounding errors:

>>> t1 = Identity.scale(0.2, 0.3).translate(0.4, 0.6)
>>> t2 = Identity.translate(0.08, 0.18).scale(0.2, 0.3)
>>> t1
<Transform [0.2 0 0 0.3 0.08 0.18]>
>>> t2
<Transform [0.2 0 0 0.3 0.08 0.18]>
>>> d = {t1: None}
>>> d
{<Transform [0.2 0 0 0.3 0.08 0.18]>: None}
>>> d[t2]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
KeyError: <Transform [0.2 0 0 0.3 0.08 0.18]>
count(value, /)

Return number of occurrences of value.

dx: float

Alias for field number 4

dy: float

Alias for field number 5

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

inverse()

Return the inverse transformation.

Example:
>>> t = Identity.translate(2, 3).scale(4, 5)
>>> t.transformPoint((10, 20))
(42, 103)
>>> it = t.inverse()
>>> it.transformPoint((42, 103))
(10.0, 20.0)
>>>
reverseTransform(other)

Return a new transformation, which is the other transformation transformed by self. self.reverseTransform(other) is equivalent to other.transform(self).

Example:
>>> t = Transform(2, 0, 0, 3, 1, 6)
>>> t.reverseTransform((4, 3, 2, 1, 5, 6))
<Transform [8 6 6 3 21 15]>
>>> Transform(4, 3, 2, 1, 5, 6).transform((2, 0, 0, 3, 1, 6))
<Transform [8 6 6 3 21 15]>
>>>
rotate(angle)

Return a new transformation, rotated by ‘angle’ (radians).

Example:
>>> import math
>>> t = Transform()
>>> t.rotate(math.pi / 2)
<Transform [0 1 -1 0 0 0]>
>>>
scale(x=1, y=None)

Return a new transformation, scaled by x, y. The ‘y’ argument may be None, which implies to use the x value for y as well.

Example:
>>> t = Transform()
>>> t.scale(5)
<Transform [5 0 0 5 0 0]>
>>> t.scale(5, 6)
<Transform [5 0 0 6 0 0]>
>>>
skew(x=0, y=0)

Return a new transformation, skewed by x and y.

Example:
>>> import math
>>> t = Transform()
>>> t.skew(math.pi / 4)
<Transform [1 0 1 1 0 0]>
>>>
toDecomposed() DecomposedTransform

Decompose into a DecomposedTransform.

toPS()

Return a PostScript representation

Example:
>>> t = Identity.scale(2, 3).translate(4, 5)
>>> t.toPS()
'[2 0 0 3 8 15]'
>>>
transform(other)

Return a new transformation, transformed by another transformation.

Example:
>>> t = Transform(2, 0, 0, 3, 1, 6)
>>> t.transform((4, 3, 2, 1, 5, 6))
<Transform [8 9 4 3 11 24]>
>>>
transformPoint(p)

Transform a point.

Example:
>>> t = Transform()
>>> t = t.scale(2.5, 5.5)
>>> t.transformPoint((100, 100))
(250.0, 550.0)
transformPoints(points)

Transform a list of points.

Example:
>>> t = Scale(2, 3)
>>> t.transformPoints([(0, 0), (0, 100), (100, 100), (100, 0)])
[(0, 0), (0, 300), (200, 300), (200, 0)]
>>>
transformVector(v)

Transform an (dx, dy) vector, treating translation as zero.

Example:
>>> t = Transform(2, 0, 0, 2, 10, 20)
>>> t.transformVector((3, -4))
(6, -8)
>>>
transformVectors(vectors)

Transform a list of (dx, dy) vector, treating translation as zero.

Example:
>>> t = Transform(2, 0, 0, 2, 10, 20)
>>> t.transformVectors([(3, -4), (5, -6)])
[(6, -8), (10, -12)]
>>>
translate(x=0, y=0)

Return a new transformation, translated (offset) by x, y.

Example:
>>> t = Transform()
>>> t.translate(20, 30)
<Transform [1 0 0 1 20 30]>
>>>
xx: float

Alias for field number 0

xy: float

Alias for field number 1

yx: float

Alias for field number 2

yy: float

Alias for field number 3

xmlReader

class fontTools.misc.xmlReader.ProgressPrinter(title, maxval=100)
increment(val=1)
set(val, maxval=None)
setLabel(text)
exception fontTools.misc.xmlReader.TTXParseError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.misc.xmlReader.XMLReader(fileOrPath, ttFont, progress=None, quiet=None, contentOnly=False)
close()
read(rootless=False)

xmlWriter

xmlWriter.py – Simple XML authoring class

class fontTools.misc.xmlWriter.XMLWriter(fileOrPath, indentwhite='  ', idlefunc=None, encoding='utf_8', newlinestr='\n')
begintag(_TAG_, *args, **kwargs)
close()
comment(data)
dedent()
dumphex(data)
endtag(_TAG_)
indent()
newline()
simpletag(_TAG_, *args, **kwargs)
stringifyattrs(*args, **kwargs)
write(string, indent=True)

Writes text.

write8bit(data, strip=False)

Writes a bytes() sequence into the XML, escaping non-ASCII bytes. When this is read in xmlReader, the original bytes can be recovered by encoding to ‘latin-1’.

write_noindent(string)

Writes text without indentation.

writecdata(string)

Writes text in a CDATA section.

fontTools.misc.xmlWriter.escape(data)
fontTools.misc.xmlWriter.escape8bit(data)

Input is Unicode string.

fontTools.misc.xmlWriter.escapeattr(data)
fontTools.misc.xmlWriter.hexStr(s)

mtiLib: Read Monotype FontDame source files

FontTools provides support for reading the OpenType layout tables produced by Monotype’s FontDame and Font Chef font editors. These tables are written in a simple textual format. The mtiLib library parses these text files and creates table objects representing their contents.

Additionally, fonttools mtiLib will convert a text file to TTX XML.

class fontTools.mtiLib.DeferredMapping
clear() None.  Remove all items from D.
copy() a shallow copy of D
fromkeys(value=None, /)

Create a new dictionary with keys from iterable and values set to value.

get(key, default=None, /)

Return the value for key if key is in the dictionary, else default.

items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
pop(k[, d]) v, remove specified key and return the corresponding value.

If the key is not found, return the default if given; otherwise, raise a KeyError.

popitem()

Remove and return a (key, value) pair as a 2-tuple.

Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.

setdefault(key, default=None, /)

Insert key with a value of default if key is not in the dictionary.

Return the value for key if key is in the dictionary, else default.

update([E, ]**F) None.  Update D from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values() an object providing a view on D's values
exception fontTools.mtiLib.FeatureNotFoundError
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.mtiLib.LookupNotFoundError
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.mtiLib.MtiLibError
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.mtiLib.ReferenceNotFoundError
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

fontTools.mtiLib.build(f, font, tableTag=None)

Convert a Monotype font layout file to an OpenType layout object

A font object must be passed, but this may be a “dummy” font; it is only used for sorting glyph sets when making coverage tables and to hold the OpenType layout table while it is being built.

Parameters:
  • f – A file object.

  • font (TTFont) – A font object.

  • tableTag (string) – If provided, asserts that the file contains data for the given OpenType table.

Returns:

An object representing the table. (e.g. table_G_S_U_B_)

fontTools.mtiLib.main(args=None, font=None)

Convert a FontDame OTL file to TTX XML

Writes XML output to stdout.

Parameters:

args – Command line arguments (--font, --table, input files).

otlLib: Routines for working with OpenType Layout

The fontTools.otlLib library provides routines to help you create the subtables and other data structures you need when you are editing a font’s GSUB and GPOS tables: substitution and positioning rules, anchors, lookups, coverage tables and so on.

High-level OpenType Layout Lookup Builders

class fontTools.otlLib.builder.AlternateSubstBuilder(font, location)

Builds an Alternate Substitution (GSUB3) lookup.

Users are expected to manually add alternate glyph substitutions to the alternates attribute after the object has been initialized, e.g.:

builder.alternates["A"] = ["A.alt1", "A.alt2"]
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

alternates

An ordered dictionary of alternates, mapping glyph names to a list of names of alternates.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the alternate substitution lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.ChainContextPosBuilder(font, location)

Builds a Chained Contextual Positioning (GPOS8) lookup.

Users are expected to manually add rules to the rules attribute after the object has been initialized, e.g.:

# pos [A B] [C D] x' lookup lu1 y' z' lookup lu2 E;

prefix  = [ ["A", "B"], ["C", "D"] ]
suffix  = [ ["E"] ]
glyphs  = [ ["x"], ["y"], ["z"] ]
lookups = [ [lu1], None,  [lu2] ]
builder.rules.append( (prefix, glyphs, suffix, lookups) )
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

rules

A list of tuples representing the rules in this lookup.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the chained contextual positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

find_chainable_single_pos(lookups, glyphs, value)

Helper for add_single_pos_chained_()

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.ChainContextSubstBuilder(font, location)

Builds a Chained Contextual Substitution (GSUB6) lookup.

Users are expected to manually add rules to the rules attribute after the object has been initialized, e.g.:

# sub [A B] [C D] x' lookup lu1 y' z' lookup lu2 E;

prefix  = [ ["A", "B"], ["C", "D"] ]
suffix  = [ ["E"] ]
glyphs  = [ ["x"], ["y"], ["z"] ]
lookups = [ [lu1], None,  [lu2] ]
builder.rules.append( (prefix, glyphs, suffix, lookups) )
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

rules

A list of tuples representing the rules in this lookup.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the chained contextual positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

find_chainable_single_subst(mapping)

Helper for add_single_subst_chained_()

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.LigatureSubstBuilder(font, location)

Builds a Ligature Substitution (GSUB4) lookup.

Users are expected to manually add ligatures to the ligatures attribute after the object has been initialized, e.g.:

# sub f i by f_i;
builder.ligatures[("f","f","i")] = "f_f_i"
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

ligatures

An ordered dictionary mapping a tuple of glyph names to the ligature glyphname.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the ligature substitution lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.MultipleSubstBuilder(font, location)

Builds a Multiple Substitution (GSUB2) lookup.

Users are expected to manually add substitutions to the mapping attribute after the object has been initialized, e.g.:

# sub uni06C0 by uni06D5.fina hamza.above;
builder.mapping["uni06C0"] = [ "uni06D5.fina", "hamza.above"]
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

mapping

An ordered dictionary mapping a glyph name to a list of substituted glyph names.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.CursivePosBuilder(font, location)

Builds a Cursive Positioning (GPOS3) lookup.

font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

attachments

An ordered dictionary mapping a glyph name to a two-element tuple of otTables.Anchor objects.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_attachment(location, glyphs, entryAnchor, exitAnchor)

Adds attachment information to the cursive positioning lookup.

Parameters:
  • location – A string or tuple representing the location in the original source which produced this lookup. (Unused.)

  • glyphs – A list of glyph names sharing these entry and exit anchor locations.

  • entryAnchor – A otTables.Anchor object representing the entry anchor, or None if no entry anchor is present.

  • exitAnchor – A otTables.Anchor object representing the exit anchor, or None if no exit anchor is present.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the cursive positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.MarkBasePosBuilder(font, location)

Builds a Mark-To-Base Positioning (GPOS4) lookup.

Users are expected to manually add marks and bases to the marks and bases attributes after the object has been initialized, e.g.:

builder.marks["acute"]   = (0, a1)
builder.marks["grave"]   = (0, a1)
builder.marks["cedilla"] = (1, a2)
builder.bases["a"] = {0: a3, 1: a5}
builder.bases["b"] = {0: a4, 1: a5}
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

marks

An dictionary mapping a glyph name to a two-element tuple containing a mark class ID and otTables.Anchor object.

bases

An dictionary mapping a glyph name to a dictionary of mark class IDs and otTables.Anchor object.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the mark-to-base positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.MarkLigPosBuilder(font, location)

Builds a Mark-To-Ligature Positioning (GPOS5) lookup.

Users are expected to manually add marks and bases to the marks and ligatures attributes after the object has been initialized, e.g.:

builder.marks["acute"]   = (0, a1)
builder.marks["grave"]   = (0, a1)
builder.marks["cedilla"] = (1, a2)
builder.ligatures["f_i"] = [
    { 0: a3, 1: a5 }, # f
    { 0: a4, 1: a5 }  # i
]
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

marks

An dictionary mapping a glyph name to a two-element tuple containing a mark class ID and otTables.Anchor object.

ligatures

An dictionary mapping a glyph name to an array with one element for each ligature component. Each array element should be a dictionary mapping mark class IDs to otTables.Anchor objects.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the mark-to-ligature positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.MarkMarkPosBuilder(font, location)

Builds a Mark-To-Mark Positioning (GPOS6) lookup.

Users are expected to manually add marks and bases to the marks and baseMarks attributes after the object has been initialized, e.g.:

builder.marks["acute"]     = (0, a1)
builder.marks["grave"]     = (0, a1)
builder.marks["cedilla"]   = (1, a2)
builder.baseMarks["acute"] = {0: a3}
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

marks

An dictionary mapping a glyph name to a two-element tuple containing a mark class ID and otTables.Anchor object.

baseMarks

An dictionary mapping a glyph name to a dictionary containing one item: a mark class ID and a otTables.Anchor object.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the mark-to-mark positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.ReverseChainSingleSubstBuilder(font, location)

Builds a Reverse Chaining Contextual Single Substitution (GSUB8) lookup.

Users are expected to manually add substitutions to the substitutions attribute after the object has been initialized, e.g.:

# reversesub [a e n] d' by d.alt;
prefix = [ ["a", "e", "n"] ]
suffix = []
mapping = { "d": "d.alt" }
builder.substitutions.append( (prefix, suffix, mapping) )
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

substitutions

A three-element tuple consisting of a prefix sequence, a suffix sequence, and a dictionary of single substitutions.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the chained contextual substitution lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.SingleSubstBuilder(font, location)

Builds a Single Substitution (GSUB1) lookup.

Users are expected to manually add substitutions to the mapping attribute after the object has been initialized, e.g.:

# sub x by y;
builder.mapping["x"] = "y"
font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

mapping

A dictionary mapping a single glyph name to another glyph name.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the multiple substitution lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.ClassPairPosSubtableBuilder(builder)

Builds class-based Pair Positioning (GPOS2 format 2) subtables.

Note that this does not build a GPOS2 otTables.Lookup directly, but builds a list of otTables.PairPos subtables. It is used by the PairPosBuilder below.

builder

A pair positioning lookup builder.

Type:

PairPosBuilder

addPair(gc1, value1, gc2, value2)

Add a pair positioning rule.

Parameters:
  • gc1 – A set of glyph names for the “left” glyph

  • value1 – An otTables.ValueRecord object for the left glyph’s positioning.

  • gc2 – A set of glyph names for the “right” glyph

  • value2 – An otTables.ValueRecord object for the right glyph’s positioning.

addSubtableBreak()

Add an explicit subtable break at this point.

subtables()

Return the list of otTables.PairPos subtables constructed.

class fontTools.otlLib.builder.PairPosBuilder(font, location)

Builds a Pair Positioning (GPOS2) lookup.

font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

pairs

An array of class-based pair positioning tuples. Usually manipulated with the addClassPair() method below.

glyphPairs

A dictionary mapping a tuple of glyph names to a tuple of otTables.ValueRecord objects. Usually manipulated with the addGlyphPair() method below.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

addClassPair(location, glyphclass1, value1, glyphclass2, value2)

Add a class pair positioning rule to the current lookup.

Parameters:
  • location – A string or tuple representing the location in the original source which produced this rule. Unused.

  • glyphclass1 – A set of glyph names for the “left” glyph in the pair.

  • value1 – A otTables.ValueRecord for positioning the left glyph.

  • glyphclass2 – A set of glyph names for the “right” glyph in the pair.

  • value2 – A otTables.ValueRecord for positioning the right glyph.

addGlyphPair(location, glyph1, value1, glyph2, value2)

Add a glyph pair positioning rule to the current lookup.

Parameters:
  • location – A string or tuple representing the location in the original source which produced this rule.

  • glyph1 – A glyph name for the “left” glyph in the pair.

  • value1 – A otTables.ValueRecord for positioning the left glyph.

  • glyph2 – A glyph name for the “right” glyph in the pair.

  • value2 – A otTables.ValueRecord for positioning the right glyph.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the pair positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

class fontTools.otlLib.builder.SinglePosBuilder(font, location)

Builds a Single Positioning (GPOS1) lookup.

font

A font object.

Type:

fontTools.TTLib.TTFont

location

A string or tuple representing the location in the original source which produced this lookup.

mapping

A dictionary mapping a glyph name to a otTables.ValueRecord objects. Usually manipulated with the add_pos() method below.

lookupflag

The lookup’s flag

Type:

int

markFilterSet

Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

add_pos(location, glyph, otValueRecord)

Add a single positioning rule.

Parameters:
  • location – A string or tuple representing the location in the original source which produced this lookup.

  • glyph – A glyph name.

  • otValueRection – A otTables.ValueRecord used to position the glyph.

add_subtable_break(location)

Add an explicit subtable break.

Parameters:

location – A string or tuple representing the location in the original source which produced this break, or None if no location is provided.

build()

Build the lookup.

Returns:

An otTables.Lookup object representing the single positioning lookup.

buildMarkClasses_(marks)

{“cedilla”: (“BOTTOM”, ast.Anchor), …} –> {“BOTTOM”:0, “TOP”:1}

Helper for MarkBasePostBuilder, MarkLigPosBuilder, and MarkMarkPosBuilder. Seems to return the same numeric IDs for mark classes as the AFDKO makeotf tool.

getAlternateGlyphs()

Helper for building ‘aalt’ features.

inferGlyphClasses()

Infers glyph glasses for the GDEF table, such as {“cedilla”:3}.

Common OpenType Layout Data Structures

fontTools.otlLib.builder.buildCoverage(glyphs, glyphMap)

Builds a coverage table.

Coverage tables (as defined in the OpenType spec) are used in all OpenType Layout lookups apart from the Extension type, and define the glyphs involved in a layout subtable. This allows shaping engines to compare the glyph stream with the coverage table and quickly determine whether a subtable should be involved in a shaping operation.

This function takes a list of glyphs and a glyphname-to-ID map, and returns a Coverage object representing the coverage table.

Example:

glyphMap = font.getReverseGlyphMap()
glyphs = [ "A", "B", "C" ]
coverage = buildCoverage(glyphs, glyphMap)
Parameters:
  • glyphs – a sequence of glyph names.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

An otTables.Coverage object or None if there are no glyphs supplied.

fontTools.otlLib.builder.buildLookup(subtables, flags=0, markFilterSet=None)

Turns a collection of rules into a lookup.

A Lookup (as defined in the OpenType Spec) wraps the individual rules in a layout operation (substitution or positioning) in a data structure expressing their overall lookup type - for example, single substitution, mark-to-base attachment, and so on - as well as the lookup flags and any mark filtering sets. You may import the following constants to express lookup flags:

  • LOOKUP_FLAG_RIGHT_TO_LEFT

  • LOOKUP_FLAG_IGNORE_BASE_GLYPHS

  • LOOKUP_FLAG_IGNORE_LIGATURES

  • LOOKUP_FLAG_IGNORE_MARKS

  • LOOKUP_FLAG_USE_MARK_FILTERING_SET

Parameters:
  • subtables – A list of layout subtable objects (e.g. MultipleSubst, PairPos, etc.) or None.

  • flags (int) – This lookup’s flags.

  • markFilterSet – Either None if no mark filtering set is used, or an integer representing the filtering set to be used for this lookup. If a mark filtering set is provided, LOOKUP_FLAG_USE_MARK_FILTERING_SET will be set on the lookup’s flags.

Returns:

An otTables.Lookup object or None if there are no subtables supplied.

Low-level GSUB Table Lookup Builders

These functions deal with the “simple” lookup types. See above for classes to help build more complex lookups (contextual and chaining lookups).

fontTools.otlLib.builder.buildSingleSubstSubtable(mapping)

Builds a single substitution (GSUB1) subtable.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.SingleSubstBuilder instead.

Parameters:

mapping – A dictionary mapping input glyph names to output glyph names.

Returns:

An otTables.SingleSubst object, or None if the mapping dictionary is empty.

fontTools.otlLib.builder.buildMultipleSubstSubtable(mapping)

Builds a multiple substitution (GSUB2) subtable.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.MultipleSubstBuilder instead.

Example:

# sub uni06C0 by uni06D5.fina hamza.above
# sub uni06C2 by uni06C1.fina hamza.above;

subtable = buildMultipleSubstSubtable({
    "uni06C0": [ "uni06D5.fina", "hamza.above"],
    "uni06C2": [ "uni06D1.fina", "hamza.above"]
})
Parameters:

mapping – A dictionary mapping input glyph names to a list of output glyph names.

Returns:

An otTables.MultipleSubst object or None if the mapping dictionary is empty.

fontTools.otlLib.builder.buildAlternateSubstSubtable(mapping)

Builds an alternate substitution (GSUB3) subtable.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.AlternateSubstBuilder instead.

Parameters:

mapping – A dictionary mapping input glyph names to a list of output glyph names.

Returns:

An otTables.AlternateSubst object or None if the mapping dictionary is empty.

fontTools.otlLib.builder.buildLigatureSubstSubtable(mapping)

Builds a ligature substitution (GSUB4) subtable.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.LigatureSubstBuilder instead.

Example:

# sub f f i by f_f_i;
# sub f i by f_i;

subtable = buildLigatureSubstSubtable({
    ("f", "f", "i"): "f_f_i",
    ("f", "i"): "f_i",
})
Parameters:

mapping – A dictionary mapping tuples of glyph names to output glyph names.

Returns:

An otTables.LigatureSubst object or None if the mapping dictionary is empty.

GPOS Shared Table Builders

The functions help build the GPOS shared tables as defined in the OpenType spec: value records, anchors, mark arrays and mark record tables.

fontTools.otlLib.builder.buildValue(value)

Builds a positioning value record.

Value records are used to specify coordinates and adjustments for positioning and attaching glyphs. Many of the positioning functions in this library take otTables.ValueRecord objects as arguments. This function builds value records from dictionaries.

Parameters:

value (dict) – A dictionary with zero or more of the following keys: - xPlacement - yPlacement - xAdvance - yAdvance - xPlaDevice - yPlaDevice - xAdvDevice - yAdvDevice

Returns:

An otTables.ValueRecord object.

fontTools.otlLib.builder.buildAnchor(x, y, point=None, deviceX=None, deviceY=None)

Builds an Anchor table.

This determines the appropriate anchor format based on the passed parameters.

Parameters:
  • x (int) – X coordinate.

  • y (int) – Y coordinate.

  • point (int) – Index of glyph contour point, if provided.

  • deviceX (otTables.Device) – X coordinate device table, if provided.

  • deviceY (otTables.Device) – Y coordinate device table, if provided.

Returns:

An otTables.Anchor object.

fontTools.otlLib.builder.buildMarkArray(marks, glyphMap)

Builds a mark array subtable.

As part of building mark-to-* positioning rules, you will need to define a MarkArray subtable, which “defines the class and the anchor point for a mark glyph.” This function builds the mark array subtable.

Example:

mark = {
    "acute": (0, buildAnchor(300,712)),
    # ...
}
markarray = buildMarkArray(marks, font.getReverseGlyphMap())
Parameters:
  • marks (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being a tuple of mark class number and an otTables.Anchor object representing the mark’s attachment point.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

An otTables.MarkArray object.

fontTools.otlLib.builder.buildDevice(deltas)

Builds a Device record as part of a ValueRecord or Anchor.

Device tables specify size-specific adjustments to value records and anchors to reflect changes based on the resolution of the output. For example, one could specify that an anchor’s Y position should be increased by 1 pixel when displayed at 8 pixels per em. This routine builds device records.

Parameters:

deltas – A dictionary mapping pixels-per-em sizes to the delta adjustment in pixels when the font is displayed at that size.

Returns:

An otTables.Device object if any deltas were supplied, or None otherwise.

fontTools.otlLib.builder.buildBaseArray(bases, numMarkClasses, glyphMap)

Builds a base array record.

As part of building mark-to-base positioning rules, you will need to define a BaseArray record, which “defines for each base glyph an array of anchors, one for each mark class.” This function builds the base array subtable.

Example:

bases = {"a": {0: a3, 1: a5}, "b": {0: a4, 1: a5}}
basearray = buildBaseArray(bases, 2, font.getReverseGlyphMap())
Parameters:
  • bases (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being dictionaries mapping mark class ID to the appropriate otTables.Anchor object used for attaching marks of that class.

  • numMarkClasses (int) – The total number of mark classes for which anchors are defined.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

An otTables.BaseArray object.

fontTools.otlLib.builder.buildComponentRecord(anchors)

Builds a component record.

As part of building mark-to-ligature positioning rules, you will need to define ComponentRecord objects, which contain “an array of offsets… to the Anchor tables that define all the attachment points used to attach marks to the component.” This function builds the component record.

Parameters:

anchors – A list of otTables.Anchor objects or None.

Returns:

A otTables.ComponentRecord object or None if no anchors are supplied.

Low-level GPOS Table Lookup Builders

These functions deal with the “simple” lookup types. See above for classes to help build more complex lookups (contextual and chaining lookups).

fontTools.otlLib.builder.buildCursivePosSubtable(attach, glyphMap)

Builds a cursive positioning (GPOS3) subtable.

Cursive positioning lookups are made up of a coverage table of glyphs, and a set of EntryExitRecord records containing the anchors for each glyph. This function builds the cursive positioning subtable.

Example:

subtable = buildCursivePosSubtable({
    "AlifIni": (None, buildAnchor(0, 50)),
    "BehMed": (buildAnchor(500,250), buildAnchor(0,50)),
    # ...
}, font.getReverseGlyphMap())
Parameters:
  • attach (dict) – A mapping between glyph names and a tuple of two otTables.Anchor objects representing entry and exit anchors.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

An otTables.CursivePos object, or None if the attachment dictionary was empty.

fontTools.otlLib.builder.buildLigatureArray(ligs, numMarkClasses, glyphMap)

Builds a LigatureArray subtable.

As part of building a mark-to-ligature lookup, you will need to define the set of anchors (for each mark class) on each component of the ligature where marks can be attached. For example, for an Arabic divine name ligature (lam lam heh), you may want to specify mark attachment positioning for superior marks (fatha, etc.) and inferior marks (kasra, etc.) on each glyph of the ligature. This routine builds the ligature array record.

Example:

buildLigatureArray({
    "lam-lam-heh": [
        { 0: superiorAnchor1, 1: inferiorAnchor1 }, # attach points for lam1
        { 0: superiorAnchor2, 1: inferiorAnchor2 }, # attach points for lam2
        { 0: superiorAnchor3, 1: inferiorAnchor3 }, # attach points for heh
    ]
}, 2, font.getReverseGlyphMap())
Parameters:
  • ligs (dict) – A mapping of ligature names to an array of dictionaries: for each component glyph in the ligature, an dictionary mapping mark class IDs to anchors.

  • numMarkClasses (int) – The number of mark classes.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

An otTables.LigatureArray object if deltas were supplied.

fontTools.otlLib.builder.buildMarkBasePos(marks, bases, glyphMap)

Build a list of MarkBasePos (GPOS4) subtables.

This routine turns a set of marks and bases into a list of mark-to-base positioning subtables. Currently the list will contain a single subtable containing all marks and bases, although at a later date it may return the optimal list of subtables subsetting the marks and bases into groups which save space. See buildMarkBasePosSubtable() below.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.MarkBasePosBuilder instead.

Example:

# a1, a2, a3, a4, a5 = buildAnchor(500, 100), ...

marks = {"acute": (0, a1), "grave": (0, a1), "cedilla": (1, a2)}
bases = {"a": {0: a3, 1: a5}, "b": {0: a4, 1: a5}}
markbaseposes = buildMarkBasePos(marks, bases, font.getReverseGlyphMap())
Parameters:
  • marks (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being a tuple of mark class number and an otTables.Anchor object representing the mark’s attachment point. (See buildMarkArray().)

  • bases (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being dictionaries mapping mark class ID to the appropriate otTables.Anchor object used for attaching marks of that class. (See buildBaseArray().)

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A list of otTables.MarkBasePos objects.

fontTools.otlLib.builder.buildMarkBasePosSubtable(marks, bases, glyphMap)

Build a single MarkBasePos (GPOS4) subtable.

This builds a mark-to-base lookup subtable containing all of the referenced marks and bases. See buildMarkBasePos().

Parameters:
  • marks (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being a tuple of mark class number and an otTables.Anchor object representing the mark’s attachment point. (See buildMarkArray().)

  • bases (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being dictionaries mapping mark class ID to the appropriate otTables.Anchor object used for attaching marks of that class. (See buildBaseArray().)

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A otTables.MarkBasePos object.

fontTools.otlLib.builder.buildMarkLigPos(marks, ligs, glyphMap)

Build a list of MarkLigPos (GPOS5) subtables.

This routine turns a set of marks and ligatures into a list of mark-to-ligature positioning subtables. Currently the list will contain a single subtable containing all marks and ligatures, although at a later date it may return the optimal list of subtables subsetting the marks and ligatures into groups which save space. See buildMarkLigPosSubtable() below.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.MarkLigPosBuilder instead.

Example:

# a1, a2, a3, a4, a5 = buildAnchor(500, 100), ...
marks = {
    "acute": (0, a1),
    "grave": (0, a1),
    "cedilla": (1, a2)
}
ligs = {
    "f_i": [
        { 0: a3, 1: a5 }, # f
        { 0: a4, 1: a5 }  # i
        ],
#   "c_t": [{...}, {...}]
}
markligposes = buildMarkLigPos(marks, ligs,
    font.getReverseGlyphMap())
Parameters:
  • marks (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being a tuple of mark class number and an otTables.Anchor object representing the mark’s attachment point. (See buildMarkArray().)

  • ligs (dict) – A mapping of ligature names to an array of dictionaries: for each component glyph in the ligature, an dictionary mapping mark class IDs to anchors. (See buildLigatureArray().)

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A list of otTables.MarkLigPos objects.

fontTools.otlLib.builder.buildMarkLigPosSubtable(marks, ligs, glyphMap)

Build a single MarkLigPos (GPOS5) subtable.

This builds a mark-to-base lookup subtable containing all of the referenced marks and bases. See buildMarkLigPos().

Parameters:
  • marks (dict) – A dictionary mapping anchors to glyphs; the keys being glyph names, and the values being a tuple of mark class number and an otTables.Anchor object representing the mark’s attachment point. (See buildMarkArray().)

  • ligs (dict) – A mapping of ligature names to an array of dictionaries: for each component glyph in the ligature, an dictionary mapping mark class IDs to anchors. (See buildLigatureArray().)

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A otTables.MarkLigPos object.

fontTools.otlLib.builder.buildPairPosClassesSubtable(pairs, glyphMap, valueFormat1=None, valueFormat2=None)

Builds a class pair adjustment (GPOS2 format 2) subtable.

Kerning tables are generally expressed as pair positioning tables using class-based pair adjustments. This routine builds format 2 PairPos subtables.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.ClassPairPosSubtableBuilder instead, as this takes care of ensuring that the supplied pairs can be formed into non-overlapping classes and emitting individual subtables whenever the non-overlapping requirement means that a new subtable is required.

Example:

pairs = {}

pairs[(
    [ "K", "X" ],
    [ "W", "V" ]
)] = ( buildValue(xAdvance=+5), buildValue() )
# pairs[(... , ...)] = (..., ...)

pairpos = buildPairPosClassesSubtable(pairs, font.getReverseGlyphMap())
Parameters:
  • pairs (dict) – Pair positioning data; the keys being a two-element tuple of lists of glyphnames, and the values being a two-element tuple of otTables.ValueRecord objects.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

  • valueFormat1 – Force the “left” value records to the given format.

  • valueFormat2 – Force the “right” value records to the given format.

Returns:

A otTables.PairPos object.

fontTools.otlLib.builder.buildPairPosGlyphs(pairs, glyphMap)

Builds a list of glyph-based pair adjustment (GPOS2 format 1) subtables.

This organises a list of pair positioning adjustments into subtables based on common value record formats.

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.PairPosBuilder instead.

Example:

pairs = {
    ("K", "W"): ( buildValue(xAdvance=+5), buildValue() ),
    ("K", "V"): ( buildValue(xAdvance=+5), buildValue() ),
    # ...
}

subtables = buildPairPosGlyphs(pairs, font.getReverseGlyphMap())
Parameters:
  • pairs (dict) – Pair positioning data; the keys being a two-element tuple of glyphnames, and the values being a two-element tuple of otTables.ValueRecord objects.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A list of otTables.PairPos objects.

fontTools.otlLib.builder.buildPairPosGlyphsSubtable(pairs, glyphMap, valueFormat1=None, valueFormat2=None)

Builds a single glyph-based pair adjustment (GPOS2 format 1) subtable.

This builds a PairPos subtable from a dictionary of glyph pairs and their positioning adjustments. See also buildPairPosGlyphs().

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.PairPosBuilder instead.

Example:

pairs = {
    ("K", "W"): ( buildValue(xAdvance=+5), buildValue() ),
    ("K", "V"): ( buildValue(xAdvance=+5), buildValue() ),
    # ...
}

pairpos = buildPairPosGlyphsSubtable(pairs, font.getReverseGlyphMap())
Parameters:
  • pairs (dict) – Pair positioning data; the keys being a two-element tuple of glyphnames, and the values being a two-element tuple of otTables.ValueRecord objects.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

  • valueFormat1 – Force the “left” value records to the given format.

  • valueFormat2 – Force the “right” value records to the given format.

Returns:

A otTables.PairPos object.

fontTools.otlLib.builder.buildSinglePos(mapping, glyphMap)

Builds a list of single adjustment (GPOS1) subtables.

This builds a list of SinglePos subtables from a dictionary of glyph names and their positioning adjustments. The format of the subtables are determined to optimize the size of the resulting subtables. See also buildSinglePosSubtable().

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.SinglePosBuilder instead.

Example:

mapping = {
    "V": buildValue({ "xAdvance" : +5 }),
    # ...
}

subtables = buildSinglePos(pairs, font.getReverseGlyphMap())
Parameters:
  • mapping (dict) – A mapping between glyphnames and otTables.ValueRecord objects.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A list of otTables.SinglePos objects.

fontTools.otlLib.builder.buildSinglePosSubtable(values, glyphMap)

Builds a single adjustment (GPOS1) subtable.

This builds a list of SinglePos subtables from a dictionary of glyph names and their positioning adjustments. The format of the subtable is determined to optimize the size of the output. See also buildSinglePos().

Note that if you are implementing a layout compiler, you may find it more flexible to use fontTools.otlLib.lookupBuilders.SinglePosBuilder instead.

Example:

mapping = {
    "V": buildValue({ "xAdvance" : +5 }),
    # ...
}

subtable = buildSinglePos(pairs, font.getReverseGlyphMap())
Parameters:
  • mapping (dict) – A mapping between glyphnames and otTables.ValueRecord objects.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A otTables.SinglePos object.

GDEF Table Subtable Builders

These functions build subtables for elements of the GDEF table.

fontTools.otlLib.builder.buildAttachList(attachPoints, glyphMap)

Builds an AttachList subtable.

A GDEF table may contain an Attachment Point List table (AttachList) which stores the contour indices of attachment points for glyphs with attachment points. This routine builds AttachList subtables.

Parameters:

attachPoints (dict) – A mapping between glyph names and a list of contour indices.

Returns:

An otTables.AttachList object if attachment points are supplied,

or None otherwise.

fontTools.otlLib.builder.buildLigCaretList(coords, points, glyphMap)

Builds a ligature caret list table.

Ligatures appear as a single glyph representing multiple characters; however when, for example, editing text containing a f_i ligature, the user may want to place the cursor between the f and the i. The ligature caret list in the GDEF table specifies the position to display the “caret” (the character insertion indicator, typically a flashing vertical bar) “inside” the ligature to represent an insertion point. The insertion positions may be specified either by coordinate or by contour point.

Example:

coords = {
    "f_f_i": [300, 600] # f|fi cursor at 300 units, ff|i cursor at 600.
}
points = {
    "c_t": [28] # c|t cursor appears at coordinate of contour point 28.
}
ligcaretlist = buildLigCaretList(coords, points, font.getReverseGlyphMap())
Parameters:
  • coords – A mapping between glyph names and a list of coordinates for the insertion point of each ligature component after the first one.

  • points – A mapping between glyph names and a list of contour points for the insertion point of each ligature component after the first one.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns:

A otTables.LigCaretList object if any carets are present, or

None otherwise.

fontTools.otlLib.builder.buildMarkGlyphSetsDef(markSets, glyphMap)

Builds a mark glyph sets definition table.

OpenType Layout lookups may choose to use mark filtering sets to consider or ignore particular combinations of marks. These sets are specified by setting a flag on the lookup, but the mark filtering sets are defined in the GDEF table. This routine builds the subtable containing the mark glyph set definitions.

Example:

set0 = set("acute", "grave")
set1 = set("caron", "grave")

markglyphsets = buildMarkGlyphSetsDef([set0, set1], font.getReverseGlyphMap())
Parameters:
  • markSets – A list of sets of glyphnames.

  • glyphMap – a glyph name to ID map, typically returned from font.getReverseGlyphMap().

Returns

An otTables.MarkGlyphSetsDef object.

STAT Table Builder

fontTools.otlLib.builder.buildStatTable(ttFont, axes, locations=None, elidedFallbackName=2, windowsNames=True, macNames=True)

Add a ‘STAT’ table to ‘ttFont’.

‘axes’ is a list of dictionaries describing axes and their values.

Example:

axes = [
    dict(
        tag="wght",
        name="Weight",
        ordering=0,  # optional
        values=[
            dict(value=100, name='Thin'),
            dict(value=300, name='Light'),
            dict(value=400, name='Regular', flags=0x2),
            dict(value=900, name='Black'),
        ],
    )
]

Each axis dict must have ‘tag’ and ‘name’ items. ‘tag’ maps to the ‘AxisTag’ field. ‘name’ can be a name ID (int), a string, or a dictionary containing multilingual names (see the addMultilingualName() name table method), and will translate to the AxisNameID field.

An axis dict may contain an ‘ordering’ item that maps to the AxisOrdering field. If omitted, the order of the axes list is used to calculate AxisOrdering fields.

The axis dict may contain a ‘values’ item, which is a list of dictionaries describing AxisValue records belonging to this axis.

Each value dict must have a ‘name’ item, which can be a name ID (int), a string, or a dictionary containing multilingual names, like the axis name. It translates to the ValueNameID field.

Optionally the value dict can contain a ‘flags’ item. It maps to the AxisValue Flags field, and will be 0 when omitted.

The format of the AxisValue is determined by the remaining contents of the value dictionary:

If the value dict contains a ‘value’ item, an AxisValue record Format 1 is created. If in addition to the ‘value’ item it contains a ‘linkedValue’ item, an AxisValue record Format 3 is built.

If the value dict contains a ‘nominalValue’ item, an AxisValue record Format 2 is built. Optionally it may contain ‘rangeMinValue’ and ‘rangeMaxValue’ items. These map to -Infinity and +Infinity respectively if omitted.

You cannot specify Format 4 AxisValue tables this way, as they are not tied to a single axis, and specify a name for a location that is defined by multiple axes values. Instead, you need to supply the ‘locations’ argument.

The optional ‘locations’ argument specifies AxisValue Format 4 tables. It should be a list of dicts, where each dict has a ‘name’ item, which works just like the value dicts above, an optional ‘flags’ item (defaulting to 0x0), and a ‘location’ dict. A location dict key is an axis tag, and the associated value is the location on the specified axis. They map to the AxisIndex and Value fields of the AxisValueRecord.

Example:

locations = [
    dict(name='Regular ABCD', location=dict(wght=300, ABCD=100)),
    dict(name='Bold ABCD XYZ', location=dict(wght=600, ABCD=200)),
]

The optional ‘elidedFallbackName’ argument can be a name ID (int), a string, a dictionary containing multilingual names, or a list of STATNameStatements. It translates to the ElidedFallbackNameID field.

The ‘ttFont’ argument must be a TTFont instance that already has a ‘name’ table. If a ‘STAT’ table already exists, it will be overwritten by the newly created one.

pens

areaPen

Calculate the area of a glyph.

class fontTools.pens.areaPen.AreaPen(glyphset=None)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

basePen

fontTools.pens.basePen.py – Tools and base classes to build pen objects.

The Pen Protocol

A Pen is a kind of object that standardizes the way how to “draw” outlines: it is a middle man between an outline and a drawing. In other words: it is an abstraction for drawing outlines, making sure that outline objects don’t need to know the details about how and where they’re being drawn, and that drawings don’t need to know the details of how outlines are stored.

The most basic pattern is this:

outline.draw(pen)  # 'outline' draws itself onto 'pen'

Pens can be used to render outlines to the screen, but also to construct new outlines. Eg. an outline object can be both a drawable object (it has a draw() method) as well as a pen itself: you build an outline using pen methods.

The AbstractPen class defines the Pen protocol. It implements almost nothing (only no-op closePath() and endPath() methods), but is useful for documentation purposes. Subclassing it basically tells the reader: “this class implements the Pen protocol.”. An examples of an AbstractPen subclass is fontTools.pens.transformPen.TransformPen.

The BasePen class is a base implementation useful for pens that actually draw (for example a pen renders outlines using a native graphics engine). BasePen contains a lot of base functionality, making it very easy to build a pen that fully conforms to the pen protocol. Note that if you subclass BasePen, you don’t override moveTo(), lineTo(), etc., but _moveTo(), _lineTo(), etc. See the BasePen doc string for details. Examples of BasePen subclasses are fontTools.pens.boundsPen.BoundsPen and fontTools.pens.cocoaPen.CocoaPen.

Coordinates are usually expressed as (x, y) tuples, but generally any sequence of length 2 will do.

class fontTools.pens.basePen.AbstractPen
addComponent(glyphName: str, transformation: Tuple[float, float, float, float, float, float]) None

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath() None

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points: Tuple[float, float]) None

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath() None

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt: Tuple[float, float]) None

Draw a straight line from the current point to ‘pt’.

moveTo(pt: Tuple[float, float]) None

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points: Tuple[float, float]) None

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

class fontTools.pens.basePen.BasePen(glyphSet=None)

Base class for drawing pens. You must override _moveTo, _lineTo and _curveToOne. You may additionally override _closePath, _endPath, addComponent, addVarComponent, and/or _qCurveToOne. You should not override any other methods.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True
class fontTools.pens.basePen.NullPen

A pen that does nothing.

addComponent(glyphName, transformation)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

exception fontTools.pens.basePen.PenError

Represents an error during penning.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

fontTools.pens.basePen.decomposeQuadraticSegment(points)

Split the quadratic curve segment described by ‘points’ into a list of “atomic” quadratic segments. The ‘points’ argument must be a sequence with length 2 or greater, containing (x, y) coordinates. The last point is the destination on-curve point, the rest of the points are off-curve points. The start point should not be supplied.

This function returns a list of (pt1, pt2) tuples, which each specify a plain quadratic bezier segment.

fontTools.pens.basePen.decomposeSuperBezierSegment(points)

Split the SuperBezier described by ‘points’ into a list of regular bezier segments. The ‘points’ argument must be a sequence with length 3 or greater, containing (x, y) coordinates. The last point is the destination on-curve point, the rest of the points are off-curve points. The start point should not be supplied.

This function returns a list of (pt1, pt2, pt3) tuples, which each specify a regular curveto-style bezier segment.

boundsPen

class fontTools.pens.boundsPen.BoundsPen(glyphSet, ignoreSinglePoints=False)

Pen to calculate the bounds of a shape. It calculates the correct bounds even when the shape contains curves that don’t have points on their extremes. This is somewhat slower to compute than the “control bounds”.

When the shape has been drawn, the bounds are available as the bounds attribute of the pen object. It’s a 4-tuple:

(xMin, yMin, xMax, yMax)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

init()
lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True
class fontTools.pens.boundsPen.ControlBoundsPen(glyphSet, ignoreSinglePoints=False)

Pen to calculate the “control bounds” of a shape. This is the bounding box of all control points, so may be larger than the actual bounding box if there are curves that don’t have points on their extremes.

When the shape has been drawn, the bounds are available as the bounds attribute of the pen object. It’s a 4-tuple:

(xMin, yMin, xMax, yMax).

If ignoreSinglePoints is True, single points are ignored.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

init()
lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

cocoaPen

class fontTools.pens.cocoaPen.CocoaPen(glyphSet, path=None)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

cu2quPen

class fontTools.pens.cu2quPen.Cu2QuMultiPen(other_pens, max_err, reverse_direction=False)

A filter multi-pen to convert cubic bezier curves to quadratic b-splines in a interpolation-compatible manner, using the FontTools SegmentPen protocol.

Parameters:
  • other_pens – list of SegmentPens used to draw the transformed outlines.

  • max_err – maximum approximation error in font units. For optimal results, if you know the UPEM of the font, we recommend setting this to a value equal, or close to UPEM / 1000.

  • reverse_direction – flip the contours’ direction but keep starting point.

This pen does not follow the normal SegmentPen protocol. Instead, its moveTo/lineTo/qCurveTo/curveTo methods take a list of tuples that are arguments that would normally be passed to a SegmentPen, one item for each of the pens in other_pens.

addComponent(glyphName, transformations)
closePath()
curveTo(pointsList)
endPath()
lineTo(pts)
moveTo(pts)
qCurveTo(pointsList)
class fontTools.pens.cu2quPen.Cu2QuPen(other_pen, max_err, reverse_direction=False, stats=None, all_quadratic=True)

A filter pen to convert cubic bezier curves to quadratic b-splines using the FontTools SegmentPen protocol.

Parameters:
  • other_pen – another SegmentPen used to draw the transformed outline.

  • max_err – maximum approximation error in font units. For optimal results, if you know the UPEM of the font, we recommend setting this to a value equal, or close to UPEM / 1000.

  • reverse_direction – flip the contours’ direction but keep starting point.

  • stats – a dictionary counting the point numbers of quadratic segments.

  • all_quadratic – if True (default), only quadratic b-splines are generated. if False, quadratic curves or cubic curves are generated depending on which one is more economical.

addComponent(glyphName, transformation, **kwargs)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

class fontTools.pens.cu2quPen.Cu2QuPointPen(other_point_pen, max_err, reverse_direction=False, stats=None, all_quadratic=True)

A filter pen to convert cubic bezier curves to quadratic b-splines using the FontTools PointPen protocol.

Parameters:
  • other_point_pen – another PointPen used to draw the transformed outline.

  • max_err – maximum approximation error in font units. For optimal results, if you know the UPEM of the font, we recommend setting this to a value equal, or close to UPEM / 1000.

  • reverse_direction – reverse the winding direction of all contours.

  • stats – a dictionary counting the point numbers of quadratic segments.

  • all_quadratic – if True (default), only quadratic b-splines are generated. if False, quadratic curves or cubic curves are generated depending on which one is more economical.

addComponent(baseGlyphName, transformation)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

endPath()

End the current sub path.

filterPen

class fontTools.pens.filterPen.ContourFilterPen(outPen)

A “buffered” filter pen that accumulates contour data, passes it through a filterContour method when the contour is closed or ended, and finally draws the result with the output pen.

Components are passed through unchanged.

addComponent(glyphName, transformation, **kwargs)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

draw(pen)
endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

filterContour(contour)

Subclasses must override this to perform the filtering.

The contour is a list of pen (operator, operands) tuples. Operators are strings corresponding to the AbstractPen methods: “moveTo”, “lineTo”, “curveTo”, “qCurveTo”, “closePath” and “endPath”. The operands are the positional arguments that are passed to each method.

If the method doesn’t return a value (i.e. returns None), it’s assumed that the argument was modified in-place. Otherwise, the return value is drawn with the output pen.

lineTo(p1)

Draw a straight line from the current point to ‘pt’.

moveTo(p0)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

replay(pen)
class fontTools.pens.filterPen.DecomposingFilterPen(outPen, glyphSet, skipMissingComponents=None, reverseFlipped=False, include: set[str] | None = None, decomposeNested: bool = True)

Filter pen that draws components as regular contours.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(baseGlyphName, transformation, **kwargs)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = False
class fontTools.pens.filterPen.DecomposingFilterPointPen(outPen, glyphSet, skipMissingComponents=None, reverseFlipped=False, include: set[str] | None = None, decomposeNested: bool = True)

Filter point pen that draws components as regular contours.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(baseGlyphName, transformation, **kwargs)

Transform the points of the base glyph and draw it onto self.

The identifier parameter and any extra kwargs are ignored.

addPoint(pt, segmentType=None, smooth=False, name=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(**kwargs)

Start a new sub path.

endPath()

End the current sub path.

property log
skipMissingComponents = False
class fontTools.pens.filterPen.FilterPen(outPen)

Base class for pens that apply some transformation to the coordinates they receive and pass them to another pen.

You can override any of its methods. The default implementation does nothing, but passes the commands unmodified to the other pen.

>>> from fontTools.pens.recordingPen import RecordingPen
>>> rec = RecordingPen()
>>> pen = FilterPen(rec)
>>> v = iter(rec.value)
>>> pen.moveTo((0, 0))
>>> next(v)
('moveTo', ((0, 0),))
>>> pen.lineTo((1, 1))
>>> next(v)
('lineTo', ((1, 1),))
>>> pen.curveTo((2, 2), (3, 3), (4, 4))
>>> next(v)
('curveTo', ((2, 2), (3, 3), (4, 4)))
>>> pen.qCurveTo((5, 5), (6, 6), (7, 7), (8, 8))
>>> next(v)
('qCurveTo', ((5, 5), (6, 6), (7, 7), (8, 8)))
>>> pen.closePath()
>>> next(v)
('closePath', ())
>>> pen.moveTo((9, 9))
>>> next(v)
('moveTo', ((9, 9),))
>>> pen.endPath()
>>> next(v)
('endPath', ())
>>> pen.addComponent('foo', (1, 0, 0, 1, 0, 0))
>>> next(v)
('addComponent', ('foo', (1, 0, 0, 1, 0, 0)))
addComponent(glyphName, transformation, **kwargs)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

class fontTools.pens.filterPen.FilterPointPen(outPen)

Baseclass for point pens that apply some transformation to the coordinates they receive and pass them to another point pen.

You can override any of its methods. The default implementation does nothing, but passes the commands unmodified to the other pen.

>>> from fontTools.pens.recordingPen import RecordingPointPen
>>> rec = RecordingPointPen()
>>> pen = FilterPointPen(rec)
>>> v = iter(rec.value)
>>> pen.beginPath(identifier="abc")
>>> next(v)
('beginPath', (), {'identifier': 'abc'})
>>> pen.addPoint((1, 2), "line", False)
>>> next(v)
('addPoint', ((1, 2), 'line', False, None), {})
>>> pen.addComponent("a", (2, 0, 0, 2, 10, -10), identifier="0001")
>>> next(v)
('addComponent', ('a', (2, 0, 0, 2, 10, -10)), {'identifier': '0001'})
>>> pen.endPath()
>>> next(v)
('endPath', (), {})
addComponent(glyphName, transformation, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(**kwargs)

Start a new sub path.

endPath()

End the current sub path.

freetypePen

momentsPen

class fontTools.pens.momentsPen.MomentsPen(glyphset=None)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

perimeterPen

Calculate the perimeter of a glyph.

class fontTools.pens.perimeterPen.PerimeterPen(glyphset=None, tolerance=0.005)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

pointInsidePen

fontTools.pens.pointInsidePen – Pen implementing “point inside” testing for shapes.

class fontTools.pens.pointInsidePen.PointInsidePen(glyphSet, testPoint, evenOdd=False)

This pen implements “point inside” testing: to test whether a given point lies inside the shape (black) or outside (white). Instances of this class can be recycled, as long as the setTestPoint() method is used to set the new point to test.

Typical usage:

pen = PointInsidePen(glyphSet, (100, 200)) outline.draw(pen) isInside = pen.getResult()

Both the even-odd algorithm and the non-zero-winding-rule algorithm are implemented. The latter is the default, specify True for the evenOdd argument of __init__ or setTestPoint to use the even-odd algorithm.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

getResult()

After the shape has been drawn, getResult() returns True if the test point lies within the (black) shape, and False if it doesn’t.

getWinding()
lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

setTestPoint(testPoint, evenOdd=False)

Set the point to test. Call this _before_ the outline gets drawn.

skipMissingComponents = True

pointPen

PointPens

Where SegmentPens have an intuitive approach to drawing (if you’re familiar with postscript anyway), the PointPen is geared towards accessing all the data in the contours of the glyph. A PointPen has a very simple interface, it just steps through all the points in a call from glyph.drawPoints(). This allows the caller to provide more data for each point. For instance, whether or not a point is smooth, and its name.

class fontTools.pens.pointPen.AbstractPointPen

Baseclass for all PointPens.

addComponent(baseGlyphName: str, transformation: Tuple[float, float, float, float, float, float], identifier: str | None = None, **kwargs: Any) None

Add a sub glyph.

addPoint(pt: Tuple[float, float], segmentType: str | None = None, smooth: bool = False, name: str | None = None, identifier: str | None = None, **kwargs: Any) None

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier: str | None = None, **kwargs: Any) None

Start a new sub path.

endPath() None

End the current sub path.

class fontTools.pens.pointPen.BasePointToSegmentPen

Base class for retrieving the outline in a segment-oriented way. The PointPen protocol is simple yet also a little tricky, so when you need an outline presented as segments but you have as points, do use this base implementation as it properly takes care of all the edge cases.

addComponent(baseGlyphName: str, transformation: Tuple[float, float, float, float, float, float], identifier: str | None = None, **kwargs: Any) None

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

endPath()

End the current sub path.

class fontTools.pens.pointPen.GuessSmoothPointPen(outPen, error=0.05)

Filtering PointPen that tries to determine whether an on-curve point should be “smooth”, ie. that it’s a “tangent” point or a “curve” point.

addComponent(glyphName, transformation, identifier=None, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName, transformation, location, identifier=None, **kwargs)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

endPath()

End the current sub path.

class fontTools.pens.pointPen.PointToSegmentPen(segmentPen, outputImpliedClosingLine=False)

Adapter class that converts the PointPen protocol to the (Segment)Pen protocol.

NOTE: The segment pen does not support and will drop point names, identifiers and kwargs.

addComponent(glyphName, transform, identifier=None, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

endPath()

End the current sub path.

class fontTools.pens.pointPen.ReverseContourPointPen(outputPointPen)

This is a PointPen that passes outline data to another PointPen, but reversing the winding direction of all contours. Components are simply passed through unchanged.

Closed contours are reversed in such a way that the first point remains the first point.

addComponent(glyphName, transform, identifier=None, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

endPath()

End the current sub path.

class fontTools.pens.pointPen.SegmentToPointPen(pointPen, guessSmooth=True)

Adapter class that converts the (Segment)Pen protocol to the PointPen protocol.

addComponent(glyphName, transform)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*pts)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*pts)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

qtPen

class fontTools.pens.qtPen.QtPen(glyphSet, path=None)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

recordingPen

Pen recording operations that can be accessed or replayed.

class fontTools.pens.recordingPen.DecomposingRecordingPen(glyphSet, *args, skipMissingComponents=None, reverseFlipped=False, **kwargs)

Same as RecordingPen, except that it doesn’t keep components as references, but draws them decomposed as regular contours.

The constructor takes a required ‘glyphSet’ positional argument, a dictionary of glyph objects (i.e. with a ‘draw’ method) keyed by thir name; other arguments are forwarded to the DecomposingPen’s constructor:

>>> class SimpleGlyph(object):

… def draw(self, pen): … pen.moveTo((0, 0)) … pen.curveTo((1, 1), (2, 2), (3, 3)) … pen.closePath() >>> class CompositeGlyph(object): … def draw(self, pen): … pen.addComponent(‘a’, (1, 0, 0, 1, -1, 1)) >>> class MissingComponent(object): … def draw(self, pen): … pen.addComponent(‘foobar’, (1, 0, 0, 1, 0, 0)) >>> class FlippedComponent(object): … def draw(self, pen): … pen.addComponent(‘a’, (-1, 0, 0, 1, 0, 0)) >>> glyphSet = { … ‘a’: SimpleGlyph(), … ‘b’: CompositeGlyph(), … ‘c’: MissingComponent(), … ‘d’: FlippedComponent(), … } >>> for name, glyph in sorted(glyphSet.items()): … pen = DecomposingRecordingPen(glyphSet) … try: … glyph.draw(pen) … except pen.MissingComponentError: … pass … print(“{}: {}”.format(name, pen.value)) a: [(‘moveTo’, ((0, 0),)), (‘curveTo’, ((1, 1), (2, 2), (3, 3))), (‘closePath’, ())] b: [(‘moveTo’, ((-1, 1),)), (‘curveTo’, ((0, 2), (1, 3), (2, 4))), (‘closePath’, ())] c: [] d: [(‘moveTo’, ((0, 0),)), (‘curveTo’, ((-1, 1), (-2, 2), (-3, 3))), (‘closePath’, ())] >>> for name, glyph in sorted(glyphSet.items()): … pen = DecomposingRecordingPen( … glyphSet, skipMissingComponents=True, reverseFlipped=True, … ) … glyph.draw(pen) … print(“{}: {}”.format(name, pen.value)) a: [(‘moveTo’, ((0, 0),)), (‘curveTo’, ((1, 1), (2, 2), (3, 3))), (‘closePath’, ())] b: [(‘moveTo’, ((-1, 1),)), (‘curveTo’, ((0, 2), (1, 3), (2, 4))), (‘closePath’, ())] c: [] d: [(‘moveTo’, ((0, 0),)), (‘lineTo’, ((-3, 3),)), (‘curveTo’, ((-2, 2), (-1, 1), (0, 0))), (‘closePath’, ())]

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

draw(pen)
endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(p1)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(p0)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

replay(pen)
skipMissingComponents = False
class fontTools.pens.recordingPen.DecomposingRecordingPointPen(glyphSet, *args, skipMissingComponents=None, reverseFlipped=False, **kwargs)

Same as RecordingPointPen, except that it doesn’t keep components as references, but draws them decomposed as regular contours.

The constructor takes a required ‘glyphSet’ positional argument, a dictionary of pointPen-drawable glyph objects (i.e. with a ‘drawPoints’ method) keyed by thir name; other arguments are forwarded to the DecomposingPointPen’s constructor:

>>> from pprint import pprint
>>> class SimpleGlyph(object):

… def drawPoints(self, pen): … pen.beginPath() … pen.addPoint((0, 0), “line”) … pen.addPoint((1, 1)) … pen.addPoint((2, 2)) … pen.addPoint((3, 3), “curve”) … pen.endPath() >>> class CompositeGlyph(object): … def drawPoints(self, pen): … pen.addComponent(‘a’, (1, 0, 0, 1, -1, 1)) >>> class MissingComponent(object): … def drawPoints(self, pen): … pen.addComponent(‘foobar’, (1, 0, 0, 1, 0, 0)) >>> class FlippedComponent(object): … def drawPoints(self, pen): … pen.addComponent(‘a’, (-1, 0, 0, 1, 0, 0)) >>> glyphSet = { … ‘a’: SimpleGlyph(), … ‘b’: CompositeGlyph(), … ‘c’: MissingComponent(), … ‘d’: FlippedComponent(), … } >>> for name, glyph in sorted(glyphSet.items()): … pen = DecomposingRecordingPointPen(glyphSet) … try: … glyph.drawPoints(pen) … except pen.MissingComponentError: … pass … pprint({name: pen.value}) {‘a’: [(‘beginPath’, (), {}),

(‘addPoint’, ((0, 0), ‘line’, False, None), {}), (‘addPoint’, ((1, 1), None, False, None), {}), (‘addPoint’, ((2, 2), None, False, None), {}), (‘addPoint’, ((3, 3), ‘curve’, False, None), {}), (‘endPath’, (), {})]}

{‘b’: [(‘beginPath’, (), {}),

(‘addPoint’, ((-1, 1), ‘line’, False, None), {}), (‘addPoint’, ((0, 2), None, False, None), {}), (‘addPoint’, ((1, 3), None, False, None), {}), (‘addPoint’, ((2, 4), ‘curve’, False, None), {}), (‘endPath’, (), {})]}

{‘c’: []} {‘d’: [(‘beginPath’, (), {}),

(‘addPoint’, ((0, 0), ‘line’, False, None), {}), (‘addPoint’, ((-1, 1), None, False, None), {}), (‘addPoint’, ((-2, 2), None, False, None), {}), (‘addPoint’, ((-3, 3), ‘curve’, False, None), {}), (‘endPath’, (), {})]}

>>> for name, glyph in sorted(glyphSet.items()):
...     pen = DecomposingRecordingPointPen(
...         glyphSet, skipMissingComponents=True, reverseFlipped=True,
...     )
...     glyph.drawPoints(pen)
...     pprint({name: pen.value})
{'a': [('beginPath', (), {}),
       ('addPoint', ((0, 0), 'line', False, None), {}),
       ('addPoint', ((1, 1), None, False, None), {}),
       ('addPoint', ((2, 2), None, False, None), {}),
       ('addPoint', ((3, 3), 'curve', False, None), {}),
       ('endPath', (), {})]}
{'b': [('beginPath', (), {}),
       ('addPoint', ((-1, 1), 'line', False, None), {}),
       ('addPoint', ((0, 2), None, False, None), {}),
       ('addPoint', ((1, 3), None, False, None), {}),
       ('addPoint', ((2, 4), 'curve', False, None), {}),
       ('endPath', (), {})]}
{'c': []}
{'d': [('beginPath', (), {}),
       ('addPoint', ((0, 0), 'curve', False, None), {}),
       ('addPoint', ((-3, 3), 'line', False, None), {}),
       ('addPoint', ((-2, 2), None, False, None), {}),
       ('addPoint', ((-1, 1), None, False, None), {}),
       ('endPath', (), {})]}
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(baseGlyphName, transformation, identifier=None, **kwargs)

Transform the points of the base glyph and draw it onto self.

The identifier parameter and any extra kwargs are ignored.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(baseGlyphName, transformation, location, identifier=None, **kwargs)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

drawPoints(pointPen)
endPath()

End the current sub path.

property log
replay(pointPen)
skipMissingComponents = False
class fontTools.pens.recordingPen.RecordingPen

Pen recording operations that can be accessed or replayed.

The recording can be accessed as pen.value; or replayed using pen.replay(otherPen).

Example:

from fontTools.ttLib import TTFont from fontTools.pens.recordingPen import RecordingPen

glyph_name = ‘dollar’ font_path = ‘MyFont.otf’

font = TTFont(font_path) glyphset = font.getGlyphSet() glyph = glyphset[glyph_name]

pen = RecordingPen() glyph.draw(pen) print(pen.value)

addComponent(glyphName, transformation)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

draw(pen)
endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(p1)

Draw a straight line from the current point to ‘pt’.

moveTo(p0)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

replay(pen)
class fontTools.pens.recordingPen.RecordingPointPen

PointPen recording operations that can be accessed or replayed.

The recording can be accessed as pen.value; or replayed using pointPen.replay(otherPointPen).

Example:

from defcon import Font from fontTools.pens.recordingPen import RecordingPointPen

glyph_name = ‘a’ font_path = ‘MyFont.ufo’

font = Font(font_path) glyph = font[glyph_name]

pen = RecordingPointPen() glyph.drawPoints(pen) print(pen.value)

new_glyph = font.newGlyph(‘b’) pen.replay(new_glyph.getPointPen())

addComponent(baseGlyphName, transformation, identifier=None, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(baseGlyphName, transformation, location, identifier=None, **kwargs)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier=None, **kwargs)

Start a new sub path.

drawPoints(pointPen)
endPath()

End the current sub path.

replay(pointPen)
fontTools.pens.recordingPen.lerpRecordings(recording1, recording2, factor=0.5)

Linearly interpolate between two recordings. The recordings must be decomposed, i.e. they must not contain any components.

Factor is typically between 0 and 1. 0 means the first recording, 1 means the second recording, and 0.5 means the average of the two recordings. Other values are possible, and can be useful to extrapolate. Defaults to 0.5.

Returns a generator with the new recording.

fontTools.pens.recordingPen.replayRecording(recording, pen)

Replay a recording, as produced by RecordingPen or DecomposingRecordingPen, to a pen.

Note that recording does not have to be produced by those pens. It can be any iterable of tuples of method name and tuple-of-arguments. Likewise, pen can be any objects receiving those method calls.

reportLabPen

class fontTools.pens.reportLabPen.ReportLabPen(glyphSet, path=None)

A pen for drawing onto a reportlab.graphics.shapes.Path object.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

reverseContourPen

class fontTools.pens.reverseContourPen.ReverseContourPen(outPen, outputImpliedClosingLine=False)

Filter pen that passes outline data to another pen, but reversing the winding direction of all contours. Components are simply passed through unchanged.

Closed contours are reversed in such a way that the first point remains the first point.

addComponent(glyphName, transformation, **kwargs)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

draw(pen)
endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

filterContour(contour)

Subclasses must override this to perform the filtering.

The contour is a list of pen (operator, operands) tuples. Operators are strings corresponding to the AbstractPen methods: “moveTo”, “lineTo”, “curveTo”, “qCurveTo”, “closePath” and “endPath”. The operands are the positional arguments that are passed to each method.

If the method doesn’t return a value (i.e. returns None), it’s assumed that the argument was modified in-place. Otherwise, the return value is drawn with the output pen.

lineTo(p1)

Draw a straight line from the current point to ‘pt’.

moveTo(p0)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

replay(pen)
fontTools.pens.reverseContourPen.reversedContour(contour, outputImpliedClosingLine=False)

Generator that takes a list of pen’s (operator, operands) tuples, and yields them with the winding direction reversed.

roundingPen

class fontTools.pens.roundingPen.RoundingPen(outPen, roundFunc=<function otRound>, transformRoundFunc=<function noRound>)

Filter pen that rounds point coordinates and component XY offsets to integer. For rounding the component transform values, a separate round function can be passed to the pen.

>>> from fontTools.pens.recordingPen import RecordingPen
>>> recpen = RecordingPen()
>>> roundpen = RoundingPen(recpen)
>>> roundpen.moveTo((0.4, 0.6))
>>> roundpen.lineTo((1.6, 2.5))
>>> roundpen.qCurveTo((2.4, 4.6), (3.3, 5.7), (4.9, 6.1))
>>> roundpen.curveTo((6.4, 8.6), (7.3, 9.7), (8.9, 10.1))
>>> roundpen.addComponent("a", (1.5, 0, 0, 1.5, 10.5, -10.5))
>>> recpen.value == [
...     ('moveTo', ((0, 1),)),
...     ('lineTo', ((2, 3),)),
...     ('qCurveTo', ((2, 5), (3, 6), (5, 6))),
...     ('curveTo', ((6, 9), (7, 10), (9, 10))),
...     ('addComponent', ('a', (1.5, 0, 0, 1.5, 11, -10))),
... ]
True
addComponent(glyphName, transformation)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

class fontTools.pens.roundingPen.RoundingPointPen(outPen, roundFunc=<function otRound>, transformRoundFunc=<function noRound>)

Filter point pen that rounds point coordinates and component XY offsets to integer. For rounding the component scale values, a separate round function can be passed to the pen.

>>> from fontTools.pens.recordingPen import RecordingPointPen
>>> recpen = RecordingPointPen()
>>> roundpen = RoundingPointPen(recpen)
>>> roundpen.beginPath()
>>> roundpen.addPoint((0.4, 0.6), 'line')
>>> roundpen.addPoint((1.6, 2.5), 'line')
>>> roundpen.addPoint((2.4, 4.6))
>>> roundpen.addPoint((3.3, 5.7))
>>> roundpen.addPoint((4.9, 6.1), 'qcurve')
>>> roundpen.endPath()
>>> roundpen.addComponent("a", (1.5, 0, 0, 1.5, 10.5, -10.5))
>>> recpen.value == [
...     ('beginPath', (), {}),
...     ('addPoint', ((0, 1), 'line', False, None), {}),
...     ('addPoint', ((2, 3), 'line', False, None), {}),
...     ('addPoint', ((2, 5), None, False, None), {}),
...     ('addPoint', ((3, 6), None, False, None), {}),
...     ('addPoint', ((5, 6), 'qcurve', False, None), {}),
...     ('endPath', (), {}),
...     ('addComponent', ('a', (1.5, 0, 0, 1.5, 11, -10)), {}),
... ]
True
addComponent(baseGlyphName, transformation, identifier=None, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(**kwargs)

Start a new sub path.

endPath()

End the current sub path.

statisticsPen

Pen calculating area, center of mass, variance and standard-deviation, covariance and correlation, and slant, of glyph shapes.

class fontTools.pens.statisticsPen.StatisticsControlPen(glyphset=None)

Pen calculating area, center of mass, variance and standard-deviation, covariance and correlation, and slant, of glyph shapes, using the control polygon only.

Note that if the glyph shape is self-intersecting, the values are not correct (but well-defined). Moreover, area will be negative if contour directions are clockwise.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True
class fontTools.pens.statisticsPen.StatisticsPen(glyphset=None)

Pen calculating area, center of mass, variance and standard-deviation, covariance and correlation, and slant, of glyph shapes.

Note that if the glyph shape is self-intersecting, the values are not correct (but well-defined). Moreover, area will be negative if contour directions are clockwise.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

svgPathPen

class fontTools.pens.svgPathPen.SVGPathPen(glyphSet, ntos: ~typing.Callable[[float], str] = <class 'str'>)

Pen to draw SVG path d commands.

Example::
>>> pen = SVGPathPen(None)
>>> pen.moveTo((0, 0))
>>> pen.lineTo((1, 1))
>>> pen.curveTo((2, 2), (3, 3), (4, 4))
>>> pen.closePath()
>>> pen.getCommands()
'M0 0 1 1C2 2 3 3 4 4Z'
Parameters:
  • glyphSet – a dictionary of drawable glyph objects keyed by name used to resolve component references in composite glyphs.

  • ntos – a callable that takes a number and returns a string, to customize how numbers are formatted (default: str).

Note

Fonts have a coordinate system where Y grows up, whereas in SVG, Y grows down. As such, rendering path data from this pen in SVG typically results in upside-down glyphs. You can fix this by wrapping the data from this pen in an SVG group element with transform, or wrap this pen in a transform pen. For example:

spen = svgPathPen.SVGPathPen(glyphset) pen= TransformPen(spen , (1, 0, 0, -1, 0, 0)) glyphset[glyphname].draw(pen) print(tpen.getCommands())

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

getCommands()
lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True
fontTools.pens.svgPathPen.main(args=None)

Generate per-character SVG from font and text

fontTools.pens.svgPathPen.pointToString(pt, ntos=<class 'str'>)

t2CharStringPen

class fontTools.pens.t2CharStringPen.T2CharStringPen(width, glyphSet, roundTolerance=0.5, CFF2=False)

Pen to draw Type 2 CharStrings.

The ‘roundTolerance’ argument controls the rounding of point coordinates. It is defined as the maximum absolute difference between the original float and the rounded integer value. The default tolerance of 0.5 means that all floats are rounded to integer; a value of 0 disables rounding; values in between will only round floats which are close to their integral part within the tolerated range.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

getCharString(private=None, globalSubrs=None, optimize=True)
lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

teePen

Pen multiplexing drawing to one or more pens.

class fontTools.pens.teePen.TeePen(*pens)

Pen multiplexing drawing to one or more pens.

Use either as TeePen(pen1, pen2, …) or TeePen(iterableOfPens).

addComponent(glyphName, transformation)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(p1)

Draw a straight line from the current point to ‘pt’.

moveTo(p0)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

transformPen

class fontTools.pens.transformPen.TransformPen(outPen, transformation)

Pen that transforms all coordinates using a Affine transformation, and passes them to another pen.

addComponent(glyphName, transformation)

Add a sub glyph. The ‘transformation’ argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

class fontTools.pens.transformPen.TransformPointPen(outPointPen, transformation)

PointPen that transforms all coordinates using a Affine transformation, and passes them to another PointPen.

>>> from fontTools.pens.recordingPen import RecordingPointPen
>>> rec = RecordingPointPen()
>>> pen = TransformPointPen(rec, (2, 0, 0, 2, -10, 5))
>>> v = iter(rec.value)
>>> pen.beginPath(identifier="contour-0")
>>> next(v)
('beginPath', (), {'identifier': 'contour-0'})
>>> pen.addPoint((100, 100), "line")
>>> next(v)
('addPoint', ((190, 205), 'line', False, None), {})
>>> pen.endPath()
>>> next(v)
('endPath', (), {})
>>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0")
>>> next(v)
('addComponent', ('a', <Transform [2 0 0 2 -30 15]>), {'identifier': 'component-0'})
addComponent(baseGlyphName, transformation, **kwargs)

Add a sub glyph.

addPoint(pt, segmentType=None, smooth=False, name=None, **kwargs)

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(**kwargs)

Start a new sub path.

endPath()

End the current sub path.

ttGlyphPen

class fontTools.pens.ttGlyphPen.TTGlyphPen(glyphSet: Dict[str, Any] | None = None, handleOverflowingTransforms: bool = True, outputImpliedClosingLine: bool = False)

Pen used for drawing to a TrueType glyph.

This pen can be used to construct or modify glyphs in a TrueType format font. After using the pen to draw, use the .glyph() method to retrieve a Glyph object representing the glyph.

addComponent(baseGlyphName: str, transformation: Tuple[float, float, float, float, float, float], identifier: str | None = None, **kwargs: Any) None

Add a sub glyph.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float]) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath() None

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points) None

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

drawMethod = 'draw'
endPath() None

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

glyph(componentFlags: int = 4, dropImpliedOnCurves: bool = False, *, round: ~typing.Callable[[float], int] = <function otRound>) Glyph

Returns a Glyph object representing the glyph.

Parameters:
  • componentFlags – Flags to use for component glyphs. (default: 0x04)

  • dropImpliedOnCurves – Whether to remove implied-oncurve points. (default: False)

init() None
lineTo(pt: Tuple[float, float]) None

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt: Tuple[float, float]) None

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points) None

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

transformPen

alias of TransformPen

class fontTools.pens.ttGlyphPen.TTGlyphPointPen(glyphSet: Dict[str, Any] | None, handleOverflowingTransforms: bool = True)

Point pen used for drawing to a TrueType glyph.

This pen can be used to construct or modify glyphs in a TrueType format font. After using the pen to draw, use the .glyph() method to retrieve a Glyph object representing the glyph.

addComponent(baseGlyphName: str, transformation: Tuple[float, float, float, float, float, float], identifier: str | None = None, **kwargs: Any) None

Add a sub glyph.

addPoint(pt: Tuple[float, float], segmentType: str | None = None, smooth: bool = False, name: str | None = None, identifier: str | None = None, **kwargs: Any) None

Add a point to the current sub path.

addVarComponent(glyphName: str, transformation: DecomposedTransform, location: Dict[str, float], identifier: str | None = None, **kwargs: Any) None

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

beginPath(identifier: str | None = None, **kwargs: Any) None

Start a new sub path.

drawMethod = 'drawPoints'
endPath() None

End the current sub path.

glyph(componentFlags: int = 4, dropImpliedOnCurves: bool = False, *, round: ~typing.Callable[[float], int] = <function otRound>) Glyph

Returns a Glyph object representing the glyph.

Parameters:
  • componentFlags – Flags to use for component glyphs. (default: 0x04)

  • dropImpliedOnCurves – Whether to remove implied-oncurve points. (default: False)

init() None
property log
transformPen

alias of TransformPointPen

wxPen

class fontTools.pens.wxPen.WxPen(glyphSet, path=None)
exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

skipMissingComponents = True

subset

cff

pyftsubset – OpenType font subsetter and optimizer

pyftsubset is an OpenType font subsetter and optimizer, based on fontTools. It accepts any TT- or CFF-flavored OpenType (.otf or .ttf) or WOFF (.woff) font file. The subsetted glyph set is based on the specified glyphs or characters, and specified OpenType layout features.

The tool also performs some size-reducing optimizations, aimed for using subset fonts as webfonts. Individual optimizations can be enabled or disabled, and are enabled by default when they are safe.

Usage: pyftsubset font-file [glyph…] [–option=value]…

At least one glyph or one of –gids, –gids-file, –glyphs, –glyphs-file, –text, –text-file, –unicodes, or –unicodes-file, must be specified.

Args:

font-file

The input font file.

glyph

Specify one or more glyph identifiers to include in the subset. Must be PS glyph names, or the special string ‘*’ to keep the entire glyph set.

Initial glyph set specification

These options populate the initial glyph set. Same option can appear multiple times, and the results are accummulated.

–gids=<NNN>[,<NNN>…]

Specify comma/whitespace-separated list of glyph IDs or ranges as decimal numbers. For example, –gids=10-12,14 adds glyphs with numbers 10, 11, 12, and 14.

--gids-file=<path>

Like –gids but reads from a file. Anything after a ‘#’ on any line is ignored as comments.

–glyphs=<glyphname>[,<glyphname>…]

Specify comma/whitespace-separated PS glyph names to add to the subset. Note that only PS glyph names are accepted, not gidNNN, U+XXXX, etc that are accepted on the command line. The special string ‘*’ will keep the entire glyph set.

--glyphs-file=<path>

Like –glyphs but reads from a file. Anything after a ‘#’ on any line is ignored as comments.

--text=<text>

Specify characters to include in the subset, as UTF-8 string.

--text-file=<path>

Like –text but reads from a file. Newline character are not added to the subset.

–unicodes=<XXXX>[,<XXXX>…]

Specify comma/whitespace-separated list of Unicode codepoints or ranges as hex numbers, optionally prefixed with ‘U+’, ‘u’, etc. For example, –unicodes=41-5a,61-7a adds ASCII letters, so does the more verbose –unicodes=U+0041-005A,U+0061-007A. The special strings ‘*’ will choose all Unicode characters mapped by the font.

--unicodes-file=<path>

Like –unicodes, but reads from a file. Anything after a ‘#’ on any line in the file is ignored as comments.

--ignore-missing-glyphs

Do not fail if some requested glyphs or gids are not available in the font.

--no-ignore-missing-glyphs

Stop and fail if some requested glyphs or gids are not available in the font. [default]

–ignore-missing-unicodes [default]

Do not fail if some requested Unicode characters (including those indirectly specified using –text or –text-file) are not available in the font.

--no-ignore-missing-unicodes

Stop and fail if some requested Unicode characters are not available in the font. Note the default discrepancy between ignoring missing glyphs versus unicodes. This is for historical reasons and in the future –no-ignore-missing-unicodes might become default.

Other options

For the other options listed below, to see the current value of the option, pass a value of ‘?’ to it, with or without a ‘=’.

Examples:

$ pyftsubset --glyph-names?
Current setting for 'glyph-names' is: False
$ ./pyftsubset --name-IDs=?
Current setting for 'name-IDs' is: [0, 1, 2, 3, 4, 5, 6]
$ ./pyftsubset --hinting? --no-hinting --hinting?
Current setting for 'hinting' is: True
Current setting for 'hinting' is: False

Output options

--output-file=<path>

The output font file. If not specified, the subsetted font will be saved in as font-file.subset.

--flavor=<type>

Specify flavor of output font file. May be ‘woff’ or ‘woff2’. Note that WOFF2 requires the Brotli Python extension, available at https://github.com/google/brotli

--with-zopfli

Use the Google Zopfli algorithm to compress WOFF. The output is 3-8 % smaller than pure zlib, but the compression speed is much slower. The Zopfli Python bindings are available at: https://pypi.python.org/pypi/zopfli

--harfbuzz-repacker

By default, we serialize GPOS/GSUB using the HarfBuzz Repacker when uharfbuzz can be imported and is successful, otherwise fall back to the pure-python serializer. Set the option to force using the HarfBuzz Repacker (raises an error if uharfbuzz can’t be found or fails).

--no-harfbuzz-repacker

Always use the pure-python serializer even if uharfbuzz is available.

Glyph set expansion

These options control how additional glyphs are added to the subset.

--retain-gids

Retain glyph indices; just empty glyphs not needed in-place.

--notdef-glyph

Add the ‘.notdef’ glyph to the subset (ie, keep it). [default]

--no-notdef-glyph

Drop the ‘.notdef’ glyph unless specified in the glyph set. This saves a few bytes, but is not possible for Postscript-flavored fonts, as those require ‘.notdef’. For TrueType-flavored fonts, this works fine as long as no unsupported glyphs are requested from the font.

--notdef-outline

Keep the outline of ‘.notdef’ glyph. The ‘.notdef’ glyph outline is used when glyphs not supported by the font are to be shown. It is not needed otherwise.

--no-notdef-outline

When including a ‘.notdef’ glyph, remove its outline. This saves a few bytes. [default]

--recommended-glyphs

Add glyphs 0, 1, 2, and 3 to the subset, as recommended for TrueType-flavored fonts: ‘.notdef’, ‘NULL’ or ‘.null’, ‘CR’, ‘space’. Some legacy software might require this, but no modern system does.

--no-recommended-glyphs

Do not add glyphs 0, 1, 2, and 3 to the subset, unless specified in glyph set. [default]

--no-layout-closure

Do not expand glyph set to add glyphs produced by OpenType layout features. Instead, OpenType layout features will be subset to only rules that are relevant to the otherwise-specified glyph set.

–layout-features[+|-]=<feature>[,<feature>…]

Specify (=), add to (+=) or exclude from (-=) the comma-separated set of OpenType layout feature tags that will be preserved. Glyph variants used by the preserved features are added to the specified subset glyph set. By default, ‘calt’, ‘ccmp’, ‘clig’, ‘curs’, ‘dnom’, ‘frac’, ‘kern’, ‘liga’, ‘locl’, ‘mark’, ‘mkmk’, ‘numr’, ‘rclt’, ‘rlig’, ‘rvrn’, and all features required for script shaping are preserved. To see the full list, try ‘–layout-features=?’. Use ‘*’ to keep all features. Multiple –layout-features options can be provided if necessary. Examples:

–layout-features+=onum,pnum,ss01
  • Keep the default set of features and ‘onum’, ‘pnum’, ‘ss01’.

–layout-features-=’mark’,’mkmk’
  • Keep the default set of features but drop ‘mark’ and ‘mkmk’.

–layout-features=’kern’
  • Only keep the ‘kern’ feature, drop all others.

–layout-features=’’
  • Drop all features.

–layout-features=’*’
  • Keep all features.

–layout-features+=aalt –layout-features-=vrt2
  • Keep default set of features plus ‘aalt’, but drop ‘vrt2’.

–layout-scripts[+|-]=<script>[,<script>…]

Specify (=), add to (+=) or exclude from (-=) the comma-separated set of OpenType layout script tags that will be preserved. LangSys tags can be appended to script tag, separated by ‘.’, for example: ‘arab.dflt,arab.URD,latn.TRK’. By default all scripts are retained (‘*’).

Hinting options

--hinting

Keep hinting [default]

--no-hinting

Drop glyph-specific hinting and font-wide hinting tables, as well as remove hinting-related bits and pieces from other tables (eg. GPOS). See –hinting-tables for list of tables that are dropped by default. Instructions and hints are stripped from ‘glyf’ and ‘CFF ‘ tables respectively. This produces (sometimes up to 30%) smaller fonts that are suitable for extremely high-resolution systems, like high-end mobile devices and retina displays.

Optimization options

--desubroutinize

Remove CFF use of subroutinizes. Subroutinization is a way to make CFF fonts smaller. For small subsets however, desubroutinizing might make the font smaller. It has even been reported that desubroutinized CFF fonts compress better (produce smaller output) WOFF and WOFF2 fonts. Also see note under –no-hinting.

–no-desubroutinize [default]

Leave CFF subroutinizes as is, only throw away unused subroutinizes.

Font table options

–drop-tables[+|-]=<table>[,<table>…]

Specify (=), add to (+=) or exclude from (-=) the comma-separated set of tables that will be be dropped. By default, the following tables are dropped: ‘BASE’, ‘JSTF’, ‘DSIG’, ‘EBDT’, ‘EBLC’, ‘EBSC’, ‘PCLT’, ‘LTSH’ and Graphite tables: ‘Feat’, ‘Glat’, ‘Gloc’, ‘Silf’, ‘Sill’. The tool will attempt to subset the remaining tables.

Examples:

--drop-tables-=BASE
  • Drop the default set of tables but keep ‘BASE’.

–drop-tables+=GSUB
  • Drop the default set of tables and ‘GSUB’.

--drop-tables=DSIG
  • Only drop the ‘DSIG’ table, keep all others.

–drop-tables=
  • Keep all tables.

–no-subset-tables+=<table>[,<table>…]

Add to the set of tables that will not be subsetted. By default, the following tables are included in this list, as they do not need subsetting (ignore the fact that ‘loca’ is listed here): ‘gasp’, ‘head’, ‘hhea’, ‘maxp’, ‘vhea’, ‘OS/2’, ‘loca’, ‘name’, ‘cvt ‘, ‘fpgm’, ‘prep’, ‘VMDX’, ‘DSIG’, ‘CPAL’, ‘MVAR’, ‘cvar’, ‘STAT’. By default, tables that the tool does not know how to subset and are not specified here will be dropped from the font, unless –passthrough-tables option is passed.

Example:

–no-subset-tables+=FFTM
  • Keep ‘FFTM’ table in the font by preventing subsetting.

--passthrough-tables

Do not drop tables that the tool does not know how to subset.

--no-passthrough-tables

Tables that the tool does not know how to subset and are not specified in –no-subset-tables will be dropped from the font. [default]

–hinting-tables[-]=<table>[,<table>…]

Specify (=), add to (+=) or exclude from (-=) the list of font-wide hinting tables that will be dropped if –no-hinting is specified.

Examples:

--hinting-tables-=VDMX
  • Drop font-wide hinting tables except ‘VDMX’.

–hinting-tables=
  • Keep all font-wide hinting tables (but strip hints from glyphs).

--legacy-kern

Keep TrueType ‘kern’ table even when OpenType ‘GPOS’ is available.

--no-legacy-kern

Drop TrueType ‘kern’ table if OpenType ‘GPOS’ is available. [default]

Font naming options

These options control what is retained in the ‘name’ table. For numerical codes, see: http://www.microsoft.com/typography/otspec/name.htm

–name-IDs[+|-]=<nameID>[,<nameID>…]

Specify (=), add to (+=) or exclude from (-=) the set of ‘name’ table entry nameIDs that will be preserved. By default, only nameIDs between 0 and 6 are preserved, the rest are dropped. Use ‘*’ to keep all entries.

Examples:

–name-IDs+=7,8,9
  • Also keep Trademark, Manufacturer and Designer name entries.

–name-IDs=
  • Drop all ‘name’ table entries.

–name-IDs=*
  • keep all ‘name’ table entries

--name-legacy

Keep legacy (non-Unicode) ‘name’ table entries (0.x, 1.x etc.). XXX Note: This might be needed for some fonts that have no Unicode name entires for English. See: https://github.com/fonttools/fonttools/issues/146

--no-name-legacy

Drop legacy (non-Unicode) ‘name’ table entries [default]

–name-languages[+|-]=<langID>[,<langID>]

Specify (=), add to (+=) or exclude from (-=) the set of ‘name’ table langIDs that will be preserved. By default only records with langID 0x0409 (English) are preserved. Use ‘*’ to keep all langIDs.

--obfuscate-names

Make the font unusable as a system font by replacing name IDs 1, 2, 3, 4, and 6 with dummy strings (it is still fully functional as webfont).

Glyph naming and encoding options

--glyph-names

Keep PS glyph names in TT-flavored fonts. In general glyph names are not needed for correct use of the font. However, some PDF generators and PDF viewers might rely on glyph names to extract Unicode text from PDF documents.

--no-glyph-names

Drop PS glyph names in TT-flavored fonts, by using ‘post’ table version 3.0. [default]

--legacy-cmap

Keep the legacy ‘cmap’ subtables (0.x, 1.x, 4.x etc.).

--no-legacy-cmap

Drop the legacy ‘cmap’ subtables. [default]

--symbol-cmap

Keep the 3.0 symbol ‘cmap’.

--no-symbol-cmap

Drop the 3.0 symbol ‘cmap’. [default]

Other font-specific options

--recalc-bounds

Recalculate font bounding boxes.

--no-recalc-bounds

Keep original font bounding boxes. This is faster and still safe for all practical purposes. [default]

--recalc-timestamp

Set font ‘modified’ timestamp to current time.

--no-recalc-timestamp

Do not modify font ‘modified’ timestamp. [default]

--canonical-order

Order tables as recommended in the OpenType standard. This is not required by the standard, nor by any known implementation.

--no-canonical-order

Keep original order of font tables. This is faster. [default]

--prune-unicode-ranges

Update the ‘OS/2 ulUnicodeRange*’ bits after subsetting. The Unicode ranges defined in the OpenType specification v1.7 are intersected with the Unicode codepoints specified in the font’s Unicode ‘cmap’ subtables: when no overlap is found, the bit will be switched off. However, it will not be switched on if an intersection is found. [default]

--no-prune-unicode-ranges

Don’t change the ‘OS/2 ulUnicodeRange*’ bits.

--prune-codepage-ranges

Update the ‘OS/2 ulCodePageRange*’ bits after subsetting. [default]

--no-prune-codepage-ranges

Don’t change the ‘OS/2 ulCodePageRange*’ bits.

--recalc-average-width

Update the ‘OS/2 xAvgCharWidth’ field after subsetting.

--no-recalc-average-width

Don’t change the ‘OS/2 xAvgCharWidth’ field. [default]

--recalc-max-context

Update the ‘OS/2 usMaxContext’ field after subsetting.

--no-recalc-max-context

Don’t change the ‘OS/2 usMaxContext’ field. [default]

--font-number=<number>

Select font number for TrueType Collection (.ttc/.otc), starting from 0.

--pretty-svg

When subsetting SVG table, use lxml pretty_print=True option to indent the XML output (only recommended for debugging purposes).

Application options

--verbose

Display verbose information of the subsetting process.

--timing

Display detailed timing information of the subsetting process.

--xml

Display the TTX XML representation of subsetted font.

Example

Produce a subset containing the characters ‘ !”#$%’ without performing size-reducing optimizations:

$ pyftsubset font.ttf --unicodes="U+0020-0025" \
  --layout-features=* --glyph-names --symbol-cmap --legacy-cmap \
  --notdef-glyph --notdef-outline --recommended-glyphs \
  --name-IDs=* --name-legacy --name-languages=*
class fontTools.subset.Options(**kwargs)
exception OptionError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception UnknownOptionError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

parse_opts(argv, ignore_unknown=[])
set(**kwargs)
class fontTools.subset.Subsetter(options=None)
exception MissingGlyphsSubsettingError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception MissingUnicodesSubsettingError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception SubsettingError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

populate(glyphs=[], gids=[], unicodes=[], text='')
subset(font)
fontTools.subset.load_font(fontFile, options, checkChecksums=0, dontLoadGlyphNames=False, lazy=True)
fontTools.subset.main(args=None)

OpenType font subsetter and optimizer

fontTools.subset.parse_gids(s)
fontTools.subset.parse_glyphs(s)
fontTools.subset.parse_unicodes(s)
fontTools.subset.save_font(font, outfile, options)

svgLib

path

parser
fontTools.svgLib.path.parser.parse_path(pathdef, pen, current_pos=(0, 0), arc_class=<class 'fontTools.svgLib.path.arc.EllipticalArc'>)

Parse SVG path definition (i.e. “d” attribute of <path> elements) and call a ‘pen’ object’s moveTo, lineTo, curveTo, qCurveTo and closePath methods.

If ‘current_pos’ (2-float tuple) is provided, the initial moveTo will be relative to that instead being absolute.

If the pen has an “arcTo” method, it is called with the original values of the elliptical arc curve commands:

pen.arcTo(rx, ry, rotation, arc_large, arc_sweep, (x, y))

Otherwise, the arcs are approximated by series of cubic Bezier segments (“curveTo”), one every 90 degrees.

class fontTools.svgLib.path.SVGPath(filename=None, transform=None)

Parse SVG path elements from a file or string, and draw them onto a glyph object that supports the FontTools Pen protocol.

For example, reading from an SVG file and drawing to a Defcon Glyph:

import defcon glyph = defcon.Glyph() pen = glyph.getPen() svg = SVGPath(“path/to/a.svg”) svg.draw(pen)

Or reading from a string containing SVG data, using the alternative ‘fromstring’ (a class method):

data = ‘<?xml version=”1.0” …’ svg = SVGPath.fromstring(data) svg.draw(pen)

Both constructors can optionally take a ‘transform’ matrix (6-float tuple, or a FontTools Transform object) to modify the draw output.

draw(pen)
classmethod fromstring(data, transform=None)
fontTools.svgLib.path.parse_path(pathdef, pen, current_pos=(0, 0), arc_class=<class 'fontTools.svgLib.path.arc.EllipticalArc'>)

Parse SVG path definition (i.e. “d” attribute of <path> elements) and call a ‘pen’ object’s moveTo, lineTo, curveTo, qCurveTo and closePath methods.

If ‘current_pos’ (2-float tuple) is provided, the initial moveTo will be relative to that instead being absolute.

If the pen has an “arcTo” method, it is called with the original values of the elliptical arc curve commands:

pen.arcTo(rx, ry, rotation, arc_large, arc_sweep, (x, y))

Otherwise, the arcs are approximated by series of cubic Bezier segments (“curveTo”), one every 90 degrees.

t1Lib

fontTools.t1Lib.py – Tools for PostScript Type 1 fonts.

Functions for reading and writing raw Type 1 data:

read(path)

reads any Type 1 font file, returns the raw data and a type indicator: ‘LWFN’, ‘PFB’ or ‘OTHER’, depending on the format of the file pointed to by ‘path’. Raises an error when the file does not contain valid Type 1 data.

write(path, data, kind=’OTHER’, dohex=False)

writes raw Type 1 data to the file pointed to by ‘path’. ‘kind’ can be one of ‘LWFN’, ‘PFB’ or ‘OTHER’; it defaults to ‘OTHER’. ‘dohex’ is a flag which determines whether the eexec encrypted part should be written as hexadecimal or binary, but only if kind is ‘OTHER’.

exception fontTools.t1Lib.T1Error
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.t1Lib.T1Font(path, encoding='ascii', kind=None)

Type 1 font class.

Uses a minimal interpeter that supports just about enough PS to parse Type 1 fonts.

createData()
encode_eexec(eexec_dict)
getData()
getGlyphSet()

Return a generic GlyphSet, which is a dict-like object mapping glyph names to glyph objects. The returned glyph objects have a .draw() method that supports the Pen protocol, and will have an attribute named ‘width’, but only after the .draw() method has been called.

In the case of Type 1, the GlyphSet is simply the CharStrings dict.

parse()
saveAs(path, type, dohex=False)
fontTools.t1Lib.assertType1(data)
fontTools.t1Lib.deHexString(hexstring)
fontTools.t1Lib.decryptType1(data)
fontTools.t1Lib.findEncryptedChunks(data)
fontTools.t1Lib.isHex(text)
fontTools.t1Lib.longToString(long)
fontTools.t1Lib.read(path, onlyHeader=False)

reads any Type 1 font file, returns raw data

fontTools.t1Lib.readLWFN(path, onlyHeader=False)

reads an LWFN font file, returns raw data

fontTools.t1Lib.readOther(path)

reads any (font) file, returns raw data

fontTools.t1Lib.readPFB(path, onlyHeader=False)

reads a PFB font file, returns raw data

fontTools.t1Lib.stringToLong(s)
fontTools.t1Lib.write(path, data, kind='OTHER', dohex=False)
fontTools.t1Lib.writeLWFN(path, data)
fontTools.t1Lib.writeOther(path, data, dohex=False)
fontTools.t1Lib.writePFB(path, data)

tfmLib: Read TeX Font Metrics files

Module for reading TFM (TeX Font Metrics) files.

The TFM format is described in the TFtoPL WEB source code, whose typeset form can be found on CTAN.

>>> from fontTools.tfmLib import TFM
>>> tfm = TFM("Tests/tfmLib/data/cmr10.tfm")
>>>
>>> # Accessing an attribute gets you metadata.
>>> tfm.checksum
1274110073
>>> tfm.designsize
10.0
>>> tfm.codingscheme
'TeX text'
>>> tfm.family
'CMR'
>>> tfm.seven_bit_safe_flag
False
>>> tfm.face
234
>>> tfm.extraheader
{}
>>> tfm.fontdimens
{'SLANT': 0.0, 'SPACE': 0.33333396911621094, 'STRETCH': 0.16666698455810547, 'SHRINK': 0.11111164093017578, 'XHEIGHT': 0.4305553436279297, 'QUAD': 1.0000028610229492, 'EXTRASPACE': 0.11111164093017578}
>>> # Accessing a character gets you its metrics.
>>> # “width” is always available, other metrics are available only when
>>> # applicable. All values are relative to “designsize”.
>>> tfm.chars[ord("g")]
{'width': 0.5000019073486328, 'height': 0.4305553436279297, 'depth': 0.1944446563720703, 'italic': 0.013888359069824219}
>>> # Kerning and ligature can be accessed as well.
>>> tfm.kerning[ord("c")]
{104: -0.02777862548828125, 107: -0.02777862548828125}
>>> tfm.ligatures[ord("f")]
{105: ('LIG', 12), 102: ('LIG', 11), 108: ('LIG', 13)}
exception fontTools.tfmLib.TFMException(message)
add_note()

Exception.add_note(note) – add a note to the exception

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class fontTools.tfmLib.TFM(file)

ttLib: Read/write OpenType and TrueType fonts

Most users of the fontTools library will be using it to generate or manipulate OpenType and TrueType fonts. (FontTools initially only supported TrueType fonts, gaining OpenType support in version 2.0, and so uses the tt prefix to refer to both kinds of font. Because of this we will refer to both as “TrueType fonts” unless we need to make a distinction.)

The main entry point for such operations is the fontTools.ttLib.ttFont module, but other modules also provide useful functionality for handling OpenType fonts.

ttFont: Read/write OpenType and TrueType fonts

class fontTools.ttLib.ttFont.TTFont(file=None, res_name_or_index=None, sfntVersion='\x00\x01\x00\x00', flavor=None, checkChecksums=0, verbose=None, recalcBBoxes=True, allowVID=NotImplemented, ignoreDecompileErrors=False, recalcTimestamp=True, fontNumber=-1, lazy=None, quiet=None, _tableCache=None, cfg={})

Represents a TrueType font.

The object manages file input and output, and offers a convenient way of accessing tables. Tables will be only decompiled when necessary, ie. when they’re actually accessed. This means that simple operations can be extremely fast.

Example usage:

>> from fontTools import ttLib
>> tt = ttLib.TTFont("afont.ttf") # Load an existing font file
>> tt['maxp'].numGlyphs
242
>> tt['OS/2'].achVendID
'B&H'
>> tt['head'].unitsPerEm
2048

For details of the objects returned when accessing each table, see tables. To add a table to the font, use the newTable() function:

>> os2 = newTable("OS/2")
>> os2.version = 4
>> # set other attributes
>> font["OS/2"] = os2

TrueType fonts can also be serialized to and from XML format (see also the ttx binary):

>> tt.saveXML("afont.ttx")
Dumping 'LTSH' table...
Dumping 'OS/2' table...
[...]

>> tt2 = ttLib.TTFont() # Create a new font object
>> tt2.importXML("afont.ttx")
>> tt2['maxp'].numGlyphs
242

The TTFont object may be used as a context manager; this will cause the file reader to be closed after the context with block is exited:

with TTFont(filename) as f:
        # Do stuff
Parameters:
  • file – When reading a font from disk, either a pathname pointing to a file, or a readable file object.

  • res_name_or_index – If running on a Macintosh, either a sfnt resource name or an sfnt resource index number. If the index number is zero, TTLib will autodetect whether the file is a flat file or a suitcase. (If it is a suitcase, only the first ‘sfnt’ resource will be read.)

  • sfntVersion (str) – When constructing a font object from scratch, sets the four-byte sfnt magic number to be used. Defaults to \\\ (TrueType). To create an OpenType file, use OTTO.

  • flavor (str) – Set this to woff when creating a WOFF file or woff2 for a WOFF2 file.

  • checkChecksums (int) – How checksum data should be treated. Default is 0 (no checking). Set to 1 to check and warn on wrong checksums; set to 2 to raise an exception if any wrong checksums are found.

  • recalcBBoxes (bool) – If true (the default), recalculates glyf, CFF ``, ``head bounding box values and hhea/vhea min/max values on save. Also compiles the glyphs on importing, which saves memory consumption and time.

  • ignoreDecompileErrors (bool) – If true, exceptions raised during table decompilation will be ignored, and the binary data will be returned for those tables instead.

  • recalcTimestamp (bool) – If true (the default), sets the modified timestamp in the head table on save.

  • fontNumber (int) – The index of the font in a TrueType Collection file.

  • lazy (bool) – If lazy is set to True, many data structures are loaded lazily, upon access only. If it is set to False, many data structures are loaded immediately. The default is lazy=None which is somewhere in between.

close()

If we still have a reader object, close it.

ensureDecompiled(recurse=None)

Decompile all the tables, even if a TTFont was opened in ‘lazy’ mode.

get(tag, default=None)

Returns the table if it exists or (optionally) a default if it doesn’t.

getBestCmap(cmapPreferences=((3, 10), (0, 6), (0, 4), (3, 1), (0, 3), (0, 2), (0, 1), (0, 0)))

Returns the ‘best’ Unicode cmap dictionary available in the font or None, if no Unicode cmap subtable is available.

By default it will search for the following (platformID, platEncID) pairs in order:

(3, 10), # Windows Unicode full repertoire
(0, 6),  # Unicode full repertoire (format 13 subtable)
(0, 4),  # Unicode 2.0 full repertoire
(3, 1),  # Windows Unicode BMP
(0, 3),  # Unicode 2.0 BMP
(0, 2),  # Unicode ISO/IEC 10646
(0, 1),  # Unicode 1.1
(0, 0)   # Unicode 1.0

This particular order matches what HarfBuzz uses to choose what subtable to use by default. This order prefers the largest-repertoire subtable, and among those, prefers the Windows-platform over the Unicode-platform as the former has wider support.

This order can be customized via the cmapPreferences argument.

getGlyphID(glyphName)

Returns the ID of the glyph with the given name.

getGlyphIDMany(lst)

Converts a list of glyph names into a list of glyph IDs.

getGlyphName(glyphID)

Returns the name for the glyph with the given ID.

If no name is available, synthesises one with the form glyphXXXXX` where `XXXXX is the zero-padded glyph ID.

getGlyphNameMany(lst)

Converts a list of glyph IDs into a list of glyph names.

getGlyphNames()

Get a list of glyph names, sorted alphabetically.

getGlyphNames2()

Get a list of glyph names, sorted alphabetically, but not case sensitive.

getGlyphOrder()

Returns a list of glyph names ordered by their position in the font.

getGlyphSet(preferCFF=True, location=None, normalized=False, recalcBounds=True)

Return a generic GlyphSet, which is a dict-like object mapping glyph names to glyph objects. The returned glyph objects have a .draw() method that supports the Pen protocol, and will have an attribute named ‘width’.

If the font is CFF-based, the outlines will be taken from the CFF `` or ``CFF2 tables. Otherwise the outlines will be taken from the glyf table.

If the font contains both a CFF ``/``CFF2 and a glyf table, you can use the preferCFF argument to specify which one should be taken. If the font contains both a CFF `` and a ``CFF2 table, the latter is taken.

If the location parameter is set, it should be a dictionary mapping four-letter variation tags to their float values, and the returned glyph-set will represent an instance of a variable font at that location.

If the normalized variable is set to True, that location is interpreted as in the normalized (-1..+1) space, otherwise it is in the font’s defined axes space.

getReverseGlyphMap(rebuild=False)

Returns a mapping of glyph names to glyph IDs.

getTableData(tag)

Returns the binary representation of a table.

If the table is currently loaded and in memory, the data is compiled to binary and returned; if it is not currently loaded, the binary data is read from the font file and returned.

has_key(tag)

Test if the table identified by tag is present in the font.

As well as this method, tag in font can also be used to determine the presence of the table.

importXML(fileOrPath, quiet=None)

Import a TTX file (an XML-based text format), so as to recreate a font object.

isLoaded(tag)

Return true if the table identified by tag has been decompiled and loaded into memory.

keys()

Returns the list of tables in the font, along with the GlyphOrder pseudo-table.

normalizeLocation(location)

Normalize a location from the font’s defined axes space (also known as user space) into the normalized (-1..+1) space. It applies avar mapping if the font contains an avar table.

The location parameter should be a dictionary mapping four-letter variation tags to their float values.

Raises TTLibError if the font is not a variable font.

save(file, reorderTables=True)

Save the font to disk.

Parameters:
  • file – Similarly to the constructor, can be either a pathname or a writable file object.

  • reorderTables (Option[bool]) – If true (the default), reorder the tables, sorting them by tag (recommended by the OpenType specification). If false, retain the original font order. If None, reorder by table dependency (fastest).

saveXML(fileOrPath, newlinestr='\n', **kwargs)

Export the font as TTX (an XML-based text file), or as a series of text files when splitTables is true. In the latter case, the ‘fileOrPath’ argument should be a path to a directory. The ‘tables’ argument must either be false (dump all tables) or a list of tables to dump. The ‘skipTables’ argument may be a list of tables to skip, but only when the ‘tables’ argument is false.

setGlyphOrder(glyphOrder)

Set the glyph order

Parameters:

glyphOrder ([str]) – List of glyph names in order.

class fontTools.ttLib.ttFont.GlyphOrder(tag=None)

A pseudo table. The glyph order isn’t in the font as a separate table, but it’s nice to present it as such in the TTX format.

fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.ttFont.GlyphOrder(tag=None)

A pseudo table. The glyph order isn’t in the font as a separate table, but it’s nice to present it as such in the TTX format.

class fontTools.ttLib.ttFont.TTFont(file=None, res_name_or_index=None, sfntVersion='\x00\x01\x00\x00', flavor=None, checkChecksums=0, verbose=None, recalcBBoxes=True, allowVID=NotImplemented, ignoreDecompileErrors=False, recalcTimestamp=True, fontNumber=-1, lazy=None, quiet=None, _tableCache=None, cfg={})

Represents a TrueType font.

The object manages file input and output, and offers a convenient way of accessing tables. Tables will be only decompiled when necessary, ie. when they’re actually accessed. This means that simple operations can be extremely fast.

Example usage:

>> from fontTools import ttLib
>> tt = ttLib.TTFont("afont.ttf") # Load an existing font file
>> tt['maxp'].numGlyphs
242
>> tt['OS/2'].achVendID
'B&H'
>> tt['head'].unitsPerEm
2048

For details of the objects returned when accessing each table, see tables. To add a table to the font, use the newTable() function:

>> os2 = newTable("OS/2")
>> os2.version = 4
>> # set other attributes
>> font["OS/2"] = os2

TrueType fonts can also be serialized to and from XML format (see also the ttx binary):

>> tt.saveXML("afont.ttx")
Dumping 'LTSH' table...
Dumping 'OS/2' table...
[...]

>> tt2 = ttLib.TTFont() # Create a new font object
>> tt2.importXML("afont.ttx")
>> tt2['maxp'].numGlyphs
242

The TTFont object may be used as a context manager; this will cause the file reader to be closed after the context with block is exited:

with TTFont(filename) as f:
        # Do stuff
Parameters:
  • file – When reading a font from disk, either a pathname pointing to a file, or a readable file object.

  • res_name_or_index – If running on a Macintosh, either a sfnt resource name or an sfnt resource index number. If the index number is zero, TTLib will autodetect whether the file is a flat file or a suitcase. (If it is a suitcase, only the first ‘sfnt’ resource will be read.)

  • sfntVersion (str) – When constructing a font object from scratch, sets the four-byte sfnt magic number to be used. Defaults to \\\ (TrueType). To create an OpenType file, use OTTO.

  • flavor (str) – Set this to woff when creating a WOFF file or woff2 for a WOFF2 file.

  • checkChecksums (int) – How checksum data should be treated. Default is 0 (no checking). Set to 1 to check and warn on wrong checksums; set to 2 to raise an exception if any wrong checksums are found.

  • recalcBBoxes (bool) – If true (the default), recalculates glyf, CFF ``, ``head bounding box values and hhea/vhea min/max values on save. Also compiles the glyphs on importing, which saves memory consumption and time.

  • ignoreDecompileErrors (bool) – If true, exceptions raised during table decompilation will be ignored, and the binary data will be returned for those tables instead.

  • recalcTimestamp (bool) – If true (the default), sets the modified timestamp in the head table on save.

  • fontNumber (int) – The index of the font in a TrueType Collection file.

  • lazy (bool) – If lazy is set to True, many data structures are loaded lazily, upon access only. If it is set to False, many data structures are loaded immediately. The default is lazy=None which is somewhere in between.

close()

If we still have a reader object, close it.

ensureDecompiled(recurse=None)

Decompile all the tables, even if a TTFont was opened in ‘lazy’ mode.

get(tag, default=None)

Returns the table if it exists or (optionally) a default if it doesn’t.

getBestCmap(cmapPreferences=((3, 10), (0, 6), (0, 4), (3, 1), (0, 3), (0, 2), (0, 1), (0, 0)))

Returns the ‘best’ Unicode cmap dictionary available in the font or None, if no Unicode cmap subtable is available.

By default it will search for the following (platformID, platEncID) pairs in order:

(3, 10), # Windows Unicode full repertoire
(0, 6),  # Unicode full repertoire (format 13 subtable)
(0, 4),  # Unicode 2.0 full repertoire
(3, 1),  # Windows Unicode BMP
(0, 3),  # Unicode 2.0 BMP
(0, 2),  # Unicode ISO/IEC 10646
(0, 1),  # Unicode 1.1
(0, 0)   # Unicode 1.0

This particular order matches what HarfBuzz uses to choose what subtable to use by default. This order prefers the largest-repertoire subtable, and among those, prefers the Windows-platform over the Unicode-platform as the former has wider support.

This order can be customized via the cmapPreferences argument.

getGlyphID(glyphName)

Returns the ID of the glyph with the given name.

getGlyphIDMany(lst)

Converts a list of glyph names into a list of glyph IDs.

getGlyphName(glyphID)

Returns the name for the glyph with the given ID.

If no name is available, synthesises one with the form glyphXXXXX` where `XXXXX is the zero-padded glyph ID.

getGlyphNameMany(lst)

Converts a list of glyph IDs into a list of glyph names.

getGlyphNames()

Get a list of glyph names, sorted alphabetically.

getGlyphNames2()

Get a list of glyph names, sorted alphabetically, but not case sensitive.

getGlyphOrder()

Returns a list of glyph names ordered by their position in the font.

getGlyphSet(preferCFF=True, location=None, normalized=False, recalcBounds=True)

Return a generic GlyphSet, which is a dict-like object mapping glyph names to glyph objects. The returned glyph objects have a .draw() method that supports the Pen protocol, and will have an attribute named ‘width’.

If the font is CFF-based, the outlines will be taken from the CFF `` or ``CFF2 tables. Otherwise the outlines will be taken from the glyf table.

If the font contains both a CFF ``/``CFF2 and a glyf table, you can use the preferCFF argument to specify which one should be taken. If the font contains both a CFF `` and a ``CFF2 table, the latter is taken.

If the location parameter is set, it should be a dictionary mapping four-letter variation tags to their float values, and the returned glyph-set will represent an instance of a variable font at that location.

If the normalized variable is set to True, that location is interpreted as in the normalized (-1..+1) space, otherwise it is in the font’s defined axes space.

getReverseGlyphMap(rebuild=False)

Returns a mapping of glyph names to glyph IDs.

getTableData(tag)

Returns the binary representation of a table.

If the table is currently loaded and in memory, the data is compiled to binary and returned; if it is not currently loaded, the binary data is read from the font file and returned.

has_key(tag)

Test if the table identified by tag is present in the font.

As well as this method, tag in font can also be used to determine the presence of the table.

importXML(fileOrPath, quiet=None)

Import a TTX file (an XML-based text format), so as to recreate a font object.

isLoaded(tag)

Return true if the table identified by tag has been decompiled and loaded into memory.

keys()

Returns the list of tables in the font, along with the GlyphOrder pseudo-table.

normalizeLocation(location)

Normalize a location from the font’s defined axes space (also known as user space) into the normalized (-1..+1) space. It applies avar mapping if the font contains an avar table.

The location parameter should be a dictionary mapping four-letter variation tags to their float values.

Raises TTLibError if the font is not a variable font.

save(file, reorderTables=True)

Save the font to disk.

Parameters:
  • file – Similarly to the constructor, can be either a pathname or a writable file object.

  • reorderTables (Option[bool]) – If true (the default), reorder the tables, sorting them by tag (recommended by the OpenType specification). If false, retain the original font order. If None, reorder by table dependency (fastest).

saveXML(fileOrPath, newlinestr='\n', **kwargs)

Export the font as TTX (an XML-based text file), or as a series of text files when splitTables is true. In the latter case, the ‘fileOrPath’ argument should be a path to a directory. The ‘tables’ argument must either be false (dump all tables) or a list of tables to dump. The ‘skipTables’ argument may be a list of tables to skip, but only when the ‘tables’ argument is false.

setGlyphOrder(glyphOrder)

Set the glyph order

Parameters:

glyphOrder ([str]) – List of glyph names in order.

fontTools.ttLib.ttFont.getClassTag(klass)

Fetch the table tag for a class object.

fontTools.ttLib.ttFont.getCustomTableClass(tag)

Return the custom table class for tag, if one has been registered with ‘registerCustomTableClass()’. Else return None.

fontTools.ttLib.ttFont.getSearchRange(n, itemSize=16)

Calculate searchRange, entrySelector, rangeShift.

fontTools.ttLib.ttFont.getTableClass(tag)

Fetch the packer/unpacker class for a table.

fontTools.ttLib.ttFont.getTableModule(tag)

Fetch the packer/unpacker module for a table. Return None when no module is found.

fontTools.ttLib.ttFont.identifierToTag(ident)

the opposite of tagToIdentifier()

fontTools.ttLib.ttFont.maxPowerOfTwo(x)

Return the highest exponent of two, so that (2 ** exponent) <= x. Return 0 if x is 0.

fontTools.ttLib.ttFont.newTable(tag)

Return a new instance of a table.

fontTools.ttLib.ttFont.registerCustomTableClass(tag, moduleName, className=None)

Register a custom packer/unpacker class for a table.

The ‘moduleName’ must be an importable module. If no ‘className’ is given, it is derived from the tag, for example it will be table_C_U_S_T_ for a ‘CUST’ tag.

The registered table class should be a subclass of fontTools.ttLib.tables.DefaultTable.DefaultTable

fontTools.ttLib.ttFont.reorderFontTables(inFile, outFile, tableOrder=None, checkChecksums=False)

Rewrite a font file, ordering the tables as recommended by the OpenType specification 1.4.

fontTools.ttLib.ttFont.sortedTagList(tagList, tableOrder=None)

Return a sorted copy of tagList, sorted according to the OpenType specification, or according to a custom tableOrder. If given and not None, tableOrder needs to be a list of tag names.

fontTools.ttLib.ttFont.tagToIdentifier(tag)

Convert a table tag to a valid (but UGLY) python identifier, as well as a filename that’s guaranteed to be unique even on a caseless file system. Each character is mapped to two characters. Lowercase letters get an underscore before the letter, uppercase letters get an underscore after the letter. Trailing spaces are trimmed. Illegal characters are escaped as two hex bytes. If the result starts with a number (as the result of a hex escape), an extra underscore is prepended. Examples:

>>> tagToIdentifier('glyf')
'_g_l_y_f'
>>> tagToIdentifier('cvt ')
'_c_v_t'
>>> tagToIdentifier('OS/2')
'O_S_2f_2'
fontTools.ttLib.ttFont.tagToXML(tag)

Similarly to tagToIdentifier(), this converts a TT tag to a valid XML element name. Since XML element names are case sensitive, this is a fairly simple/readable translation.

fontTools.ttLib.ttFont.unregisterCustomTableClass(tag)

Unregister the custom packer/unpacker class for a table.

fontTools.ttLib.ttFont.xmlToTag(tag)

The opposite of tagToXML()

ttCollection

class fontTools.ttLib.ttCollection.TTCollection(file=None, shareTables=False, **kwargs)

Object representing a TrueType Collection / OpenType Collection. The main API is self.fonts being a list of TTFont instances.

If shareTables is True, then different fonts in the collection might point to the same table object if the data for the table was the same in the font file. Note, however, that this might result in suprises and incorrect behavior if the different fonts involved have different GlyphOrder. Use only if you know what you are doing.

close()
save(file, shareTables=True)

Save the font to disk. Similarly to the constructor, the ‘file’ argument can be either a pathname or a writable file object.

saveXML(fileOrPath, newlinestr='\n', writeVersion=True, **kwargs)

macUtils

ttLib.macUtils.py – Various Mac-specific stuff.

class fontTools.ttLib.macUtils.SFNTResourceReader(path, res_name_or_index)

Simple read-only file wrapper for ‘sfnt’ resources.

close()

Disable all I/O operations.

closed

True if the file is closed.

detach()

Disconnect this buffer from its underlying raw stream and return it.

After the raw stream has been detached, the buffer is in an unusable state.

fileno()

Returns underlying file descriptor if one exists.

OSError is raised if the IO object does not use a file descriptor.

flush()

Does nothing.

getbuffer()

Get a read-write view over the contents of the BytesIO object.

getvalue()

Retrieve the entire contents of the BytesIO object.

isatty()

Always returns False.

BytesIO objects are not connected to a TTY-like device.

read(size=-1, /)

Read at most size bytes, returned as a bytes object.

If the size argument is negative, read until EOF is reached. Return an empty bytes object at EOF.

read1(size=-1, /)

Read at most size bytes, returned as a bytes object.

If the size argument is negative or omitted, read until EOF is reached. Return an empty bytes object at EOF.

readable()

Returns True if the IO object can be read.

readinto(buffer, /)

Read bytes into buffer.

Returns number of bytes read (0 for EOF), or None if the object is set not to block and has no data to read.

readinto1(buffer, /)
readline(size=-1, /)

Next line from the file, as a bytes object.

Retain newline. A non-negative size argument limits the maximum number of bytes to return (an incomplete line may be returned then). Return an empty bytes object at EOF.

readlines(size=None, /)

List of bytes objects, each a line from the file.

Call readline() repeatedly and return a list of the lines so read. The optional size argument, if given, is an approximate bound on the total number of bytes in the lines returned.

seek(pos, whence=0, /)

Change stream position.

Seek to byte offset pos relative to position indicated by whence:

0 Start of stream (the default). pos should be >= 0; 1 Current position - pos may be negative; 2 End of stream - pos usually negative.

Returns the new absolute position.

seekable()

Returns True if the IO object can be seeked.

tell()

Current file position, an integer.

truncate(size=None, /)

Truncate the file to at most size bytes.

Size defaults to the current file position, as returned by tell(). The current file position is unchanged. Returns the new size.

writable()

Returns True if the IO object can be written.

write(b, /)

Write bytes to file.

Return the number of bytes written.

writelines(lines, /)

Write lines to the file.

Note that newlines are not added. lines can be any iterable object producing bytes-like objects. This is equivalent to calling write() for each element.

fontTools.ttLib.macUtils.getSFNTResIndices(path)

Determine whether a file has a ‘sfnt’ resource fork or not.

fontTools.ttLib.macUtils.openTTFonts(path)

Given a pathname, return a list of TTFont objects. In the case of a flat TTF/OTF file, the list will contain just one font object; but in the case of a Mac font suitcase it will contain as many font objects as there are sfnt resources in the file.

sfnt

ttLib/sfnt.py – low-level module to deal with the sfnt file format.

Defines two public classes:

SFNTReader SFNTWriter

(Normally you don’t have to use these classes explicitly; they are used automatically by ttLib.TTFont.)

The reading and writing of sfnt files is separated in two distinct classes, since whenever the number of tables changes or whenever a table’s length changes you need to rewrite the whole file anyway.

class fontTools.ttLib.sfnt.DirectoryEntry
decodeData(rawData)
encodeData(data)
fromFile(file)
fromString(str)
loadData(file)
saveData(file, data)
toString()
class fontTools.ttLib.sfnt.SFNTDirectoryEntry
decodeData(rawData)
encodeData(data)
format = '\n\t\t> # big endian\n\t\ttag:            4s\n\t\tcheckSum:       L\n\t\toffset:         L\n\t\tlength:         L\n'
formatSize = 16
fromFile(file)
fromString(str)
loadData(file)
saveData(file, data)
toString()
class fontTools.ttLib.sfnt.SFNTReader(*args, **kwargs)
close()
has_key(tag)
keys()
class fontTools.ttLib.sfnt.SFNTWriter(*args, **kwargs)
close()

All tables must have been written to disk. Now write the directory.

reordersTables()
setEntry(tag, entry)
writeMasterChecksum(directory)
class fontTools.ttLib.sfnt.WOFFDirectoryEntry
decodeData(rawData)
encodeData(data)
format = '\n\t\t> # big endian\n\t\ttag:            4s\n\t\toffset:         L\n\t\tlength:         L    # compressed length\n\t\torigLength:     L    # original length\n\t\tcheckSum:       L    # original checksum\n'
formatSize = 20
fromFile(file)
fromString(str)
loadData(file)
saveData(file, data)
toString()
class fontTools.ttLib.sfnt.WOFFFlavorData(reader=None)
Flavor = 'woff'
fontTools.ttLib.sfnt.calcChecksum(data)

Calculate the checksum for an arbitrary block of data.

If the data length is not a multiple of four, it assumes it is to be padded with null byte.

>>> print(calcChecksum(b"abcd"))
1633837924
>>> print(calcChecksum(b"abcdxyz"))
3655064932
fontTools.ttLib.sfnt.compress(data, level=6)

Compress ‘data’ to Zlib format. If ‘USE_ZOPFLI’ variable is True, zopfli is used instead of the zlib module. The compression ‘level’ must be between 0 and 9. 1 gives best speed, 9 gives best compression (0 gives no compression at all). The default value is a compromise between speed and compression (6).

fontTools.ttLib.sfnt.readTTCHeader(file)
fontTools.ttLib.sfnt.writeTTCHeader(file, numFonts)

standardGlyphOrder

fontTools.ttLib.standardGlyphOrder.standardGlyphOrder

A Python list of “standard” glyphs required by post table formats 1.0 and 2.0.

TrueType/OpenType Table Modules

This folder is a subpackage of fontTools.ttLib. Each module here is a specialized TT/OT table converter: they can convert raw data to Python objects and vice versa. Usually you don’t need to use the modules directly: they are imported and used automatically when needed by fontTools.ttLib. The tables currently supported are:

ankr: Anchor Point Table
class fontTools.ttLib.tables._a_n_k_r.table__a_n_k_r(tag=None)

The anchor point table provides a way to define anchor points. These are points within the coordinate space of a given glyph, independent of the control points used to render the glyph. Anchor points are used in conjunction with the ‘kerx’ table.

See also https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html

compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
avar: Axis Variations Table
class fontTools.ttLib.tables._a_v_a_r.table__a_v_a_r(tag=None)

Axis Variations Table

This class represents the avar table of a variable font. The object has one substantive attribute, segments, which maps axis tags to a segments dictionary:

>>> font["avar"].segments   
{'wght': {-1.0: -1.0,
  0.0: 0.0,
  0.125: 0.11444091796875,
  0.25: 0.23492431640625,
  0.5: 0.35540771484375,
  0.625: 0.5,
  0.75: 0.6566162109375,
  0.875: 0.81927490234375,
  1.0: 1.0},
 'ital': {-1.0: -1.0, 0.0: 0.0, 1.0: 1.0}}

Notice that the segments dictionary is made up of normalized values. A valid avar segment mapping must contain the entries -1.0: -1.0, 0.0: 0.0, 1.0: 1.0. fontTools does not enforce this, so it is your responsibility to ensure that mappings are valid.

compile(ttFont)

Compiles the table into binary. Called automatically on save.

decompile(data, ttFont)

Create an object from the binary data. Called automatically on access.

dependencies = ['fvar']
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
BASE: Baseline Table
class fontTools.ttLib.tables.B_A_S_E_.table_B_A_S_E_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
mergeMap = {'table': <function mergeObjects>, 'tableTag': <function onlyExisting.<locals>.wrapper>}
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
bsln: Baseline
class fontTools.ttLib.tables._b_s_l_n.table__b_s_l_n(tag=None)
closure_glyphs(s)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
CBDT: Color Bitmap Data Table
class fontTools.ttLib.tables.C_B_D_T_.ColorBitmapGlyph(data, ttFont)
ensureDecompiled(recurse=False)
fileExtension = '.png'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>)}
class fontTools.ttLib.tables.C_B_D_T_.cbdt_bitmap_format_17(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.png'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>)}
class fontTools.ttLib.tables.C_B_D_T_.cbdt_bitmap_format_18(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.png'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>)}
class fontTools.ttLib.tables.C_B_D_T_.cbdt_bitmap_format_19(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.png'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>)}
class fontTools.ttLib.tables.C_B_D_T_.table_C_B_D_T_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
getImageFormatClass(imageFormat)
locatorName = 'CBLC'
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
CBLC: Color Bitmap Location Table
class fontTools.ttLib.tables.C_B_L_C_.table_C_B_L_C_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['CBDT']
fromXML(name, attrs, content, ttFont)
getIndexFormatClass(indexFormat)
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
CFF: Compact Font Format Table
class fontTools.ttLib.tables.C_F_F_.table_C_F_F_(tag=None)
closure_glyphs(s)
compile(otFont)
decompile(data, otFont)
dependencies = []
desubroutinize()
fromXML(name, attrs, content, otFont)
getGlyphOrder()
haveGlyphNames()
merge(m, tables)
prune_post_subset(ttfFont, options)
prune_pre_subset(font, options)
remove_hints()
remove_unused_subroutines()
setGlyphOrder(glyphOrder)
subset_glyphs(s)
toXML(writer, otFont)
CFF2: Compact Font Format (CFF) Version 2
class fontTools.ttLib.tables.C_F_F__2.table_C_F_F__2(tag=None)
closure_glyphs(s)
compile(otFont)
decompile(data, otFont)
dependencies = []
desubroutinize()
fromXML(name, attrs, content, otFont)
getGlyphOrder()
haveGlyphNames()
merge(m, tables)
prune_post_subset(ttfFont, options)
prune_pre_subset(font, options)
remove_hints()
remove_unused_subroutines()
setGlyphOrder(glyphOrder)
subset_glyphs(s)
toXML(writer, otFont)
cidg: CID to Glyph ID table
class fontTools.ttLib.tables._c_i_d_g.table__c_i_d_g(tag=None)

The AAT cidg table has almost the same structure as gidc, just mapping CIDs to GlyphIDs instead of the reverse direction.

It is useful for fonts that may be used by a PDF renderer in lieu of a font reference with a known glyph collection but no subsetted glyphs. For instance, a PDF can say “please use a font conforming to Adobe-Japan-1”; the cidg mapping is necessary if the font is, say, a TrueType font. gidc is lossy for this purpose and is obsoleted by cidg.

For example, the first font in /System/Library/Fonts/PingFang.ttc (which Apple ships pre-installed on MacOS 10.12.6) has a cidg table.

compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
cmap: Character to Glyph Index Mapping Table
class fontTools.ttLib.tables._c_m_a_p.table__c_m_a_p(tag=None)

Character to Glyph Index Mapping Table

This class represents the cmap table, which maps between input characters (in Unicode or other system encodings) and glyphs within the font. The cmap table contains one or more subtables which determine the mapping of of characters to glyphs across different platforms and encoding systems.

table__c_m_a_p objects expose an accessor .tables which provides access to the subtables, although it is normally easier to retrieve individual subtables through the utility methods described below. To add new subtables to a font, first determine the subtable format (if in doubt use format 4 for glyphs within the BMP, format 12 for glyphs outside the BMP, and format 14 for Unicode Variation Sequences) construct subtable objects with CmapSubtable.newSubtable(format), and append them to the .tables list.

Within a subtable, the mapping of characters to glyphs is provided by the .cmap attribute.

Example:

cmap4_0_3 = CmapSubtable.newSubtable(4)
cmap4_0_3.platformID = 0
cmap4_0_3.platEncID = 3
cmap4_0_3.language = 0
cmap4_0_3.cmap = { 0xC1: "Aacute" }

cmap = newTable("cmap")
cmap.tableVersion = 0
cmap.tables = [cmap4_0_3]
buildReversed()

Builds a reverse mapping dictionary

Iterates over all Unicode cmap tables and returns a dictionary mapping glyphs to sets of codepoints, such as:

{
        'one': {0x31}
        'A': {0x41,0x391}
}

The values are sets of Unicode codepoints because some fonts map different codepoints to the same glyph. For example, U+0041 LATIN CAPITAL LETTER A and U+0391 GREEK CAPITAL LETTER ALPHA are sometimes the same glyph.

getBestCmap(cmapPreferences=((3, 10), (0, 6), (0, 4), (3, 1), (0, 3), (0, 2), (0, 1), (0, 0)))

Returns the ‘best’ Unicode cmap dictionary available in the font or None, if no Unicode cmap subtable is available.

By default it will search for the following (platformID, platEncID) pairs in order:

(3, 10), # Windows Unicode full repertoire
(0, 6),  # Unicode full repertoire (format 13 subtable)
(0, 4),  # Unicode 2.0 full repertoire
(3, 1),  # Windows Unicode BMP
(0, 3),  # Unicode 2.0 BMP
(0, 2),  # Unicode ISO/IEC 10646
(0, 1),  # Unicode 1.1
(0, 0)   # Unicode 1.0

This particular order matches what HarfBuzz uses to choose what subtable to use by default. This order prefers the largest-repertoire subtable, and among those, prefers the Windows-platform over the Unicode-platform as the former has wider support.

This order can be customized via the cmapPreferences argument.

getcmap(platformID, platEncID)

Returns the first subtable which matches the given platform and encoding.

Parameters:
  • platformID (int) – The platform ID. Use 0 for Unicode, 1 for Macintosh (deprecated for new fonts), 2 for ISO (deprecated) and 3 for Windows.

  • encodingID (int) – Encoding ID. Interpretation depends on the platform ID. See the OpenType specification for details.

Returns:

An object which is a subclass of CmapSubtable if a matching subtable is found within the font, or None otherwise.

class fontTools.ttLib.tables._c_m_a_p.CmapSubtable(format)

Base class for all cmap subtable formats.

Subclasses which handle the individual subtable formats are named cmap_format_0, cmap_format_2 etc. Use getSubtableClass() to retrieve the concrete subclass, or newSubtable() to get a new subtable object for a given format.

The object exposes a .cmap attribute, which contains a dictionary mapping character codepoints to glyph names.

getEncoding(default=None)

Returns the Python encoding name for this cmap subtable based on its platformID, platEncID, and language. If encoding for these values is not known, by default None is returned. That can be overridden by passing a value to the default argument.

Note that if you want to choose a “preferred” cmap subtable, most of the time self.isUnicode() is what you want as that one only returns true for the modern, commonly used, Unicode-compatible triplets, not the legacy ones.

static getSubtableClass(format)

Return the subtable class for a format.

isSymbol()

Returns true if the subtable is for the Symbol encoding (3,0)

isUnicode()

Returns true if the characters are interpreted as Unicode codepoints.

static newSubtable(format)

Return a new instance of a subtable for the given format .

platEncID

The encoding ID of this subtable (interpretation depends on platformID)

platformID

The platform ID of this subtable

COLR: Color Table
class fontTools.ttLib.tables.C_O_L_R_.LayerRecord(name=None, colorID=None)
fromXML(eltname, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.C_O_L_R_.table_C_O_L_R_(tag=None)

This table is structured so that you can treat it like a dictionary keyed by glyph name.

ttFont['COLR'][<glyphName>] will return the color layers for any glyph.

ttFont['COLR'][<glyphName>] = <value> will set the color layers for any glyph.

closure_glyphs(s)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
CPAL: Color Palette Table
class fontTools.ttLib.tables.C_P_A_L_.Color(blue, green, red, alpha)
alpha

Alias for field number 3

blue

Alias for field number 0

count(value, /)

Return number of occurrences of value.

classmethod fromHex(value)
classmethod fromRGBA(red, green, blue, alpha)
green

Alias for field number 1

hex()
index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

red

Alias for field number 2

toXML(writer, ttFont, index=None)
class fontTools.ttLib.tables.C_P_A_L_.table_C_P_A_L_(tag=None)
DEFAULT_PALETTE_TYPE = 0
NO_NAME_ID = 65535
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
prune_post_subset(font, options)
toXML(writer, ttFont)
cvar: CVT Variations Table
class fontTools.ttLib.tables._c_v_a_r.table__c_v_a_r(tag=None)
compile(ttFont, useSharedPoints=False)
decompile(data, ttFont)
dependencies = ['cvt ', 'fvar']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TupleVariation
class fontTools.ttLib.tables.TupleVariation.TupleVariation(axes, coordinates)
calcInferredDeltas(origCoords, endPts)
compile(axisTags, sharedCoordIndices={}, pointData=None)
compileCoord(axisTags)
static compileDeltaValues_(deltas, bytearr=None)

[value1, value2, value3, …] –> bytearray

Emits a sequence of runs. Each run starts with a byte-sized header whose 6 least significant bits (header & 0x3F) indicate how many values are encoded in this run. The stored length is the actual length minus one; run lengths are thus in the range [1..64]. If the header byte has its most significant bit (0x80) set, all values in this run are zero, and no data follows. Otherwise, the header byte is followed by ((header & 0x3F) + 1) signed values. If (header & 0x40) is clear, the delta values are stored as signed bytes; if (header & 0x40) is set, the delta values are signed 16-bit integers.

compileDeltas()
compileIntermediateCoord(axisTags)
static compilePoints(points)
static decompileCoord_(axisTags, data, offset)
static decompileDeltas_(numDeltas, data, offset)

(numDeltas, data, offset) –> ([delta, delta, …], newOffset)

static decompilePoints_(numPoints, data, offset, tableTag)

(numPoints, data, offset, tableTag) –> ([point1, point2, …], newOffset)

static encodeDeltaRunAsBytes_(deltas, offset, bytearr)
static encodeDeltaRunAsWords_(deltas, offset, bytearr)
static encodeDeltaRunAsZeroes_(deltas, offset, bytearr)
fromXML(name, attrs, _content)
getCoordWidth()

Return 2 if coordinates are (x, y) as in gvar, 1 if single values as in cvar, or 0 if empty.

static getTupleSize_(flags, axisCount)
getUsedPoints()
hasImpact()

Returns True if this TupleVariation has any visible impact.

If the result is False, the TupleVariation can be omitted from the font without making any visible difference.

optimize(origCoords, endPts, tolerance=0.5, isComposite=False)
roundDeltas()
scaleDeltas(scalar)
toXML(writer, axisTags)
fontTools.ttLib.tables.TupleVariation.compileSharedTuples(axisTags, variations, MAX_NUM_SHARED_COORDS=4096)
fontTools.ttLib.tables.TupleVariation.compileTupleVariationStore(variations, pointCount, axisTags, sharedTupleIndices, useSharedPoints=True)
fontTools.ttLib.tables.TupleVariation.decompileSharedTuples(axisTags, sharedTupleCount, data, offset)
fontTools.ttLib.tables.TupleVariation.decompileTupleVariationStore(tableTag, axisTags, tupleVariationCount, pointCount, sharedTuples, data, pos, dataPos)
fontTools.ttLib.tables.TupleVariation.decompileTupleVariation_(pointCount, sharedTuples, sharedPoints, tableTag, axisTags, data, tupleData)
fontTools.ttLib.tables.TupleVariation.inferRegion_(peak)

Infer start and end for a (non-intermediate) region

This helper function computes the applicability region for variation tuples whose INTERMEDIATE_REGION flag is not set in the TupleVariationHeader structure. Variation tuples apply only to certain regions of the variation space; outside that region, the tuple has no effect. To make the binary encoding more compact, TupleVariationHeaders can omit the intermediateStartTuple and intermediateEndTuple fields.

cvt: Control Value Table
class fontTools.ttLib.tables._c_v_t.table__c_v_t(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap(lst)
toXML(writer, ttFont)
DSIG: Digital Signature Table
class fontTools.ttLib.tables.D_S_I_G_.SignatureRecord
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
fontTools.ttLib.tables.D_S_I_G_.b64encode(b)
fontTools.ttLib.tables.D_S_I_G_.pem_spam(l, spam={'': True, '-----BEGIN PKCS7-----': True, '-----END PKCS7-----': True})
class fontTools.ttLib.tables.D_S_I_G_.table_D_S_I_G_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
prune_pre_subset(font, options)
toXML(xmlWriter, ttFont)
EBDT: Embedded Bitmap Data Table
class fontTools.ttLib.tables.E_B_D_T_.BitAlignedBitmapMixin
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
class fontTools.ttLib.tables.E_B_D_T_.BitmapGlyph(data, ttFont)
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
fontTools.ttLib.tables.E_B_D_T_.BitmapPlusBigMetricsMixin

alias of BitmapPlusMetricsMixin

fontTools.ttLib.tables.E_B_D_T_.BitmapPlusSmallMetricsMixin

alias of BitmapPlusMetricsMixin

class fontTools.ttLib.tables.E_B_D_T_.ByteAlignedBitmapMixin
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
class fontTools.ttLib.tables.E_B_D_T_.ComponentBitmapGlyph(data, ttFont)
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.EbdtComponent
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_1(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_2(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_5(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_6(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_7(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
getRow(row, bitDepth=1, metrics=None, reverseBytes=False)
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
setRows(dataRows, bitDepth=1, metrics=None, reverseBytes=False)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_8(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.ebdt_bitmap_format_9(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fileExtension = '.bin'
fromXML(name, attrs, content, ttFont)
getFormat()
readData(name, attrs, content, ttFont)
readMetrics(name, attrs, content, ttFont)
toXML(strikeIndex, glyphName, writer, ttFont)
writeData(strikeIndex, glyphName, writer, ttFont)
writeMetrics(writer, ttFont)
xmlDataFunctions = {'bitwise': (<function _writeBitwiseImageData>, <function _readBitwiseImageData>), 'extfile': (<function _writeExtFileImageData>, <function _readExtFileImageData>), 'raw': (<function _writeRawImageData>, <function _readRawImageData>), 'row': (<function _writeRowImageData>, <function _readRowImageData>)}
class fontTools.ttLib.tables.E_B_D_T_.table_E_B_D_T_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
getImageFormatClass(imageFormat)
locatorName = 'EBLC'
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
BitmapGlyphMetrics
class fontTools.ttLib.tables.BitmapGlyphMetrics.BigGlyphMetrics
binaryFormat = '\n  > # big endian\n  height:       B\n  width:        B\n  horiBearingX: b\n  horiBearingY: b\n  horiAdvance:  B\n  vertBearingX: b\n  vertBearingY: b\n  vertAdvance:  B\n'
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.BitmapGlyphMetrics.BitmapGlyphMetrics
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.BitmapGlyphMetrics.SmallGlyphMetrics
binaryFormat = '\n  > # big endian\n  height:   B\n  width:    B\n  BearingX: b\n  BearingY: b\n  Advance:  B\n'
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
EBLC: Embedded Bitmap Location Table
class fontTools.ttLib.tables.E_B_L_C_.BitmapSizeTable
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.EblcIndexSubTable(data, ttFont)
compile(ttFont)
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
removeSkipGlyphs()
toXML(writer, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.FixedSizeIndexSubTableMixin
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.SbitLineMetrics
fromXML(name, attrs, content, ttFont)
toXML(name, writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.Strike
fromXML(name, attrs, content, ttFont, locator)
toXML(strikeIndex, writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.eblc_index_sub_table_1(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
removeSkipGlyphs()
toXML(writer, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.eblc_index_sub_table_2(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
removeSkipGlyphs()
toXML(writer, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.eblc_index_sub_table_3(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
removeSkipGlyphs()
toXML(writer, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.eblc_index_sub_table_4(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
removeSkipGlyphs()
toXML(writer, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.eblc_index_sub_table_5(data, ttFont)
compile(ttFont)
decompile()
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
padBitmapData(data)
readMetrics(name, attrs, content, ttFont)
removeSkipGlyphs()
toXML(writer, ttFont)
writeMetrics(writer, ttFont)
class fontTools.ttLib.tables.E_B_L_C_.table_E_B_L_C_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['EBDT']
fromXML(name, attrs, content, ttFont)
getIndexFormatClass(indexFormat)
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
BitmapGlyphMetrics
class fontTools.ttLib.tables.BitmapGlyphMetrics.BigGlyphMetrics
binaryFormat = '\n  > # big endian\n  height:       B\n  width:        B\n  horiBearingX: b\n  horiBearingY: b\n  horiAdvance:  B\n  vertBearingX: b\n  vertBearingY: b\n  vertAdvance:  B\n'
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.BitmapGlyphMetrics.BitmapGlyphMetrics
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.BitmapGlyphMetrics.SmallGlyphMetrics
binaryFormat = '\n  > # big endian\n  height:   B\n  width:    B\n  BearingX: b\n  BearingY: b\n  Advance:  B\n'
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
Feat: Graphite Feature Table
class fontTools.ttLib.tables.F__e_a_t.Feature
class fontTools.ttLib.tables.F__e_a_t.table_F__e_a_t(tag=None)

The Feat table is used exclusively by the Graphite shaping engine to store features and possible settings specified in GDL. Graphite features determine what rules are applied to transform a glyph stream.

Not to be confused with feat, or the OpenType Layout tables GSUB/GPOS.

compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
feat: Feature name table
class fontTools.ttLib.tables._f_e_a_t.table__f_e_a_t(tag=None)

The feature name table is an AAT (Apple Advanced Typography) table for storing font features, settings, and their human-readable names. It should not be confused with the Feat table or the OpenType Layout GSUB/GPOS tables. See Feature Name Table in the TrueType Reference Manual for more information on the structure and purpose of this table.

compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
FFTM: FontForge Time Stamp Table
class fontTools.ttLib.tables.F_F_T_M_.table_F_F_T_M_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
fpgm: Font Program
class fontTools.ttLib.tables._f_p_g_m.table__f_p_g_m(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap(lst)
toXML(writer, ttFont)
fvar: Font Variations Table
class fontTools.ttLib.tables._f_v_a_r.Axis
compile()
decompile(data)
fromXML(name, _attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables._f_v_a_r.NamedInstance
compile(axisTags, includePostScriptName)
decompile(data, axisTags)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables._f_v_a_r.table__f_v_a_r(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['name']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
gasp: Grid-fitting and Scan-conversion Procedure Table
class fontTools.ttLib.tables._g_a_s_p.table__g_a_s_p(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap(lst)
toXML(writer, ttFont)
gcid: Glyph ID to CID table
class fontTools.ttLib.tables._g_c_i_d.table__g_c_i_d(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
GDEF: Glyph Definition Table
class fontTools.ttLib.tables.G_D_E_F_.table_G_D_E_F_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
mergeMap = {'table': <function mergeObjects>, 'tableTag': <function onlyExisting.<locals>.wrapper>}
prune_post_subset(font, options)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
Glat: Graphite Glyph Attributes Table
class fontTools.ttLib.tables.G__l_a_t.table_G__l_a_t(tag=None)

Support Graphite Glat tables

compile(ttFont)
compileAttributes12(attrs, fmt)
compileAttributes3(attrs)
decompile(data, ttFont)
decompileAttributes12(data, fmt)
decompileAttributes3(data)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
Gloc: Graphite index to glyph attributes table
class fontTools.ttLib.tables.G__l_o_c.table_G__l_o_c(tag=None)

Support Graphite Gloc tables

compile(ttFont)
decompile(data, ttFont)
dependencies = ['Glat']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
set(locations)
toXML(writer, ttFont)
glyf: Glyph Data
class fontTools.ttLib.tables._g_l_y_f.table__g_l_y_f(tag=None)

Glyph Data Table

This class represents the glyf table, which contains outlines for glyphs in TrueType format. In many cases, it is easier to access and manipulate glyph outlines through the GlyphSet object returned from fontTools.ttLib.ttFont.getGlyphSet():

>> from fontTools.pens.boundsPen import BoundsPen
>> glyphset = font.getGlyphSet()
>> bp = BoundsPen(glyphset)
>> glyphset["A"].draw(bp)
>> bp.bounds
(19, 0, 633, 716)

However, this class can be used for low-level access to the glyf table data. Objects of this class support dictionary-like access, mapping glyph names to Glyph objects:

>> glyf = font["glyf"]
>> len(glyf["Aacute"].components)
2

Note that when adding glyphs to the font via low-level access to the glyf table, the new glyphs must also be added to the hmtx/vmtx table:

>> font["glyf"]["divisionslash"] = Glyph()
>> font["hmtx"]["divisionslash"] = (640, 0)
getCoordinatesAndControls(glyphName, ttFont, defaultVerticalOrigin=None)

Old public name for self._getCoordinatesAndControls(). See: https://github.com/fonttools/fonttools/pull/2266

getGlyphID(glyphName)

Returns the ID of the glyph with the given name.

Raises a ValueError if the glyph is not found in the font.

getGlyphName(glyphID)

Returns the name for the glyph with the given ID.

Raises a KeyError if the glyph name is not found in the font.

getPhantomPoints(glyphName, ttFont, defaultVerticalOrigin=None)

Old public name for self._getPhantomPoints(). See: https://github.com/fonttools/fonttools/pull/2266

removeHinting()

Removes TrueType hints from all glyphs in the glyphset.

See Glyph.removeHinting().

setCoordinates(glyphName, ttFont)

Old public name for self._setCoordinates(). See: https://github.com/fonttools/fonttools/pull/2266

setGlyphOrder(glyphOrder)

Sets the glyph order

Parameters:

glyphOrder ([str]) – List of glyph names in order.

class fontTools.ttLib.tables._g_l_y_f.Glyph(data=b'')

This class represents an individual TrueType glyph.

TrueType glyph objects come in two flavours: simple and composite. Simple glyph objects contain contours, represented via the .coordinates, .flags, .numberOfContours, and .endPtsOfContours attributes; composite glyphs contain components, available through the .components attributes.

Because the .coordinates attribute (and other simple glyph attributes mentioned above) is only set on simple glyphs and the .components attribute is only set on composite glyphs, it is necessary to use the isComposite() method to test whether a glyph is simple or composite before attempting to access its data.

For a composite glyph, the components can also be accessed via array-like access:

>> assert(font["glyf"]["Aacute"].isComposite())
>> font["glyf"]["Aacute"][0]
<fontTools.ttLib.tables._g_l_y_f.GlyphComponent at 0x1027b2ee0>
draw(pen, glyfTable, offset=0)

Draws the glyph using the supplied pen object.

Parameters:
  • pen – An object conforming to the pen protocol.

  • glyfTable – A table__g_l_y_f object, to resolve components.

  • offset (int) – A horizontal offset. If provided, all coordinates are translated by this offset.

drawPoints(pen, glyfTable, offset=0)

Draw the glyph using the supplied pointPen. As opposed to Glyph.draw(), this will not change the point indices.

getComponentNames(glyfTable)

Returns a list of names of component glyphs used in this glyph

This method can be used on simple glyphs (in which case it returns an empty list) or composite glyphs.

getCoordinates(glyfTable)

Return the coordinates, end points and flags

This method returns three values: A GlyphCoordinates object, a list of the indexes of the final points of each contour (allowing you to split up the coordinates list into contours) and a list of flags.

On simple glyphs, this method returns information from the glyph’s own contours; on composite glyphs, it “flattens” all components recursively to return a list of coordinates representing all the components involved in the glyph.

To interpret the flags for each point, see the “Simple Glyph Flags” section of the glyf table specification <https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description>.

isComposite()

Test whether a glyph has components

isVarComposite()

Test whether a glyph has variable components

recalcBounds(glyfTable, *, boundsDone=None)

Recalculates the bounds of the glyph.

Each glyph object stores its bounding box in the xMin/yMin/xMax/yMax attributes. These bounds must be recomputed when the coordinates change. The table__g_l_y_f bounds must be provided to resolve component bounds.

removeHinting()

Removes TrueType hinting instructions from the glyph.

trim(remove_hinting=False)

Remove padding and, if requested, hinting, from a glyph. This works on both expanded and compacted glyphs, without expanding it.

tryRecalcBoundsComposite(glyfTable, *, boundsDone=None)

Try recalculating the bounds of a composite glyph that has certain constrained properties. Namely, none of the components have a transform other than an integer translate, and none uses the anchor points.

Each glyph object stores its bounding box in the xMin/yMin/xMax/yMax attributes. These bounds must be recomputed when the coordinates change. The table__g_l_y_f bounds must be provided to resolve component bounds.

Return True if bounds were calculated, False otherwise.

class fontTools.ttLib.tables._g_l_y_f.GlyphComponent

Represents a component within a composite glyph.

The component is represented internally with four attributes: glyphName, x, y and transform. If there is no “two-by-two” matrix (i.e no scaling, reflection, or rotation; only translation), the transform attribute is not present.

getComponentInfo()

Return information about the component

This method returns a tuple of two values: the glyph name of the component’s base glyph, and a transformation matrix. As opposed to accessing the attributes directly, getComponentInfo always returns a six-element tuple of the component’s transformation matrix, even when the two-by-two .transform matrix is not present.

class fontTools.ttLib.tables._g_l_y_f.GlyphCoordinates(iterable=[])

A list of glyph coordinates.

Unlike an ordinary list, this is a numpy-like matrix object which supports matrix addition, scalar multiplication and other operations described below.

property array

Returns the underlying array of coordinates

copy()

Creates a new GlyphCoordinates object which is a copy of the current one.

scale(p)
>>> GlyphCoordinates([(1,2)]).scale((.5,0))
transform(t)
>>> GlyphCoordinates([(1,2)]).transform(((.5,0),(.2,.5)))
translate(p)
>>> GlyphCoordinates([(1,2)]).translate((.5,0))
static zeros(count)

Creates a new GlyphCoordinates object with all coordinates set to (0,0)

GMAP: SING Glyphlet Summary Table
class fontTools.ttLib.tables.G_M_A_P_.GMAPRecord(uv=0, cid=0, gid=0, ggid=0, name='')
compile(ttFont)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.G_M_A_P_.table_G_M_A_P_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
GPKG: SING Glyphlet Wrapper Table
class fontTools.ttLib.tables.G_P_K_G_.table_G_P_K_G_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
GPOS: Glyph Positioning Table
class fontTools.ttLib.tables.G_P_O_S_.table_G_P_O_S_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
mergeMap = {'table': <function mergeObjects>, 'tableTag': <function onlyExisting.<locals>.wrapper>}
neuter_lookups(lookup_indices)

Sets lookups not in lookup_indices to None.

prune_features()

Remove unreferenced features

prune_lookups(remap=True)

Remove (default) or neuter unreferenced lookups

prune_post_subset(font, options)
prune_pre_subset(font, options)
remove_redundant_langsys()
retain_empty_scripts()
subset_feature_tags(feature_tags)
subset_glyphs(s)
subset_lookups(lookup_indices)

Retains specified lookups, then removes empty features, language systems, and scripts.

subset_script_tags(tags)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
GSUB: Glyph Substitution Table
class fontTools.ttLib.tables.G_S_U_B_.table_G_S_U_B_(tag=None)
closure_glyphs(s)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
mergeMap = {'table': <function mergeObjects>, 'tableTag': <function onlyExisting.<locals>.wrapper>}
neuter_lookups(lookup_indices)

Sets lookups not in lookup_indices to None.

prune_features()

Remove unreferenced features

prune_lookups(remap=True)

Remove (default) or neuter unreferenced lookups

prune_post_subset(font, options)
prune_pre_subset(font, options)
remove_redundant_langsys()
retain_empty_scripts()
subset_feature_tags(feature_tags)
subset_glyphs(s)
subset_lookups(lookup_indices)

Retains specified lookups, then removes empty features, language systems, and scripts.

subset_script_tags(tags)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
gvar: Glyph Variations Table
fontTools.ttLib.tables._g_v_a_r.compileGlyph_(variations, pointCount, axisTags, sharedCoordIndices)
fontTools.ttLib.tables._g_v_a_r.decompileGlyph_(pointCount, sharedTuples, axisTags, data)
class fontTools.ttLib.tables._g_v_a_r.table__g_v_a_r(tag=None)
compile(ttFont)
compileGlyphs_(ttFont, axisTags, sharedCoordIndices)
static compileOffsets_(offsets)

Packs a list of offsets into a ‘gvar’ offset table.

Returns a pair (bytestring, tableFormat). Bytestring is the packed offset table. Format indicates whether the table uses short (tableFormat=0) or long (tableFormat=1) integers. The returned tableFormat should get packed into the flags field of the ‘gvar’ header.

decompile(data, ttFont)
static decompileOffsets_(data, tableFormat, glyphCount)
dependencies = ['fvar', 'glyf']
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
static getNumPoints_(glyph)
merge(m, tables)
prune_pre_subset(font, options)
subset_glyphs(s)
toXML(writer, ttFont)
TupleVariation
class fontTools.ttLib.tables.TupleVariation.TupleVariation(axes, coordinates)
calcInferredDeltas(origCoords, endPts)
compile(axisTags, sharedCoordIndices={}, pointData=None)
compileCoord(axisTags)
static compileDeltaValues_(deltas, bytearr=None)

[value1, value2, value3, …] –> bytearray

Emits a sequence of runs. Each run starts with a byte-sized header whose 6 least significant bits (header & 0x3F) indicate how many values are encoded in this run. The stored length is the actual length minus one; run lengths are thus in the range [1..64]. If the header byte has its most significant bit (0x80) set, all values in this run are zero, and no data follows. Otherwise, the header byte is followed by ((header & 0x3F) + 1) signed values. If (header & 0x40) is clear, the delta values are stored as signed bytes; if (header & 0x40) is set, the delta values are signed 16-bit integers.

compileDeltas()
compileIntermediateCoord(axisTags)
static compilePoints(points)
static decompileCoord_(axisTags, data, offset)
static decompileDeltas_(numDeltas, data, offset)

(numDeltas, data, offset) –> ([delta, delta, …], newOffset)

static decompilePoints_(numPoints, data, offset, tableTag)

(numPoints, data, offset, tableTag) –> ([point1, point2, …], newOffset)

static encodeDeltaRunAsBytes_(deltas, offset, bytearr)
static encodeDeltaRunAsWords_(deltas, offset, bytearr)
static encodeDeltaRunAsZeroes_(deltas, offset, bytearr)
fromXML(name, attrs, _content)
getCoordWidth()

Return 2 if coordinates are (x, y) as in gvar, 1 if single values as in cvar, or 0 if empty.

static getTupleSize_(flags, axisCount)
getUsedPoints()
hasImpact()

Returns True if this TupleVariation has any visible impact.

If the result is False, the TupleVariation can be omitted from the font without making any visible difference.

optimize(origCoords, endPts, tolerance=0.5, isComposite=False)
roundDeltas()
scaleDeltas(scalar)
toXML(writer, axisTags)
fontTools.ttLib.tables.TupleVariation.compileSharedTuples(axisTags, variations, MAX_NUM_SHARED_COORDS=4096)
fontTools.ttLib.tables.TupleVariation.compileTupleVariationStore(variations, pointCount, axisTags, sharedTupleIndices, useSharedPoints=True)
fontTools.ttLib.tables.TupleVariation.decompileSharedTuples(axisTags, sharedTupleCount, data, offset)
fontTools.ttLib.tables.TupleVariation.decompileTupleVariationStore(tableTag, axisTags, tupleVariationCount, pointCount, sharedTuples, data, pos, dataPos)
fontTools.ttLib.tables.TupleVariation.decompileTupleVariation_(pointCount, sharedTuples, sharedPoints, tableTag, axisTags, data, tupleData)
fontTools.ttLib.tables.TupleVariation.inferRegion_(peak)

Infer start and end for a (non-intermediate) region

This helper function computes the applicability region for variation tuples whose INTERMEDIATE_REGION flag is not set in the TupleVariationHeader structure. Variation tuples apply only to certain regions of the variation space; outside that region, the tuple has no effect. To make the binary encoding more compact, TupleVariationHeaders can omit the intermediateStartTuple and intermediateEndTuple fields.

hdmx: Horizontal Device Metrics
class fontTools.ttLib.tables._h_d_m_x.table__h_d_m_x(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
head: Font Header Table
class fontTools.ttLib.tables._h_e_a_d.table__h_e_a_d(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['maxp', 'loca', 'CFF ', 'CFF2']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap = {'checkSumAdjustment': <function <lambda>>, 'created': <function current_time>, 'flags': <function mergeBits.<locals>.wrapper>, 'fontDirectionHint': <function <lambda>>, 'fontRevision': <built-in function max>, 'glyphDataFormat': <function equal>, 'indexToLocFormat': <function first>, 'lowestRecPPEM': <built-in function max>, 'macStyle': <function first>, 'magicNumber': <function equal>, 'modified': <function current_time>, 'tableTag': <function equal>, 'tableVersion': <built-in function max>, 'unitsPerEm': <function equal>, 'xMax': <built-in function max>, 'xMin': <built-in function min>, 'yMax': <built-in function max>, 'yMin': <built-in function min>}
prune_post_subset(font, options)
toXML(writer, ttFont)
hhea: Horizontal Header Table
class fontTools.ttLib.tables._h_h_e_a.table__h_h_e_a(tag=None)
property ascender
compile(ttFont)
decompile(data, ttFont)
dependencies = ['hmtx', 'glyf', 'CFF ', 'CFF2']
property descender
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap = {'*': <function equal>, 'advanceWidthMax': <built-in function max>, 'ascent': <built-in function max>, 'caretOffset': <function first>, 'caretSlopeRise': <function first>, 'caretSlopeRun': <function first>, 'descent': <built-in function min>, 'lineGap': <built-in function max>, 'minLeftSideBearing': <built-in function min>, 'minRightSideBearing': <built-in function min>, 'numberOfHMetrics': <function recalculate>, 'tableTag': <function equal>, 'tableVersion': <built-in function max>, 'xMaxExtent': <built-in function max>}
recalc(ttFont)
toXML(writer, ttFont)
hmtx: Horizontal Metrics Table
class fontTools.ttLib.tables._h_m_t_x.table__h_m_t_x(tag=None)
advanceName = 'width'
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
headerTag = 'hhea'
longMetricFormat = 'Hh'
merge(m, tables)
mergeMap = {'metrics': <function sumDicts>, 'tableTag': <function equal>}
numberOfMetricsName = 'numberOfHMetrics'
sideBearingName = 'lsb'
subset_glyphs(s)
toXML(writer, ttFont)
HVAR:Horizontal Metrics Variations Table
class fontTools.ttLib.tables.H_V_A_R_.table_H_V_A_R_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
JSTF: Justification Table
class fontTools.ttLib.tables.J_S_T_F_.table_J_S_T_F_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
mergeMap = {'table': <function mergeObjects>, 'tableTag': <function onlyExisting.<locals>.wrapper>}
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
kern: Kerning
class fontTools.ttLib.tables._k_e_r_n.KernTable_format_0(apple=False)
compile(ttFont)
decompile(data, ttFont)
format = 0
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
version = 0
class fontTools.ttLib.tables._k_e_r_n.KernTable_format_unkown(format)
compile(ttFont)
decompile(data, ttFont)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables._k_e_r_n.table__k_e_r_n(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
getkern(format)
merge(m, tables)
prune_pre_subset(font, options)
subset_glyphs(s)
toXML(writer, ttFont)
lcar: Ligature Caret Table
class fontTools.ttLib.tables._l_c_a_r.table__l_c_a_r(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
loca: Index to Location
class fontTools.ttLib.tables._l_o_c_a.table__l_o_c_a(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['glyf']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap = {'*': <function recalculate>, 'tableTag': <function equal>}
set(locations)
toXML(writer, ttFont)
ltag: Language Tag
class fontTools.ttLib.tables._l_t_a_g.table__l_t_a_g(tag=None)
addTag(tag)

Add ‘tag’ to the list of langauge tags if not already there.

Returns the integer index of ‘tag’ in the list of all tags.

compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
LTSH: Linear Threshold
class fontTools.ttLib.tables.L_T_S_H_.table_L_T_S_H_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
MATH: Mathematical Typesetting Table
class fontTools.ttLib.tables.M_A_T_H_.table_M_A_T_H_(tag=None)
closure_glyphs(s)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
mergeMap = {'table': <function mergeObjects>, 'tableTag': <function onlyExisting.<locals>.wrapper>}
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
maxp: Maximum Profile
class fontTools.ttLib.tables._m_a_x_p.table__m_a_x_p(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['glyf']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap = {'*': <built-in function max>, 'maxFunctionDefs': <function first>, 'maxInstructionDefs': <function first>, 'maxStorage': <function first>, 'numGlyphs': <built-in function sum>, 'tableTag': <function equal>, 'tableVersion': <function equal>}
prune_pre_subset(font, options)
recalc(ttFont)

Recalculate the font bounding box, and most other maxp values except for the TT instructions values. Also recalculate the value of bit 1 of the flags field and the font bounding box of the ‘head’ table.

testrepr()
toXML(writer, ttFont)
META: SING Glyphlet Metadata Table
class fontTools.ttLib.tables.M_E_T_A_.GlyphRecord
compile(parentTable)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.M_E_T_A_.StringRecord
compile(parentTable)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
fontTools.ttLib.tables.M_E_T_A_.getLabelString(labelID)
fontTools.ttLib.tables.M_E_T_A_.mapUTF8toXML(string)
fontTools.ttLib.tables.M_E_T_A_.mapXMLToUTF8(string)
class fontTools.ttLib.tables.M_E_T_A_.table_M_E_T_A_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
meta: Metadata Table
class fontTools.ttLib.tables._m_e_t_a.table__m_e_t_a(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
mort: Glyph Metamorphosis Table
class fontTools.ttLib.tables._m_o_r_t.table__m_o_r_t(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
morx: Extended Glyph Metamorphosis Table
class fontTools.ttLib.tables._m_o_r_x.table__m_o_r_x(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
MVAR: Metrics Variations Table
class fontTools.ttLib.tables.M_V_A_R_.table_M_V_A_R_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
name: Naming Table
class fontTools.ttLib.tables._n_a_m_e.NameRecord
encodingIsUnicodeCompatible()
fromXML(name, attrs, content, ttFont)
getEncoding(default='ascii')

Returns the Python encoding name for this name entry based on its platformID, platEncID, and langID. If encoding for these values is not known, by default ‘ascii’ is returned. That can be overriden by passing a value to the default argument.

isUnicode()
toBytes(errors='strict')

If self.string is a bytes object, return it; otherwise try encoding the Unicode string in self.string to bytes using the encoding of this entry as returned by self.getEncoding(); Note that self.getEncoding() returns ‘ascii’ if the encoding is unknown to the library.

If the Unicode string cannot be encoded to bytes in the chosen encoding, the error is handled according to the errors parameter to this function, which is passed to the underlying encode() function; by default it throws a UnicodeEncodeError exception.

toStr(errors='strict')

If self.string is a Unicode string, return it; otherwise try decoding the bytes in self.string to a Unicode string using the encoding of this entry as returned by self.getEncoding(); Note that self.getEncoding() returns ‘ascii’ if the encoding is unknown to the library.

Certain heuristics are performed to recover data from bytes that are ill-formed in the chosen encoding, or that otherwise look misencoded (mostly around bad UTF-16BE encoded bytes, or bytes that look like UTF-16BE but marked otherwise). If the bytes are ill-formed and the heuristics fail, the error is handled according to the errors parameter to this function, which is passed to the underlying decode() function; by default it throws a UnicodeDecodeError exception.

Note: The mentioned heuristics mean that roundtripping a font to XML and back to binary might recover some misencoded data whereas just loading the font and saving it back will not change them.

toUnicode(errors='strict')

If self.string is a Unicode string, return it; otherwise try decoding the bytes in self.string to a Unicode string using the encoding of this entry as returned by self.getEncoding(); Note that self.getEncoding() returns ‘ascii’ if the encoding is unknown to the library.

Certain heuristics are performed to recover data from bytes that are ill-formed in the chosen encoding, or that otherwise look misencoded (mostly around bad UTF-16BE encoded bytes, or bytes that look like UTF-16BE but marked otherwise). If the bytes are ill-formed and the heuristics fail, the error is handled according to the errors parameter to this function, which is passed to the underlying decode() function; by default it throws a UnicodeDecodeError exception.

Note: The mentioned heuristics mean that roundtripping a font to XML and back to binary might recover some misencoded data whereas just loading the font and saving it back will not change them.

toXML(writer, ttFont)
class fontTools.ttLib.tables._n_a_m_e.NameRecordVisitor
TABLES = ('GSUB', 'GPOS', 'fvar', 'CPAL', 'STAT')
defaultStop = False
classmethod register(clazzes)
classmethod register_attr(clazzes, attrs)
classmethod register_attrs(clazzes_attrs)
visit(obj, *args, **kwargs)

This is the main entry to the visitor. The visitor will visit object obj.

The visitor will first determine if there is a registered (via @register()) visit function for the type of object. If there is, it will be called, and (visitor, obj, *args, **kwargs) will be passed to the user visit function.

If there is no user-registered visit function, of if there is and it returns True, or it returns None (or doesn’t return anything) and visitor.defaultStop is False (default), then the visitor will proceed to dispatch to one of self.visitObject(), self.visitList(), self.visitDict(), or self.visitLeaf() (any of which can be overriden in a subclass).

visitAttr(obj, attr, value, *args, **kwargs)

Called to visit an attribute of an object.

visitDict(obj, *args, **kwargs)

Called to visit any value that is a dictionary.

visitLeaf(obj, *args, **kwargs)

Called to visit any value that is not an object, list, or dictionary.

visitList(obj, *args, **kwargs)

Called to visit any value that is a list.

visitObject(obj, *args, **kwargs)

Called to visit an object. This function loops over all non-private attributes of the objects and calls any user-registered (via @register_attr() or @register_attrs()) visit() functions.

If there is no user-registered visit function, of if there is and it returns True, or it returns None (or doesn’t return anything) and visitor.defaultStop is False (default), then the visitor will proceed to call self.visitAttr()

fontTools.ttLib.tables._n_a_m_e.makeName(string, nameID, platformID, platEncID, langID)
class fontTools.ttLib.tables._n_a_m_e.table__n_a_m_e(tag=None)
addMultilingualName(names, ttFont=None, nameID=None, windows=True, mac=True, minNameID=0)

Add a multilingual name, returning its name ID

‘names’ is a dictionary with the name in multiple languages, such as {‘en’: ‘Pale’, ‘de’: ‘Blaß’, ‘de-CH’: ‘Blass’}. The keys can be arbitrary IETF BCP 47 language codes; the values are Unicode strings.

‘ttFont’ is the TTFont to which the names are added, or None. If present, the font’s ‘ltag’ table can get populated to store exotic language codes, which allows encoding names that otherwise cannot get encoded at all.

‘nameID’ is the name ID to be used, or None to let the library find an existing set of name records that match, or pick an unused name ID.

If ‘windows’ is True, a platformID=3 name record will be added. If ‘mac’ is True, a platformID=1 name record will be added.

If the ‘nameID’ argument is None, the created nameID will not be less than the ‘minNameID’ argument.

addName(string, platforms=((1, 0, 0), (3, 1, 1033)), minNameID=255)

Add a new name record containing ‘string’ for each (platformID, platEncID, langID) tuple specified in the ‘platforms’ list.

The nameID is assigned in the range between ‘minNameID’+1 and 32767 (inclusive), following the last nameID in the name table. If no ‘platforms’ are specified, two English name records are added, one for the Macintosh (platformID=0), and one for the Windows platform (3).

The ‘string’ must be a Unicode string, so it can be encoded with different, platform-specific encodings.

Return the new nameID.

compile(ttFont)
decompile(data, ttFont)
dependencies = ['ltag']
findMultilingualName(names, windows=True, mac=True, minNameID=0, ttFont=None)

Return the name ID of an existing multilingual name that matches the ‘names’ dictionary, or None if not found.

‘names’ is a dictionary with the name in multiple languages, such as {‘en’: ‘Pale’, ‘de’: ‘Blaß’, ‘de-CH’: ‘Blass’}. The keys can be arbitrary IETF BCP 47 language codes; the values are Unicode strings.

If ‘windows’ is True, the returned name ID is guaranteed exist for all requested languages for platformID=3 and platEncID=1. If ‘mac’ is True, the returned name ID is guaranteed to exist for all requested languages for platformID=1 and platEncID=0.

The returned name ID will not be less than the ‘minNameID’ argument.

fromXML(name, attrs, content, ttFont)
getBestFamilyName()
getBestFullName()
getBestSubFamilyName()
getDebugName(nameID)
getFirstDebugName(nameIDs)
getName(nameID, platformID, platEncID, langID=None)
merge(m, tables)
mergeMap = {'names': <function first>, 'tableTag': <function equal>}
prune_post_subset(font, options)
removeNames(nameID=None, platformID=None, platEncID=None, langID=None)

Remove any name records identified by the given combination of ‘nameID’, ‘platformID’, ‘platEncID’ and ‘langID’.

static removeUnusedNames(ttFont)

Remove any name records which are not in NameID range 0-255 and not utilized within the font itself.

setName(string, nameID, platformID, platEncID, langID)

Set the ‘string’ for the name record identified by ‘nameID’, ‘platformID’, ‘platEncID’ and ‘langID’. If a record with that nameID doesn’t exist, create it and append to the name table.

‘string’ can be of type str (unicode in PY2) or bytes. In the latter case, it is assumed to be already encoded with the correct plaform-specific encoding identified by the (platformID, platEncID, langID) triplet. A warning is issued to prevent unexpected results.

toXML(writer, ttFont)
opbd: Optical Bounds Table
class fontTools.ttLib.tables._o_p_b_d.table__o_p_b_d(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
OS/2: OS/2 and Windows Metrics Table
class fontTools.ttLib.tables.O_S_2f_2.Panose(**kwargs)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
fontTools.ttLib.tables.O_S_2f_2.calcCodePageRanges(unicodes)

Given a set of Unicode codepoints (integers), calculate the corresponding OS/2 CodePage range bits. This is a direct translation of FontForge implementation: https://github.com/fontforge/fontforge/blob/7b2c074/fontforge/tottf.c#L3158

fontTools.ttLib.tables.O_S_2f_2.intersectUnicodeRanges(unicodes, inverse=False)

Intersect a sequence of (int) Unicode codepoints with the Unicode block ranges defined in the OpenType specification v1.7, and return the set of ‘ulUnicodeRanges’ bits for which there is at least ONE intersection. If ‘inverse’ is True, return the the bits for which there is NO intersection.

>>> intersectUnicodeRanges([0x0410]) == {9}
True
>>> intersectUnicodeRanges([0x0410, 0x1F000]) == {9, 57, 122}
True
>>> intersectUnicodeRanges([0x0410, 0x1F000], inverse=True) == (
...     set(range(len(OS2_UNICODE_RANGES))) - {9, 57, 122})
True
class fontTools.ttLib.tables.O_S_2f_2.table_O_S_2f_2(tag=None)

the OS/2 table

compile(ttFont)
decompile(data, ttFont)
dependencies = ['head']
fromXML(name, attrs, content, ttFont)
property fsFirstCharIndex
property fsLastCharIndex
getCodePageRanges()

Return the set of ‘ulCodePageRange*’ bits currently enabled.

getUnicodeRanges()

Return the set of ‘ulUnicodeRange*’ bits currently enabled.

merge(m, tables)
mergeMap = {'*': <function first>, 'fsFirstCharIndex': <built-in function min>, 'fsLastCharIndex': <built-in function max>, 'fsType': <function mergeOs2FsType>, 'panose': <function first>, 'sCapHeight': <function onlyExisting.<locals>.wrapper>, 'sTypoAscender': <built-in function max>, 'sTypoDescender': <built-in function min>, 'sTypoLineGap': <built-in function max>, 'sxHeight': <function onlyExisting.<locals>.wrapper>, 'tableTag': <function equal>, 'ulCodePageRange1': <function onlyExisting.<locals>.wrapper>, 'ulCodePageRange2': <function onlyExisting.<locals>.wrapper>, 'ulUnicodeRange1': <function bitwise_or>, 'ulUnicodeRange2': <function bitwise_or>, 'ulUnicodeRange3': <function bitwise_or>, 'ulUnicodeRange4': <function bitwise_or>, 'usBreakChar': <function onlyExisting.<locals>.wrapper>, 'usDefaultChar': <function onlyExisting.<locals>.wrapper>, 'usLowerOpticalPointSize': <function onlyExisting.<locals>.wrapper>, 'usMaxContext': <function onlyExisting.<locals>.wrapper>, 'usUpperOpticalPointSize': <function onlyExisting.<locals>.wrapper>, 'usWinAscent': <built-in function max>, 'usWinDescent': <built-in function max>, 'version': <built-in function max>, 'xAvgCharWidth': <function first>}
recalcAvgCharWidth(ttFont)

Recalculate xAvgCharWidth using metrics from ttFont’s ‘hmtx’ table.

Set it to 0 if the unlikely event ‘hmtx’ table is not found.

recalcCodePageRanges(ttFont, pruneOnly=False)
recalcUnicodeRanges(ttFont, pruneOnly=False)

Intersect the codepoints in the font’s Unicode cmap subtables with the Unicode block ranges defined in the OpenType specification (v1.7), and set the respective ‘ulUnicodeRange*’ bits if there is at least ONE intersection. If ‘pruneOnly’ is True, only clear unused bits with NO intersection.

setCodePageRanges(bits)

Set the ‘ulCodePageRange*’ fields to the specified ‘bits’.

setUnicodeRanges(bits)

Set the ‘ulUnicodeRange*’ fields to the specified ‘bits’.

toXML(writer, ttFont)
updateFirstAndLastCharIndex(ttFont)
property usMaxContex
post: PostScript Table
fontTools.ttLib.tables._p_o_s_t.packPStrings(strings)
class fontTools.ttLib.tables._p_o_s_t.table__p_o_s_t(tag=None)
build_psNameMapping(ttFont)
compile(ttFont)
decode_format_1_0(data, ttFont)
decode_format_2_0(data, ttFont)
decode_format_3_0(data, ttFont)
decode_format_4_0(data, ttFont)
decompile(data, ttFont)
dependencies = []
encode_format_2_0(ttFont)
encode_format_4_0(ttFont)
fromXML(name, attrs, content, ttFont)
getGlyphOrder()

This function will get called by a ttLib.TTFont instance. Do not call this function yourself, use TTFont().getGlyphOrder() or its relatives instead!

merge(m, tables)
mergeMap = {'*': <function first>, 'extraNames': <function <lambda>>, 'formatType': <built-in function max>, 'isFixedPitch': <built-in function min>, 'mapping': <function onlyExisting.<locals>.wrapper>, 'maxMemType1': <function <lambda>>, 'maxMemType42': <function <lambda>>, 'minMemType1': <built-in function max>, 'minMemType42': <built-in function max>, 'tableTag': <function equal>}
prune_pre_subset(font, options)
subset_glyphs(s)
toXML(writer, ttFont)
fontTools.ttLib.tables._p_o_s_t.unpackPStrings(data, n)
prep: Control Value Program
class fontTools.ttLib.tables._p_r_e_p.table__p_r_e_p(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap(lst)
toXML(writer, ttFont)
prop: Glyph Properties Table
class fontTools.ttLib.tables._p_r_o_p.table__p_r_o_p(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
sbix: Standard Bitmap Graphics Table
class fontTools.ttLib.tables._s_b_i_x.sbixStrikeOffset
class fontTools.ttLib.tables._s_b_i_x.table__s_b_i_x(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
subset_glyphs(s)
toXML(xmlWriter, ttFont)
sbixGlyph
class fontTools.ttLib.tables.sbixGlyph.Glyph(glyphName=None, referenceGlyphName=None, originOffsetX=0, originOffsetY=0, graphicType=None, imageData=None, rawdata=None, gid=0)
compile(ttFont)
decompile(ttFont)
fromXML(name, attrs, content, ttFont)
is_reference_type()

Returns True if this glyph is a reference to another glyph’s image data.

toXML(xmlWriter, ttFont)
sbixStrike
class fontTools.ttLib.tables.sbixStrike.Strike(rawdata=None, ppem=0, resolution=72)
compile(ttFont)
decompile(ttFont)
fromXML(name, attrs, content, ttFont)
toXML(xmlWriter, ttFont)
Silf: Graphite Rules Table
class fontTools.ttLib.tables.S__i_l_f.Classes
compile(ttFont, version=2.0)
decompile(data, ttFont, version=2.0)
fromXML(name, attrs, content, ttFont, version=2.0)
toXML(writer, ttFont, version=2.0)
class fontTools.ttLib.tables.S__i_l_f.Pass
compile(ttFont, base, version=2.0)
decompile(data, ttFont, version=2.0)
fromXML(name, attrs, content, ttFont, version=2.0)
toXML(writer, ttFont, version=2.0)
class fontTools.ttLib.tables.S__i_l_f.Silf

A particular Silf subtable

compile(ttFont, version=2.0)
decompile(data, ttFont, version=2.0)
fromXML(name, attrs, content, ttFont, version=2.0)
toXML(writer, ttFont, version=2.0)
fontTools.ttLib.tables.S__i_l_f.assemble(instrs)
fontTools.ttLib.tables.S__i_l_f.content_string(contents)
fontTools.ttLib.tables.S__i_l_f.disassemble(aCode)
fontTools.ttLib.tables.S__i_l_f.getSimple(self, attrs, *attr_list)
fontTools.ttLib.tables.S__i_l_f.readcode(content)
class fontTools.ttLib.tables.S__i_l_f.table_S__i_l_f(tag=None)

Silf table support

compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
fontTools.ttLib.tables.S__i_l_f.wrapline(writer, dat, length=80)
fontTools.ttLib.tables.S__i_l_f.writecode(tag, writer, instrs)
fontTools.ttLib.tables.S__i_l_f.writesimple(tag, self, writer, *attrkeys)
Sill: Graphite Languages Table
class fontTools.ttLib.tables.S__i_l_l.table_S__i_l_l(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
SING: SING Glyphlet Basic Information Table
class fontTools.ttLib.tables.S_I_N_G_.table_S_I_N_G_(tag=None)
compile(ttFont)
compilecompileUniqueName(name, length)
decompile(data, ttFont)
decompileUniqueName(data)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
STAT: Style Attributes Table
class fontTools.ttLib.tables.S_T_A_T_.table_S_T_A_T_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
SVG: SVG (Scalable Vector Graphics) Table

Compiles/decompiles SVG table.

https://docs.microsoft.com/en-us/typography/opentype/spec/svg

The XML format is:

<SVG>
        <svgDoc endGlyphID="1" startGlyphID="1">
                <![CDATA[ <complete SVG doc> ]]
        </svgDoc>
...
        <svgDoc endGlyphID="n" startGlyphID="m">
                <![CDATA[ <complete SVG doc> ]]
        </svgDoc>
</SVG>
class fontTools.ttLib.tables.S_V_G_.DocumentIndexEntry
class fontTools.ttLib.tables.S_V_G_.SVGDocument(data: str, startGlyphID: int, endGlyphID: int, compressed: bool = False)
compressed: bool = False
count(value) integer -- return number of occurrences of value
data: str
endGlyphID: int
index(value[, start[, stop]]) integer -- return first index of value.

Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

startGlyphID: int
class fontTools.ttLib.tables.S_V_G_.table_S_V_G_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
subset_glyphs(s) bool
toXML(writer, ttFont)
trak: Tracking table
class fontTools.ttLib.tables._t_r_a_k.TrackData(initialdata={})
clear() None.  Remove all items from D.
compile(offset)
decompile(data, offset)
fromXML(name, attrs, content, ttFont)
get(k[, d]) D[k] if k in D, else d.  d defaults to None.
items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) D.get(k,d), also set D[k]=d if k not in D
sizes()
toXML(writer, ttFont)
tracks()

D.keys() -> a set-like object providing a view on D’s keys

update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() an object providing a view on D's values
class fontTools.ttLib.tables._t_r_a_k.TrackTableEntry(values={}, nameIndex=None)
clear() None.  Remove all items from D.
fromXML(name, attrs, content, ttFont)
get(k[, d]) D[k] if k in D, else d.  d defaults to None.
items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) D.get(k,d), also set D[k]=d if k not in D
sizes()

D.keys() -> a set-like object providing a view on D’s keys

toXML(writer, ttFont)
update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() an object providing a view on D's values
class fontTools.ttLib.tables._t_r_a_k.table__t_r_a_k(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['name']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TTFA: ttfautohint Parameter Table
class fontTools.ttLib.tables.T_T_F_A_.table_T_T_F_A_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
VDMX: Vertical Device Metrics
class fontTools.ttLib.tables.V_D_M_X_.table_V_D_M_X_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
vhea: Vertical Header Table
class fontTools.ttLib.tables._v_h_e_a.table__v_h_e_a(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['vmtx', 'glyf', 'CFF ', 'CFF2']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap = {'*': <function equal>, 'advanceHeightMax': <built-in function max>, 'ascent': <built-in function max>, 'caretOffset': <function first>, 'caretSlopeRise': <function first>, 'caretSlopeRun': <function first>, 'descent': <built-in function min>, 'lineGap': <built-in function max>, 'minBottomSideBearing': <built-in function min>, 'minTopSideBearing': <built-in function min>, 'numberOfVMetrics': <function recalculate>, 'tableTag': <function equal>, 'tableVersion': <built-in function max>, 'yMaxExtent': <built-in function max>}
recalc(ttFont)
property reserved0
toXML(writer, ttFont)
vmtx: Vertical Metrics Table
class fontTools.ttLib.tables._v_m_t_x.table__v_m_t_x(tag=None)
advanceName = 'height'
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
headerTag = 'vhea'
longMetricFormat = 'Hh'
merge(m, tables)
mergeMap = {'metrics': <function sumDicts>, 'tableTag': <function equal>}
numberOfMetricsName = 'numberOfVMetrics'
sideBearingName = 'tsb'
subset_glyphs(s)
toXML(writer, ttFont)
VORG: Vertical Origin Table
class fontTools.ttLib.tables.V_O_R_G_.VOriginRecord(name=None, vOrigin=None)
fromXML(name, attrs, content, ttFont)
toXML(writer, ttFont)
class fontTools.ttLib.tables.V_O_R_G_.table_V_O_R_G_(tag=None)

This table is structured so that you can treat it like a dictionary keyed by glyph name.

ttFont['VORG'][<glyphName>] will return the vertical origin for any glyph.

ttFont['VORG'][<glyphName>] = <value> will set the vertical origin for any glyph.

compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
subset_glyphs(s)
toXML(writer, ttFont)
Visual TrueType Private Tables
TSI0: Glyph Program Text Indices

TSI{0,1,2,3,5} are private tables used by Microsoft Visual TrueType (VTT) tool to store its hinting source data.

TSI0 is the index table containing the lengths and offsets for the glyph programs and ‘extra’ programs (‘fpgm’, ‘prep’, and ‘cvt’) that are contained in the TSI1 table.

fontTools.ttLib.tables.T_S_I__0.fixlongs(glyphID, textLength, textOffset)
class fontTools.ttLib.tables.T_S_I__0.table_T_S_I__0(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['TSI1']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
set(indices, extra_indices)
toXML(writer, ttFont)
TSI1: Glyph Program Text UTF-8 Text Dump

TSI{0,1,2,3,5} are private tables used by Microsoft Visual TrueType (VTT) tool to store its hinting source data.

TSI1 contains the text of the glyph programs in the form of low-level assembly code, as well as the ‘extra’ programs ‘fpgm’, ‘ppgm’ (i.e. ‘prep’), and ‘cvt’.

class fontTools.ttLib.tables.T_S_I__1.table_T_S_I__1(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
extras = {65530: 'ppgm', 65531: 'cvt', 65532: 'reserved', 65533: 'fpgm'}
fromXML(name, attrs, content, ttFont)
indextable = 'TSI0'
property log
merge(m, tables)
toXML(writer, ttFont)
TSI2: VTT Talk Text Indices

TSI{0,1,2,3,5} are private tables used by Microsoft Visual TrueType (VTT) tool to store its hinting source data.

TSI2 is the index table containing the lengths and offsets for the glyph programs that are contained in the TSI3 table. It uses the same format as the TSI0 table.

class fontTools.ttLib.tables.T_S_I__2.table_T_S_I__2(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['TSI3']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
set(indices, extra_indices)
toXML(writer, ttFont)
TSI3: VTT Talk UTF-8 Text Dump

TSI{0,1,2,3,5} are private tables used by Microsoft Visual TrueType (VTT) tool to store its hinting source data.

TSI3 contains the text of the glyph programs in the form of ‘VTTTalk’ code.

class fontTools.ttLib.tables.T_S_I__3.table_T_S_I__3(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
extras = {65530: 'reserved0', 65531: 'reserved1', 65532: 'reserved2', 65533: 'reserved3'}
fromXML(name, attrs, content, ttFont)
indextable = 'TSI2'
property log
merge(m, tables)
toXML(writer, ttFont)
TSI5: VTT Character Group Flag

TSI{0,1,2,3,5} are private tables used by Microsoft Visual TrueType (VTT) tool to store its hinting source data.

TSI5 contains the VTT character groups.

class fontTools.ttLib.tables.T_S_I__5.table_T_S_I__5(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TSIB
class fontTools.ttLib.tables.T_S_I_B_.table_T_S_I_B_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TSIC: VTT Variation CVT Window Source
class fontTools.ttLib.tables.T_S_I_C_.table_T_S_I_C_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)
TSID: VTT GDEF Table Text Source
class fontTools.ttLib.tables.T_S_I_D_.table_T_S_I_D_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TSIJ: VTT JSTF Table Text Source
class fontTools.ttLib.tables.T_S_I_J_.table_T_S_I_J_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TSIP: VTT GPOS Table Text Source
class fontTools.ttLib.tables.T_S_I_P_.table_T_S_I_P_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TSIS: VTT GSUB Table Text Source
class fontTools.ttLib.tables.T_S_I_S_.table_T_S_I_S_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
TSIV
class fontTools.ttLib.tables.T_S_I_V_.table_T_S_I_V_(tag=None)
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
merge(m, tables)
toXML(writer, ttFont)
VVAR: Vertical Metrics Variations Table
class fontTools.ttLib.tables.V_V_A_R_.table_V_V_A_R_(tag=None)
compile(font)

Compiles the table into binary. Called automatically on save.

decompile(data, font)

Create an object from the binary data. Called automatically on access.

dependencies = []
ensureDecompiled(recurse=True)
fromXML(name, attrs, content, font)
merge(m, tables)
subset_glyphs(s)
toXML(writer, font)
tryPackingFontTools(writer)
tryPackingHarfbuzz(writer, hb_first_error_logged)
tryResolveOverflow(font, e, lastOverflowRecord)

The Python modules representing the tables have pretty strange names: this is due to the fact that we need to map TT table tags (which are case sensitive) to filenames (which on Mac and Win aren’t case sensitive) as well as to Python identifiers. The latter means it can only contain [A-Za-z0-9_] and cannot start with a number.

fontTools.ttLib provides functions to expand a tag into the format used here:

>>> from fontTools import ttLib
>>> ttLib.tagToIdentifier("FOO ")
'F_O_O_'
>>> ttLib.tagToIdentifier("cvt ")
'_c_v_t'
>>> ttLib.tagToIdentifier("OS/2")
'O_S_2f_2'
>>> ttLib.tagToIdentifier("glyf")
'_g_l_y_f'
>>>

And vice versa:

>>> ttLib.identifierToTag("F_O_O_")
'FOO '
>>> ttLib.identifierToTag("_c_v_t")
'cvt '
>>> ttLib.identifierToTag("O_S_2f_2")
'OS/2'
>>> ttLib.identifierToTag("_g_l_y_f")
'glyf'
>>>

Eg. the ‘glyf’ table converter lives in a Python file called:

_g_l_y_f.py

The converter itself is a class, named table_ + expandedtag. Eg:

class table__g_l_y_f:
        etc.

Note that if you _do_ need to use such modules or classes manually, there are two convenient API functions that let you find them by tag:

>>> ttLib.getTableModule('glyf')
<module 'ttLib.tables._g_l_y_f'>
>>> ttLib.getTableClass('glyf')
<class ttLib.tables._g_l_y_f.table__g_l_y_f at 645f400>
>>
ttProgram: TrueType bytecode assembler/disassembler

ttLib.tables.ttProgram.py – Assembler/disassembler for TrueType bytecode programs.

class fontTools.ttLib.tables.ttProgram.Program
fromAssembly(assembly: List[str] | str) None
fromBytecode(bytecode: bytes) None
fromXML(name, attrs, content, ttFont) None
getAssembly(preserve=True) List[str]
getBytecode() bytes
toXML(writer, ttFont) None
fontTools.ttLib.tables.ttProgram.bitRepr(value, bits)
exception fontTools.ttLib.tables.ttProgram.tt_instructions_error(error)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

Contributing your own table convertors

To add support for a new font table that fontTools does not currently implement, you must subclass from fontTools.ttLib.tables.DefaultTable.DefaultTable. It provides some default behavior, as well as a constructor method (__init__) that you don’t need to override.

Your converter should minimally provide two methods:

class table_F_O_O_(DefaultTable.DefaultTable): # converter for table 'FOO '

    def decompile(self, data, ttFont):
        # 'data' is the raw table data. Unpack it into a
        # Python data structure.
        # 'ttFont' is a ttLib.TTfile instance, enabling you to
        # refer to other tables. Do ***not*** keep a reference to
        # it: it will cause a circular reference (ttFont saves
        # a reference to us), and that means we'll be leaking
        # memory. If you need to use it in other methods, just
        # pass it around as a method argument.

    def compile(self, ttFont):
        # Return the raw data, as converted from the Python
        # data structure.
        # Again, 'ttFont' is there so you can access other tables.
        # Same warning applies.

If you want to support TTX import/export as well, you need to provide two additional methods:

def toXML(self, writer, ttFont):
   # XXX

def fromXML(self, (name, attrs, content), ttFont):
   # XXX

woff2

class fontTools.ttLib.woff2.WOFF2DirectoryEntry
decodeData(rawData)
encodeData(data)
fromFile(file)
fromString(data)
loadData(file)
saveData(file, data)
toString()
property transformVersion

Return bits 6-7 of table entry’s flags, which indicate the preprocessing transformation version number (between 0 and 3).

property transformed

Return True if the table has any transformation, else return False.

class fontTools.ttLib.woff2.WOFF2FlavorData(reader=None, data=None, transformedTables=None)
Flavor = 'woff2'
class fontTools.ttLib.woff2.WOFF2GlyfTable(tag=None)

Decoder/Encoder for WOFF2 ‘glyf’ table transform.

closure_glyphs(s)
compile(ttFont)
decompile(data, ttFont)
dependencies = ['fvar']
ensureDecompiled(recurse=False)
fromXML(name, attrs, content, ttFont)
get(glyphName, default=None)
getCoordinatesAndControls(glyphName, ttFont, defaultVerticalOrigin=None)

Old public name for self._getCoordinatesAndControls(). See: https://github.com/fonttools/fonttools/pull/2266

getGlyphID(glyphName)

Returns the ID of the glyph with the given name.

Raises a ValueError if the glyph is not found in the font.

getGlyphName(glyphID)

Returns the name for the glyph with the given ID.

Raises a KeyError if the glyph name is not found in the font.

getPhantomPoints(glyphName, ttFont, defaultVerticalOrigin=None)

Old public name for self._getPhantomPoints(). See: https://github.com/fonttools/fonttools/pull/2266

has_key(glyphName)
keys()
merge(m, tables)
mergeMap = {'_reverseGlyphOrder': <function recalculate>, 'axisTags': <function equal>, 'glyphOrder': <function sumLists>, 'glyphs': <function sumDicts>, 'tableTag': <function equal>}
padding = 1
prune_post_subset(font, options)
prune_pre_subset(font, options)
reconstruct(data, ttFont)

Decompile transformed ‘glyf’ data.

removeHinting()

Removes TrueType hints from all glyphs in the glyphset.

See Glyph.removeHinting().

setCoordinates(glyphName, ttFont)

Old public name for self._setCoordinates(). See: https://github.com/fonttools/fonttools/pull/2266

setGlyphOrder(glyphOrder)

Sets the glyph order

Parameters:

glyphOrder ([str]) – List of glyph names in order.

subStreams = ('nContourStream', 'nPointsStream', 'flagStream', 'glyphStream', 'compositeStream', 'bboxStream', 'instructionStream')
subset_glyphs(s)
toXML(writer, ttFont, splitGlyphs=False)
transform(ttFont)

Return transformed ‘glyf’ data

class fontTools.ttLib.woff2.WOFF2HmtxTable(tag=None)
advanceName = 'width'
compile(ttFont)
decompile(data, ttFont)
dependencies = []
fromXML(name, attrs, content, ttFont)
headerTag = 'hhea'
longMetricFormat = 'Hh'
merge(m, tables)
mergeMap = {'metrics': <function sumDicts>, 'tableTag': <function equal>}
numberOfMetricsName = 'numberOfHMetrics'
reconstruct(data, ttFont)
sideBearingName = 'lsb'
subset_glyphs(s)
toXML(writer, ttFont)
transform(ttFont)
class fontTools.ttLib.woff2.WOFF2LocaTable(tag=None)

Same as parent class. The only difference is that it attempts to preserve the ‘indexFormat’ as encoded in the WOFF2 glyf table.

compile(ttFont)
decompile(data, ttFont)
dependencies = ['glyf']
fromXML(name, attrs, content, ttFont)
merge(m, tables)
mergeMap = {'*': <function recalculate>, 'tableTag': <function equal>}
set(locations)
toXML(writer, ttFont)
class fontTools.ttLib.woff2.WOFF2Reader(*args, **kwargs)
close()
flavor = 'woff2'
has_key(tag)
keys()
reconstructTable(tag)

Reconstruct table named ‘tag’ from transformed data.

class fontTools.ttLib.woff2.WOFF2Writer(*args, **kwargs)
close()

All tags must have been specified. Now write the table data and directory.

flavor = 'woff2'
reordersTables()
setEntry(tag, entry)
transformTable(tag)

Return transformed table data, or None if some pre-conditions aren’t met – in which case, the non-transformed table data will be used.

writeMasterChecksum()

Write checkSumAdjustment to the transformBuffer.

fontTools.ttLib.woff2.base128Size(n)

Return the length in bytes of a UIntBase128-encoded sequence with value n.

>>> base128Size(0)
1
>>> base128Size(24567)
3
>>> base128Size(2**32-1)
5
fontTools.ttLib.woff2.compress(input_file, output_file, transform_tables=None)

Compress OpenType font to WOFF2.

Parameters:
  • input_file – a file path, file or file-like object (open in binary mode) containing an OpenType font (either CFF- or TrueType-flavored).

  • output_file – a file path, file or file-like object where to save the compressed WOFF2 font.

  • transform_tables – Optional[Iterable[str]]: a set of table tags for which to enable preprocessing transformations. By default, only ‘glyf’ and ‘loca’ tables are transformed. An empty set means disable all transformations.

fontTools.ttLib.woff2.decompress(input_file, output_file)

Decompress WOFF2 font to OpenType font.

Parameters:
  • input_file – a file path, file or file-like object (open in binary mode) containing a compressed WOFF2 font.

  • output_file – a file path, file or file-like object where to save the decompressed OpenType font.

fontTools.ttLib.woff2.getKnownTagIndex(tag)

Return index of ‘tag’ in woff2KnownTags list. Return 63 if not found.

fontTools.ttLib.woff2.main(args=None)

Compress and decompress WOFF2 fonts

fontTools.ttLib.woff2.pack255UShort(value)

Encode unsigned integer in range 0 to 65535 (inclusive) to a bytestring using 255UInt16 variable-length encoding.

>>> pack255UShort(252) == b'\xfc'
True
>>> pack255UShort(506) == b'\xfe\x00'
True
>>> pack255UShort(762) == b'\xfd\x02\xfa'
True
fontTools.ttLib.woff2.packBase128(n)

Encode unsigned integer in range 0 to 2**32-1 (inclusive) to a string of bytes using UIntBase128 variable-length encoding. Produce the shortest possible encoding.

>>> packBase128(63) == b"\x3f"
True
>>> packBase128(2**32-1) == b'\x8f\xff\xff\xff\x7f'
True
fontTools.ttLib.woff2.unpack255UShort(data)

Read one to three bytes from 255UInt16-encoded input string, and return a tuple containing the decoded integer plus any leftover data.

>>> unpack255UShort(bytechr(252))[0]
252

Note that some numbers (e.g. 506) can have multiple encodings: >>> unpack255UShort(struct.pack(“BB”, 254, 0))[0] 506 >>> unpack255UShort(struct.pack(“BB”, 255, 253))[0] 506 >>> unpack255UShort(struct.pack(“BBB”, 253, 1, 250))[0] 506

fontTools.ttLib.woff2.unpackBase128(data)

Read one to five bytes from UIntBase128-encoded input string, and return a tuple containing the decoded integer plus any leftover data.

>>> unpackBase128(b'\x3f\x00\x00') == (63, b"\x00\x00")
True
>>> unpackBase128(b'\x8f\xff\xff\xff\x7f')[0] == 4294967295
True
>>> unpackBase128(b'\x80\x80\x3f')  
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TTLibError: UIntBase128 value must not start with leading zeros
>>> unpackBase128(b'\x8f\xff\xff\xff\xff\x7f')[0]  
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TTLibError: UIntBase128-encoded sequence is longer than 5 bytes
>>> unpackBase128(b'\x90\x80\x80\x80\x00')[0]  
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TTLibError: UIntBase128 value exceeds 2**32-1

ttx

TTX – From OpenType and TrueType to XML and Back

Once installed you can use the ttx command to convert binary font files (.otf, .ttf, etc) to the TTX XML format, edit them, and convert them back to binary format. TTX files have a .ttx file extension:

ttx /path/to/font.otf
ttx /path/to/font.ttx

The TTX application can be used in two ways, depending on what platform you run it on:

  • As a command line tool (Windows/DOS, Unix, macOS)

  • By dropping files onto the application (Windows, macOS)

TTX detects what kind of files it is fed: it will output a .ttx file when it sees a .ttf or .otf, and it will compile a .ttf or .otf when the input file is a .ttx file. By default, the output file is created in the same folder as the input file, and will have the same name as the input file but with a different extension. TTX will never overwrite existing files, but if necessary will append a unique number to the output filename (before the extension) such as Arial#1.ttf.

When using TTX from the command line there are a bunch of extra options. These are explained in the help text, as displayed when typing ttx -h at the command prompt. These additional options include:

  • specifying the folder where the output files are created

  • specifying which tables to dump or which tables to exclude

  • merging partial .ttx files with existing .ttf or .otf files

  • listing brief table info instead of dumping to .ttx

  • splitting tables to separate .ttx files

  • disabling TrueType instruction disassembly

The TTX file format

The following tables are currently supported:

BASE, CBDT, CBLC, CFF, CFF2, COLR, CPAL, DSIG, Debg, EBDT, EBLC,
FFTM, Feat, GDEF, GMAP, GPKG, GPOS, GSUB, Glat, Gloc, HVAR, JSTF,
LTSH, MATH, META, MVAR, OS/2, SING, STAT, SVG, Silf, Sill, TSI0,
TSI1, TSI2, TSI3, TSI5, TSIB, TSIC, TSID, TSIJ, TSIP, TSIS, TSIV,
TTFA, VDMX, VORG, VVAR, ankr, avar, bsln, cidg, cmap, cvar, cvt,
feat, fpgm, fvar, gasp, gcid, glyf, gvar, hdmx, head, hhea, hmtx,
kern, lcar, loca, ltag, maxp, meta, mort, morx, name, opbd, post,
prep, prop, sbix, trak, vhea and vmtx

Other tables are dumped as hexadecimal data.

TrueType fonts use glyph indices (GlyphIDs) to refer to glyphs in most places. While this is fine in binary form, it is really hard to work with for humans. Therefore we use names instead.

The glyph names are either extracted from the CFF table or the post table, or are derived from a Unicode cmap table. In the latter case the Adobe Glyph List is used to calculate names based on Unicode values. If all of these methods fail, names are invented based on GlyphID (eg glyph00142)

It is possible that different glyphs use the same name. If this happens, we force the names to be unique by appending #n to the name (n being an integer number.) The original names are being kept, so this has no influence on a “round tripped” font.

Because the order in which glyphs are stored inside the binary font is important, we maintain an ordered list of glyph names in the font.

usage: ttx [options] inputfile1 [… inputfileN]

TTX – From OpenType To XML And Back

If an input file is a TrueType or OpenType font file, it will be decompiled to a TTX file (an XML-based text format). If an input file is a TTX file, it will be compiled to whatever format the data is in, a TrueType or OpenType/CFF font file. A special input value of - means read from the standard input.

Output files are created so they are unique: an existing file is never overwritten.

General options
-h Help

print this message.

--version

show version and exit.

-d <outputfolder>

Specify a directory where the output files are to be created.

-o <outputfile>

Specify a file to write the output to. A special value of - would use the standard output.

-f

Overwrite existing output file(s), ie. don’t append numbers.

-v

Verbose: more messages will be written to stdout about what is being done.

-q

Quiet: No messages will be written to stdout about what is being done.

-a

allow virtual glyphs ID’s on compile or decompile.

Dump options
-l

List table info: instead of dumping to a TTX file, list some minimal info about each table.

-t <table>

Specify a table to dump. Multiple -t options are allowed. When no -t option is specified, all tables will be dumped.

-x <table>

Specify a table to exclude from the dump. Multiple -x options are allowed. -t and -x are mutually exclusive.

-s

Split tables: save the TTX data into separate TTX files per table and write one small TTX file that contains references to the individual table dumps. This file can be used as input to ttx, as long as the table files are in the same directory.

-g

Split glyf table: Save the glyf data into separate TTX files per glyph and write a small TTX for the glyf table which contains references to the individual TTGlyph elements. NOTE: specifying -g implies -s (no need for -s together with -g)

-i

Do NOT disassemble TT instructions: when this option is given, all TrueType programs (glyph programs, the font program and the pre-program) will be written to the TTX file as hex data instead of assembly. This saves some time and makes the TTX file smaller.

-z <format>

Specify a bitmap data export option for EBDT: {‘raw’, ‘row’, ‘bitwise’, ‘extfile’} or for the CBDT: {‘raw’, ‘extfile’} Each option does one of the following:

-z raw

export the bitmap data as a hex dump

-z row

export each row as hex data

-z bitwise

export each row as binary in an ASCII art style

-z extfile

export the data as external files with XML references

If no export format is specified ‘raw’ format is used.

-e

Don’t ignore decompilation errors, but show a full traceback and abort.

-y <number>

Select font number for TrueType Collection (.ttc/.otc), starting from 0.

--unicodedata <UnicodeData.txt>

Use custom database file to write character names in the comments of the cmap TTX output.

--newline <value>

Control how line endings are written in the XML file. It can be ‘LF’, ‘CR’, or ‘CRLF’. If not specified, the default platform-specific line endings are used.

Compile options
-m

Merge with TrueType-input-file: specify a TrueType or OpenType font file to be merged with the TTX file. This option is only valid when at most one TTX file is specified.

-b

Don’t recalc glyph bounding boxes: use the values in the TTX file as-is.

--recalc-timestamp

Set font ‘modified’ timestamp to current time. By default, the modification time of the TTX file will be used.

--no-recalc-timestamp

Keep the original font ‘modified’ timestamp.

--flavor <type>

Specify flavor of output font file. May be ‘woff’ or ‘woff2’. Note that WOFF2 requires the Brotli Python extension, available at https://github.com/google/brotli

--with-zopfli

Use Zopfli instead of Zlib to compress WOFF. The Python extension is available at https://pypi.python.org/pypi/zopfli

class fontTools.ttx.Options(rawOptions, numFiles)
bitmapGlyphDataFormat = 'raw'
disassembleInstructions = True
flavor = None
ignoreDecompileErrors = True
listTables = False
mergeFile = None
newlinestr = '\n'
outputDir = None
outputFile = None
overWrite = False
quiet = False
recalcBBoxes = True
recalcTimestamp = None
splitGlyphs = False
splitTables = False
unicodedata = None
useZopfli = False
verbose = False
fontTools.ttx.guessFileType(fileName)
fontTools.ttx.main(args=None)

Convert OpenType fonts to XML and back

fontTools.ttx.parseOptions(args)
fontTools.ttx.process(jobs, options)
fontTools.ttx.ttCompile(input, output, options)
fontTools.ttx.ttDump(input, output, options)
fontTools.ttx.ttList(input, output, options)

ufoLib

converters

errors

filenames

glifLib

kerning

plistlib

pointPen

utils

validators

unicode

fontTools.unicode.setUnicodeData(f)

unicodedata

Blocks

fontTools.unicodedata.Blocks.RANGES
fontTools.unicodedata.Blocks.VALUES

OTTags

fontTools.unicodedata.OTTags.DEFAULT_SCRIPT
fontTools.unicodedata.OTTags.SCRIPT_EXCEPTIONS
fontTools.unicodedata.OTTags.NEW_SCRIPT_TAGS
fontTools.unicodedata.OTTags.NEW_SCRIPT_TAGS_REVERSED

ScriptExtensions

fontTools.unicodedata.ScriptExtensions.RANGES
fontTools.unicodedata.ScriptExtensions.VALUES

Scripts

fontTools.unicodedata.Scripts.NAMES
fontTools.unicodedata.Scripts.RANGES
fontTools.unicodedata.Scripts.VALUES
fontTools.unicodedata.bidirectional(chr, /)

Returns the bidirectional class assigned to the character chr as string.

If no such value is defined, an empty string is returned.

fontTools.unicodedata.block(char)

Return the block property assigned to the Unicode character ‘char’ as a string.

>>> block("a")
'Basic Latin'
>>> block(chr(0x060C))
'Arabic'
>>> block(chr(0xEFFFF))
'No_Block'
fontTools.unicodedata.category(chr, /)

Returns the general category assigned to the character chr as string.

fontTools.unicodedata.combining(chr, /)

Returns the canonical combining class assigned to the character chr as integer.

Returns 0 if no combining class is defined.

fontTools.unicodedata.decimal()

Converts a Unicode character into its equivalent decimal value.

Returns the decimal value assigned to the character chr as integer. If no such value is defined, default is returned, or, if not given, ValueError is raised.

fontTools.unicodedata.decomposition(chr, /)

Returns the character decomposition mapping assigned to the character chr as string.

An empty string is returned in case no such mapping is defined.

fontTools.unicodedata.digit()

Converts a Unicode character into its equivalent digit value.

Returns the digit value assigned to the character chr as integer. If no such value is defined, default is returned, or, if not given, ValueError is raised.

fontTools.unicodedata.east_asian_width(chr, /)

Returns the east asian width assigned to the character chr as string.

fontTools.unicodedata.lookup(name, /)

Look up character by name.

If a character with the given name is found, return the corresponding character. If not found, KeyError is raised.

fontTools.unicodedata.mirrored(chr, /)

Returns the mirrored property assigned to the character chr as integer.

Returns 1 if the character has been identified as a “mirrored” character in bidirectional text, 0 otherwise.

fontTools.unicodedata.name()

Returns the name assigned to the character chr as a string.

If no name is defined, default is returned, or, if not given, ValueError is raised.

fontTools.unicodedata.normalize(form, unistr, /)

Return the normal form ‘form’ for the Unicode string unistr.

Valid values for form are ‘NFC’, ‘NFKC’, ‘NFD’, and ‘NFKD’.

fontTools.unicodedata.numeric()

Converts a Unicode character into its equivalent numeric value.

Returns the numeric value assigned to the character chr as float. If no such value is defined, default is returned, or, if not given, ValueError is raised.

fontTools.unicodedata.ot_tag_to_script(tag)

Return the Unicode script code for the given OpenType script tag, or None for “DFLT” tag or if there is no Unicode script associated with it. Raises ValueError if the tag is invalid.

fontTools.unicodedata.ot_tags_from_script(script_code)

Return a list of OpenType script tags associated with a given Unicode script code. Return [‘DFLT’] script tag for invalid/unknown script codes.

fontTools.unicodedata.script(char)

Return the four-letter script code assigned to the Unicode character ‘char’ as string.

>>> script("a")
'Latn'
>>> script(",")
'Zyyy'
>>> script(chr(0x10FFFF))
'Zzzz'
fontTools.unicodedata.script_code(script_name, default=<class 'KeyError'>)

Returns the four-letter Unicode script code from its long name

If no matching script code is found, a KeyError is raised by default.

You can use the ‘default’ argument to return a fallback string (e.g. ‘Zzzz’ or None) instead of throwing an error.

fontTools.unicodedata.script_extension(char)

Return the script extension property assigned to the Unicode character ‘char’ as a set of string.

>>> script_extension("a") == {'Latn'}
True
>>> script_extension(chr(0x060C)) == {'Rohg', 'Syrc', 'Yezi', 'Arab', 'Thaa', 'Nkoo'}
True
>>> script_extension(chr(0x10FFFF)) == {'Zzzz'}
True
fontTools.unicodedata.script_horizontal_direction(script_code: str, default: T) Literal['RTL', 'LTR'] | T
fontTools.unicodedata.script_horizontal_direction(script_code: str, default: type[KeyError] = KeyError) Literal['RTL', 'LTR']

Return “RTL” for scripts that contain right-to-left characters according to the Bidi_Class property. Otherwise return “LTR”.

fontTools.unicodedata.script_name(code, default=<class 'KeyError'>)

Return the long, human-readable script name given a four-letter Unicode script code.

If no matching name is found, a KeyError is raised by default.

You can use the ‘default’ argument to return a fallback value (e.g. ‘Unknown’ or None) instead of throwing an error.

varLib: OpenType Variation Support

builder

fontTools.varLib.builder.VarData_CalculateNumShorts(self, optimize=True)

Deprecated name for VarData_calculateNumShorts() which defaults to optimize=True. Use varData.calculateNumShorts() or varData.optimize().

fontTools.varLib.builder.VarData_calculateNumShorts(self, optimize=False)
fontTools.varLib.builder.VarData_optimize(self)
fontTools.varLib.builder.buildDeltaSetIndexMap(varIdxes)
fontTools.varLib.builder.buildVarData(varRegionIndices, items, optimize=True)
fontTools.varLib.builder.buildVarDevTable(varIdx)
fontTools.varLib.builder.buildVarIdxMap(varIdxes, glyphOrder)
fontTools.varLib.builder.buildVarRegion(support, axisTags)
fontTools.varLib.builder.buildVarRegionAxis(axisSupport)
fontTools.varLib.builder.buildVarRegionList(supports, axisTags)
fontTools.varLib.builder.buildVarStore(varRegionList, varDataList)

cff

class fontTools.varLib.cff.CFF2CharStringMergePen(default_commands, glyphName, num_masters, master_idx, roundTolerance=0.01)

Pen to merge Type 2 CharStrings.

exception MissingComponentError

Indicates a component pointing to a non-existent glyph in the glyphset.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

addComponent(glyphName, transformation)

Transform the points of the base glyph and draw it onto self.

addVarComponent(glyphName, transformation, location)

Add a VarComponent sub glyph. The ‘transformation’ argument must be a DecomposedTransform from the fontTools.misc.transform module, and the ‘location’ argument must be a dictionary mapping axis tags to their locations.

add_hint(hint_type, args)
add_hintmask(hint_type, abs_args)
add_point(point_type, pt_coords)
closePath()

Close the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path.

curveTo(*points)

Draw a cubic bezier with an arbitrary number of control points.

The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this:

Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment().

The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType “implied points” principle. See also decomposeQuadraticSegment().

endPath()

End the current sub path, but don’t close it. You must call either pen.closePath() or pen.endPath() after each sub path.

getCharString(private=None, globalSubrs=None, var_model=None, optimize=True)
getCommands()
lineTo(pt)

Draw a straight line from the current point to ‘pt’.

property log
moveTo(pt)

Begin a new sub path, set the current point to ‘pt’. You must end each sub path with a call to pen.closePath() or pen.endPath().

qCurveTo(*points)

Draw a whole string of quadratic curve segments.

The last point specified is on-curve, all others are off-curve points.

This method implements TrueType-style curves, breaking up curves using ‘implied points’: between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment().

The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines).

reorder_blend_args(commands, get_delta_func)

We first re-order the master coordinate values. For a moveto to lineto, the args are now arranged as:

[ [master_0 x,y], [master_1 x,y], [master_2 x,y] ]

We re-arrange this to:

[       [master_0 x, master_1 x, master_2 x],
        [master_0 y, master_1 y, master_2 y]
]

If the master values are all the same, we collapse the list to as single value instead of a list.

We then convert this to:

[ [master_0 x] + [x delta tuple] + [numBlends=1]
  [master_0 y] + [y delta tuple] + [numBlends=1]
]
restart(region_idx)
skipMissingComponents = True
class fontTools.varLib.cff.CFFToCFF2OutlineExtractor(pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None, blender=None)

This class is used to remove the initial width from the CFF charstring without trying to add the width to self.nominalWidthX, which is None.

alternatingLineto(isHorizontal)
closePath()
countHints()
endPath()
execute(charString)
hcurveto(args)
op_abs(index)
op_add(index)
op_and(index)
op_blend(index)
op_callgsubr(index)
op_callsubr(index)
op_cntrmask(index)
op_div(index)
op_drop(index)
op_dup(index)
op_endchar(index)
op_eq(index)
op_exch(index)
op_flex(index)
op_flex1(index)
op_get(index)
op_hflex(index)
op_hflex1(index)
op_hhcurveto(index)

dy1? {dxa dxb dyb dxc}+ hhcurveto

op_hintmask(index)
op_hlineto(index)
op_hmoveto(index)
op_hstem(index)
op_hstemhm(index)
op_hvcurveto(index)

dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?

op_ifelse(index)
op_ignore(index)
op_index(index)
op_load(index)
op_mul(index)
op_neg(index)
op_not(index)
op_or(index)
op_put(index)
op_random(index)
op_rcurveline(index)

{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline

op_return(index)
op_rlinecurve(index)

{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve

op_rlineto(index)
op_rmoveto(index)
op_roll(index)
op_rrcurveto(index)

{dxa dya dxb dyb dxc dyc}+ rrcurveto

op_sqrt(index)
op_store(index)
op_sub(index)
op_vhcurveto(index)

dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30) {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto

op_vlineto(index)
op_vmoveto(index)
op_vsindex(index)
op_vstem(index)
op_vstemhm(index)
op_vvcurveto(index)

dx1? {dya dxb dyb dyc}+ vvcurveto

pop()
popall()
popallWidth(evenOdd=0)
push(value)
rCurveTo(pt1, pt2, pt3)
rLineTo(point)
rMoveTo(point)
reset()
vcurveto(args)
class fontTools.varLib.cff.CVarData(varDataList, masterSupports, vsindex_dict)
count(value, /)

Return number of occurrences of value.

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

masterSupports

Alias for field number 1

varDataList

Alias for field number 0

vsindex_dict

Alias for field number 2

class fontTools.varLib.cff.MergeOutlineExtractor(pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None, blender=None)

Used to extract the charstring commands - including hints - from a CFF charstring in order to merge it as another set of region data into a CFF2 variable font charstring.

alternatingLineto(isHorizontal)
closePath()
countHints()
endPath()
execute(charString)
hcurveto(args)
op_abs(index)
op_add(index)
op_and(index)
op_blend(index)
op_callgsubr(index)
op_callsubr(index)
op_cntrmask(index)
op_div(index)
op_drop(index)
op_dup(index)
op_endchar(index)
op_eq(index)
op_exch(index)
op_flex(index)
op_flex1(index)
op_get(index)
op_hflex(index)
op_hflex1(index)
op_hhcurveto(index)

dy1? {dxa dxb dyb dxc}+ hhcurveto

op_hintmask(index)
op_hlineto(index)
op_hmoveto(index)
op_hstem(index)
op_hstemhm(index)
op_hvcurveto(index)

dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?

op_ifelse(index)
op_ignore(index)
op_index(index)
op_load(index)
op_mul(index)
op_neg(index)
op_not(index)
op_or(index)
op_put(index)
op_random(index)
op_rcurveline(index)

{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline

op_return(index)
op_rlinecurve(index)

{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve

op_rlineto(index)
op_rmoveto(index)
op_roll(index)
op_rrcurveto(index)

{dxa dya dxb dyb dxc dyc}+ rrcurveto

op_sqrt(index)
op_store(index)
op_sub(index)
op_vhcurveto(index)

dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30) {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto

op_vlineto(index)
op_vmoveto(index)
op_vsindex(index)
op_vstem(index)
op_vstemhm(index)
op_vvcurveto(index)

dx1? {dya dxb dyb dyc}+ vvcurveto

pop()
popall()
popallWidth(evenOdd=0)
push(value)
rCurveTo(pt1, pt2, pt3)
rLineTo(point)
rMoveTo(point)
reset()
vcurveto(args)
fontTools.varLib.cff.addCFFVarStore(varFont, varModel, varDataList, masterSupports)
fontTools.varLib.cff.conv_to_int(num)
fontTools.varLib.cff.convertCFFtoCFF2(varFont)
fontTools.varLib.cff.get_private(regionFDArrays, fd_index, ri, fd_map)
fontTools.varLib.cff.getfd_map(varFont, fonts_list)

Since a subset source font may have fewer FontDicts in their FDArray than the default font, we have to match up the FontDicts in the different fonts . We do this with the FDSelect array, and by assuming that the same glyph will reference matching FontDicts in each source font. We return a mapping from fdIndex in the default font to a dictionary which maps each master list index of each region font to the equivalent fdIndex in the region font.

fontTools.varLib.cff.lib_convertCFFToCFF2(cff, otFont)
fontTools.varLib.cff.merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map)

I step through the FontDicts in the FDArray of the varfont TopDict. For each varfont FontDict:

  • step through each key in FontDict.Private.

  • For each key, step through each relevant source font Private dict, and

    build a list of values to blend.

The ‘relevant’ source fonts are selected by first getting the right submodel using vsindex_dict[vsindex]. The indices of the subModel.locations are mapped to source font list indices by assuming the latter order is the same as the order of the var_model.locations. I can then get the index of each subModel location in the list of var_model.locations.

fontTools.varLib.cff.merge_charstrings(glyphOrder, num_masters, top_dicts, masterModel)
fontTools.varLib.cff.merge_region_fonts(varFont, model, ordered_fonts_list, glyphOrder)

errors

exception fontTools.varLib.errors.FoundANone(merger=None, **kwargs)

one of the values in a list was empty when it shouldn’t have been

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.InconsistentExtensions(merger=None, **kwargs)

the masters use extension lookups in inconsistent ways

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.InconsistentFormats(merger=None, **kwargs)

an OpenType subtable (%s) had inconsistent formats between masters

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.InconsistentGlyphOrder(merger=None, **kwargs)

the glyph order was inconsistent between masters

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.KeysDiffer(merger=None, **kwargs)

a list of objects had different keys

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.LengthsDiffer(merger=None, **kwargs)

a list of objects had inconsistent lengths

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.MismatchedTypes(merger=None, **kwargs)

data had inconsistent types

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.NotANone(merger=None, **kwargs)

one of the values in a list was not empty when it should have been

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.ShouldBeConstant(merger=None, **kwargs)

some values were different, but should have been the same

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.UnsupportedFormat(merger=None, **kwargs)

an OpenType subtable (%s) had a format I didn’t expect

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibCFFDictMergeError(key, value, values)

Raised when a CFF PrivateDict cannot be merged.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibCFFHintTypeMergeError(hint_type, cmd_index, m_index, default_type, glyph_name)

Raised when a CFF glyph cannot be merged because of hint type differences.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibCFFMergeError
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibCFFPointTypeMergeError(point_type, pt_index, m_index, default_type, glyph_name)

Raised when a CFF glyph cannot be merged because of point type differences.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibError

Base exception for the varLib module.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibMergeError(merger=None, **kwargs)

Raised when input data cannot be merged into a variable font.

add_note()

Exception.add_note(note) – add a note to the exception

args
property details
property offender
property reason
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VarLibValidationError

Raised when input data is invalid from varLib’s point of view.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fontTools.varLib.errors.VariationModelError

Raised when a variation model is faulty.

add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

featureVars

Module to build FeatureVariation tables: https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table

NOTE: The API is experimental and subject to change.

class fontTools.varLib.featureVars.ShifterVisitor(shift)
defaultStop = False
classmethod register(clazzes)
classmethod register_attr(clazzes, attrs)
classmethod register_attrs(clazzes_attrs)
visit(obj, *args, **kwargs)

This is the main entry to the visitor. The visitor will visit object obj.

The visitor will first determine if there is a registered (via @register()) visit function for the type of object. If there is, it will be called, and (visitor, obj, *args, **kwargs) will be passed to the user visit function.

If there is no user-registered visit function, of if there is and it returns True, or it returns None (or doesn’t return anything) and visitor.defaultStop is False (default), then the visitor will proceed to dispatch to one of self.visitObject(), self.visitList(), self.visitDict(), or self.visitLeaf() (any of which can be overriden in a subclass).

visitAttr(obj, attr, value, *args, **kwargs)

Called to visit an attribute of an object.

visitDict(obj, *args, **kwargs)

Called to visit any value that is a dictionary.

visitLeaf(obj, *args, **kwargs)

Called to visit any value that is not an object, list, or dictionary.

visitList(obj, *args, **kwargs)

Called to visit any value that is a list.

visitObject(obj, *args, **kwargs)

Called to visit an object. This function loops over all non-private attributes of the objects and calls any user-registered (via @register_attr() or @register_attrs()) visit() functions.

If there is no user-registered visit function, of if there is and it returns True, or it returns None (or doesn’t return anything) and visitor.defaultStop is False (default), then the visitor will proceed to call self.visitAttr()

fontTools.varLib.featureVars.addFeatureVariations(font, conditionalSubstitutions, featureTag='rvrn')

Add conditional substitutions to a Variable Font.

The conditionalSubstitutions argument is a list of (Region, Substitutions) tuples.

A Region is a list of Boxes. A Box is a dict mapping axisTags to (minValue, maxValue) tuples. Irrelevant axes may be omitted and they are interpretted as extending to end of axis in each direction. A Box represents an orthogonal ‘rectangular’ subset of an N-dimensional design space. A Region represents a more complex subset of an N-dimensional design space, ie. the union of all the Boxes in the Region. For efficiency, Boxes within a Region should ideally not overlap, but functionality is not compromised if they do.

The minimum and maximum values are expressed in normalized coordinates.

A Substitution is a dict mapping source glyph names to substitute glyph names.

Example:

# >>> f = TTFont(srcPath) # >>> condSubst = [ # … # A list of (Region, Substitution) tuples. # … ([{“wdth”: (0.5, 1.0)}], {“cent”: “cent.rvrn”}), # … ([{“wght”: (0.5, 1.0)}], {“dollar”: “dollar.rvrn”}), # … ] # >>> addFeatureVariations(f, condSubst) # >>> f.save(dstPath)

The featureTag parameter takes either a str or a iterable of str (the single str is kept for backwards compatibility), and defines which feature(s) will be associated with the feature variations. Note, if this is “rvrn”, then the substitution lookup will be inserted at the beginning of the lookup list so that it is processed before others, otherwise for any other feature tags it will be appended last.

fontTools.varLib.featureVars.addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag='rvrn')

Low level implementation of addFeatureVariations that directly models the possibilities of the FeatureVariations table.

fontTools.varLib.featureVars.bit_count(self, /)

Number of ones in the binary representation of the absolute value of self.

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3
fontTools.varLib.featureVars.buildConditionTable(axisIndex, filterRangeMinValue, filterRangeMaxValue)

Build a ConditionTable.

fontTools.varLib.featureVars.buildFeatureRecord(featureTag, lookupListIndices)

Build a FeatureRecord.

fontTools.varLib.featureVars.buildFeatureTableSubstitutionRecord(featureIndex, lookupListIndices)

Build a FeatureTableSubstitutionRecord.

fontTools.varLib.featureVars.buildFeatureVariationRecord(conditionTable, substitutionRecords)

Build a FeatureVariationRecord.

fontTools.varLib.featureVars.buildFeatureVariations(featureVariationRecords)

Build the FeatureVariations subtable.

fontTools.varLib.featureVars.buildGSUB()

Build a GSUB table from scratch.

fontTools.varLib.featureVars.buildSubstitutionLookups(gsub, allSubstitutions, processLast=False)

Build the lookups for the glyph substitutions, return a dict mapping the substitution to lookup indices.

fontTools.varLib.featureVars.cleanupBox(box)

Return a sparse copy of box, without redundant (default) values.

>>> cleanupBox({})
{}
>>> cleanupBox({'wdth': (0.0, 1.0)})
{'wdth': (0.0, 1.0)}
>>> cleanupBox({'wdth': (-1.0, 1.0)})
{}
fontTools.varLib.featureVars.findFeatureVariationRecord(featureVariations, conditionTable)

Find a FeatureVariationRecord that has the same conditionTable.

fontTools.varLib.featureVars.makeSubstitutionsHashable(conditionalSubstitutions)

Turn all the substitution dictionaries in sorted tuples of tuples so they are hashable, to detect duplicates so we don’t write out redundant data.

fontTools.varLib.featureVars.overlayBox(top, bot)

Overlays top box on top of bot box.

Returns two items:

  • Box for intersection of top and bot, or None if they don’t intersect.

  • Box for remainder of bot. Remainder box might not be exact (since the remainder might not be a simple box), but is inclusive of the exact remainder.

fontTools.varLib.featureVars.overlayFeatureVariations(conditionalSubstitutions)

Compute overlaps between all conditional substitutions.

The conditionalSubstitutions argument is a list of (Region, Substitutions) tuples.

A Region is a list of Boxes. A Box is a dict mapping axisTags to (minValue, maxValue) tuples. Irrelevant axes may be omitted and they are interpretted as extending to end of axis in each direction. A Box represents an orthogonal ‘rectangular’ subset of an N-dimensional design space. A Region represents a more complex subset of an N-dimensional design space, ie. the union of all the Boxes in the Region. For efficiency, Boxes within a Region should ideally not overlap, but functionality is not compromised if they do.

The minimum and maximum values are expressed in normalized coordinates.

A Substitution is a dict mapping source glyph names to substitute glyph names.

Returns data is in similar but different format. Overlaps of distinct substitution Boxes (not Regions) are explicitly listed as distinct rules, and rules with the same Box merged. The more specific rules appear earlier in the resulting list. Moreover, instead of just a dictionary of substitutions, a list of dictionaries is returned for substitutions corresponding to each unique space, with each dictionary being identical to one of the input substitution dictionaries. These dictionaries are not merged to allow data sharing when they are converted into font tables.

Example:

>>> condSubst = [
...     # A list of (Region, Substitution) tuples.
...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
...     ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}),
...     ([{"wght": (0.5, 1.0), "wdth": (-1, 1.0)}], {"dollar": "dollar.rvrn"}),
... ]
>>> from pprint import pprint
>>> pprint(overlayFeatureVariations(condSubst))
[({'wdth': (0.5, 1.0), 'wght': (0.5, 1.0)},
  [{'dollar': 'dollar.rvrn'}, {'cent': 'cent.rvrn'}]),
 ({'wdth': (0.5, 1.0)}, [{'cent': 'cent.rvrn'}]),
 ({'wght': (0.5, 1.0)}, [{'dollar': 'dollar.rvrn'}])]
fontTools.varLib.featureVars.remapFeatures(table, featureRemap)

Go through the scripts list, and remap feature indices.

fontTools.varLib.featureVars.sortFeatureList(table)

Sort the feature list by feature tag, and remap the feature indices elsewhere. This is needed after the feature list has been modified.

instancer

Partially instantiate a variable font.

The module exports an instantiateVariableFont function and CLI that allow to create full instances (i.e. static fonts) from variable fonts, as well as “partial” variable fonts that only contain a subset of the original variation space.

For example, if you wish to pin the width axis to a given location while also restricting the weight axis to 400..700 range, you can do:

$ fonttools varLib.instancer ./NotoSans-VF.ttf wdth=85 wght=400:700

See fonttools varLib.instancer –help for more info on the CLI options.

The module’s entry point is the instantiateVariableFont function, which takes a TTFont object and a dict specifying either axis coodinates or (min, max) ranges, and returns a new TTFont representing either a partial VF, or full instance if all the VF axes were given an explicit coordinate.

E.g. here’s how to pin the wght axis at a given location in a wght+wdth variable font, keeping only the deltas associated with the wdth axis:

| >>> from fontTools import ttLib
| >>> from fontTools.varLib import instancer
| >>> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf")
| >>> [a.axisTag for a in varfont["fvar"].axes]  # the varfont's current axes
| ['wght', 'wdth']
| >>> partial = instancer.instantiateVariableFont(varfont, {"wght": 300})
| >>> [a.axisTag for a in partial["fvar"].axes]  # axes left after pinning 'wght'
| ['wdth']

If the input location specifies all the axes, the resulting instance is no longer ‘variable’ (same as using fontools varLib.mutator):

>>> instance = instancer.instantiateVariableFont(
… varfont, {“wght”: 700, “wdth”: 67.5}
… )
>>> “fvar” not in instance
True

If one just want to drop an axis at the default location, without knowing in advance what the default value for that axis is, one can pass a None value:

>>> instance = instancer.instantiateVariableFont(varfont, {“wght”: None})
>>> len(varfont[“fvar”].axes)
1

From the console script, this is equivalent to passing wght=drop as input.

This module is similar to fontTools.varLib.mutator, which it’s intended to supersede. Note that, unlike varLib.mutator, when an axis is not mentioned in the input location, the varLib.instancer will keep the axis and the corresponding deltas, whereas mutator implicitly drops the axis at its default coordinate.

The module supports all the following “levels” of instancing, which can of course be combined:

L1

dropping one or more axes while leaving the default tables unmodified;

>>> font = instancer.instantiateVariableFont(varfont, {“wght”: None})
L2

dropping one or more axes while pinning them at non-default locations;

>>> font = instancer.instantiateVariableFont(varfont, {“wght”: 700})
L3

restricting the range of variation of one or more axes, by setting either a new minimum or maximum, potentially – though not necessarily – dropping entire regions of variations that fall completely outside this new range.

>>> font = instancer.instantiateVariableFont(varfont, {“wght”: (100, 300)})
L4

moving the default location of an axis, by specifying (min,defalt,max) values:

>>> font = instancer.instantiateVariableFont(varfont, {“wght”: (100, 300, 700)})

Currently only TrueType-flavored variable fonts (i.e. containing ‘glyf’ table) are supported, but support for CFF2 variable fonts will be added soon.

The discussion and implementation of these features are tracked at https://github.com/fonttools/fonttools/issues/1537

class fontTools.varLib.instancer.AxisLimits(*args, **kwargs)

Maps axis tags (str) to AxisTriple values.

defaultLocation() Dict[str, float]

Return a dict of default axis values.

get(k[, d]) D[k] if k in D, else d.  d defaults to None.
items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
limitAxesAndPopulateDefaults(varfont) AxisLimits

Return a new AxisLimits with defaults filled in from fvar table.

If all axis limits already have defaults, return self.

normalize(varfont, usingAvar=True) NormalizedAxisLimits

Return a new NormalizedAxisLimits with normalized -1..0..+1 values.

If usingAvar is True, the avar table is used to warp the default normalization.

pinnedLocation() Dict[str, float]

Return a location dict with only the pinned axes.

values() an object providing a view on D's values
fontTools.varLib.instancer.AxisRange(minimum, maximum)
class fontTools.varLib.instancer.AxisTriple(minimum: float | None, default: float | None, maximum: float | None)

A triple of (min, default, max) axis values.

Any of the values can be None, in which case the limitRangeAndPopulateDefaults() method can be used to fill in the missing values based on the fvar axis values.

count(value) integer -- return number of occurrences of value
default: float | None
classmethod expand(v: AxisTriple | float | Tuple[float, float] | Tuple[float, float, float]) AxisTriple

Convert a single value or a tuple into an AxisTriple.

If the input is a single value, it is interpreted as a pin at that value. If the input is a tuple, it is interpreted as (min, max) or (min, default, max).

index(value[, start[, stop]]) integer -- return first index of value.

Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

limitRangeAndPopulateDefaults(fvarTriple) AxisTriple

Return a new AxisTriple with the default value filled in.

Set default to fvar axis default if the latter is within the min/max range, otherwise set default to the min or max value, whichever is closer to the fvar axis default. If the default value is already set, return self.

maximum: float | None
minimum: float | None
class fontTools.varLib.instancer.NormalizedAxisLimits(*args, **kwargs)

Maps axis tags (str) to NormalizedAxisTriple values.

defaultLocation() Dict[str, float]

Return a dict of default axis values.

get(k[, d]) D[k] if k in D, else d.  d defaults to None.
items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
pinnedLocation() Dict[str, float]

Return a location dict with only the pinned axes.

values() an object providing a view on D's values
fontTools.varLib.instancer.NormalizedAxisRange(minimum, maximum)
class fontTools.varLib.instancer.NormalizedAxisTriple(minimum: float, default: float, maximum: float)

A triple of (min, default, max) normalized axis values.

count(value) integer -- return number of occurrences of value
default: float
classmethod expand(v: AxisTriple | float | Tuple[float, float] | Tuple[float, float, float]) AxisTriple

Convert a single value or a tuple into an AxisTriple.

If the input is a single value, it is interpreted as a pin at that value. If the input is a tuple, it is interpreted as (min, max) or (min, default, max).

index(value[, start[, stop]]) integer -- return first index of value.

Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

limitRangeAndPopulateDefaults(fvarTriple) AxisTriple

Return a new AxisTriple with the default value filled in.

Set default to fvar axis default if the latter is within the min/max range, otherwise set default to the min or max value, whichever is closer to the fvar axis default. If the default value is already set, return self.

maximum: float
minimum: float
class fontTools.varLib.instancer.NormalizedAxisTripleAndDistances(minimum: float, default: float, maximum: float, distanceNegative: float | None = 1, distancePositive: float | None = 1)

A triple of (min, default, max) normalized axis values, with distances between min and default, and default and max, in the pre-normalized space.

count(value) integer -- return number of occurrences of value
default: float
distanceNegative: float | None = 1
distancePositive: float | None = 1
classmethod expand(v: AxisTriple | float | Tuple[float, float] | Tuple[float, float, float]) AxisTriple

Convert a single value or a tuple into an AxisTriple.

If the input is a single value, it is interpreted as a pin at that value. If the input is a tuple, it is interpreted as (min, max) or (min, default, max).

index(value[, start[, stop]]) integer -- return first index of value.

Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

limitRangeAndPopulateDefaults(fvarTriple) AxisTriple

Return a new AxisTriple with the default value filled in.

Set default to fvar axis default if the latter is within the min/max range, otherwise set default to the min or max value, whichever is closer to the fvar axis default. If the default value is already set, return self.

maximum: float
minimum: float
renormalizeValue(v, extrapolate=True)

Renormalizes a normalized value v to the range of this axis, considering the pre-normalized distances as well as the new axis limits.

reverse_negate()
class fontTools.varLib.instancer.OverlapMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
KEEP_AND_DONT_SET_FLAGS = 0
KEEP_AND_SET_FLAGS = 1
REMOVE = 2
REMOVE_AND_IGNORE_ERRORS = 3
as_integer_ratio()

Return integer ratio.

Return a pair of integers, whose ratio is exactly equal to the original int and with a positive denominator.

>>> (10).as_integer_ratio()
(10, 1)
>>> (-10).as_integer_ratio()
(-10, 1)
>>> (0).as_integer_ratio()
(0, 1)
bit_count()

Number of ones in the binary representation of the absolute value of self.

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3
bit_length()

Number of bits necessary to represent self in binary.

>>> bin(37)
'0b100101'
>>> (37).bit_length()
6
conjugate()

Returns self, the complex conjugate of any int.

denominator

the denominator of a rational number in lowest terms

from_bytes(byteorder='big', *, signed=False)

Return the integer represented by the given array of bytes.

bytes

Holds the array of bytes to convert. The argument must either support the buffer protocol or be an iterable object producing bytes. Bytes and bytearray are examples of built-in objects that support the buffer protocol.

byteorder

The byte order used to represent the integer. If byteorder is ‘big’, the most significant byte is at the beginning of the byte array. If byteorder is ‘little’, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder’ as the byte order value. Default is to use ‘big’.

signed

Indicates whether two’s complement is used to represent the integer.

imag

the imaginary part of a complex number

numerator

the numerator of a rational number in lowest terms

real

the real part of a complex number

to_bytes(length=1, byteorder='big', *, signed=False)

Return an array of bytes representing an integer.

length

Length of bytes object to use. An OverflowError is raised if the integer is not representable with the given number of bytes. Default is length 1.

byteorder

The byte order used to represent the integer. If byteorder is ‘big’, the most significant byte is at the beginning of the byte array. If byteorder is ‘little’, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder’ as the byte order value. Default is to use ‘big’.

signed

Determines whether two’s complement is used to represent the integer. If signed is False and a negative integer is given, an OverflowError is raised.

fontTools.varLib.instancer.axisValuesFromAxisLimits(stat, axisLimits)
fontTools.varLib.instancer.changeTupleVariationAxisLimit(var, axisTag, axisLimit)
fontTools.varLib.instancer.changeTupleVariationsAxisLimits(variations, axisLimits)
fontTools.varLib.instancer.instantiateAvar(varfont, axisLimits)
fontTools.varLib.instancer.instantiateCvar(varfont, axisLimits)
fontTools.varLib.instancer.instantiateFvar(varfont, axisLimits)
fontTools.varLib.instancer.instantiateGvar(varfont, axisLimits, optimize=True)
fontTools.varLib.instancer.instantiateGvarGlyph(varfont, glyphname, axisLimits, optimize=True)

Remove? https://github.com/fonttools/fonttools/pull/2266

fontTools.varLib.instancer.instantiateHVAR(varfont, axisLimits)
fontTools.varLib.instancer.instantiateItemVariationStore(itemVarStore, fvarAxes, axisLimits)

Compute deltas at partial location, and update varStore in-place.

Remove regions in which all axes were instanced, or fall outside the new axis limits. Scale the deltas of the remaining regions where only some of the axes were instanced.

The number of VarData subtables, and the number of items within each, are not modified, in order to keep the existing VariationIndex valid. One may call VarStore.optimize() method after this to further optimize those.

Parameters:
  • varStore – An otTables.VarStore object (Item Variation Store)

  • fvarAxes – list of fvar’s Axis objects

  • axisLimits – NormalizedAxisLimits: mapping axis tags to normalized min/default/max axis coordinates. May not specify coordinates/ranges for all the fvar axes.

Returns:

to be added to the default instance, of type dict of floats

keyed by VariationIndex compound values: i.e. (outer << 16) + inner.

Return type:

defaultDeltas

fontTools.varLib.instancer.instantiateMVAR(varfont, axisLimits)
fontTools.varLib.instancer.instantiateOTL(varfont, axisLimits)
fontTools.varLib.instancer.instantiateSTAT(varfont, axisLimits)
fontTools.varLib.instancer.instantiateTupleVariationStore(variations, axisLimits, origCoords=None, endPts=None)

Instantiate TupleVariation list at the given location, or limit axes’ min/max.

The ‘variations’ list of TupleVariation objects is modified in-place. The ‘axisLimits’ (dict) maps axis tags (str) to NormalizedAxisTriple namedtuples specifying (minimum, default, maximum) in the -1,0,+1 normalized space. Pinned axes have minimum == default == maximum.

A ‘full’ instance (i.e. static font) is produced when all the axes are pinned to single coordinates; a ‘partial’ instance (i.e. a less variable font) is produced when some of the axes are omitted, or restricted with a new range.

Tuples that do not participate are kept as they are. Those that have 0 influence at the given location are removed from the variation store. Those that are fully instantiated (i.e. all their axes are being pinned) are also removed from the variation store, their scaled deltas accummulated and returned, so that they can be added by the caller to the default instance’s coordinates. Tuples that are only partially instantiated (i.e. not all the axes that they participate in are being pinned) are kept in the store, and their deltas multiplied by the scalar support of the axes to be pinned at the desired location.

Parameters:
  • variations – List[TupleVariation] from either ‘gvar’ or ‘cvar’.

  • axisLimits – NormalizedAxisLimits: map from axis tags to (min, default, max) normalized coordinates for the full or partial instance.

  • origCoords – GlyphCoordinates: default instance’s coordinates for computing ‘gvar’ inferred points (cf. table__g_l_y_f._getCoordinatesAndControls).

  • endPts – List[int]: indices of contour end points, for inferring ‘gvar’ deltas.

Returns:

the overall delta adjustment after applicable deltas were summed.

Return type:

List[float]

fontTools.varLib.instancer.instantiateVVAR(varfont, axisLimits)
fontTools.varLib.instancer.instantiateVariableFont(varfont, axisLimits, inplace=False, optimize=True, overlap=OverlapMode.KEEP_AND_SET_FLAGS, updateFontNames=False)

Instantiate variable font, either fully or partially.

Depending on whether the axisLimits dictionary references all or some of the input varfont’s axes, the output font will either be a full instance (static font) or a variable font with possibly less variation data.

Parameters:
  • varfont – a TTFont instance, which must contain at least an ‘fvar’ table. Note that variable fonts with ‘CFF2’ table are not supported yet.

  • axisLimits – a dict keyed by axis tags (str) containing the coordinates (float) along one or more axes where the desired instance will be located. If the value is None, the default coordinate as per ‘fvar’ table for that axis is used. The limit values can also be (min, max) tuples for restricting an axis’s variation range. The default axis value must be included in the new range.

  • inplace (bool) – whether to modify input TTFont object in-place instead of returning a distinct object.

  • optimize (bool) – if False, do not perform IUP-delta optimization on the remaining ‘gvar’ table’s deltas. Possibly faster, and might work around rendering issues in some buggy environments, at the cost of a slightly larger file size.

  • overlap (OverlapMode) – variable fonts usually contain overlapping contours, and some font rendering engines on Apple platforms require that the OVERLAP_SIMPLE and OVERLAP_COMPOUND flags in the ‘glyf’ table be set to force rendering using a non-zero fill rule. Thus we always set these flags on all glyphs to maximise cross-compatibility of the generated instance. You can disable this by passing OverlapMode.KEEP_AND_DONT_SET_FLAGS. If you want to remove the overlaps altogether and merge overlapping contours and components, you can pass OverlapMode.REMOVE (or REMOVE_AND_IGNORE_ERRORS to not hard-fail on tricky glyphs). Note that this requires the skia-pathops package (available to pip install). The overlap parameter only has effect when generating full static instances.

  • updateFontNames (bool) – if True, update the instantiated font’s name table using the Axis Value Tables from the STAT table. The name table and the style bits in the head and OS/2 table will be updated so they conform to the R/I/B/BI model. If the STAT table is missing or an Axis Value table is missing for a given axis coordinate, a ValueError will be raised.

fontTools.varLib.instancer.isInstanceWithinAxisRanges(location, axisRanges)
fontTools.varLib.instancer.main(args=None)

Partially instantiate a variable font

fontTools.varLib.instancer.normalize(value, triple, avarMapping)
fontTools.varLib.instancer.parseArgs(args)

Parse argv.

Returns:

3-tuple (infile, axisLimits, options) axisLimits is either a Dict[str, Optional[float]], for pinning variation axes to specific coordinates along those axes (with None as a placeholder for an axis’ default value); or a Dict[str, Tuple(float, float)], meaning limit this axis to min/max range. Axes locations are in user-space coordinates, as defined in the “fvar” table.

fontTools.varLib.instancer.parseLimits(limits: Iterable[str]) Dict[str, AxisTriple | None]
fontTools.varLib.instancer.sanityCheckVariableTables(varfont)
fontTools.varLib.instancer.setCvarDeltas(cvt, deltas)
fontTools.varLib.instancer.setMacOverlapFlags(glyfTable)
fontTools.varLib.instancer.setMvarDeltas(varfont, deltas)
fontTools.varLib.instancer.setRibbiBits(font)

Set the head.macStyle and OS/2.fsSelection style bits appropriately.

fontTools.varLib.instancer.verticalMetricsKeptInSync(varfont)

Ensure hhea vertical metrics stay in sync with OS/2 ones after instancing.

When applying MVAR deltas to the OS/2 table, if the ascender, descender and line gap change but they were the same as the respective hhea metrics in the original font, this context manager ensures that hhea metrcs also get updated accordingly. The MVAR spec only has tags for the OS/2 metrics, but it is common in fonts to have the hhea metrics be equal to those for compat reasons.

https://learn.microsoft.com/en-us/typography/opentype/spec/mvar https://googlefonts.github.io/gf-guide/metrics.html#7-hhea-and-typo-metrics-should-be-equal https://github.com/fonttools/fonttools/issues/3297

interpolatable

Tool to find wrong contour order between different masters, and other interpolatability (or lack thereof) issues.

Call as: $ fonttools varLib.interpolatable font1 font2 …

class fontTools.varLib.interpolatable.Glyph(glyphname, glyphset)
ITEMS = ('recordings', 'greenStats', 'controlStats', 'greenVectors', 'controlVectors', 'nodeTypes', 'isomorphisms', 'points', 'openContours')
draw(pen, countor_idx=None)
fontTools.varLib.interpolatable.ensure_parent_dir(path)
fontTools.varLib.interpolatable.main(args=None)

Test for interpolatability issues between fonts

fontTools.varLib.interpolatable.recursivelyAddGlyph(glyphname, glyphset, ttGlyphSet, glyf)
fontTools.varLib.interpolatable.test(glyphsets, glyphs=None, names=None, ignore_missing=False, *, locations=None, tolerance=0.95, kinkiness=0.5, upem=1000, show_all=False)
fontTools.varLib.interpolatable.test_gen(glyphsets, glyphs=None, names=None, ignore_missing=False, *, locations=None, tolerance=0.95, kinkiness=0.5, upem=1000, show_all=False)

interpolate_layout

Interpolate OpenType Layout tables (GDEF / GPOS / GSUB).

fontTools.varLib.interpolate_layout.interpolate_layout(designspace, loc, master_finder=<function <lambda>>, mapped=False)

Interpolate GPOS from a designspace file and location.

If master_finder is set, it should be a callable that takes master filename as found in designspace file and map it to master font binary as to be opened (eg. .ttf or .otf).

If mapped is False (default), then location is mapped using the map element of the axes in designspace file. If mapped is True, it is assumed that location is in designspace’s internal space and no mapping is performed.

fontTools.varLib.interpolate_layout.main(args=None)

Interpolate GDEF/GPOS/GSUB tables for a point on a designspace

iup

fontTools.varLib.iup.iup_contour(deltas: _DeltaOrNoneSegment, coords: _PointSegment) _DeltaSegment

For the contour given in coords, interpolate any missing delta values in delta vector deltas.

Returns fully filled-out delta vector.

fontTools.varLib.iup.iup_contour_optimize(deltas: _DeltaSegment, coords: _PointSegment, tolerance: Real = 0.0) _DeltaOrNoneSegment

For contour with coordinates coords, optimize a set of delta values deltas within error tolerance.

Returns delta vector that has most number of None items instead of the input delta.

fontTools.varLib.iup.iup_delta(deltas: _DeltaOrNoneSegment, coords: _PointSegment, ends: _Endpoints) _DeltaSegment

For the outline given in coords, with contour endpoints given in sorted increasing order in ends, interpolate any missing delta values in delta vector deltas.

Returns fully filled-out delta vector.

fontTools.varLib.iup.iup_delta_optimize(deltas: _DeltaSegment, coords: _PointSegment, ends: _Endpoints, tolerance: Real = 0.0) _DeltaOrNoneSegment

For the outline given in coords, with contour endpoints given in sorted increasing order in ends, optimize a set of delta values deltas within error tolerance.

Returns delta vector that has most number of None items instead of the input delta.

merger

Merge OpenType Layout tables (GDEF / GPOS / GSUB).

class fontTools.varLib.merger.AligningMerger(font=None)
mergeLists(out, lst)
mergeObjects(out, lst, exclude=())
mergeTables(font, master_ttfs, tableTags)
mergeThings(out, lst)
classmethod merger(clazzes, attrs=(None,))
mergers = {<class 'fontTools.ttLib.tables.otBase.ValueRecord'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.Anchor'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.CursivePos'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.EntryExitRecord'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.GDEF'>: {'GlyphClassDef': <function merge>}, <class 'fontTools.ttLib.tables.otTables.Lookup'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.MarkBasePos'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.MarkMarkPos'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.PairPos'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.PairSet'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.SinglePos'>: {None: <function merge>}}
classmethod mergersFor(thing, _default={})
class fontTools.varLib.merger.COLRVariationMerger(model, axisTags, font, allowLayerReuse=True)

A specialized VariationMerger that takes multiple master fonts containing COLRv1 tables, and builds a variable COLR font.

COLR tables are special in that variable subtables can be associated with multiple delta-set indices (via VarIndexBase). They also contain tables that must change their type (not simply the Format) as they become variable (e.g. Affine2x3 -> VarAffine2x3) so this merger takes care of that too.

checkFormatEnum(out, lst, validate=<function COLRVariationMerger.<lambda>>)
classmethod convertSubTablesToVarType(table)
static expandPaintColrLayers(colr)

Rebuild LayerList without PaintColrLayers reuse.

Each base paint graph is fully DFS-traversed (with exception of PaintColrGlyph which are irrelevant for this); any layers referenced via PaintColrLayers are collected into a new LayerList and duplicated when reuse is detected, to ensure that all paints are distinct objects at the end of the process. PaintColrLayers’s FirstLayerIndex/NumLayers are updated so that no overlap is left. Also, any consecutively nested PaintColrLayers are flattened. The COLR table’s LayerList is replaced with the new unique layers. A side effect is also that any layer from the old LayerList which is not referenced by any PaintColrLayers is dropped.

mergeAttrs(out, lst, attrs)
mergeLists(out, lst)
mergeObjects(out, lst, exclude=())
mergeSparseDict(out, lst)
mergeTables(font, master_ttfs, tableTags=('COLR',))
mergeThings(out, lst)
mergeVariableAttrs(out, lst, attrs) int
classmethod merger(clazzes, attrs=(None,))
mergers = {<class 'fontTools.ttLib.tables.otTables.Affine2x3'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.BaseGlyphList'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.ClipBox'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.ClipList'>: {'clips': <function merge>}, <class 'fontTools.ttLib.tables.otTables.ColorLine'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.ColorStop'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.LayerList'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.Paint'>: {None: <function merge>}}
classmethod mergersFor(thing, _default={})
setModel(model)
storeMastersForAttr(out, lst, attr)
storeVariationIndices(varIdxes) int
class fontTools.varLib.merger.InstancerMerger(font, model, location)

A merger that takes multiple master fonts, and instantiates an instance.

mergeLists(out, lst)
mergeObjects(out, lst, exclude=())
mergeTables(font, master_ttfs, tableTags)
mergeThings(out, lst)
classmethod merger(clazzes, attrs=(None,))
mergers = {<class 'fontTools.ttLib.tables.otBase.ValueRecord'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.Anchor'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.CaretValue'>: {None: <function merge>}}
classmethod mergersFor(thing, _default={})
class fontTools.varLib.merger.Merger(font=None)
mergeLists(out, lst)
mergeObjects(out, lst, exclude=())
mergeTables(font, master_ttfs, tableTags)
mergeThings(out, lst)
classmethod merger(clazzes, attrs=(None,))
classmethod mergersFor(thing, _default={})
class fontTools.varLib.merger.MutatorMerger(font, instancer, deleteVariations=True)

A merger that takes a variable font, and instantiates an instance. While there’s no “merging” to be done per se, the operation can benefit from many operations that the aligning merger does.

mergeLists(out, lst)
mergeObjects(out, lst, exclude=())
mergeTables(font, master_ttfs, tableTags)
mergeThings(out, lst)
classmethod merger(clazzes, attrs=(None,))
mergers = {<class 'fontTools.ttLib.tables.otBase.ValueRecord'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.Anchor'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.CaretValue'>: {None: <function merge>}}
classmethod mergersFor(thing, _default={})
class fontTools.varLib.merger.VariationMerger(model, axisTags, font)

A merger that takes multiple master fonts, and builds a variable font.

mergeLists(out, lst)
mergeObjects(out, lst, exclude=())
mergeTables(font, master_ttfs, tableTags)
mergeThings(out, lst)
classmethod merger(clazzes, attrs=(None,))
mergers = {<class 'fontTools.ttLib.tables.otBase.ValueRecord'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.Anchor'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.BaseCoord'>: {None: <function merge>}, <class 'fontTools.ttLib.tables.otTables.CaretValue'>: {None: <function merge>}}
classmethod mergersFor(thing, _default={})
setModel(model)
fontTools.varLib.merger.buildVarDevTable(store_builder, master_values)

models

Variation fonts interpolation models.

class fontTools.varLib.models.VariationModel(locations, axisOrder=None, extrapolate=False)

Locations must have the base master at the origin (ie. 0).

If the extrapolate argument is set to True, then values are extrapolated outside the axis range.

>>> from pprint import pprint
>>> locations = [       {'wght':100},       {'wght':-100},       {'wght':-180},       {'wdth':+.3},       {'wght':+120,'wdth':.3},       {'wght':+120,'wdth':.2},       {},       {'wght':+180,'wdth':.3},       {'wght':+180},       ]
>>> model = VariationModel(locations, axisOrder=['wght'])
>>> pprint(model.locations)
[{},
 {'wght': -100},
 {'wght': -180},
 {'wght': 100},
 {'wght': 180},
 {'wdth': 0.3},
 {'wdth': 0.3, 'wght': 180},
 {'wdth': 0.3, 'wght': 120},
 {'wdth': 0.2, 'wght': 120}]
>>> pprint(model.deltaWeights)
[{},
 {0: 1.0},
 {0: 1.0},
 {0: 1.0},
 {0: 1.0},
 {0: 1.0},
 {0: 1.0, 4: 1.0, 5: 1.0},
 {0: 1.0, 3: 0.75, 4: 0.25, 5: 1.0, 6: 0.6666666666666666},
 {0: 1.0,
  3: 0.75,
  4: 0.25,
  5: 0.6666666666666667,
  6: 0.4444444444444445,
  7: 0.6666666666666667}]
static computeAxisRanges(locations)
getDeltas(masterValues, *, round=<function noRound>)
getDeltasAndSupports(items, *, round=<function noRound>)
static getMasterLocationsSortKeyFunc(locations, axisOrder=[])
getMasterScalars(targetLocation)

Return multipliers for each master, for the given location. If interpolating many master-values at the same location, this function allows speed up by fetching the scalars once and using them with interpolateFromValuesAndScalars().

Note that the scalars used in interpolateFromMastersAndScalars(), are not the same as the ones returned here. They are the result of getScalars().

getScalars(loc)

Return scalars for each delta, for the given location. If interpolating many master-values at the same location, this function allows speed up by fetching the scalars once and using them with interpolateFromMastersAndScalars().

getSubModel(items)

Return a sub-model and the items that are not None.

The sub-model is necessary for working with the subset of items when some are None.

The sub-model is cached.

interpolateFromDeltas(loc, deltas)

Interpolate from deltas, at location loc.

static interpolateFromDeltasAndScalars(deltas, scalars)

Interpolate from deltas and scalars fetched from getScalars().

interpolateFromMasters(loc, masterValues, *, round=<function noRound>)

Interpolate from master-values, at location loc.

interpolateFromMastersAndScalars(masterValues, scalars, *, round=<function noRound>)

Interpolate from master-values, and scalars fetched from getScalars(), which is useful when you want to interpolate multiple master-values with the same location.

static interpolateFromValuesAndScalars(values, scalars)

Interpolate from values and scalars coefficients.

If the values are master-values, then the scalars should be fetched from getMasterScalars().

If the values are deltas, then the scalars should be fetched from getScalars(); in which case this is the same as interpolateFromDeltasAndScalars().

reorderMasters(master_list, mapping)
fontTools.varLib.models.normalizeLocation(location, axes, extrapolate=False)

Normalizes location based on axis min/default/max values from axes.

>>> axes = {"wght": (100, 400, 900)}
>>> normalizeLocation({"wght": 400}, axes)
{'wght': 0.0}
>>> normalizeLocation({"wght": 100}, axes)
{'wght': -1.0}
>>> normalizeLocation({"wght": 900}, axes)
{'wght': 1.0}
>>> normalizeLocation({"wght": 650}, axes)
{'wght': 0.5}
>>> normalizeLocation({"wght": 1000}, axes)
{'wght': 1.0}
>>> normalizeLocation({"wght": 0}, axes)
{'wght': -1.0}
>>> axes = {"wght": (0, 0, 1000)}
>>> normalizeLocation({"wght": 0}, axes)
{'wght': 0.0}
>>> normalizeLocation({"wght": -1}, axes)
{'wght': 0.0}
>>> normalizeLocation({"wght": 1000}, axes)
{'wght': 1.0}
>>> normalizeLocation({"wght": 500}, axes)
{'wght': 0.5}
>>> normalizeLocation({"wght": 1001}, axes)
{'wght': 1.0}
>>> axes = {"wght": (0, 1000, 1000)}
>>> normalizeLocation({"wght": 0}, axes)
{'wght': -1.0}
>>> normalizeLocation({"wght": -1}, axes)
{'wght': -1.0}
>>> normalizeLocation({"wght": 500}, axes)
{'wght': -0.5}
>>> normalizeLocation({"wght": 1000}, axes)
{'wght': 0.0}
>>> normalizeLocation({"wght": 1001}, axes)
{'wght': 0.0}
fontTools.varLib.models.normalizeValue(v, triple, extrapolate=False)

Normalizes value based on a min/default/max triple.

>>> normalizeValue(400, (100, 400, 900))
0.0
>>> normalizeValue(100, (100, 400, 900))
-1.0
>>> normalizeValue(650, (100, 400, 900))
0.5
fontTools.varLib.models.piecewiseLinearMap(v, mapping)
fontTools.varLib.models.supportScalar(location, support, ot=True, extrapolate=False, axisRanges=None)

Returns the scalar multiplier at location, for a master with support. If ot is True, then a peak value of zero for support of an axis means “axis does not participate”. That is how OpenType Variation Font technology works.

If extrapolate is True, axisRanges must be a dict that maps axis names to (axisMin, axisMax) tuples.

>>> supportScalar({}, {})
1.0
>>> supportScalar({'wght':.2}, {})
1.0
>>> supportScalar({'wght':.2}, {'wght':(0,2,3)})
0.1
>>> supportScalar({'wght':2.5}, {'wght':(0,2,4)})
0.75
>>> supportScalar({'wght':2.5, 'wdth':0}, {'wght':(0,2,4), 'wdth':(-1,0,+1)})
0.75
>>> supportScalar({'wght':2.5, 'wdth':.5}, {'wght':(0,2,4), 'wdth':(-1,0,+1)}, ot=False)
0.375
>>> supportScalar({'wght':2.5, 'wdth':0}, {'wght':(0,2,4), 'wdth':(-1,0,+1)})
0.75
>>> supportScalar({'wght':2.5, 'wdth':.5}, {'wght':(0,2,4), 'wdth':(-1,0,+1)})
0.75
>>> supportScalar({'wght':3}, {'wght':(0,1,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
-1.0
>>> supportScalar({'wght':-1}, {'wght':(0,1,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
-1.0
>>> supportScalar({'wght':3}, {'wght':(0,2,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
1.5
>>> supportScalar({'wght':-1}, {'wght':(0,2,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
-0.5

mutator

Instantiate a variation font. Run, eg:

$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85

fontTools.varLib.mutator.instantiateVariableFont(varfont, location, inplace=False, overlap=True)

Generate a static instance from a variable TTFont and a dictionary defining the desired location along the variable font’s axes. The location values must be specified as user-space coordinates, e.g.:

{‘wght’: 400, ‘wdth’: 100}

By default, a new TTFont object is returned. If inplace is True, the input varfont is modified and reduced to a static font.

When the overlap parameter is defined as True, OVERLAP_SIMPLE and OVERLAP_COMPOUND bits are set to 1. See https://docs.microsoft.com/en-us/typography/opentype/spec/glyf

fontTools.varLib.mutator.interpolate_cff2_PrivateDict(topDict, interpolateFromDeltas)
fontTools.varLib.mutator.interpolate_cff2_charstrings(topDict, interpolateFromDeltas, glyphOrder)
fontTools.varLib.mutator.interpolate_cff2_metrics(varfont, topDict, glyphOrder, loc)

Unlike TrueType glyphs, neither advance width nor bounding box info is stored in a CFF2 charstring. The width data exists only in the hmtx and HVAR tables. Since LSB data cannot be interpolated reliably from the master LSB values in the hmtx table, we traverse the charstring to determine the actual bound box.

fontTools.varLib.mutator.main(args=None)

Instantiate a variation font

mvar

fontTools.varLib.mvar.MVAR_ENTRIES

plot

varStore

fontTools.varLib.varStore.Object_collect_device_varidxes(self, varidxes)
fontTools.varLib.varStore.Object_remap_device_varidxes(self, varidxes_map)
class fontTools.varLib.varStore.OnlineVarStoreBuilder(axisTags)
finish(optimize=True)
setModel(model)
setSupports(supports)
storeDeltas(deltas, *, round=<built-in function round>)
storeMasters(master_values, *, round=<built-in function round>)
fontTools.varLib.varStore.VarData_addItem(self, deltas, *, round=<built-in function round>)
fontTools.varLib.varStore.VarRegion_get_support(self, fvar_axes)
class fontTools.varLib.varStore.VarStoreInstancer(varstore, fvar_axes, location={})
interpolateFromDeltas(varDataIndex, deltas)
static interpolateFromDeltasAndScalars(deltas, scalars)
setLocation(location)
fontTools.varLib.varStore.VarStore___bool__(self)
fontTools.varLib.varStore.VarStore_optimize(self, use_NO_VARIATION_INDEX=True, quantization=1)

Optimize storage. Returns mapping from old VarIdxes to new ones.

fontTools.varLib.varStore.VarStore_prune_regions(self)

Remove unused VarRegions.

fontTools.varLib.varStore.VarStore_subset_varidxes(self, varIdxes, optimize=True, retainFirstMap=False, advIdxes={})
fontTools.varLib.varStore.bit_count(self, /)

Number of ones in the binary representation of the absolute value of self.

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3
fontTools.varLib.varStore.main(args=None)

Optimize a font’s GDEF variation store

The fontTools.varLib package contains a number of classes and routines for handling, building and interpolating variable font data. These routines rely on a common set of concepts, many of which are equivalent to concepts in the OpenType Specification, but some of which are unique to varLib.

Terminology

axis

“A designer-determined variable in a font face design that can be used to derive multiple, variant designs within a family.” (OpenType Specification) An axis has a minimum value, a maximum value and a default value.

designspace

The n-dimensional space formed by the font’s axes. (OpenType Specification calls this the “design-variation space”)

scalar

A value which is able to be varied at different points in the designspace: for example, the horizontal advance width of the glyph “a” is a scalar. However, see also support scalar below.

default location

A point in the designspace whose coordinates are the default value of all axes.

location

A point in the designspace, specified as a set of coordinates on one or more axes. In the context of varLib, a location is a dictionary with the keys being the axis tags and the values being the coordinates on the respective axis. A varLib location dictionary may be “sparse”, in the sense that axes defined in the font may be omitted from the location’s coordinates, in which case the default value of the axis is assumed. For example, given a font having a wght axis ranging from 200-1000 with default 400, and a wdth axis ranging 100-300 with default 150, the location {"wdth": 200} represents the point wght=400,wdth=200.

master

The value of a scalar at a given location. Note that this is a considerably more general concept than the usual type design sense of the term “master”.

normalized location

While the range of an axis is determined by its minimum and maximum values as set by the designer, locations are specified internally to the font binary in the range -1 to 1, with 0 being the default, -1 being the minimum and 1 being the maximum. A normalized location is one which is scaled to the range (-1,1) on all of its axes. Note that as the range from minimum to default and from default to maximum on a given axis may differ (for example, given wght min=200 default=500 max=1000, the difference between a normalized location -1 of a normalized location of 0 represents a difference of 300 units while the difference between a normalized location of 0 and a normalized location of 1 represents a difference of 700 units), a location is scaled by a different factor depending on whether it is above or below the axis’ default value.

support

While designers tend to think in terms of masters - that is, a precise location having a particular value - OpenType Variations specifies the variation of scalars in terms of deltas which are themselves composed of the combined contributions of a set of triangular regions, each having a contribution value of 0 at its minimum value, rising linearly to its full contribution at the peak and falling linearly to zero from the peak to the maximum value. The OpenType Specification calls these “regions”, while varLib calls them “supports” (a mathematical term used in real analysis) and expresses them as a dictionary mapping each axis tag to a tuple (min, peak, max).

box

varLib uses the term “box” to denote the minimum and maximum “corners” of a support, ignoring its peak value.

delta

The term “delta” is used in OpenType Variations in two senses. In the more general sense, a delta is the difference between a scalar at a given location and its value at the default location. Additionally, inside the font, variation data is stored as a mapping between supports and deltas. The delta (in the first sense) is computed by summing the product of the delta of each support by a factor representing the support’s contribution at this location (see “support scalar” below).

support scalar

When interpolating a set of variation data, the support scalar represents the scalar multiplier of the support’s contribution at this location. For example, the support scalar will be 1 at the support’s peak location, and 0 below its minimum or above its maximum.

Module for dealing with ‘gvar’-style font variations, also known as run-time interpolation.

The ideas here are very similar to MutatorMath. There is even code to read MutatorMath .designspace files in the varLib.designspace module.

For now, if you run this file on a designspace file, it tries to find ttf-interpolatable files for the masters and build a variable-font from them. Such ttf-interpolatable and designspace files can be generated from a Glyphs source, eg., using noto-source as an example:

$ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs

Then you can make a variable-font this way:

$ fonttools varLib master_ufo/NotoSansArabic.designspace

API will change in near future.

class fontTools.varLib.MasterFinder(template)
fontTools.varLib.addGSUBFeatureVariations(vf, designspace, featureTags=(), *, log_enabled=False)

Add GSUB FeatureVariations table to variable font, based on DesignSpace rules.

Parameters:
  • vf – A TTFont object representing the variable font.

  • designspace – A DesignSpaceDocument object.

  • featureTags – Optional feature tag(s) to use for the FeatureVariations records. If unset, the key ‘com.github.fonttools.varLib.featureVarsFeatureTag’ is looked up in the DS <lib> and used; otherwise the default is ‘rclt’ if the <rules processing=”last”> attribute is set, else ‘rvrn’. See <https://fonttools.readthedocs.io/en/latest/designspaceLib/xml.html#rules-element>

  • log_enabled – If True, log info about DS axes and sources. Default is False, as the same info may have already been logged as part of varLib.build.

fontTools.varLib.build(designspace, master_finder=<function <lambda>>, exclude=[], optimize=True, colr_layer_reuse=True, drop_implied_oncurves=False)

Build variation font from a designspace file.

If master_finder is set, it should be a callable that takes master filename as found in designspace file and map it to master font binary as to be opened (eg. .ttf or .otf).

fontTools.varLib.build_many(designspace: ~fontTools.designspaceLib.DesignSpaceDocument, master_finder=<function <lambda>>, exclude=[], optimize=True, skip_vf=<function <lambda>>, colr_layer_reuse=True, drop_implied_oncurves=False)

Build variable fonts from a designspace file, version 5 which can define several VFs, or version 4 which has implicitly one VF covering the whole doc.

If master_finder is set, it should be a callable that takes master filename as found in designspace file and map it to master font binary as to be opened (eg. .ttf or .otf).

skip_vf can be used to skip building some of the variable fonts defined in the input designspace. It’s a predicate that takes as argument the name of the variable font and returns bool.

Always returns a Dict[str, TTFont] keyed by VariableFontDescriptor.name

fontTools.varLib.drop_implied_oncurve_points(*masters: TTFont) int

Drop impliable on-curve points from all the simple glyphs in masters.

In TrueType glyf outlines, on-curve points can be implied when they are located exactly at the midpoint of the line connecting two consecutive off-curve points.

The input masters’ glyf tables are assumed to contain same-named glyphs that are interpolatable. Oncurve points are only dropped if they can be implied for all the masters. The fonts are modified in-place.

Parameters:

masters – The TTFont(s) to modify

Returns:

The total number of points that were dropped if any.

Reference: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html

fontTools.varLib.load_designspace(designspace, log_enabled=True)
fontTools.varLib.load_masters(designspace, master_finder=<function <lambda>>)

Ensure that all SourceDescriptor.font attributes have an appropriate TTFont object loaded, or else open TTFont objects from the SourceDescriptor.path attributes.

The paths can point to either an OpenType font, a TTX file, or a UFO. In the latter case, use the provided master_finder callable to map from UFO paths to the respective master font binaries (e.g. .ttf, .otf or .ttx).

Return list of master TTFont objects in the same order they are listed in the DesignSpaceDocument.

fontTools.varLib.main(args=None)

Build variable fonts from a designspace file and masters

fontTools.varLib.set_default_weight_width_slant(font, location)

voltLib: Read/write MS VOLT projects

voltToFea: Convert MS VOLT to AFDKO feature files

MS VOLT .vtp to AFDKO .fea OpenType Layout converter.

Usage

To convert a VTP project file:

$ fonttools voltLib.voltToFea input.vtp output.fea

It is also possible convert font files with TSIV table (as saved from Volt), in this case the glyph names used in the Volt project will be mapped to the actual glyph names in the font files when written to the feature file:

$ fonttools voltLib.voltToFea input.ttf output.fea

The --quiet option can be used to suppress warnings.

The --traceback can be used to get Python traceback in case of exceptions, instead of suppressing the traceback.

Limitations
  • Not all VOLT features are supported, the script will error if it it encounters something it does not understand. Please report an issue if this happens.

  • AFDKO feature file syntax for mark positioning is awkward and does not allow setting the mark coverage. It also defines mark anchors globally, as a result some mark positioning lookups might cover many marks than what was in the VOLT file. This should not be an issue in practice, but if it is then the only way is to modify the VOLT file or the generated feature file manually to use unique mark anchors for each lookup.

  • VOLT allows subtable breaks in any lookup type, but AFDKO feature file implementations vary in their support; currently AFDKO’s makeOTF supports subtable breaks in pair positioning lookups only, while FontTools’ feaLib support it for most substitution lookups and only some positioning lookups.

class fontTools.voltLib.voltToFea.Group(group)
class fontTools.voltLib.voltToFea.MarkClassDefinition(markClass, anchor, glyphs, location=None)
asFea(indent='')

Returns this element as a string of feature code. For block-type elements (such as FeatureBlock), the indent string is added to the start of each line in the output.

build(builder)
glyphSet()

The glyphs in this class as a tuple of GlyphName objects.

class fontTools.voltLib.voltToFea.VoltToFea(file_or_path, font=None)
convert(tables=None)
fontTools.voltLib.voltToFea.main(args=None)

Convert MS VOLT to AFDKO feature files.

fontTools.voltLib – a package for dealing with Visual OpenType Layout Tool (VOLT) files.

ast

class fontTools.voltLib.ast.AnchorDefinition(name, gid, glyph_name, component, locked, pos, location=None)
build(builder)
class fontTools.voltLib.ast.ContextDefinition(ex_or_in, left=None, right=None, location=None)
build(builder)
class fontTools.voltLib.ast.Element(location=None)
build(builder)
class fontTools.voltLib.ast.Enum(enum, location=None)

An enum

build(builder)
glyphSet(groups=None)
class fontTools.voltLib.ast.Expression(location=None)
build(builder)
class fontTools.voltLib.ast.FeatureDefinition(name, tag, lookups, location=None)
build(builder)
class fontTools.voltLib.ast.GlyphDefinition(name, gid, gunicode, gtype, components, location=None)
build(builder)
class fontTools.voltLib.ast.GlyphName(glyph, location=None)

A single glyph name, such as cedilla.

build(builder)
glyphSet()
class fontTools.voltLib.ast.GroupDefinition(name, enum, location=None)
build(builder)
glyphSet(groups=None)
class fontTools.voltLib.ast.GroupName(group, parser, location=None)

A glyph group

build(builder)
glyphSet(groups=None)
class fontTools.voltLib.ast.LangSysDefinition(name, tag, features, location=None)
build(builder)
class fontTools.voltLib.ast.LookupDefinition(name, process_base, process_marks, mark_glyph_set, direction, reversal, comments, context, sub, pos, location=None)
build(builder)
class fontTools.voltLib.ast.Pos(adv, dx, dy, adv_adjust_by, dx_adjust_by, dy_adjust_by)
adv: int

Alias for field number 0

adv_adjust_by: dict

Alias for field number 3

count(value, /)

Return number of occurrences of value.

dx: int

Alias for field number 1

dx_adjust_by: dict

Alias for field number 4

dy: int

Alias for field number 2

dy_adjust_by: dict

Alias for field number 5

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

class fontTools.voltLib.ast.PositionAdjustPairDefinition(coverages_1, coverages_2, adjust_pair, location=None)
build(builder)
class fontTools.voltLib.ast.PositionAdjustSingleDefinition(adjust_single, location=None)
build(builder)
class fontTools.voltLib.ast.PositionAttachCursiveDefinition(coverages_exit, coverages_enter, location=None)
build(builder)
class fontTools.voltLib.ast.PositionAttachDefinition(coverage, coverage_to, location=None)
build(builder)
class fontTools.voltLib.ast.Range(start, end, parser, location=None)

A glyph range

build(builder)
glyphSet()
class fontTools.voltLib.ast.ScriptDefinition(name, tag, langs, location=None)
build(builder)
class fontTools.voltLib.ast.SettingDefinition(name, value, location=None)
build(builder)
class fontTools.voltLib.ast.Statement(location=None)
build(builder)
class fontTools.voltLib.ast.SubstitutionDefinition(mapping, location=None)
build(builder)
class fontTools.voltLib.ast.SubstitutionLigatureDefinition(mapping, location=None)
build(builder)
class fontTools.voltLib.ast.SubstitutionMultipleDefinition(mapping, location=None)
build(builder)
class fontTools.voltLib.ast.SubstitutionReverseChainingSingleDefinition(mapping, location=None)
build(builder)
class fontTools.voltLib.ast.SubstitutionSingleDefinition(mapping, location=None)
build(builder)
class fontTools.voltLib.ast.VoltFile
build(builder)

error

exception fontTools.voltLib.error.VoltLibError(message, location)
add_note()

Exception.add_note(note) – add a note to the exception

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

lexer

class fontTools.voltLib.lexer.Lexer(text, filename)
CHAR_DIGIT_ = '0123456789'
CHAR_LC_LETTER_ = 'abcdefghijklmnopqrstuvwxyz'
CHAR_NAME_CONTINUATION_ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._0123456789'
CHAR_NAME_START_ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._'
CHAR_NEWLINE_ = '\r\n'
CHAR_PERIOD_ = '.'
CHAR_UC_LETTER_ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
CHAR_UNDERSCORE_ = '_'
CHAR_WHITESPACE_ = ' \t'
NAME = 'NAME'
NEWLINE = 'NEWLINE'
NUMBER = 'NUMBER'
STRING = 'STRING'
location_()
next()
next_()
scan_over_(valid)
scan_until_(stop_at)

parser

class fontTools.voltLib.parser.OrderedSymbolTable
define(name, item)
enter_scope()
exit_scope()
range(start, end)
resolve(name, case_insensitive=False)
class fontTools.voltLib.parser.Parser(path)
advance_lexer_()
expect_keyword_(keyword)
expect_name_()
expect_number_()
expect_string_()
glyph_range(start, end)
is_cur_keyword_(k)
make_lexer_(file_or_path)
parse()
parse_adjust_by_()
parse_adjust_pair_()
parse_adjust_single_()
parse_attach_()
parse_attach_cursive_()
parse_cmap_format()
parse_context_()
parse_coverage_()
parse_def_anchor_()
parse_def_glyph_()
parse_def_group_()
parse_def_lookup_()
parse_def_script_()
parse_enum_()
parse_feature_()
parse_langsys_()
parse_noarg_option_()
parse_pos_()
parse_position_()
parse_ppem_()
parse_substitution_(reversal)
parse_unicode_values_()
resolve_group(group_name)
class fontTools.voltLib.parser.SymbolTable
define(name, item)
enter_scope()
exit_scope()
resolve(name, case_insensitive=True)