Example #1
0
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 = 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 test_decompileCoord_roundTrip(self):
		# Make sure we are not affected by https://github.com/behdad/fonttools/issues/286
		data = deHexStr("7F B9 80 35")
		values, _ = GlyphVariation.decompileCoord_(["wght", "wdth"], data, 0)
		axisValues = {axis:(val, val, val) for axis, val in  values.items()}
		gvar = GlyphVariation(axisValues, [None] * 4)
		self.assertEqual("7F B9 80 35", hexencode(gvar.compileCoord(["wght", "wdth"])))
Example #3
0
 def test_decompileCoord_roundTrip(self):
     # Make sure we are not affected by https://github.com/behdad/fonttools/issues/286
     data = deHexStr("7F B9 80 35")
     values, _ = GlyphVariation.decompileCoord_(["wght", "wdth"], data, 0)
     axisValues = {axis: (val, val, val) for axis, val in values.items()}
     gvar = GlyphVariation(axisValues, [None] * 4)
     self.assertEqual("7F B9 80 35",
                      hexencode(gvar.compileCoord(["wght", "wdth"])))
Example #4
0
 def test_toXML_allDeltasNone(self):
     writer = XMLWriter(BytesIO())
     axes = {"wght": (0.0, 1.0, 1.0)}
     g = GlyphVariation(axes, [None] * 5)
     g.toXML(writer, ["wght", "wdth"])
     self.assertEqual([
         '<tuple>', '<coord axis="wght" value="1.0"/>',
         '<!-- no deltas -->', '</tuple>'
     ], GlyphVariationTest.xml_lines(writer))
	def test_decompilePoints_roundTrip(self):
		numPointsInGlyph = 500  # greater than 255, so we also exercise code path for 16-bit encoding
		compile = lambda points: GlyphVariation.compilePoints(points, numPointsInGlyph)
		decompile = lambda data: set(GlyphVariation.decompilePoints_(numPointsInGlyph, data, 0)[0])
		for i in range(50):
			points = set(random.sample(range(numPointsInGlyph), 30))
			self.assertSetEqual(points, decompile(compile(points)),
					    "failed round-trip decompile/compilePoints; points=%s" % points)
		allPoints = set(range(numPointsInGlyph))
		self.assertSetEqual(allPoints, decompile(compile(allPoints)))
	def test_toXML_allDeltasNone(self):
		writer = XMLWriter(BytesIO())
		axes = {"wght":(0.0, 1.0, 1.0)}
		g = GlyphVariation(axes, [None] * 5)
		g.toXML(writer, ["wght", "wdth"])
		self.assertEqual([
			'<tuple>',
			  '<coord axis="wght" value="1.0"/>',
			  '<!-- no deltas -->',
			'</tuple>'
		], GlyphVariationTest.xml_lines(writer))
Example #7
0
 def test_compileCoord(self):
     gvar = GlyphVariation(
         {
             "wght": (-1.0, -1.0, -1.0),
             "wdth": (0.4, 0.5, 0.6)
         }, [None] * 4)
     self.assertEqual("C0 00 20 00",
                      hexencode(gvar.compileCoord(["wght", "wdth"])))
     self.assertEqual("20 00 C0 00",
                      hexencode(gvar.compileCoord(["wdth", "wght"])))
     self.assertEqual("C0 00", hexencode(gvar.compileCoord(["wght"])))
	def test_compile_embeddedCoords_intermediate_sharedPoints(self):
		gvar = GlyphVariation({"wght": (0.0, 0.5, 1.0), "wdth": (0.0, 0.8, 0.8)},
				      [(7,4), (8,5), (9,6)])
		axisTags = ["wght", "wdth"]
		tuple, data = gvar.compile(axisTags, sharedCoordIndices={}, sharedPoints={0,1,2})
		# len(data)=8; flags=EMBEDDED_TUPLE_COORD
		# embeddedCoord=[(0.5, 0.8)]; intermediateCoord=[(0.0, 0.0), (1.0, 0.8)]
		self.assertEqual("00 08 C0 00 20 00 33 33 00 00 00 00 40 00 33 33", hexencode(tuple))
		self.assertEqual("02 07 08 09 "     # deltaX: [7, 8, 9]
				 "02 04 05 06",     # deltaY: [4, 5, 6]
				 hexencode(data))
Example #9
0
	def test_toXML_allDeltasZero(self):
		writer = XMLWriter(StringIO())
		axes = {"wght":(0.0, 1.0, 1.0)}
		g = GlyphVariation(axes, GlyphCoordinates.zeros(5))
		g.toXML(writer, ["wght", "wdth"])
		self.assertEqual([
			'<tuple>',
			  '<coord axis="wght" value="1.0"/>',
			  '<!-- all deltas are (0,0) -->',
			'</tuple>'
		], GlyphVariationTest.xml_lines(writer))
	def test_compile_sharedCoords_nonIntermediate_sharedPoints(self):
		gvar = GlyphVariation({"wght": (0.0, 0.5, 0.5), "wdth": (0.0, 0.8, 0.8)},
				      [(7,4), (8,5), (9,6)])
		axisTags = ["wght", "wdth"]
		sharedCoordIndices = { gvar.compileCoord(axisTags): 0x77 }
		tuple, data = gvar.compile(axisTags, sharedCoordIndices, sharedPoints={0,1,2})
		# len(data)=8; flags=None; tupleIndex=0x77
		# embeddedCoord=[]; intermediateCoord=[]
		self.assertEqual("00 08 00 77", hexencode(tuple))
		self.assertEqual("02 07 08 09 "     # deltaX: [7, 8, 9]
				 "02 04 05 06",     # deltaY: [4, 5, 6]
				 hexencode(data))
	def test_compile_sharedCoords_intermediate_sharedPoints(self):
		gvar = GlyphVariation({"wght": (0.3, 0.5, 0.7), "wdth": (0.1, 0.8, 0.9)},
				      [(7,4), (8,5), (9,6)])
		axisTags = ["wght", "wdth"]
		sharedCoordIndices = { gvar.compileCoord(axisTags): 0x77 }
		tuple, data = gvar.compile(axisTags, sharedCoordIndices, sharedPoints={0,1,2})
		# len(data)=8; flags=INTERMEDIATE_TUPLE; tupleIndex=0x77
		# embeddedCoord=[]; intermediateCoord=[(0.3, 0.1), (0.7, 0.9)]
		self.assertEqual("00 08 40 77 13 33 06 66 2C CD 39 9A", hexencode(tuple))
		self.assertEqual("02 07 08 09 "     # deltaX: [7, 8, 9]
				 "02 04 05 06",     # deltaY: [4, 5, 6]
				 hexencode(data))
	def test_compile_embeddedCoords_intermediate_privatePoints(self):
		gvar = GlyphVariation({"wght": (0.4, 0.5, 0.6), "wdth": (0.7, 0.8, 0.9)},
				      [(7,4), (8,5), (9,6)])
		axisTags = ["wght", "wdth"]
		tuple, data = gvar.compile(axisTags, sharedCoordIndices={}, sharedPoints=None)
		# len(data)=13; flags=PRIVATE_POINT_NUMBERS|INTERMEDIATE_TUPLE|EMBEDDED_TUPLE_COORD
		# embeddedCoord=(0.5, 0.8); intermediateCoord=[(0.4, 0.7), (0.6, 0.9)]
		self.assertEqual("00 09 E0 00 20 00 33 33 19 9A 2C CD 26 66 39 9A", hexencode(tuple))
		self.assertEqual("00 "              # all points in glyph
				 "02 07 08 09 "     # deltaX: [7, 8, 9]
				 "02 04 05 06",     # deltaY: [4, 5, 6]
				 hexencode(data))
Example #13
0
	def test_compile_embeddedCoords_nonIntermediate_privatePoints(self):
		gvar = GlyphVariation({"wght": (0.0, 0.5, 0.5), "wdth": (0.0, 0.8, 0.8)},
				      GlyphCoordinates([(7,4), (8,5), (9,6)]))
		axisTags = ["wght", "wdth"]
		tuple, data = gvar.compile(axisTags, sharedCoordIndices={}, sharedPoints=None)
		# len(data)=13; flags=PRIVATE_POINT_NUMBERS|EMBEDDED_TUPLE_COORD
		# embeddedCoord=[(0.5, 0.8)]; intermediateCoord=[]
		self.assertEqual("00 0D A0 00 20 00 33 33", hexencode(tuple))
		self.assertEqual("03 02 00 01 01 "  # 3 points: [0, 1, 2]
				 "02 07 08 09 "     # deltaX: [7, 8, 9]
				 "02 04 05 06",     # deltaY: [4, 5, 6]
				 hexencode(data))
Example #14
0
 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_compile_sharedCoords_intermediate_privatePoints(self):
		gvar = GlyphVariation({"wght": (0.0, 0.5, 1.0), "wdth": (0.0, 0.8, 1.0)},
				      [(7,4), (8,5), (9,6)])
		axisTags = ["wght", "wdth"]
		sharedCoordIndices = { gvar.compileCoord(axisTags): 0x77 }
		tuple, data = gvar.compile(axisTags, sharedCoordIndices, sharedPoints=None)
		# len(data)=13; flags=PRIVATE_POINT_NUMBERS; tupleIndex=0x77
		# embeddedCoord=[]; intermediateCoord=[(0.0, 0.0), (1.0, 1.0)]
		self.assertEqual("00 09 60 77 00 00 00 00 40 00 40 00", hexencode(tuple))
		self.assertEqual("00 "              # all points in glyph
				 "02 07 08 09 "     # deltaX: [7, 8, 9]
				 "02 04 05 06",     # deltaY: [4, 5, 6]
				 hexencode(data))
Example #16
0
 def test_decompilePoints_roundTrip(self):
     numPointsInGlyph = 500  # greater than 255, so we also exercise code path for 16-bit encoding
     compile = lambda points: GlyphVariation.compilePoints(
         points, numPointsInGlyph)
     decompile = lambda data: set(
         GlyphVariation.decompilePoints_(numPointsInGlyph, data, 0)[0])
     for i in range(50):
         points = set(random.sample(range(numPointsInGlyph), 30))
         self.assertSetEqual(
             points, decompile(compile(points)),
             "failed round-trip decompile/compilePoints; points=%s" %
             points)
     allPoints = set(range(numPointsInGlyph))
     self.assertSetEqual(allPoints, decompile(compile(allPoints)))
Example #17
0
	def test_toXML(self):
		writer = XMLWriter(StringIO())
		axes = {"wdth":(0.3, 0.4, 0.5), "wght":(0.0, 1.0, 1.0), "opsz":(-0.7, -0.7, 0.0)}
		g = GlyphVariation(axes, GlyphCoordinates([(9,8), (7,6), (0,0), (-1,-2)]))
		g.toXML(writer, ["wdth", "wght", "opsz"])
		self.assertEqual([
			'<tuple>',
			  '<coord axis="wdth" max="0.5" min="0.3" value="0.4"/>',
			  '<coord axis="wght" value="1.0"/>',
			  '<coord axis="opsz" value="-0.7"/>',
			  '<delta pt="0" x="9" y="8"/>',
			  '<delta pt="1" x="7" y="6"/>',
			  '<delta pt="3" x="-1" y="-2"/>',
			'</tuple>'
		], GlyphVariationTest.xml_lines(writer))
	def test_fromXML(self):
		g = GlyphVariation({}, [None] * 4)
		for name, attrs, content in parseXML(
				'<coord axis="wdth" min="0.3" value="0.4" max="0.5"/>'
				'<coord axis="wght" value="1.0"/>'
				'<coord axis="opsz" value="-0.5"/>'
				'<delta pt="1" x="33" y="44"/>'
				'<delta pt="2" x="-2" y="170"/>'):
			g.fromXML(name, attrs, content)
		self.assertEqual({
			"wdth":( 0.3,  0.4, 0.5),
			"wght":( 0.0,  1.0, 1.0),
			"opsz":(-0.5, -0.5, 0.0)
		}, g.axes)
		self.assertEqual([None, (33, 44), (-2, 170), None], g.coordinates)
Example #19
0
def _add_gvar(font, model, master_ttfs):

    print("Generating gvar")
    assert "gvar" not in font
    gvar = font["gvar"] = newTable('gvar')
    gvar.version = 1
    gvar.reserved = 0
    gvar.variations = {}

    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

        # Update gvar
        gvar.variations[glyph] = []
        deltas = model.getDeltas(allCoords)
        supports = model.supports
        assert len(deltas) == len(supports)
        for i, (delta, support) in enumerate(zip(deltas[1:], supports[1:])):
            var = GlyphVariation(support, delta)
            gvar.variations[glyph].append(var)
Example #20
0
 def test_fromXML(self):
     g = GlyphVariation({}, [None] * 4)
     for name, attrs, content in parseXML(
             '<coord axis="wdth" min="0.3" value="0.4" max="0.5"/>'
             '<coord axis="wght" value="1.0"/>'
             '<coord axis="opsz" value="-0.5"/>'
             '<delta pt="1" x="33" y="44"/>'
             '<delta pt="2" x="-2" y="170"/>'):
         g.fromXML(name, attrs, content)
     self.assertEqual(
         {
             "wdth": (0.3, 0.4, 0.5),
             "wght": (0.0, 1.0, 1.0),
             "opsz": (-0.5, -0.5, 0.0)
         }, g.axes)
     self.assertEqual([None, (33, 44), (-2, 170), None], g.coordinates)
Example #21
0
 def test_compilePoints(self):
     compilePoints = lambda p: GlyphVariation.compilePoints(
         set(p), numPointsInGlyph=999)
     self.assertEqual("00", hexencode(compilePoints(
         range(999))))  # all points in glyph
     self.assertEqual("01 00 07", hexencode(compilePoints([7])))
     self.assertEqual("01 80 FF FF", hexencode(compilePoints([65535])))
     self.assertEqual("02 01 09 06", hexencode(compilePoints([9, 15])))
     self.assertEqual("06 05 07 01 F7 02 01 F2",
                      hexencode(compilePoints([7, 8, 255, 257, 258, 500])))
     self.assertEqual("03 01 07 01 80 01 EC",
                      hexencode(compilePoints([7, 8, 500])))
     self.assertEqual("04 01 07 01 81 BE E7 0C 0F",
                      hexencode(compilePoints([7, 8, 0xBEEF, 0xCAFE])))
     self.maxDiff = None
     self.assertEqual(
         "81 2C" +  # 300 points (0x12c) in total
         " 7F 00" +
         (127 * " 01") +  # first run, contains 128 points: [0 .. 127]
         " 7F" +
         (128 * " 01") +  # second run, contains 128 points: [128 .. 255]
         " 2B" +
         (44 * " 01"),  # third run, contains 44 points: [256 .. 299]
         hexencode(compilePoints(range(300))))
     self.assertEqual(
         "81 8F" +  # 399 points (0x18f) in total
         " 7F 00" +
         (127 * " 01") +  # first run, contains 128 points: [0 .. 127]
         " 7F" +
         (128 * " 01") +  # second run, contains 128 points: [128 .. 255]
         " 7F" +
         (128 * " 01") +  # third run, contains 128 points: [256 .. 383]
         " 0E" +
         (15 * " 01"),  # fourth run, contains 15 points: [384 .. 398]
         hexencode(compilePoints(range(399))))
Example #22
0
 def test_compile_embeddedCoords_nonIntermediate_sharedPoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 0.5),
             "wdth": (0.0, 0.8, 0.8)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices={},
                                sharedPoints={0, 1, 2})
     # len(data)=8; flags=EMBEDDED_TUPLE_COORD
     # embeddedCoord=[(0.5, 0.8)]; intermediateCoord=[]
     self.assertEqual("00 08 80 00 20 00 33 33", hexencode(tuple))
     self.assertEqual(
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Example #23
0
 def test_toXML(self):
     writer = XMLWriter(BytesIO())
     axes = {
         "wdth": (0.3, 0.4, 0.5),
         "wght": (0.0, 1.0, 1.0),
         "opsz": (-0.7, -0.7, 0.0)
     }
     g = GlyphVariation(axes, [(9, 8), None, (7, 6), (0, 0),
                               (-1, -2), None])
     g.toXML(writer, ["wdth", "wght", "opsz"])
     self.assertEqual([
         '<tuple>', '<coord axis="wdth" max="0.5" min="0.3" value="0.4"/>',
         '<coord axis="wght" value="1.0"/>',
         '<coord axis="opsz" value="-0.7"/>', '<delta pt="0" x="9" y="8"/>',
         '<delta pt="2" x="7" y="6"/>', '<delta pt="3" x="0" y="0"/>',
         '<delta pt="4" x="-1" y="-2"/>', '</tuple>'
     ], GlyphVariationTest.xml_lines(writer))
Example #24
0
 def test_compileDeltaValues(self):
     compileDeltaValues = lambda values: hexencode(
         GlyphVariation.compileDeltaValues_(values))
     # zeroes
     self.assertEqual("80", compileDeltaValues([0]))
     self.assertEqual("BF", compileDeltaValues([0] * 64))
     self.assertEqual("BF 80", compileDeltaValues([0] * 65))
     self.assertEqual("BF A3", compileDeltaValues([0] * 100))
     self.assertEqual("BF BF BF BF", compileDeltaValues([0] * 256))
     # bytes
     self.assertEqual("00 01", compileDeltaValues([1]))
     self.assertEqual("06 01 02 03 7F 80 FF FE",
                      compileDeltaValues([1, 2, 3, 127, -128, -1, -2]))
     self.assertEqual("3F" + (64 * " 7F"), compileDeltaValues([127] * 64))
     self.assertEqual("3F" + (64 * " 7F") + " 00 7F",
                      compileDeltaValues([127] * 65))
     # words
     self.assertEqual("40 66 66", compileDeltaValues([0x6666]))
     self.assertEqual("43 66 66 7F FF FF FF 80 00",
                      compileDeltaValues([0x6666, 32767, -1, -32768]))
     self.assertEqual("7F" + (64 * " 11 22"),
                      compileDeltaValues([0x1122] * 64))
     self.assertEqual("7F" + (64 * " 11 22") + " 40 11 22",
                      compileDeltaValues([0x1122] * 65))
     # bytes, zeroes, bytes: a single zero is more compact when encoded as part of the bytes run
     self.assertEqual("04 7F 7F 00 7F 7F",
                      compileDeltaValues([127, 127, 0, 127, 127]))
     self.assertEqual("01 7F 7F 81 01 7F 7F",
                      compileDeltaValues([127, 127, 0, 0, 127, 127]))
     self.assertEqual("01 7F 7F 82 01 7F 7F",
                      compileDeltaValues([127, 127, 0, 0, 0, 127, 127]))
     self.assertEqual("01 7F 7F 83 01 7F 7F",
                      compileDeltaValues([127, 127, 0, 0, 0, 0, 127, 127]))
     # bytes, zeroes
     self.assertEqual("01 01 00", compileDeltaValues([1, 0]))
     self.assertEqual("00 01 81", compileDeltaValues([1, 0, 0]))
     # words, bytes, words: a single byte is more compact when encoded as part of the words run
     self.assertEqual("42 66 66 00 02 77 77",
                      compileDeltaValues([0x6666, 2, 0x7777]))
     self.assertEqual("40 66 66 01 02 02 40 77 77",
                      compileDeltaValues([0x6666, 2, 2, 0x7777]))
     # words, zeroes, words
     self.assertEqual("40 66 66 80 40 77 77",
                      compileDeltaValues([0x6666, 0, 0x7777]))
     self.assertEqual("40 66 66 81 40 77 77",
                      compileDeltaValues([0x6666, 0, 0, 0x7777]))
     self.assertEqual("40 66 66 82 40 77 77",
                      compileDeltaValues([0x6666, 0, 0, 0, 0x7777]))
     # words, zeroes, bytes
     self.assertEqual("40 66 66 80 02 01 02 03",
                      compileDeltaValues([0x6666, 0, 1, 2, 3]))
     self.assertEqual("40 66 66 81 02 01 02 03",
                      compileDeltaValues([0x6666, 0, 0, 1, 2, 3]))
     self.assertEqual("40 66 66 82 02 01 02 03",
                      compileDeltaValues([0x6666, 0, 0, 0, 1, 2, 3]))
     # words, zeroes
     self.assertEqual("40 66 66 80", compileDeltaValues([0x6666, 0]))
     self.assertEqual("40 66 66 81", compileDeltaValues([0x6666, 0, 0]))
Example #25
0
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)
Example #26
0
 def test_compile_embeddedCoords_nonIntermediate_privatePoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 0.5),
             "wdth": (0.0, 0.8, 0.8)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices={},
                                sharedPoints=None)
     # len(data)=13; flags=PRIVATE_POINT_NUMBERS|EMBEDDED_TUPLE_COORD
     # embeddedCoord=[(0.5, 0.8)]; intermediateCoord=[]
     self.assertEqual("00 09 A0 00 20 00 33 33", hexencode(tuple))
     self.assertEqual(
         "00 "  # all points in glyph
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Example #27
0
 def test_compile_sharedCoords_nonIntermediate_sharedPoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 0.5),
             "wdth": (0.0, 0.8, 0.8)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     sharedCoordIndices = {gvar.compileCoord(axisTags): 0x77}
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices,
                                sharedPoints={0, 1, 2})
     # len(data)=8; flags=None; tupleIndex=0x77
     # embeddedCoord=[]; intermediateCoord=[]
     self.assertEqual("00 08 00 77", hexencode(tuple))
     self.assertEqual(
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Example #28
0
 def test_fromXML(self):
     g = GlyphVariation({}, [None] * 4)
     g.fromXML("coord", {
         "axis": "wdth",
         "min": "0.3",
         "value": "0.4",
         "max": "0.5"
     }, [])
     g.fromXML("coord", {"axis": "wght", "value": "1.0"}, [])
     g.fromXML("coord", {"axis": "opsz", "value": "-0.5"}, [])
     g.fromXML("delta", {"pt": "1", "x": "33", "y": "44"}, [])
     g.fromXML("delta", {"pt": "2", "x": "-2", "y": "170"}, [])
     self.assertEqual(
         {
             "wdth": (0.3, 0.4, 0.5),
             "wght": (0.0, 1.0, 1.0),
             "opsz": (-0.5, -0.5, 0.0)
         }, g.axes)
     self.assertEqual([None, (33, 44), (-2, 170), None], g.coordinates)
Example #29
0
 def test_compile_sharedCoords_intermediate_sharedPoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.3, 0.5, 0.7),
             "wdth": (0.1, 0.8, 0.9)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     sharedCoordIndices = {gvar.compileCoord(axisTags): 0x77}
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices,
                                sharedPoints={0, 1, 2})
     # len(data)=8; flags=INTERMEDIATE_TUPLE; tupleIndex=0x77
     # embeddedCoord=[]; intermediateCoord=[(0.3, 0.1), (0.7, 0.9)]
     self.assertEqual("00 08 40 77 13 33 06 66 2C CD 39 9A",
                      hexencode(tuple))
     self.assertEqual(
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
	def test_decompileDeltas_roundTrip(self):
		numDeltas = 30
		compile = GlyphVariation.compileDeltaValues_
		decompile = lambda data: GlyphVariation.decompileDeltas_(numDeltas, data, 0)[0]
		for i in range(50):
			deltas = random.sample(range(-128, 127), 10)
			deltas.extend(random.sample(range(-32768, 32767), 10))
			deltas.extend([0] * 10)
			random.shuffle(deltas)
			self.assertListEqual(deltas, decompile(compile(deltas)))
Example #31
0
 def test_decompileDeltas_roundTrip(self):
     numDeltas = 30
     compile = GlyphVariation.compileDeltaValues_
     decompile = lambda data: GlyphVariation.decompileDeltas_(
         numDeltas, data, 0)[0]
     for i in range(50):
         deltas = random.sample(range(-128, 127), 10)
         deltas.extend(random.sample(range(-32768, 32767), 10))
         deltas.extend([0] * 10)
         random.shuffle(deltas)
         self.assertListEqual(deltas, decompile(compile(deltas)))
Example #32
0
 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))
Example #33
0
 def test_compile_sharedCoords_intermediate_privatePoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 1.0),
             "wdth": (0.0, 0.8, 1.0)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     sharedCoordIndices = {gvar.compileCoord(axisTags): 0x77}
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices,
                                sharedPoints=None)
     # len(data)=13; flags=PRIVATE_POINT_NUMBERS; tupleIndex=0x77
     # embeddedCoord=[]; intermediateCoord=[(0.0, 0.0), (1.0, 1.0)]
     self.assertEqual("00 09 60 77 00 00 00 00 40 00 40 00",
                      hexencode(tuple))
     self.assertEqual(
         "00 "  # all points in glyph
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Example #34
0
	def test_decompilePoints_roundTrip(self):
		numPointsInGlyph = 500  # greater than 255, so we also exercise code path for 16-bit encoding
		compile = GlyphVariation.compilePoints
		decompile = lambda data: set(GlyphVariation.decompilePoints_(numPointsInGlyph, data, 0)[0])
		for i in range(50):
			points = set(random.sample(range(numPointsInGlyph), 30))
			if hasattr(self, "assertSetEqual"):
				# Python 2.7 and later
				self.assertSetEqual(points, decompile(compile(points)),
						    "failed round-trip decompile/compilePoints; points=%s" % points)
			else:
				self.assertEqual(points, decompile(compile(points)),
						 "failed round-trip decompile/compilePoints; points=%s" % points)
Example #35
0
	def test_decompileDeltas_roundTrip(self):
		numDeltas = 30
		compile = GlyphVariation.compileDeltaValues_
		decompile = lambda data: GlyphVariation.decompileDeltas_(numDeltas, data, 0)[0]
		for i in range(50):
			deltas = random.sample(range(-128, 127), 10)
			deltas.extend(random.sample(range(-32768, 32767), 10))
			deltas.extend([0] * 10)
			random.shuffle(deltas)
			if hasattr(self, "assertListEqual"):
				# Python 2.7 and later
				self.assertListEqual(deltas, decompile(compile(deltas)),
						     "failed round-trip decompile/compileDeltas; deltas=%s" % deltas)
			else:
				# Python 2.6
				self.assertEqual(deltas, decompile(compile(deltas)),
						 "failed round-trip decompile/compileDeltas; deltas=%s" % deltas)
Example #36
0
	def test_compilePoints(self):
		compilePoints = lambda p: GlyphVariation.compilePoints(set(p), numPointsInGlyph=999)
		self.assertEqual("00", hexencode(compilePoints(range(999))))  # all points in glyph
		self.assertEqual("01 00 07", hexencode(compilePoints([7])))
		self.assertEqual("01 80 FF FF", hexencode(compilePoints([65535])))
		self.assertEqual("02 01 09 06", hexencode(compilePoints([9, 15])))
		self.assertEqual("06 05 07 01 F7 02 01 F2", hexencode(compilePoints([7, 8, 255, 257, 258, 500])))
		self.assertEqual("03 01 07 01 80 01 F4", hexencode(compilePoints([7, 8, 500])))
		self.assertEqual("04 01 07 01 81 BE EF 0C 0F", hexencode(compilePoints([7, 8, 0xBEEF, 0xCAFE])))
		self.assertEqual("81 2C" +  # 300 points (0x12c) in total
				 " 7F 00" + (127 * " 01") +  # first run, contains 128 points: [0 .. 127]
				 " 7F 80" + (127 * " 01") +  # second run, contains 128 points: [128 .. 255]
				 " AB 01 00" + (43 * " 00 01"),  # third run, contains 44 points: [256 .. 299]
				 hexencode(compilePoints(range(300))))
		self.assertEqual("81 8F" +  # 399 points (0x18f) in total
				 " 7F 00" + (127 * " 01") +  # first run, contains 128 points: [0 .. 127]
				 " 7F 80" + (127 * " 01") +  # second run, contains 128 points: [128 .. 255]
				 " FF 01 00" + (127 * " 00 01") +  # third run, contains 128 points: [256 .. 383]
				 " 8E 01 80" + (14 * " 00 01"),  # fourth run, contains 15 points: [384 .. 398]
				 hexencode(compilePoints(range(399))))
Example #37
0
 def test_compileIntermediateCoord(self):
     gvar = GlyphVariation(
         {
             "wght": (-1.0, -1.0, 0.0),
             "wdth": (0.4, 0.5, 0.6)
         }, [None] * 4)
     self.assertEqual(
         "C0 00 19 9A 00 00 26 66",
         hexencode(gvar.compileIntermediateCoord(["wght", "wdth"])))
     self.assertEqual(
         "19 9A C0 00 26 66 00 00",
         hexencode(gvar.compileIntermediateCoord(["wdth", "wght"])))
     self.assertEqual(None, gvar.compileIntermediateCoord(["wght"]))
     self.assertEqual("19 9A 26 66",
                      hexencode(gvar.compileIntermediateCoord(["wdth"])))
	def test_compileDeltaValues(self):
		compileDeltaValues = lambda values: hexencode(GlyphVariation.compileDeltaValues_(values))
		# zeroes
		self.assertEqual("80", compileDeltaValues([0]))
		self.assertEqual("BF", compileDeltaValues([0] * 64))
		self.assertEqual("BF 80", compileDeltaValues([0] * 65))
		self.assertEqual("BF A3", compileDeltaValues([0] * 100))
		self.assertEqual("BF BF BF BF", compileDeltaValues([0] * 256))
		# bytes
		self.assertEqual("00 01", compileDeltaValues([1]))
		self.assertEqual("06 01 02 03 7F 80 FF FE", compileDeltaValues([1, 2, 3, 127, -128, -1, -2]))
		self.assertEqual("3F" + (64 * " 7F"), compileDeltaValues([127] * 64))
		self.assertEqual("3F" + (64 * " 7F") + " 00 7F", compileDeltaValues([127] * 65))
		# words
		self.assertEqual("40 66 66", compileDeltaValues([0x6666]))
		self.assertEqual("43 66 66 7F FF FF FF 80 00", compileDeltaValues([0x6666, 32767, -1, -32768]))
		self.assertEqual("7F" + (64 * " 11 22"), compileDeltaValues([0x1122] * 64))
		self.assertEqual("7F" + (64 * " 11 22") + " 40 11 22", compileDeltaValues([0x1122] * 65))
		# bytes, zeroes, bytes: a single zero is more compact when encoded as part of the bytes run
		self.assertEqual("04 7F 7F 00 7F 7F", compileDeltaValues([127, 127, 0, 127, 127]))
		self.assertEqual("01 7F 7F 81 01 7F 7F", compileDeltaValues([127, 127, 0, 0, 127, 127]))
		self.assertEqual("01 7F 7F 82 01 7F 7F", compileDeltaValues([127, 127, 0, 0, 0, 127, 127]))
		self.assertEqual("01 7F 7F 83 01 7F 7F", compileDeltaValues([127, 127, 0, 0, 0, 0, 127, 127]))
		# bytes, zeroes
		self.assertEqual("01 01 00", compileDeltaValues([1, 0]))
		self.assertEqual("00 01 81", compileDeltaValues([1, 0, 0]))
		# words, bytes, words: a single byte is more compact when encoded as part of the words run
		self.assertEqual("42 66 66 00 02 77 77", compileDeltaValues([0x6666, 2, 0x7777]))
		self.assertEqual("40 66 66 01 02 02 40 77 77", compileDeltaValues([0x6666, 2, 2, 0x7777]))
		# words, zeroes, words
		self.assertEqual("40 66 66 80 40 77 77", compileDeltaValues([0x6666, 0, 0x7777]))
		self.assertEqual("40 66 66 81 40 77 77", compileDeltaValues([0x6666, 0, 0, 0x7777]))
		self.assertEqual("40 66 66 82 40 77 77", compileDeltaValues([0x6666, 0, 0, 0, 0x7777]))
		# words, zeroes, bytes
		self.assertEqual("40 66 66 80 02 01 02 03", compileDeltaValues([0x6666, 0, 1, 2, 3]))
		self.assertEqual("40 66 66 81 02 01 02 03", compileDeltaValues([0x6666, 0, 0, 1, 2, 3]))
		self.assertEqual("40 66 66 82 02 01 02 03", compileDeltaValues([0x6666, 0, 0, 0, 1, 2, 3]))
		# words, zeroes
		self.assertEqual("40 66 66 80", compileDeltaValues([0x6666, 0]))
		self.assertEqual("40 66 66 81", compileDeltaValues([0x6666, 0, 0]))
Example #39
0
 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])
Example #40
0
	def test_fromXML(self):
		g = GlyphVariation({}, GlyphCoordinates.zeros(4))
		g.fromXML("coord", {"axis":"wdth", "min":"0.3", "value":"0.4", "max":"0.5"}, [])
		g.fromXML("coord", {"axis":"wght", "value":"1.0"}, [])
		g.fromXML("coord", {"axis":"opsz", "value":"-0.5"}, [])
		g.fromXML("delta", {"pt":"1", "x":"33", "y":"44"}, [])
		g.fromXML("delta", {"pt":"2", "x":"-2", "y":"170"}, [])
		self.assertEqual({
			"wdth":( 0.3,  0.4, 0.5),
			"wght":( 0.0,  1.0, 1.0),
			"opsz":(-0.5, -0.5, 0.0)
		}, g.axes)
		self.assertEqual("0,0 33,44 -2,170 0,0", " ".join(["%d,%d" % c for c in g.coordinates]))
	def test_compileCoord(self):
		gvar = GlyphVariation({"wght": (-1.0, -1.0, -1.0), "wdth": (0.4, 0.5, 0.6)}, [None] * 4)
		self.assertEqual("C0 00 20 00", hexencode(gvar.compileCoord(["wght", "wdth"])))
		self.assertEqual("20 00 C0 00", hexencode(gvar.compileCoord(["wdth", "wght"])))
		self.assertEqual("C0 00", hexencode(gvar.compileCoord(["wght"])))
	def test_hasImpact_someDeltasNotZero(self):
		axes = {"wght":(0.0, 1.0, 1.0)}
		gvar = GlyphVariation(axes, [(0,0), (9,8), (7,6)])
		self.assertTrue(gvar.hasImpact())
Example #43
0
 def test_hasImpact_allDeltasZero(self):
     axes = {"wght": (0.0, 1.0, 1.0)}
     gvar = GlyphVariation(axes, [(0, 0), (0, 0), (0, 0)])
     self.assertTrue(gvar.hasImpact())
Example #44
0
 def test_hasImpact_allDeltasNone(self):
     axes = {"wght": (0.0, 1.0, 1.0)}
     gvar = GlyphVariation(axes, [None, None, None])
     self.assertFalse(gvar.hasImpact())
Example #45
0
 def test_compileDeltas(self):
     gvar = GlyphVariation({}, [(0, 0), (1, 0), (2, 0), (3, 3)])
     points = {1, 2}
     # deltaX for points: [1, 2]; deltaY for points: [0, 0]
     self.assertEqual("01 01 02 81", hexencode(gvar.compileDeltas(points)))
Example #46
0
	def test_fromXML(self):
		g = GlyphVariation({}, [None] * 4)
		g.fromXML("coord", {"axis":"wdth", "min":"0.3", "value":"0.4", "max":"0.5"}, [])
		g.fromXML("coord", {"axis":"wght", "value":"1.0"}, [])
		g.fromXML("coord", {"axis":"opsz", "value":"-0.5"}, [])
		g.fromXML("delta", {"pt":"1", "x":"33", "y":"44"}, [])
		g.fromXML("delta", {"pt":"2", "x":"-2", "y":"170"}, [])
		self.assertEqual({
			"wdth":( 0.3,  0.4, 0.5),
			"wght":( 0.0,  1.0, 1.0),
			"opsz":(-0.5, -0.5, 0.0)
		}, g.axes)
		self.assertEqual([None, (33, 44), (-2, 170), None], g.coordinates)
	def test_hasImpact_allDeltasZero(self):
		axes = {"wght":(0.0, 1.0, 1.0)}
		gvar = GlyphVariation(axes, [(0,0), (0,0), (0,0)])
		self.assertTrue(gvar.hasImpact())
	def test_hasImpact_allDeltasNone(self):
		axes = {"wght":(0.0, 1.0, 1.0)}
		gvar = GlyphVariation(axes, [None, None, None])
		self.assertFalse(gvar.hasImpact())
	def test_compileIntermediateCoord(self):
		gvar = GlyphVariation({"wght": (-1.0, -1.0, 0.0), "wdth": (0.4, 0.5, 0.6)}, [None] * 4)
		self.assertEqual("C0 00 19 9A 00 00 26 66", hexencode(gvar.compileIntermediateCoord(["wght", "wdth"])))
		self.assertEqual("19 9A C0 00 26 66 00 00", hexencode(gvar.compileIntermediateCoord(["wdth", "wght"])))
		self.assertEqual(None, gvar.compileIntermediateCoord(["wght"]))
		self.assertEqual("19 9A 26 66", hexencode(gvar.compileIntermediateCoord(["wdth"])))
Example #50
0
 def test_hasImpact_someDeltasNotZero(self):
     axes = {"wght": (0.0, 1.0, 1.0)}
     gvar = GlyphVariation(axes, [(0, 0), (9, 8), (7, 6)])
     self.assertTrue(gvar.hasImpact())
		def decompilePoints(data, offset):
			points, offset = GlyphVariation.decompilePoints_(numPointsInGlyph, deHexStr(data), offset)
			# Conversion to list needed for Python 3.
			return (list(points), offset)
Example #52
0
 def test_equal_differentCoordinates(self):
     gvar1 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8),
                                                        (7, 6)])
     gvar2 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8)])
     self.assertNotEqual(gvar1, gvar2)
	def test_compileDeltas(self):
		gvar = GlyphVariation({}, [(0,0), (1, 0), (2, 0), (3, 3)])
		points = {1, 2}
		# deltaX for points: [1, 2]; deltaY for points: [0, 0]
		self.assertEqual("01 01 02 81", hexencode(gvar.compileDeltas(points)))
Example #54
0
 def test_equal(self):
     gvar1 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8),
                                                        (7, 6)])
     gvar2 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8),
                                                        (7, 6)])
     self.assertEqual(gvar1, gvar2)
Example #55
0
	def test_hasImpact_allDeltasZero(self):
		axes = {"wght":(0.0, 1.0, 1.0)}
		gvar = GlyphVariation(axes, GlyphCoordinates([(0,0), (0,0), (0,0)]))
		self.assertFalse(gvar.hasImpact())
Example #56
0
 def decompilePoints(data, offset):
     points, offset = GlyphVariation.decompilePoints_(
         numPointsInGlyph, deHexStr(data), offset)
     # Conversion to list needed for Python 3.
     return (list(points), offset)