Font Tools

—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; see fontTools.merge

  • pyftsubset: Tool for subsetting fonts; see fontTools.subset

  • ttx: Tool for converting between OTF and XML representation; see fontTools.ttx

  • fonttools: Meta-tool for accessing other fontTools components.

For fonttools, you can use subcommands like:

  • cffLib.width: Calculate optimum defaultWidthX/nominalWidthX values

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

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

  • merge: Merge multiple fonts into one

  • subset: OpenType font subsetter and optimizer

  • ttx: Convert OpenType fonts to XML and back

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

  • varLib.instancer: Partially instantiate a variable font

  • voltLib.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 files

  • fontTools.agl: Access the Adobe Glyph List

  • fontTools.cffLib: Tools for Adobe CFF fonts

  • fontTools.colorLib: Handle colors in CPAL/COLR fonts

  • fontTools.cu2qu: Convert cubic to quadratic curves

  • fontTools.designspaceLib: Read and write designspace files

  • fontTools.encodings: Support for font-related encodings

  • fontTools.feaLib: Read and write AFDKO feature files

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

  • fontTools.merge: Tools for merging font files

  • fontTools.subset: OpenType font subsetting and optimization

  • fontTools.svgLib.path: Draw SVG paths onto glyphs

  • fontTools.ttLib: Read/write OpenType and TrueType fonts

  • fontTools.ttx: Convert between OTF and XML representation

  • fontTools.ufoLib: Read and write UFO files

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

  • fontTools.varLib: Deal with ‘gvar’-style font variations

  • fontTools.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

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

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

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 field axisOrdering for this axis.

    See: OTSpec STAT Axis Record

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

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

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

Added in version 5.0.

Attributes

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

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

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

    See: OTSpec STAT Flags

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

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

  • userminimum: STAT field rangeMinValue (format 2).

  • usermaximum: STAT field rangeMaxValue (format 2).

  • linkeduservalue: STAT field linkedValue (format 3).

STAT Format

uservalue

userminimum

usermaximum

linkeduservalue

1

2

3

Example

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

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

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 its name attribute.

See: OTSpec STAT Axis value table, format 4

Added in version 5.0.

Attributes

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

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

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

    See: OTSpec STAT Flags

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

  • Encodes a dictionary of { axisname: axisvalue }.

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

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

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

Attributes

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

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

For user-space coordinates:

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

    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 as first, and put the substitution rule in the rvrn feature.

    • If processing is last, put it in rclt.

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

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

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

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

2.4.1 <rule> element
  • Defines a named rule.

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

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

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

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

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

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

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

Attributes

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

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

  • Contains zero or more <condition> elements.

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

  • Between the minimum and maximum this condition is True.

  • minimum and maximum are in designspace coordinates.

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

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

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

Attributes

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

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

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

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

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

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

Attributes

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

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

Example

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

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

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

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

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

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

  • Child element of <sources>

  • Location in designspace coordinates.

Attributes

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

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

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

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

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

2.5.1.1 <familyname> element: localised names for sources

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

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 the name. The filename may include an extension (e.g. .ttf) and the build tools can replace that extension with another (e.g. .otf or .woff2) as needed.

Example

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

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

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

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

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:

    1. the whole axis

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

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

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

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

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.

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

Example

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

Illustration of instances included in a variable font.

2.7 <instances> element

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

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

  • Child element of <instances>

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

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

  • Location in designspace coordinates.

Attributes

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

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

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

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

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

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

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

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

    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.

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

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

  • <stylename>

  • <familyname>

  • <stylemapstylename>

  • <stylemapfamilyname>

Example

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

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

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

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

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

See UFO3 fontinfo.plist specification.

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

  • Optional

  • MutatorMath only.

Deprecated since version 5.0.

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

  • May contain a <location> element.

Deprecated since version 5.0.

Attributes

  • name: string. The name of the glyph.

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

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

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

Deprecated since version 5.0.

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

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

Deprecated since version 5.0.

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

Deprecated since version 5.0.

Attributes

  • glyphname: the name of the alternate master glyph.

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

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

The <lib> element contains arbitrary data.

Example:

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

3 Scripting a designspace

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

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

Filling-in a DesignSpaceDocument

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

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

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

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

Make an axis object

Make a descriptor object and add it to the document.

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

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

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

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

Option: add label names

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

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

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

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

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

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

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

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

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

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

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

So go ahead and add another master:

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

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

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

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

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

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

  • Instances for MutatorMath will generate to UFO.

  • Instances for variable fonts become named instances.

Option: add more names

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

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

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

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

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

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

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

You can generate the UFOs with MutatorMath:

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

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

Working with DesignSpace version 5

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

  • checking that all sources are compatible for interpolation

  • building variable fonts

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

Example process diagram to check and build DesignSpace 5

Example process process to check and build Designspace 5.

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

Notes

Paths and filenames

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

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

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

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

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

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

  • Only the filename attribute is written to file.

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

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

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

Case 1

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

Action

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

Case 2

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

Action

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

Case 3

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

Action

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

Case 4

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

Action

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

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

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

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

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

Common Lib Key Registry

public.skipExportGlyphs

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

public.fontInfo

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

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

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

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

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

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

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

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

Implementation and differences

The designspace format has gone through considerable development.

  • the format was originally written for MutatorMath.

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

  • not all values are be required by all implementations.

varLib vs. MutatorMath

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

  • varLib does not support anisotropic interpolations.

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

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

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

Rules and generating static UFO instances

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

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

  • Assuming rulesProcessingLast = True:

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

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

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

Version history

Version 5.1

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

Version 5.0

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

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

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

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

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

What is currently not supported is e.g.

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

  2. Anisotropic locations for axis labels.

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

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

encodings: Support for OpenType-specific 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).

GPOS Shared Table Builders

The functions help build the GPOS shared tables as defined in the OpenType spec: value records, anchors, mark arrays and mark record tables.

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:

areaPen

basePen

boundsPen

cocoaPen

cu2quPen

filterPen

freetypePen

momentsPen

perimeterPen

pointInsidePen

pointPen

qtPen

recordingPen

reportLabPen

reverseContourPen

roundingPen

statisticsPen

svgPathPen

t2CharStringPen

teePen

transformPen

ttGlyphPen

wxPen

subset: Generate subsets of fonts or optimize file sizes

cff

svgLib: Read and write SVG-in-OpenType fonts

path

parser

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

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

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. A varLib location dictionary may be “sparse”, in the sense that axes defined in the font may be omitted from the location’s coordinates, in which case the default value of the axis is assumed. For example, given a font having a wght axis ranging from 200-1000 with default 400, and a wdth axis ranging 100-300 with default 150, the location {"wdth": 200} represents the point wght=400,wdth=200.

master

The value of a scalar at a given location. Note that this is a considerably more general concept than the usual type design sense of the term “master”.

normalized location

While the range of an axis is determined by its minimum and maximum values as set by the designer, locations are specified internally to the font binary in the range -1 to 1, with 0 being the default, -1 being the minimum and 1 being the maximum. A normalized location is one which is scaled to the range (-1,1) on all of its axes. Note that as the range from minimum to default and from default to maximum on a given axis may differ (for example, given wght min=200 default=500 max=1000, the difference between a normalized location -1 of a normalized location of 0 represents a difference of 300 units while the difference between a normalized location of 0 and a normalized location of 1 represents a difference of 700 units), a location is scaled by a different factor depending on whether it is above or below the axis’ default value.

support

While designers tend to think in terms of masters - that is, a precise location having a particular value - OpenType Variations specifies the variation of scalars in terms of deltas which are themselves composed of the combined contributions of a set of triangular regions, each having a contribution value of 0 at its minimum value, rising linearly to its full contribution at the peak and falling linearly to zero from the peak to the maximum value. The OpenType Specification calls these “regions”, while varLib calls them “supports” (a mathematical term used in real analysis) and expresses them as a dictionary mapping each axis tag to a tuple (min, peak, max).

box

varLib uses the term “box” to denote the minimum and maximum “corners” of a support, ignoring its peak value.

delta

The term “delta” is used in OpenType Variations in two senses. In the more general sense, a delta is the difference between a scalar at a given location and its value at the default location. Additionally, inside the font, variation data is stored as a mapping between supports and deltas. The delta (in the first sense) is computed by summing the product of the delta of each support by a factor representing the support’s contribution at this location (see “support scalar” below).

support scalar

When interpolating a set of variation data, the support scalar represents the scalar multiplier of the support’s contribution at this location. For example, the support scalar will be 1 at the support’s peak location, and 0 below its minimum or above its maximum.

voltLib: Read and write MS VOLT projects

voltToFea: Convert MS VOLT to AFDKO feature files

ast

error

lexer

parser