def test_decompileSharedCoords_Skia(self): table = table__g_v_a_r() table.offsetToCoord = 0 table.sharedCoordCount = 8 sharedCoords = table.decompileSharedCoords_(["wght", "wdth"], SKIA_SHARED_COORDS) self.assertEqual([{ "wght": 1.0, "wdth": 0.0 }, { "wght": -1.0, "wdth": 0.0 }, { "wght": 0.0, "wdth": 1.0 }, { "wght": 0.0, "wdth": -1.0 }, { "wght": -1.0, "wdth": -1.0 }, { "wght": 1.0, "wdth": -1.0 }, { "wght": 1.0, "wdth": 1.0 }, { "wght": -1.0, "wdth": 1.0 }], sharedCoords)
def test_decompileGlyph_empty(self): table = table__g_v_a_r() self.assertEqual([], table.decompileGlyph_(numPointsInGlyph=5, sharedCoords=[], axisTags=[], data=b""))
def AddGlyphVariations(font, thin, regular, black): assert "gvar" not in font gvar = font["gvar"] = table__g_v_a_r() gvar.version = 1 gvar.reserved = 0 gvar.variations = {} for glyphName in regular.getGlyphOrder(): regularCoord = GetCoordinates(regular, glyphName) thinCoord = GetCoordinates(thin, glyphName) blackCoord = GetCoordinates(black, glyphName) if not regularCoord or not blackCoord or not thinCoord: warnings.warn("glyph %s not present in all input fonts" % glyphName) continue if (len(regularCoord) != len(blackCoord) or len(regularCoord) != len(thinCoord)): warnings.warn("glyph %s has not the same number of " "control points in all input fonts" % glyphName) continue thinDelta = [] blackDelta = [] for ((regX, regY), (blackX, blackY), (thinX, thinY)) in \ zip(regularCoord, blackCoord, thinCoord): thinDelta.append(((thinX - regX, thinY - regY))) blackDelta.append((blackX - regX, blackY - regY)) thinVar = GlyphVariation({"wght": (-1.0, -1.0, 0.0)}, thinDelta) blackVar = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, blackDelta) gvar.variations[glyphName] = [thinVar, blackVar]
def AddGlyphVariations(font, thin, regular, black): assert "gvar" not in font gvar = font["gvar"] = table__g_v_a_r() gvar.version = 1 gvar.reserved = 0 gvar.variations = {} for glyphName in regular.getGlyphOrder(): regularCoord = GetCoordinates(regular, glyphName) thinCoord = GetCoordinates(thin, glyphName) blackCoord = GetCoordinates(black, glyphName) if not regularCoord or not blackCoord or not thinCoord: logging.warning("glyph %s not present in all input fonts", glyphName) continue if (len(regularCoord) != len(blackCoord) or len(regularCoord) != len(thinCoord)): logging.warning("glyph %s has not the same number of " "control points in all input fonts", glyphName) continue thinDelta = [] blackDelta = [] for ((regX, regY), (blackX, blackY), (thinX, thinY)) in \ zip(regularCoord, blackCoord, thinCoord): thinDelta.append(((thinX - regX, thinY - regY))) blackDelta.append((blackX - regX, blackY - regY)) thinVar = TupleVariation({"wght": (-1.0, -1.0, 0.0)}, thinDelta) blackVar = TupleVariation({"wght": (0.0, 1.0, 1.0)}, blackDelta) gvar.variations[glyphName] = [thinVar, blackVar]
def _add_gvar(font, axes, master_ttfs, master_locs, base_idx): # Make copies for modification master_ttfs = master_ttfs[:] master_locs = [l.copy() for l in master_locs] axis_tags = axes.keys() # Normalize master locations. TODO Move to a separate function. for tag, (name, lower, default, upper) in axes.items(): for l in master_locs: v = l[tag] if v == default: v = 0 elif v < default: v = (v - default) / (default - lower) else: v = (v - default) / (upper - default) l[tag] = v # Locations are normalized now print("Normalized master positions:") print(master_locs) print("Generating gvar") assert "gvar" not in font gvar = font["gvar"] = table__g_v_a_r() gvar.version = 1 gvar.reserved = 0 gvar.variations = {} # Assume single-model for now. model = VariationModel(master_locs) model_base_idx = model.mapping[base_idx] assert 0 == model_base_idx for glyph in font.getGlyphOrder(): allData = [_GetCoordinates(m, glyph) for m in master_ttfs] allCoords = [d[0] for d in allData] allControls = [d[1] for d in allData] control = allControls[0] if (any(c != control for c in allControls)): warnings.warn("glyph %s has incompatible masters; skipping" % glyph) continue del allControls gvar.variations[glyph] = [] deltas = model.getDeltas(allCoords) supports = model.supports assert len(deltas) == len(supports) for i, (delta, support) in enumerate(zip(deltas, supports)): if i == model_base_idx: continue var = GlyphVariation(support, delta) gvar.variations[glyph].append(var)
def _add_gvar(font, axes, master_ttfs, master_locs, base_idx): # Make copies for modification master_ttfs = master_ttfs[:] master_locs = [l.copy() for l in master_locs] axis_tags = axes.keys() # Normalize master locations. TODO Move to a separate function. for tag,(name,lower,default,upper) in axes.items(): for l in master_locs: v = l[tag] if v == default: v = 0 elif v < default: v = (v - default) / (default - lower) else: v = (v - default) / (upper - default) l[tag] = v # Locations are normalized now print("Normalized master positions:") print(master_locs) print("Generating gvar") assert "gvar" not in font gvar = font["gvar"] = table__g_v_a_r() gvar.version = 1 gvar.reserved = 0 gvar.variations = {} # Assume single-model for now. model = VariationModel(master_locs) model_base_idx = model.mapping[base_idx] assert 0 == model_base_idx for glyph in font.getGlyphOrder(): allData = [_GetCoordinates(m, glyph) for m in master_ttfs] allCoords = [d[0] for d in allData] allControls = [d[1] for d in allData] control = allControls[0] if (any(c != control for c in allControls)): warnings.warn("glyph %s has incompatible masters; skipping" % glyph) continue del allControls gvar.variations[glyph] = [] deltas = model.getDeltas(allCoords) supports = model.supports assert len(deltas) == len(supports) for i,(delta,support) in enumerate(zip(deltas, supports)): if i == model_base_idx: continue var = GlyphVariation(support, delta) gvar.variations[glyph].append(var)
def test_compileGlyph_onlyRedundantVariations(self): table = table__g_v_a_r() axes = {"wght": (0.3, 0.4, 0.5), "opsz": (0.7, 0.8, 0.9)} table.variations = {"glyphname": [ GlyphVariation(axes, [None] * 4), GlyphVariation(axes, [None] * 4), GlyphVariation(axes, [None] * 4) ]} self.assertEqual(b"", table.compileGlyph_("glyphname", 8, ["wght", "opsz"], {}))
def test_compileGlyph_roundTrip(self): table = table__g_v_a_r() axisTags = ["wght", "wdth"] numPointsInGlyph = 4 glyphCoords = [(1,1), (2,2), (3,3), (4,4)] gvar1 = GlyphVariation({"wght": (0.5, 1.0, 1.0), "wdth": (1.0, 1.0, 1.0)}, glyphCoords) gvar2 = GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (1.0, 1.0, 1.0)}, glyphCoords) table.variations = {"oslash": [gvar1, gvar2]} data = table.compileGlyph_("oslash", numPointsInGlyph, axisTags, {}) self.assertEqual([gvar1, gvar2], table.decompileGlyph_(numPointsInGlyph, {}, axisTags, data))
def test_compileGlyph_onlyRedundantVariations(self): table = table__g_v_a_r() axes = {"wght": (0.3, 0.4, 0.5), "opsz": (0.7, 0.8, 0.9)} table.variations = { "glyphname": [ GlyphVariation(axes, [None] * 4), GlyphVariation(axes, [None] * 4), GlyphVariation(axes, [None] * 4) ] } self.assertEqual( b"", table.compileGlyph_("glyphname", 8, ["wght", "opsz"], {}))
def test_decompileGlyph_Skia_I(self): axes = ["wght", "wdth"] table = table__g_v_a_r() table.offsetToCoord = 0 table.sharedCoordCount = 8 table.axisCount = len(axes) sharedCoords = table.decompileSharedCoords_(axes, SKIA_SHARED_COORDS) tuples = table.decompileGlyph_(18, sharedCoords, axes, SKIA_GVAR_I) self.assertEqual(8, len(tuples)) self.assertEqual({"wght": (0.0, 1.0, 1.0)}, tuples[0].axes) self.assertEqual("257,0 -127,0 -128,58 -130,90 -130,62 -130,67 -130,32 -127,0 257,0 " "259,14 260,64 260,21 260,69 258,124 0,0 130,0 0,0 0,0", " ".join(["%d,%d" % c for c in tuples[0].coordinates]))
def test_decompileGlyph_Skia_I(self): axes = ["wght", "wdth"] table = table__g_v_a_r() table.offsetToCoord = 0 table.sharedCoordCount = 8 table.axisCount = len(axes) sharedCoords = table.decompileSharedCoords_(axes, SKIA_SHARED_COORDS) tuples = table.decompileGlyph_(18, sharedCoords, axes, SKIA_GVAR_I) self.assertEqual(8, len(tuples)) self.assertEqual({"wght": (0.0, 1.0, 1.0)}, tuples[0].axes) self.assertEqual( "257,0 -127,0 -128,58 -130,90 -130,62 -130,67 -130,32 -127,0 257,0 " "259,14 260,64 260,21 260,69 258,124 0,0 130,0 0,0 0,0", " ".join(["%d,%d" % c for c in tuples[0].coordinates]))
def test_decompileSharedCoords_Skia(self): table = table__g_v_a_r() table.offsetToCoord = 0 table.sharedCoordCount = 8 sharedCoords = table.decompileSharedCoords_(["wght", "wdth"], SKIA_SHARED_COORDS) self.assertEqual([ {"wght": 1.0, "wdth": 0.0}, {"wght": -1.0, "wdth": 0.0}, {"wght": 0.0, "wdth": 1.0}, {"wght": 0.0, "wdth": -1.0}, {"wght": -1.0, "wdth": -1.0}, {"wght": 1.0, "wdth": -1.0}, {"wght": 1.0, "wdth": 1.0}, {"wght": -1.0, "wdth": 1.0} ], sharedCoords)
def test_compileGlyph_roundTrip(self): table = table__g_v_a_r() axisTags = ["wght", "wdth"] numPointsInGlyph = 4 glyphCoords = [(1, 1), (2, 2), (3, 3), (4, 4)] gvar1 = GlyphVariation( { "wght": (0.5, 1.0, 1.0), "wdth": (1.0, 1.0, 1.0) }, glyphCoords) gvar2 = GlyphVariation( { "wght": (1.0, 1.0, 1.0), "wdth": (1.0, 1.0, 1.0) }, glyphCoords) table.variations = {"oslash": [gvar1, gvar2]} data = table.compileGlyph_("oslash", numPointsInGlyph, axisTags, {}) self.assertEqual([gvar1, gvar2], table.decompileGlyph_(numPointsInGlyph, {}, axisTags, data))
def test_compileSharedCoords(self): table = table__g_v_a_r() table.variations = {} deltas = [None] * 4 table.variations["A"] = [ GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.5, 0.7, 1.0)}, deltas) ] table.variations["B"] = [ GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.2, 0.7, 1.0)}, deltas), GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.2, 0.8, 1.0)}, deltas) ] table.variations["C"] = [ GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.7, 1.0)}, deltas), GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.8, 1.0)}, deltas), GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.9, 1.0)}, deltas) ] # {"wght":1.0, "wdth":0.7} is shared 3 times; {"wght":1.0, "wdth":0.8} is shared twice. # Min and max values are not part of the shared coordinate pool and should get ignored. result = table.compileSharedCoords_(["wght", "wdth"]) self.assertEqual(["40 00 2C CD", "40 00 33 33"], [hexencode(c) for c in result])
def test_compileSharedCoords(self): table = table__g_v_a_r() table.variations = {} deltas = [None] * 4 table.variations["A"] = [ GlyphVariation({ "wght": (1.0, 1.0, 1.0), "wdth": (0.5, 0.7, 1.0) }, deltas) ] table.variations["B"] = [ GlyphVariation({ "wght": (1.0, 1.0, 1.0), "wdth": (0.2, 0.7, 1.0) }, deltas), GlyphVariation({ "wght": (1.0, 1.0, 1.0), "wdth": (0.2, 0.8, 1.0) }, deltas) ] table.variations["C"] = [ GlyphVariation({ "wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.7, 1.0) }, deltas), GlyphVariation({ "wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.8, 1.0) }, deltas), GlyphVariation({ "wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.9, 1.0) }, deltas) ] # {"wght":1.0, "wdth":0.7} is shared 3 times; {"wght":1.0, "wdth":0.8} is shared twice. # Min and max values are not part of the shared coordinate pool and should get ignored. result = table.compileSharedCoords_(["wght", "wdth"]) self.assertEqual(["40 00 2C CD", "40 00 33 33"], [hexencode(c) for c in result])
def test_compileSharedCoords(self): class FakeFont: def getGlyphOrder(self): return ["A", "B", "C"] font = FakeFont() table = table__g_v_a_r() table.variations = {} table.variations["A"] = [ GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.5, 0.7, 1.0)}, GlyphCoordinates.zeros(4)) ] table.variations["B"] = [ GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.2, 0.7, 1.0)}, GlyphCoordinates.zeros(4)), GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.2, 0.8, 1.0)}, GlyphCoordinates.zeros(4)) ] table.variations["C"] = [ GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.7, 1.0)}, GlyphCoordinates.zeros(4)), GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.8, 1.0)}, GlyphCoordinates.zeros(4)), GlyphVariation({"wght": (1.0, 1.0, 1.0), "wdth": (0.3, 0.9, 1.0)}, GlyphCoordinates.zeros(4)) ] # {"wght":1.0, "wdth":0.7} is shared 3 times; {"wght":1.0, "wdth":0.8} is shared twice. # Min and max values are not part of the shared coordinate pool and should get ignored. result = table.compileSharedCoords_(font, ["wght", "wdth"]) self.assertEqual(["40 00 2C CD", "40 00 33 33"], [hexencode(c) for c in result])
def test_decompileSharedCoords_empty(self): table = table__g_v_a_r() table.offsetToCoord = 0 table.sharedCoordCount = 0 self.assertEqual([], table.decompileSharedCoords_(["wght"], b""))
def test_compileGlyph_emptyVariations(self): table = table__g_v_a_r() table.variations = {"glyphname": []} self.assertEqual(b"", table.compileGlyph_("glyphname", 8, ["wght", "opsz"], {}))
def test_compileGlyph_emptyVariations(self): table = table__g_v_a_r() table.variations = {"glyphname": []} self.assertEqual( b"", table.compileGlyph_("glyphname", 8, ["wght", "opsz"], {}))