1from fontTools.misc.testTools import getXML, parseXML 2from fontTools.misc.textTools import deHexStr, hexStr 3from fontTools.ttLib import TTLibError, getTableModule, newTable 4from fontTools.ttLib.tables.TupleVariation import TupleVariation 5 6import unittest 7 8 9CVAR_DATA = deHexStr( 10 "0001 0000 " # 0: majorVersion=1 minorVersion=0 11 "8002 0018 " # 4: tupleVariationCount=2|TUPLES_SHARE_POINT_NUMBERS offsetToData=24 12 "0004 " # 8: tvHeader[0].variationDataSize=4 13 "8000 " # 10: tvHeader[0].tupleIndex=EMBEDDED_PEAK 14 "4000 0000 " # 12: tvHeader[0].peakTuple=[1.0, 0.0] 15 "0004 " # 16: tvHeader[1].variationDataSize=4 16 "8000 " # 18: tvHeader[1].tupleIndex=EMBEDDED_PEAK 17 "C000 3333 " # 20: tvHeader[1].peakTuple=[-1.0, 0.8] 18 "03 02 02 01 01" # 24: shared_pointCount=03, run_count=2 cvt=[2, 3, 4] 19 "02 03 01 04 " # 25: deltas=[3, 1, 4] 20 "02 09 07 08" 21) # 29: deltas=[9, 7, 8] 22 23CVAR_PRIVATE_POINT_DATA = deHexStr( 24 "0001 0000 " # 0: majorVersion=1 minorVersion=0 25 "0002 0018 " # 4: tupleVariationCount=2 offsetToData=24 26 "0009 " # 8: tvHeader[0].variationDataSize=9 27 "A000 " # 10: tvHeader[0].tupleIndex=EMBEDDED_PEAK|PRIVATE_POINT_NUMBERS 28 "4000 0000 " # 12: tvHeader[0].peakTuple=[1.0, 0.0] 29 "0009 " # 16: tvHeader[1].variationDataSize=9 30 "A000 " # 18: tvHeader[1].tupleIndex=EMBEDDED_PEAK|PRIVATE_POINT_NUMBERS 31 "C000 3333 " # 20: tvHeader[1].peakTuple=[-1.0, 0.8] 32 "03 02 02 01 01 02 03 01 04 " # 24: pointCount=3 run_count=2 cvt=2 1 1 run_count=2 deltas=[3, 1, 4] 33 "03 02 02 01 01 02 09 07 08 " 34) # 33: pointCount=3 run_count=2 cvt=2 1 1 run_count=2 deltas=[9, 7, 8] 35 36CVAR_XML = [ 37 '<version major="1" minor="0"/>', 38 "<tuple>", 39 ' <coord axis="wght" value="1.0"/>', 40 ' <delta cvt="2" value="3"/>', 41 ' <delta cvt="3" value="1"/>', 42 ' <delta cvt="4" value="4"/>', 43 "</tuple>", 44 "<tuple>", 45 ' <coord axis="wght" value="-1.0"/>', 46 ' <coord axis="wdth" value="0.8"/>', 47 ' <delta cvt="2" value="9"/>', 48 ' <delta cvt="3" value="7"/>', 49 ' <delta cvt="4" value="8"/>', 50 "</tuple>", 51] 52 53CVAR_VARIATIONS = [ 54 TupleVariation({"wght": (0.0, 1.0, 1.0)}, [None, None, 3, 1, 4]), 55 TupleVariation( 56 {"wght": (-1, -1.0, 0.0), "wdth": (0.0, 0.7999878, 0.7999878)}, 57 [None, None, 9, 7, 8], 58 ), 59] 60 61 62class CVARTableTest(unittest.TestCase): 63 def assertVariationsAlmostEqual(self, variations1, variations2): 64 self.assertEqual(len(variations1), len(variations2)) 65 for v1, v2 in zip(variations1, variations2): 66 self.assertSetEqual(set(v1.axes), set(v2.axes)) 67 for axisTag, support1 in v1.axes.items(): 68 support2 = v2.axes[axisTag] 69 self.assertEqual(len(support1), len(support2)) 70 for s1, s2 in zip(support1, support2): 71 self.assertAlmostEqual(s1, s2) 72 self.assertEqual(v1.coordinates, v2.coordinates) 73 74 def makeFont(self): 75 cvt, cvar, fvar = newTable("cvt "), newTable("cvar"), newTable("fvar") 76 font = {"cvt ": cvt, "cvar": cvar, "fvar": fvar} 77 cvt.values = [0, 0, 0, 1000, -2000] 78 Axis = getTableModule("fvar").Axis 79 fvar.axes = [Axis(), Axis()] 80 fvar.axes[0].axisTag, fvar.axes[1].axisTag = "wght", "wdth" 81 return font, cvar 82 83 def test_compile(self): 84 font, cvar = self.makeFont() 85 cvar.variations = CVAR_VARIATIONS 86 self.assertEqual(hexStr(cvar.compile(font)), hexStr(CVAR_PRIVATE_POINT_DATA)) 87 88 def test_compile_shared_points(self): 89 font, cvar = self.makeFont() 90 cvar.variations = CVAR_VARIATIONS 91 self.assertEqual( 92 hexStr(cvar.compile(font, useSharedPoints=True)), hexStr(CVAR_DATA) 93 ) 94 95 def test_decompile(self): 96 font, cvar = self.makeFont() 97 cvar.decompile(CVAR_PRIVATE_POINT_DATA, font) 98 self.assertEqual(cvar.majorVersion, 1) 99 self.assertEqual(cvar.minorVersion, 0) 100 self.assertVariationsAlmostEqual(cvar.variations, CVAR_VARIATIONS) 101 102 def test_decompile_shared_points(self): 103 font, cvar = self.makeFont() 104 cvar.decompile(CVAR_DATA, font) 105 self.assertEqual(cvar.majorVersion, 1) 106 self.assertEqual(cvar.minorVersion, 0) 107 self.assertVariationsAlmostEqual(cvar.variations, CVAR_VARIATIONS) 108 109 def test_fromXML(self): 110 font, cvar = self.makeFont() 111 for name, attrs, content in parseXML(CVAR_XML): 112 cvar.fromXML(name, attrs, content, ttFont=font) 113 self.assertEqual(cvar.majorVersion, 1) 114 self.assertEqual(cvar.minorVersion, 0) 115 self.assertVariationsAlmostEqual(cvar.variations, CVAR_VARIATIONS) 116 117 def test_toXML(self): 118 font, cvar = self.makeFont() 119 cvar.variations = CVAR_VARIATIONS 120 self.assertEqual(getXML(cvar.toXML, font), CVAR_XML) 121 122 123if __name__ == "__main__": 124 import sys 125 126 sys.exit(unittest.main()) 127