[varLib.interpolatable] Support CFF2 input font
Fixes https://github.com/fonttools/fonttools/issues/3666
This commit is contained in:
parent
885d7c1ecb
commit
b5373bf5d2
@ -752,11 +752,11 @@ def main(args=None):
|
||||
|
||||
elif args.inputs[0].endswith(".ttf") or args.inputs[0].endswith(".otf"):
|
||||
from fontTools.ttLib import TTFont
|
||||
|
||||
# Is variable font?
|
||||
|
||||
font = TTFont(args.inputs[0])
|
||||
upem = font["head"].unitsPerEm
|
||||
if "gvar" in font:
|
||||
|
||||
fvar = font["fvar"]
|
||||
axisMapping = {}
|
||||
@ -780,12 +780,14 @@ def main(args=None):
|
||||
location, fvarMapping
|
||||
)
|
||||
|
||||
gvar = font["gvar"]
|
||||
glyf = font["glyf"]
|
||||
# Gather all glyphs at their "master" locations
|
||||
ttGlyphSets = {}
|
||||
glyphsets = defaultdict(dict)
|
||||
|
||||
if "gvar" in font:
|
||||
gvar = font["gvar"]
|
||||
glyf = font["glyf"]
|
||||
|
||||
if glyphs is None:
|
||||
glyphs = sorted(gvar.variations.keys())
|
||||
for glyphname in glyphs:
|
||||
@ -806,6 +808,60 @@ def main(args=None):
|
||||
glyphname, glyphsets[locTuple], ttGlyphSets[locTuple], glyf
|
||||
)
|
||||
|
||||
elif "CFF2" in font:
|
||||
fvarAxes = font["fvar"].axes
|
||||
cff2 = font["CFF2"].cff.topDictIndex[0]
|
||||
charstrings = cff2.CharStrings
|
||||
|
||||
if glyphs is None:
|
||||
glyphs = sorted(charstrings.keys())
|
||||
for glyphname in glyphs:
|
||||
cs = charstrings[glyphname]
|
||||
private = cs.private
|
||||
|
||||
# Extract vsindex for the glyph
|
||||
vsindices = {getattr(private, "vsindex", 0)}
|
||||
vsindex = getattr(private, "vsindex", 0)
|
||||
last_op = 0
|
||||
# The spec says vsindex can only appear once and must be the first
|
||||
# operator in the charstring, but we support multiple.
|
||||
# https://github.com/harfbuzz/boring-expansion-spec/issues/158
|
||||
for op in enumerate(cs.program):
|
||||
if op == "blend":
|
||||
vsindices.add(vsindex)
|
||||
elif op == "vsindex":
|
||||
assert isinstance(last_op, int)
|
||||
vsindex = last_op
|
||||
last_op = op
|
||||
|
||||
if not hasattr(private, "vstore"):
|
||||
continue
|
||||
|
||||
varStore = private.vstore.otVarStore
|
||||
for vsindex in vsindices:
|
||||
varData = varStore.VarData[vsindex]
|
||||
for regionIndex in varData.VarRegionIndex:
|
||||
region = varStore.VarRegionList.Region[regionIndex]
|
||||
|
||||
locDict = {}
|
||||
loc = []
|
||||
for axisIndex, axis in enumerate(region.VarRegionAxis):
|
||||
tag = fvarAxes[axisIndex].axisTag
|
||||
val = axis.PeakCoord
|
||||
locDict[tag] = val
|
||||
loc.append((tag, val))
|
||||
|
||||
locTuple = tuple(loc)
|
||||
if locTuple not in ttGlyphSets:
|
||||
ttGlyphSets[locTuple] = font.getGlyphSet(
|
||||
location=locDict,
|
||||
normalized=True,
|
||||
recalcBounds=False,
|
||||
)
|
||||
|
||||
glyphset = glyphsets[locTuple]
|
||||
glyphset[glyphname] = ttGlyphSets[locTuple][glyphname]
|
||||
|
||||
names = ["''"]
|
||||
fonts = [font.getGlyphSet()]
|
||||
locations = [{}]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -94,6 +94,33 @@ class InterpolatableTest(unittest.TestCase):
|
||||
otf_paths = self.get_file_list(self.tempdir, suffix)
|
||||
self.assertIsNone(interpolatable_main(otf_paths))
|
||||
|
||||
def test_interpolatable_cff2(self):
|
||||
suffix = ".otf"
|
||||
ttx_dir = self.get_test_input("variable_ttx_interpolatable_cff2")
|
||||
ttx_path = os.path.abspath(os.path.join(ttx_dir, "interpolatable-test.ttx"))
|
||||
|
||||
self.temp_dir()
|
||||
self.compile_font(ttx_path, suffix, self.tempdir)
|
||||
|
||||
otf_path = self.get_file_list(self.tempdir, suffix)[0]
|
||||
|
||||
problems = interpolatable_main([otf_path])
|
||||
print(problems)
|
||||
self.assertEqual(
|
||||
problems["uni0408"],
|
||||
[
|
||||
{
|
||||
"type": "underweight",
|
||||
"contour": 0,
|
||||
"master_1": "'wght=200.0 opsz=20.0'",
|
||||
"master_2": "'wght=200.0 opsz=60.0'",
|
||||
"master_1_idx": 2,
|
||||
"master_2_idx": 3,
|
||||
"tolerance": 0.9184032411892079,
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
def test_interpolatable_ufo(self):
|
||||
ttx_dir = self.get_test_input("master_ufo")
|
||||
ufo_paths = self.get_file_list(ttx_dir, ".ufo", "TestFamily2-")
|
||||
|
Loading…
x
Reference in New Issue
Block a user