
—fontTools Documentation—
About
fontTools is a family of libraries and utilities for manipulating fonts in Python.
The project is licensed under the MIT open-source license, allowing free usage.
Installation
Note
fontTools requires Python 3.8 or later.
To install fontTools, use pip:
pip install fonttools
Utilities
fontTools includes the following command-line utilities:
pyftmerge
: Tool for merging fonts; seefontTools.merge
pyftsubset
: Tool for subsetting fonts; seefontTools.subset
ttx
: Tool for converting between OTF and XML representation; seefontTools.ttx
fonttools
: Meta-tool for accessing other fontTools components.
For fonttools
, you can use subcommands like:
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 fontmerge
: Merge multiple fonts into onesubset
: OpenType font subsetter and optimizerttx
: Convert OpenType fonts to XML and backvarLib
: Build a variable font from a designspace file and mastersvarLib.instancer
: Partially instantiate a variable fontvoltLib.voltToFea
: Convert MS VOLT to AFDKO feature files.
Libraries
The main library for font engineering is fontTools.ttLib.ttFont
, which handles TrueType/OpenType fonts. Other libraries include:
fontTools.afmLib
: Read and write AFM filesfontTools.agl
: Access the Adobe Glyph ListfontTools.cffLib
: Tools for Adobe CFF fontsfontTools.colorLib
: Handle colors in CPAL/COLR fontsfontTools.cu2qu
: Convert cubic to quadratic curvesfontTools.designspaceLib
: Read and write designspace filesfontTools.encodings
: Support for font-related encodingsfontTools.feaLib
: Read and write AFDKO feature filesfontTools.fontBuilder
: Construct TTF/OTF fonts from scratchfontTools.merge
: Tools for merging font filesfontTools.subset
: OpenType font subsetting and optimizationfontTools.svgLib.path
: Draw SVG paths onto glyphsfontTools.ttLib
: Read/write OpenType and TrueType fontsfontTools.ttx
: Convert between OTF and XML representationfontTools.ufoLib
: Read and write UFO filesfontTools.unicodedata
: Convert between Unicode and OpenType script infofontTools.varLib
: Deal with ‘gvar’-style font variationsfontTools.voltLib
: Deal with Visual OpenType Layout Tool (VOLT) files
Optional Dependencies
fontTools has no external dependencies besides the Python Standard Library. Some optional features require additional modules; see the optional requirements page for details.
Developer Information
For developer resources, refer to the developer information.
License
fontTools is licensed under the MIT license. Refer to the full text of the license for details.
Table of Contents
afmLib: Read and write Adobe Font Metrics files
agl: Interface to the Adobe Glyph List
cffLib: Read and write Adobe CFF fonts
Overview:
colorLib.builder: Build COLR/CPAL tables from scratch
config: Configure fontTools
cu2qu: Convert cubic curves to quadratic
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.ufo
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
AxisDescriptor
DiscreteAxisDescriptor
AxisLabelDescriptor
LocationLabelDescriptor
RuleDescriptor
Evaluating rules
SourceDescriptor
VariableFontDescriptor
RangeAxisSubsetDescriptor
ValueAxisSubsetDescriptor
InstanceDescriptor
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.
fontTools.varLib.stat
fontTools.designspaceLib.statNames
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 HeaderAdded 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.
Added 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.
Added 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.
Added 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.
Added 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
Added 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
Added 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.
Added 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.
Added 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.
Added 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
Added 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.Added 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.
Added 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
Added 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.
Added 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.
Added 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.
Added 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"/>
Added 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.
Added 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.Added 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 character 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 and 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
Building
Generation/Interrogation
In the below, a glyph-containing object is an object of one of the following
classes: GlyphName
, GlyphClass
, GlyphClassName
.
merge: Merge multiple fonts into one
fontTools.merge
provides both a library and a command line interface
(fonttools merge
) for merging multiple fonts together.
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
bezierTools: Routines for working with Bezier curves
classifyTools
cliTools: Utilities for command-line interfaces and console scripts
configTools
eexec: PostScript charstring encryption and decryption routines
encodingTools
etree
filenames: Implements UFO User Name to File Name Algorithm
fixedTools: Tools for working with fixed-point numbers
intTools: Tools for working with integer values
loggingTools: tools for interfacing with the Python logging package
macCreatorType: Functions for working with Mac file attributes
This module requires the xattr module to be installed in order to function correctly.
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.
plistlib: Tools for handling .plist files
psCharStrings
psLib
psOperators
sstruct
symfont
testTools
textTools
timeTools
transform
xmlReader
xmlWriter
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.
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
Common OpenType Layout Data Structures
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).
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).
GDEF Table Subtable Builders
These functions build subtables for elements of the GDEF
table.
STAT Table Builder
MATH Table Builder
pens: Inspect and manipulate glyph outlines
Overview:
The fontTools pens are a collection of classes that can operate on a font glyph via the points and the contours of the glyph’s outlines.
Some pens trace through the outlines and generate graphical output, such as a new glyph outline or a formatted image, but other pens analyze the outlines and return information about the glyph.
Pens that alter or produce a pen-compatible ttGlyph
object can
be chained together.
New pens can be written by sub-classing the AbstractPen
or,
somewhat more practically, BasePen
classes. The Pen Protocol is
documented on the basePen page.
Pen modules:
subset: Generate subsets of fonts or optimize file sizes
cff
svgLib: Read and write SVG-in-OpenType fonts
t1Lib: Read and write PostScript Type 1 fonts
tfmLib: Read TeX Font Metrics files
ttLib: Read and 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
ttCollection
macUtils
sfnt
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
avar
: Axis Variations Table
BASE
: Baseline Table
bsln
: Baseline
CBDT
: Color Bitmap Data Table
CBLC
: Color Bitmap Location Table
CFF
: Compact Font Format Table
CFF2
: Compact Font Format (CFF) Version 2
cidg
: CID to Glyph ID table
cmap
: Character to Glyph Index Mapping Table
COLR
: Color Table
CPAL
: Color Palette Table
cvar
: CVT Variations Table
TupleVariation
cvt
: Control Value Table
DSIG
: Digital Signature Table
EBDT
: Embedded Bitmap Data Table
BitmapGlyphMetrics
EBLC
: Embedded Bitmap Location Table
BitmapGlyphMetrics
Feat
: Graphite Feature Table
feat
: Feature name table
FFTM
: FontForge Time Stamp Table
fpgm
: Font Program
fvar
: Font Variations Table
gasp
: Grid-fitting and Scan-conversion Procedure Table
gcid
: Glyph ID to CID table
GDEF
: Glyph Definition Table
Glat
: Graphite Glyph Attributes Table
Gloc
: Graphite index to glyph attributes table
glyf
: Glyph Data
GMAP
: SING Glyphlet Summary Table
GPKG
: SING Glyphlet Wrapper Table
GPOS
: Glyph Positioning Table
GSUB
: Glyph Substitution Table
gvar
: Glyph Variations Table
TupleVariation
hdmx
: Horizontal Device Metrics
head
: Font Header Table
hhea
: Horizontal Header Table
hmtx
: Horizontal Metrics Table
HVAR
:Horizontal Metrics Variations Table
JSTF
: Justification Table
kern
: Kerning
lcar
: Ligature Caret Table
loca
: Index to Location
ltag
: Language Tag
LTSH
: Linear Threshold
MATH
: Mathematical Typesetting Table
maxp
: Maximum Profile
META
: SING Glyphlet Metadata Table
meta
: Metadata Table
mort
: Glyph Metamorphosis Table
morx
: Extended Glyph Metamorphosis Table
MVAR
: Metrics Variations Table
name
: Naming Table
opbd
: Optical Bounds Table
OS/2
: OS/2 and Windows Metrics Table
post
: PostScript Table
prep
: Control Value Program
prop
: Glyph Properties Table
sbix
: Standard Bitmap Graphics Table
sbixGlyph
sbixStrike
Silf
: Graphite Rules Table
Sill
: Graphite Languages Table
SING
: SING Glyphlet Basic Information Table
STAT
: Style Attributes Table
SVG
: SVG (Scalable Vector Graphics) Table
trak
: Tracking table
TTFA
: ttfautohint
Parameter Table
VDMX
: Vertical Device Metrics
vhea
: Vertical Header Table
vmtx
: Vertical Metrics Table
VORG
: Vertical Origin Table
Visual TrueType Private Tables
TSI0
: Glyph Program Text Indices
TSI1
: Glyph Program Text UTF-8 Text Dump
TSI2
: VTT Talk Text Indices
TSI3
: VTT Talk UTF-8 Text Dump
TSI5
: VTT Character Group Flag
TSIB
TSIC
: VTT Variation CVT Window Source
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
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
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
ttx: Convert fonts to XML and back
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, VARC, 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.
ufoLib: Read and write Unified Font Object files
Overview:
unicode
unicodedata
Blocks
- fontTools.unicodedata.Blocks.RANGES
- fontTools.unicodedata.Blocks.VALUES
ScriptExtensions
- fontTools.unicodedata.ScriptExtensions.RANGES
- fontTools.unicodedata.ScriptExtensions.VALUES
Scripts
- fontTools.unicodedata.Scripts.NAMES
- fontTools.unicodedata.Scripts.RANGES
- fontTools.unicodedata.Scripts.VALUES
varLib: Support for OpenType Variations
builder
cff
errors
featureVars
instancer
interpolatable
interpolate_layout
iup
merger
models
mutator
mvar
- fontTools.varLib.mvar.MVAR_ENTRIES
plot
varStore
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.