featureVars

Module to build FeatureVariation tables: https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table

NOTE: The API is experimental and subject to change.

class fontTools.varLib.featureVars.ShifterVisitor(shift)[source]
defaultStop = False
classmethod register(clazzes)
classmethod register_attr(clazzes, attrs)
classmethod register_attrs(clazzes_attrs)
visit(obj, *args, **kwargs)

This is the main entry to the visitor. The visitor will visit object obj.

The visitor will first determine if there is a registered (via @register()) visit function for the type of object. If there is, it will be called, and (visitor, obj, *args, **kwargs) will be passed to the user visit function.

If there is no user-registered visit function, of if there is and it returns True, or it returns None (or doesn’t return anything) and visitor.defaultStop is False (default), then the visitor will proceed to dispatch to one of self.visitObject(), self.visitList(), self.visitDict(), or self.visitLeaf() (any of which can be overriden in a subclass).

visitAttr(obj, attr, value, *args, **kwargs)

Called to visit an attribute of an object.

visitDict(obj, *args, **kwargs)

Called to visit any value that is a dictionary.

visitLeaf(obj, *args, **kwargs)

Called to visit any value that is not an object, list, or dictionary.

visitList(obj, *args, **kwargs)

Called to visit any value that is a list.

visitObject(obj, *args, **kwargs)

Called to visit an object. This function loops over all non-private attributes of the objects and calls any user-registered (via @register_attr() or @register_attrs()) visit() functions.

If there is no user-registered visit function, of if there is and it returns True, or it returns None (or doesn’t return anything) and visitor.defaultStop is False (default), then the visitor will proceed to call self.visitAttr()

fontTools.varLib.featureVars.addFeatureVariations(font, conditionalSubstitutions, featureTag='rvrn')[source]

Add conditional substitutions to a Variable Font.

The conditionalSubstitutions argument is a list of (Region, Substitutions) tuples.

A Region is a list of Boxes. A Box is a dict mapping axisTags to (minValue, maxValue) tuples. Irrelevant axes may be omitted and they are interpretted as extending to end of axis in each direction. A Box represents an orthogonal ‘rectangular’ subset of an N-dimensional design space. A Region represents a more complex subset of an N-dimensional design space, ie. the union of all the Boxes in the Region. For efficiency, Boxes within a Region should ideally not overlap, but functionality is not compromised if they do.

The minimum and maximum values are expressed in normalized coordinates.

A Substitution is a dict mapping source glyph names to substitute glyph names.

Example:

# >>> f = TTFont(srcPath) # >>> condSubst = [ # … # A list of (Region, Substitution) tuples. # … ([{“wdth”: (0.5, 1.0)}], {“cent”: “cent.rvrn”}), # … ([{“wght”: (0.5, 1.0)}], {“dollar”: “dollar.rvrn”}), # … ] # >>> addFeatureVariations(f, condSubst) # >>> f.save(dstPath)

The featureTag parameter takes either a str or a iterable of str (the single str is kept for backwards compatibility), and defines which feature(s) will be associated with the feature variations. Note, if this is “rvrn”, then the substitution lookup will be inserted at the beginning of the lookup list so that it is processed before others, otherwise for any other feature tags it will be appended last.

fontTools.varLib.featureVars.addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag='rvrn')[source]

Low level implementation of addFeatureVariations that directly models the possibilities of the FeatureVariations table.

fontTools.varLib.featureVars.bit_count(self, /)

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

Also known as the population count.

>>> bin(13)
'0b1101'
>>> (13).bit_count()
3
fontTools.varLib.featureVars.buildConditionTable(axisIndex, filterRangeMinValue, filterRangeMaxValue)[source]

Build a ConditionTable.

fontTools.varLib.featureVars.buildFeatureRecord(featureTag, lookupListIndices)[source]

Build a FeatureRecord.

fontTools.varLib.featureVars.buildFeatureTableSubstitutionRecord(featureIndex, lookupListIndices)[source]

Build a FeatureTableSubstitutionRecord.

fontTools.varLib.featureVars.buildFeatureVariationRecord(conditionTable, substitutionRecords)[source]

Build a FeatureVariationRecord.

fontTools.varLib.featureVars.buildFeatureVariations(featureVariationRecords)[source]

Build the FeatureVariations subtable.

fontTools.varLib.featureVars.buildGSUB()[source]

Build a GSUB table from scratch.

fontTools.varLib.featureVars.buildSubstitutionLookups(gsub, allSubstitutions, processLast=False)[source]

Build the lookups for the glyph substitutions, return a dict mapping the substitution to lookup indices.

fontTools.varLib.featureVars.cleanupBox(box)[source]

Return a sparse copy of box, without redundant (default) values.

>>> cleanupBox({})
{}
>>> cleanupBox({'wdth': (0.0, 1.0)})
{'wdth': (0.0, 1.0)}
>>> cleanupBox({'wdth': (-1.0, 1.0)})
{}
fontTools.varLib.featureVars.findFeatureVariationRecord(featureVariations, conditionTable)[source]

Find a FeatureVariationRecord that has the same conditionTable.

fontTools.varLib.featureVars.makeSubstitutionsHashable(conditionalSubstitutions)[source]

Turn all the substitution dictionaries in sorted tuples of tuples so they are hashable, to detect duplicates so we don’t write out redundant data.

fontTools.varLib.featureVars.overlayBox(top, bot)[source]

Overlays top box on top of bot box.

Returns two items:

  • Box for intersection of top and bot, or None if they don’t intersect.

  • Box for remainder of bot. Remainder box might not be exact (since the remainder might not be a simple box), but is inclusive of the exact remainder.

fontTools.varLib.featureVars.overlayFeatureVariations(conditionalSubstitutions)[source]

Compute overlaps between all conditional substitutions.

The conditionalSubstitutions argument is a list of (Region, Substitutions) tuples.

A Region is a list of Boxes. A Box is a dict mapping axisTags to (minValue, maxValue) tuples. Irrelevant axes may be omitted and they are interpretted as extending to end of axis in each direction. A Box represents an orthogonal ‘rectangular’ subset of an N-dimensional design space. A Region represents a more complex subset of an N-dimensional design space, ie. the union of all the Boxes in the Region. For efficiency, Boxes within a Region should ideally not overlap, but functionality is not compromised if they do.

The minimum and maximum values are expressed in normalized coordinates.

A Substitution is a dict mapping source glyph names to substitute glyph names.

Returns data is in similar but different format. Overlaps of distinct substitution Boxes (not Regions) are explicitly listed as distinct rules, and rules with the same Box merged. The more specific rules appear earlier in the resulting list. Moreover, instead of just a dictionary of substitutions, a list of dictionaries is returned for substitutions corresponding to each unique space, with each dictionary being identical to one of the input substitution dictionaries. These dictionaries are not merged to allow data sharing when they are converted into font tables.

Example:

>>> condSubst = [
...     # A list of (Region, Substitution) tuples.
...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
...     ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}),
...     ([{"wght": (0.5, 1.0), "wdth": (-1, 1.0)}], {"dollar": "dollar.rvrn"}),
... ]
>>> from pprint import pprint
>>> pprint(overlayFeatureVariations(condSubst))
[({'wdth': (0.5, 1.0), 'wght': (0.5, 1.0)},
  [{'dollar': 'dollar.rvrn'}, {'cent': 'cent.rvrn'}]),
 ({'wdth': (0.5, 1.0)}, [{'cent': 'cent.rvrn'}]),
 ({'wght': (0.5, 1.0)}, [{'dollar': 'dollar.rvrn'}])]
fontTools.varLib.featureVars.remapFeatures(table, featureRemap)[source]

Go through the scripts list, and remap feature indices.

fontTools.varLib.featureVars.sortFeatureList(table)[source]

Sort the feature list by feature tag, and remap the feature indices elsewhere. This is needed after the feature list has been modified.