[varLib] Build GX variation font using all masters
Needs some fixing, but the basics are there.
This commit is contained in:
parent
99f97e13a3
commit
fd238eb2ae
@ -6,10 +6,14 @@ from fontTools.misc.py23 import *
|
|||||||
from fontTools.ttLib import TTFont
|
from fontTools.ttLib import TTFont
|
||||||
from fontTools.ttLib.tables._n_a_m_e import NameRecord
|
from fontTools.ttLib.tables._n_a_m_e import NameRecord
|
||||||
from fontTools.ttLib.tables._f_v_a_r import table__f_v_a_r, Axis, NamedInstance
|
from fontTools.ttLib.tables._f_v_a_r import table__f_v_a_r, Axis, NamedInstance
|
||||||
|
from fontTools.ttLib.tables._g_l_y_f import table__g_l_y_f, GlyphCoordinates
|
||||||
from fontTools.ttLib.tables._g_v_a_r import table__g_v_a_r, GlyphVariation
|
from fontTools.ttLib.tables._g_v_a_r import table__g_v_a_r, GlyphVariation
|
||||||
|
import operator
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
# TODO remove me
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
#
|
#
|
||||||
# Variation space, aka design space, model
|
# Variation space, aka design space, model
|
||||||
@ -191,6 +195,18 @@ class VariationModel(object):
|
|||||||
self.deltaWeights = {mapping[i]:{mapping[i]:off for i,off in enumerate(deltaWeight) if off != 0.}
|
self.deltaWeights = {mapping[i]:{mapping[i]:off for i,off in enumerate(deltaWeight) if off != 0.}
|
||||||
for i,deltaWeight in enumerate(deltaWeights)}
|
for i,deltaWeight in enumerate(deltaWeights)}
|
||||||
|
|
||||||
|
def getDeltas(self, masterValues):
|
||||||
|
count = len(self.mapping)
|
||||||
|
assert len(masterValues) == count
|
||||||
|
out = list(masterValues)
|
||||||
|
for i in range(count):
|
||||||
|
j = self.mapping[i]
|
||||||
|
weights = self.deltaWeights[j]
|
||||||
|
items = [out[idx] * weight for idx,weight in weights.items()]
|
||||||
|
delta = reduce(operator.add, items)
|
||||||
|
out[j] = delta
|
||||||
|
return out
|
||||||
|
|
||||||
#
|
#
|
||||||
# .designspace routines
|
# .designspace routines
|
||||||
#
|
#
|
||||||
@ -281,7 +297,7 @@ def _GetCoordinates(font, glyphName):
|
|||||||
if glyphName not in glyf.glyphs: return None
|
if glyphName not in glyf.glyphs: return None
|
||||||
glyph = glyf[glyphName]
|
glyph = glyf[glyphName]
|
||||||
if glyph.isComposite():
|
if glyph.isComposite():
|
||||||
coord = [c.getComponentInfo()[1][-2:] for c in glyph.components]
|
coord = GlyphCoordinates([c.getComponentInfo()[1][-2:] for c in glyph.components])
|
||||||
control = [c.glyphName for c in glyph.components]
|
control = [c.glyphName for c in glyph.components]
|
||||||
else:
|
else:
|
||||||
allData = glyph.getCoordinates(glyf)
|
allData = glyph.getCoordinates(glyf)
|
||||||
@ -307,27 +323,18 @@ def _GetCoordinates(font, glyphName):
|
|||||||
def _sub(al, bl):
|
def _sub(al, bl):
|
||||||
return [(ax-bx,ay-by) for (ax,ay),(bx,by) in zip(al,bl)]
|
return [(ax-bx,ay-by) for (ax,ay),(bx,by) in zip(al,bl)]
|
||||||
|
|
||||||
def _add_gvar(font, axes, master_ttfs, locations, origin_idx):
|
def _add_gvar(font, axes, master_ttfs, master_locs, base_idx):
|
||||||
|
|
||||||
# Make copies for modification
|
# Make copies for modification
|
||||||
master_ttfs = master_ttfs[:]
|
master_ttfs = master_ttfs[:]
|
||||||
locations = [l.copy() for l in locations]
|
master_locs = [l.copy() for l in master_locs]
|
||||||
|
|
||||||
# Move origin to front
|
|
||||||
origin_master = master_ttfs[origin_idx]
|
|
||||||
origin_location = locations[origin_idx]
|
|
||||||
del master_ttfs[origin_idx], locations[origin_idx]
|
|
||||||
master_ttfs.insert(0, origin_master)
|
|
||||||
locations.insert(0, origin_location)
|
|
||||||
del origin_idx, origin_master, origin_location
|
|
||||||
# Neutral is zero from now on
|
|
||||||
|
|
||||||
axis_tags = axes.keys()
|
axis_tags = axes.keys()
|
||||||
|
|
||||||
# Normalize locations
|
# Normalize master_locs
|
||||||
# https://github.com/behdad/fonttools/issues/313
|
# https://github.com/behdad/fonttools/issues/313
|
||||||
for tag,(name,lower,default,upper) in axes.items():
|
for tag,(name,lower,default,upper) in axes.items():
|
||||||
for l in locations:
|
for l in master_locs:
|
||||||
v = l[tag]
|
v = l[tag]
|
||||||
if v == default:
|
if v == default:
|
||||||
v = 0
|
v = 0
|
||||||
@ -338,13 +345,9 @@ def _add_gvar(font, axes, master_ttfs, locations, origin_idx):
|
|||||||
l[tag] = v
|
l[tag] = v
|
||||||
# Locations are normalized now
|
# Locations are normalized now
|
||||||
|
|
||||||
# Find new axis mins and maxs
|
|
||||||
axis_mins = {tag:min(loc[tag] for loc in locations) for tag in axis_tags}
|
|
||||||
axis_maxs = {tag:max(loc[tag] for loc in locations) for tag in axis_tags}
|
|
||||||
|
|
||||||
print("Normalized master positions:")
|
print("Normalized master positions:")
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
pprint(locations)
|
pprint(master_locs)
|
||||||
|
|
||||||
print("Generating gvar")
|
print("Generating gvar")
|
||||||
assert "gvar" not in font
|
assert "gvar" not in font
|
||||||
@ -353,9 +356,11 @@ def _add_gvar(font, axes, master_ttfs, locations, origin_idx):
|
|||||||
gvar.reserved = 0
|
gvar.reserved = 0
|
||||||
gvar.variations = {}
|
gvar.variations = {}
|
||||||
|
|
||||||
|
# Assume single-model for now.
|
||||||
|
model = VariationModel(master_locs)
|
||||||
|
|
||||||
for glyph in font.getGlyphOrder():
|
for glyph in font.getGlyphOrder():
|
||||||
|
|
||||||
# TODO Check control data
|
|
||||||
allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
|
allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
|
||||||
allCoords = [d[0] for d in allData]
|
allCoords = [d[0] for d in allData]
|
||||||
allControls = [d[1] for d in allData]
|
allControls = [d[1] for d in allData]
|
||||||
@ -367,24 +372,14 @@ def _add_gvar(font, axes, master_ttfs, locations, origin_idx):
|
|||||||
|
|
||||||
gvar.variations[glyph] = []
|
gvar.variations[glyph] = []
|
||||||
|
|
||||||
# Subtract origin
|
deltas = model.getDeltas(allCoords)
|
||||||
allCoords = [_sub(coords, allCoords[0]) for coords in allCoords]
|
supports = model.supports
|
||||||
|
assert len(deltas) == len(supports)
|
||||||
# Add deltas for on-axis extremes
|
for i,(delta,support) in enumerate(zip(deltas, supports)):
|
||||||
for tag in axis_tags:
|
if i == base_idx:
|
||||||
for value in (axis_mins[tag], axis_maxs[tag]):
|
continue
|
||||||
if not value: continue
|
var = GlyphVariation(support, delta)
|
||||||
loc = locations[0].copy()
|
gvar.variations[glyph].append(var)
|
||||||
loc[tag] = value
|
|
||||||
idx = locations.index(loc)
|
|
||||||
loc, coords = locations[idx], allCoords[idx]
|
|
||||||
if not coords:
|
|
||||||
warnings.warn("Glyph not present in a master" + glyph)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Found master for axis extreme, add delta
|
|
||||||
var = GlyphVariation({tag: (min(value, 0.), value, max(value, 0.))}, coords)
|
|
||||||
gvar.variations[glyph].append(var)
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
|
|
||||||
@ -399,7 +394,6 @@ def main(args=None):
|
|||||||
|
|
||||||
masters, instances, base_idx = designspace_load(designspace_filename)
|
masters, instances, base_idx = designspace_load(designspace_filename)
|
||||||
|
|
||||||
from pprint import pprint
|
|
||||||
print("Masters:")
|
print("Masters:")
|
||||||
pprint(masters)
|
pprint(masters)
|
||||||
print("Instances:")
|
print("Instances:")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user