
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; seefontTools.merge
pyftsubset
, a tool for subsetting fonts; seefontTools.subset
ttx
, a tool for converting between OpenType binary fonts (OTF) and an XML representation (TTX); seefontTools.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 valuescu2qu
: Convert a UFO font from cubic to quadratic curvesfeaLib
: Add features from a feature file (.fea) into a OTF fonthelp
: Show this helpmerge
: Merge multiple fonts into onemtiLib
: Convert a FontDame OTL file to TTX XMLsubset
: OpenType font subsetter and optimizerttLib.woff2
: Compress and decompress WOFF2 fontsttx
: Convert OpenType fonts to XML and backvarLib
: Build a variable font from a designspace file and mastersvarLib.instancer
: Partially instantiate a variable font.varLib.interpolatable
: Test for interpolatability issues between fontsvarLib.interpolate_layout
: Interpolate GDEF/GPOS/GSUB tables for a point on a designspacevarLib.models
: Normalize locations on a given designspacevarLib.mutator
: Instantiate a variation fontvarLib.varStore
: Optimize a font’s GDEF variation storevoltLib.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 filesfontTools.agl
: Access to the Adobe Glyph ListfontTools.cffLib
: Read/write tools for Adobe CFF fontsfontTools.colorLib
: Module for handling colors in CPAL/COLR fontsfontTools.config
: Configure fontToolsfontTools.cu2qu
: Module for cubic to quadratic conversionfontTools.designspaceLib
: Read and write designspace filesfontTools.encodings
: Support for font-related character encodingsfontTools.feaLib
: Read and read AFDKO feature filesfontTools.fontBuilder
: Construct TTF/OTF fonts from scratchfontTools.merge
: Tools for merging font filesfontTools.pens
: Various classes for manipulating glyph outlinesfontTools.subset
: OpenType font subsetting and optimizationfontTools.svgLib.path
: Library for drawing SVG paths onto glyphsfontTools.t1Lib
: Tools for PostScript Type 1 fonts (Python2 only)fontTools.tfmLib
: Module for reading TFM filesfontTools.ttLib
: Module for reading/writing OpenType and Truetype fontsfontTools.ttx
: Module for converting between OTF and XML representationfontTools.ufoLib
: Module for reading and writing UFO filesfontTools.unicodedata
: Convert between Unicode and OpenType script informationfontTools.varLib
: Module for dealing with ‘gvar’-style font variationsfontTools.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
isTrue
, 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
’sTopDict
object. To do this, aCFFFontSet
object can either be treated as a dictionary (with appropriatekeys()
andvalues()
methods) mapping font names toTopDict
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-levelfontTools.ttLib.ttFont.TTFont
object containing this CFF file.If
isCFF2
is passed and set toTrue
orFalse
, 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-levelfontTools.ttLib.ttFont.TTFont
object containing this CFF file.If
isCFF2
is passed and set toTrue
orFalse
, 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
andfontTools.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 acallsubr
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 therawDict
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 ofPaint
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’stable_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:
a user-provided value in the options’s
self._values
dicta caller-provided default value to this method call
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. 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()
orfromfile()
.
- 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 keycom.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 ofself
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
todoc.sources
.
- addSourceDescriptor(**kwargs)
Instantiate a new
SourceDescriptor
using the givenkwargs
and add it todoc.sources
.
- addInstance(instanceDescriptor: InstanceDescriptor)
Add the given
instanceDescriptor
toinstances
.
- addInstanceDescriptor(**kwargs)
Instantiate a new
InstanceDescriptor
using the givenkwargs
and add it toinstances
.
- addAxis(axisDescriptor: AxisDescriptor | DiscreteAxisDescriptor)
Add the given
axisDescriptor
toaxes
.
- addAxisDescriptor(**kwargs)
Instantiate a new
AxisDescriptor
using the givenkwargs
and add it toaxes
.The axis will be and instance of
DiscreteAxisDescriptor
if thekwargs
provide avalue
, or aAxisDescriptor
otherwise.
- addAxisMapping(axisMappingDescriptor: AxisMappingDescriptor)
Add the given
axisMappingDescriptor
toaxisMappings
.
- addAxisMappingDescriptor(**kwargs)
Instantiate a new
AxisMappingDescriptor
using the givenkwargs
and add it torules
.
- addRule(ruleDescriptor: RuleDescriptor)
Add the given
ruleDescriptor
torules
.
- addRuleDescriptor(**kwargs)
Instantiate a new
RuleDescriptor
using the givenkwargs
and add it torules
.
- addVariableFont(variableFontDescriptor: VariableFontDescriptor)
Add the given
variableFontDescriptor
tovariableFonts
.New in version 5.0.
- addVariableFontDescriptor(**kwargs)
Instantiate a new
VariableFontDescriptor
using the givenkwargs
and add it tovariableFonts
.New in version 5.0.
- addLocationLabel(locationLabelDescriptor: LocationLabelDescriptor)
Add the given
locationLabelDescriptor
tolocationLabels
.New in version 5.0.
- addLocationLabelDescriptor(**kwargs)
Instantiate a new
LocationLabelDescriptor
using the givenkwargs
and add it tolocationLabels
.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 givenuserLocation
, orNone
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
, orNone
if no such axis exists.
- getAxisByTag(tag: str) AxisDescriptor | DiscreteAxisDescriptor | None
Return the axis with the given
tag
, orNone
if no such axis exists.
- getLocationLabel(name: str) LocationLabelDescriptor | None
Return the top-level location label with the given
name
, orNone
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.
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
.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
andmaximum
, while a discrete axis has a list ofvalues
.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.
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
.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) ornominalValue
(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 thename
.
- 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 thename
.
- 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
andmaximum
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 afontTools.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 byfilename
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 meansforeground
.
- 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
orDiscreteAxisDescriptor
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
See also
- 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’slocationLabel
.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.
See also
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 tofontTools.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 tofontTools.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
elidedfallbackname
: optional, string. STAT Style Attributes Header fieldelidedFallbackNameID
. See: OTSpec STAT Style Attributes HeaderNew in version 5.0.
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
xml:lang
: required, string. XML language definition
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 fieldaxisOrdering
for this axis.
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 itsname
attribute.
New in version 5.0.
Attributes
name
: required, string. the name of this labelelidable
: optional, boolean, default: false. STAT flagELIDABLE_AXIS_VALUE_NAME
.oldersibling
: optional, boolean, default: false. STAT flagOLDER_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 fieldvalue
(format 1, 3) ornominalValue
(format 2).userminimum
: STAT fieldrangeMinValue
(format 2).usermaximum
: STAT fieldrangeMaxValue
(format 2).linkeduservalue
: STAT fieldlinkedValue
(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 itsname
attribute.
See: OTSpec STAT Axis value table, format 4
New in version 5.0.
Attributes
name
: required, string. the name of this labelelidable
: optional, boolean, default: false. STAT flagELIDABLE_AXIS_VALUE_NAME
.oldersibling
: optional, boolean, default: false. STAT flagOLDER_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
, oroutput
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 asfirst
, and put the substitution rule in thervrn
feature.If
processing
islast
, put it inrclt
.The default is
first
. For new projects, you probably wantlast
. See the following issues for more information: fontTools#1371 fontTools#2050If you want to use a different feature(s) altogether, e.g.
calt
, use the lib keycom.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
andmaximum
this condition isTrue
.minimum
andmaximum
are in designspace coordinates.If
minimum
is not available, assume it isaxis.minimum
, mapped to designspace coordinates.If
maximum
is not available, assume it isaxis.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 definedaxis
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. Thename
attribute is the glyph that should be visible when the rule evaluates to False. Thewith
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 thename
. 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:
the whole axis
<axis-subset name="Weight"/>
a sub-range of the full axis
<axis-subset name="Weight" userminimum="400" usermaximum="500" userdefault="400"/>
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.
See also
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

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 withfont.info.familyName
stylename
: required, string. The style name of the instance font. Corresponds withfont.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 withfont.info.postscriptFontName
stylemapfamilyname
: string. Optional for MutatorMath. Corresponds withstyleMapFamilyName
stylemapstylename
: string. Optional for MutatorMath. Corresponds withstyleMapStyleName
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.
See also
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>
elementsThese
<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.
Child element of
<designspace>
,<variable-font>
and<instance>
If present, content must be an XML Property List (plist). <https://en.wikipedia.org/wiki/Property_list>__
Contains arbitrary data about the whole document or about a specific variable font or instance.
Items in the dict need to use reverse domain name notation <https://en.wikipedia.org/wiki/Reverse_domain_name_notation>__
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.
Attributes of the SourceDescriptor
Attributes of the InstanceDescriptor
Attributes of the AxisDescriptor
Read about Subclassing descriptors
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 TagsThe 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 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
andInstanceDescriptor
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:
The
public.fontInfo
key in the<lib>
element of the<variable-font>
or<instance>
elements.XML attributes for names (i.e.
familyname
,stylename
, etc.), if the target is an<instance>
element.The
public.fontInfo
key found in the<lib>
element of the designspace document’s root.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
fora.alt
, a glyph that referencesa
in a component would then show the newa.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
anda.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.
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.The axes can be discrete, to say that they do not interpolate, like a distinctly constructed upright and italic variant of a family.
The data can be used to derive style and PostScript names for instances.
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.
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).
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, passfollowIncludes=False
. Pass a directory string asincludeDir
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 relativeinclude()
paths; ifNone
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
- 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]
.- 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.
- add_range(start, end, glyphs)
Add a range (e.g.
A-Z
) to the class.start
andend
are eitherGlyphName
objects or strings representing the start and end glyphs in the class, andglyphs
is the full list ofGlyphName
objects in the range.
- add_cid_range(start, end, glyphs)
Add a range to the class by glyph ID.
start
andend
are the initial and final IDs, andglyphs
is the full list ofGlyphName
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 aGlyphClassDefinition
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.MarkClassName(markClass, location=None)
A mark class name, such as
@FRENCH_MARKS
defined withmarkClass
. This must be instantiated with aMarkClass
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.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 callend_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
- 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 eitherGlyphClass
orGlyphClassName
objects, orNone
.- 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 sameMarkClass
: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 ofMarkClassDefinition
statements.- addDefinition(definition)
Add a
MarkClassDefinition
statement to this mark class.
- class fontTools.feaLib.ast.MarkClassDefinition(markClass, anchor, glyphs, location=None)
A single
markClass
statement. ThemarkClass
should be aMarkClass
object, theanchor
anAnchor
object, and theglyphs
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;
- 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
andreplacement
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 apos
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
tableAttach
statement.- glyphs
- 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 aHorizAxis.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
, andsuffix
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 aLookupBlock
to apply a single chaining lookup at the given position, a list ofLookupBlock
s to apply multiple lookups, orNone
to apply no lookup. The length of the outer list should equal the length ofglyphs
; 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
, andsuffix
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 aLookupBlock
to apply a single chaining lookup at the given position, a list ofLookupBlock
s to apply multiple lookups, orNone
to apply no lookup. The length of the outer list should equal the length ofglyphs
; 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 orNone
.- 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
orname
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
tableFontRevision
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 ofprefix
,glyphs
andsuffix
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 ofprefix
,glyphs
andsuffix
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
tableLigatureCaretByIndex
statement.glyphs
should be a glyph-containing object, andcarets
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
tableLigatureCaretByPos
statement.glyphs
should be a glyph-containing object, andcarets
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
, andsuffix
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. Thevalue
should be an integer value representing the flags in use, but not including themarkAttachment
class andmarkFilteringSet
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 aLookupBlock
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. Themarks
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. Themarks
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. Themarks
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. Mostvalues
should be numbers or strings, apart from when the key isUnicodeRange
,CodePageRange
orPanose
, 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
andglyphs2
should be glyph-containing objects.valuerecord1
should be aValueRecord
object;valuerecord2
should be either aValueRecord
object orNone
. Ifenumerated
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, callsadd_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 beforeglyphs
.old_prefix
,old_suffix
,glyphs
andreplacements
should be lists of glyph-containing objects.glyphs
andreplacements
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
andsuffix
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 replacementglyphs
.prefix
,suffix
,glyphs
andreplace
should be lists of glyph-containing objects.glyphs
andreplace
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:
names (list) – a list of
STATNameStatement
objectslocations (list) – a list of
AxisValueLocationStatement
objectsflags (int) – an int
- 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 toparenleft#1
andparenright#1
, and a lookup will be inserted into the tolocl
feature (creating it if necessary) under thelatn
script to substituteparenleft
withparenleft#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 thesave
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 thefontTools.misc.fixedTools.otRound()
function by default, unless an optionalround
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. ReturnsFalse
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 thantolerance
.- 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 havingpt
,t1
andt2
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 havingpt
,t1
andt2
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 havingpt
,t1
andt2
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 havingpt
,t1
andt2
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 x³
b – coefficient of x²
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 x²
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, thenwhere
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, thenwhere
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, thenwhere
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
This config class is abstract because it needs its
options
class var to be set to an instance ofOptions
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:
a user-provided value in the options’s
self._values
dicta caller-provided default value to this method call
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
- 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.
- 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.
- 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. Thenamespace
andlocalname
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 theparser
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 callclose()
.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. Thetag
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 thestr
function in Py3 orunicode
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 optionsexclusive
,with_comments
andinclusive_ns_prefixes
request exclusive C14N, include comments, and list the inclusive prefixes respectively.With
method="c14n2"
(C14N version 2), thewith_comments
andstrip_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 correspondingstandalone
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 usingfloatToFixed()
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 alog
property that returns alogging.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 theDEFAULT_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 aStreamHandler
.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 toFalse
.
- 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
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. Defaultspretty_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. Defaultspretty_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 toTrue
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()
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.
- 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)
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, orNone
if no entry anchor is present.exitAnchor – A
otTables.Anchor
object representing the exit anchor, orNone
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
andbases
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
andligatures
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
andbaseMarks
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 ofotTables.PairPos
subtables. It is used by thePairPosBuilder
below.- builder
A pair positioning lookup builder.
- Type:
- 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 theaddGlyphPair()
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 theadd_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 orNone
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.) orNone
.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 orNone
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, orNone
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 orNone
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 orNone
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 orNone
if the mapping dictionary is empty.
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, orNone
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. (SeebuildMarkArray()
.)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. (SeebuildBaseArray()
.)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. (SeebuildMarkArray()
.)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. (SeebuildBaseArray()
.)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. (SeebuildMarkArray()
.)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. (SeebuildMarkArray()
.)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.
- An
- 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 thef
and thei
. 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.
- A
- 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 aGlyph
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 aGlyph
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, useOTTO
.flavor (str) – Set this to
woff
when creating a WOFF file orwoff2
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 andhhea
/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 thehead
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 theglyf
table.If the font contains both a
CFF ``/``CFF2
and aglyf
table, you can use thepreferCFF
argument to specify which one should be taken. If the font contains both aCFF `` 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 appliesavar
mapping if the font contains anavar
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, useOTTO
.flavor (str) – Set this to
woff
when creating a WOFF file orwoff2
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 andhhea
/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 thehead
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 theglyf
table.If the font contains both a
CFF ``/``CFF2
and aglyf
table, you can use thepreferCFF
argument to specify which one should be taken. If the font contains both aCFF `` 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 appliesavar
mapping if the font contains anavar
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.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()
- 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>)}
CBLC
: Color Bitmap Location Table
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 asgidc
, 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 bycidg
.For example, the first font in
/System/Library/Fonts/PingFang.ttc
(which Apple ships pre-installed on MacOS 10.12.6) has acidg
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 withCmapSubtable.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
andU+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, orNone
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. UsegetSubtableClass()
to retrieve the concrete subclass, ornewSubtable()
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 thedefault
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)
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
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})
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 tablesGSUB
/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 LayoutGSUB
/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
fpgm
: Font Program
fvar
: Font Variations Table
- class fontTools.ttLib.tables._f_v_a_r.Axis
- compile()
- decompile(data)
- fromXML(name, _attrs, content, ttFont)
- toXML(writer, ttFont)
gasp
: Grid-fitting and Scan-conversion Procedure Table
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
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 fromfontTools.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 toGlyph
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 thehmtx
/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.
- 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 theisComposite()
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 thecoordinates
change. Thetable__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 thecoordinates
change. Thetable__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
andtransform
. If there is no “two-by-two” matrix (i.e no scaling, reflection, or rotation; only translation), thetransform
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
GPKG
: SING Glyphlet Wrapper Table
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.compileTupleVariationStore(variations, pointCount, axisTags, sharedTupleIndices, useSharedPoints=True)
- 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
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
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
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
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)
meta
: Metadata Table
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
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
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
SING
: SING Glyphlet Basic Information Table
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
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
TTFA
: ttfautohint
Parameter Table
VDMX
: Vertical Device Metrics
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)
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.
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.
TSIB
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
TSIJ
: VTT JSTF Table Text Source
TSIP
: VTT GPOS Table Text Source
TSIS
: VTT GSUB Table Text Source
TSIV
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)
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
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 thesubModel.locations
are mapped to source font list indices by assuming the latter order is the same as the order of thevar_model.locations
. I can then get the index of each subModel location in the list ofvar_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.
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 ofbot
box.Returns two items:
Box for intersection of
top
andbot
, 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):
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:
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)
- 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. AvarLib
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 awght
axis ranging from 200-1000 with default 400, and awdth
axis ranging 100-300 with default 150, the location{"wdth": 200}
represents the pointwght=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.
- 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.Enum(enum, location=None)
An enum
- build(builder)
- glyphSet(groups=None)
- 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.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()
error
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)