/usr/lib/python3/dist-packages/fontTools/varLib/mutator.py is in python3-fonttools 3.21.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | """
Instantiate a variation font. Run, eg:
$ python mutator.py ./NotoSansArabic-VF.ttf wght=140 wdth=85
"""
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc.fixedTools import floatToFixedToFloat
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
from fontTools.varLib import _GetCoordinates, _SetCoordinates, _DesignspaceAxis
from fontTools.varLib.models import supportScalar, normalizeLocation
from fontTools.varLib.merger import MutatorMerger
from fontTools.varLib.varStore import VarStoreInstancer
from fontTools.varLib.mvar import MVAR_ENTRIES
from fontTools.varLib.iup import iup_delta
import os.path
import logging
log = logging.getLogger("fontTools.varlib.mutator")
def instantiateVariableFont(varfont, location, inplace=False):
""" Generate a static instance from a variable TTFont and a dictionary
defining the desired location along the variable font's axes.
The location values must be specified as user-space coordinates, e.g.:
{'wght': 400, 'wdth': 100}
By default, a new TTFont object is returned. If ``inplace`` is True, the
input varfont is modified and reduced to a static font.
"""
if not inplace:
# make a copy to leave input varfont unmodified
stream = BytesIO()
varfont.save(stream)
stream.seek(0)
varfont = TTFont(stream)
fvar = varfont['fvar']
axes = {a.axisTag:(a.minValue,a.defaultValue,a.maxValue) for a in fvar.axes}
loc = normalizeLocation(location, axes)
if 'avar' in varfont:
maps = varfont['avar'].segments
loc = {k:_DesignspaceAxis._map(v, maps[k]) for k,v in loc.items()}
# Quantize to F2Dot14, to avoid surprise interpolations.
loc = {k:floatToFixedToFloat(v, 14) for k,v in loc.items()}
# Location is normalized now
log.info("Normalized location: %s", loc)
log.info("Mutating glyf/gvar tables")
gvar = varfont['gvar']
glyf = varfont['glyf']
# get list of glyph names in gvar sorted by component depth
glyphnames = sorted(
gvar.variations.keys(),
key=lambda name: (
glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth
if glyf[name].isComposite() else 0,
name))
for glyphname in glyphnames:
variations = gvar.variations[glyphname]
coordinates,_ = _GetCoordinates(varfont, glyphname)
origCoords, endPts = None, None
for var in variations:
scalar = supportScalar(loc, var.axes)
if not scalar: continue
delta = var.coordinates
if None in delta:
if origCoords is None:
origCoords,control = _GetCoordinates(varfont, glyphname)
endPts = control[1] if control[0] >= 1 else list(range(len(control[1])))
delta = iup_delta(delta, origCoords, endPts)
coordinates += GlyphCoordinates(delta) * scalar
_SetCoordinates(varfont, glyphname, coordinates)
if 'cvar' in varfont:
log.info("Mutating cvt/cvar tables")
cvar = varfont['cvar']
cvt = varfont['cvt ']
deltas = {}
for var in cvar.variations:
scalar = supportScalar(loc, var.axes)
if not scalar: continue
for i, c in enumerate(var.coordinates):
if c is not None:
deltas[i] = deltas.get(i, 0) + scalar * c
for i, delta in deltas.items():
cvt[i] += round(delta)
if 'MVAR' in varfont:
log.info("Mutating MVAR table")
mvar = varfont['MVAR'].table
varStoreInstancer = VarStoreInstancer(mvar.VarStore, fvar.axes, loc)
records = mvar.ValueRecord
for rec in records:
mvarTag = rec.ValueTag
if mvarTag not in MVAR_ENTRIES:
continue
tableTag, itemName = MVAR_ENTRIES[mvarTag]
delta = round(varStoreInstancer[rec.VarIdx])
if not delta:
continue
setattr(varfont[tableTag], itemName,
getattr(varfont[tableTag], itemName) + delta)
if 'GDEF' in varfont:
log.info("Mutating GDEF/GPOS/GSUB tables")
merger = MutatorMerger(varfont, loc)
log.info("Building interpolated tables")
merger.instantiate()
log.info("Removing variable tables")
for tag in ('avar','cvar','fvar','gvar','HVAR','MVAR','VVAR','STAT'):
if tag in varfont:
del varfont[tag]
return varfont
def main(args=None):
from fontTools import configLogger
if args is None:
import sys
args = sys.argv[1:]
varfilename = args[0]
locargs = args[1:]
outfile = os.path.splitext(varfilename)[0] + '-instance.ttf'
# TODO Allow to specify logging verbosity as command line option
configLogger(level=logging.INFO)
loc = {}
for arg in locargs:
tag,val = arg.split('=')
assert len(tag) <= 4
loc[tag.ljust(4)] = float(val)
log.info("Location: %s", loc)
log.info("Loading variable font")
varfont = TTFont(varfilename)
instantiateVariableFont(varfont, loc, inplace=True)
log.info("Saving instance font %s", outfile)
varfont.save(outfile)
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
sys.exit(main())
import doctest
sys.exit(doctest.testmod().failed)
|