1from fontTools.misc.testTools import FakeFont, getXML, parseXML 2from fontTools.misc.textTools import deHexStr 3from fontTools.ttLib import newTable 4import unittest 5 6 7STAT_DATA = deHexStr( 8 "0001 0000 " # 0: Version=1.0 9 "0008 0002 " # 4: DesignAxisSize=8, DesignAxisCount=2 10 "0000 0012 " # 8: OffsetToDesignAxes=18 11 "0003 0000 0022 " # 12: AxisValueCount=3, OffsetToAxisValueOffsets=34 12 "7767 6874 " # 18: DesignAxis[0].AxisTag='wght' 13 "012D 0002 " # 22: DesignAxis[0].NameID=301, .AxisOrdering=2 14 "5445 5354 " # 26: DesignAxis[1].AxisTag='TEST' 15 "012E 0001 " # 30: DesignAxis[1].NameID=302, .AxisOrdering=1 16 "0006 0012 0026 " # 34: AxisValueOffsets = [6, 18, 38] (+34) 17 "0001 0000 0000 " # 40: AxisValue[0].Format=1, .AxisIndex=0, .Flags=0 18 "0191 0190 0000 " # 46: AxisValue[0].ValueNameID=401, .Value=400.0 19 "0002 0001 0000 " # 52: AxisValue[1].Format=2, .AxisIndex=1, .Flags=0 20 "0192 " # 58: AxisValue[1].ValueNameID=402 21 "0002 0000 " # 60: AxisValue[1].NominalValue=2.0 22 "0001 0000 " # 64: AxisValue[1].RangeMinValue=1.0 23 "0003 0000 " # 68: AxisValue[1].RangeMaxValue=3.0 24 "0003 0000 0000 " # 72: AxisValue[2].Format=3, .AxisIndex=0, .Flags=0 25 "0002 " # 78: AxisValue[2].ValueNameID=2 'Regular' 26 "0190 0000 02BC 0000 " # 80: AxisValue[2].Value=400.0, .LinkedValue=700.0 27) # 88: <end> 28assert len(STAT_DATA) == 88 29 30 31STAT_XML = [ 32 '<Version value="0x00010000"/>', 33 '<DesignAxisRecordSize value="8"/>', 34 "<!-- DesignAxisCount=2 -->", 35 "<DesignAxisRecord>", 36 ' <Axis index="0">', 37 ' <AxisTag value="wght"/>', 38 ' <AxisNameID value="301"/>', 39 ' <AxisOrdering value="2"/>', 40 " </Axis>", 41 ' <Axis index="1">', 42 ' <AxisTag value="TEST"/>', 43 ' <AxisNameID value="302"/>', 44 ' <AxisOrdering value="1"/>', 45 " </Axis>", 46 "</DesignAxisRecord>", 47 "<!-- AxisValueCount=3 -->", 48 "<AxisValueArray>", 49 ' <AxisValue index="0" Format="1">', 50 ' <AxisIndex value="0"/>', 51 ' <Flags value="0"/>', 52 ' <ValueNameID value="401"/>', 53 ' <Value value="400.0"/>', 54 " </AxisValue>", 55 ' <AxisValue index="1" Format="2">', 56 ' <AxisIndex value="1"/>', 57 ' <Flags value="0"/>', 58 ' <ValueNameID value="402"/>', 59 ' <NominalValue value="2.0"/>', 60 ' <RangeMinValue value="1.0"/>', 61 ' <RangeMaxValue value="3.0"/>', 62 " </AxisValue>", 63 ' <AxisValue index="2" Format="3">', 64 ' <AxisIndex value="0"/>', 65 ' <Flags value="0"/>', 66 ' <ValueNameID value="2"/>', 67 ' <Value value="400.0"/>', 68 ' <LinkedValue value="700.0"/>', 69 " </AxisValue>", 70 "</AxisValueArray>", 71] 72 73 74# Contains junk data for making sure we get our offset decoding right. 75STAT_DATA_WITH_AXIS_JUNK = deHexStr( 76 "0001 0000 " # 0: Version=1.0 77 "000A 0002 " # 4: DesignAxisSize=10, DesignAxisCount=2 78 "0000 0012 " # 8: OffsetToDesignAxes=18 79 "0000 0000 0000 " # 12: AxisValueCount=3, OffsetToAxisValueOffsets=34 80 "7767 6874 " # 18: DesignAxis[0].AxisTag='wght' 81 "012D 0002 " # 22: DesignAxis[0].NameID=301, .AxisOrdering=2 82 "DEAD " # 26: <junk> 83 "5445 5354 " # 28: DesignAxis[1].AxisTag='TEST' 84 "012E 0001 " # 32: DesignAxis[1].NameID=302, .AxisOrdering=1 85 "BEEF " # 36: <junk> 86) # 38: <end> 87 88assert len(STAT_DATA_WITH_AXIS_JUNK) == 38 89 90 91STAT_XML_WITH_AXIS_JUNK = [ 92 '<Version value="0x00010000"/>', 93 '<DesignAxisRecordSize value="10"/>', 94 "<!-- DesignAxisCount=2 -->", 95 "<DesignAxisRecord>", 96 ' <Axis index="0">', 97 ' <AxisTag value="wght"/>', 98 ' <AxisNameID value="301"/>', 99 ' <AxisOrdering value="2"/>', 100 ' <MoreBytes index="0" value="222"/>', # 0xDE 101 ' <MoreBytes index="1" value="173"/>', # 0xAD 102 " </Axis>", 103 ' <Axis index="1">', 104 ' <AxisTag value="TEST"/>', 105 ' <AxisNameID value="302"/>', 106 ' <AxisOrdering value="1"/>', 107 ' <MoreBytes index="0" value="190"/>', # 0xBE 108 ' <MoreBytes index="1" value="239"/>', # 0xEF 109 " </Axis>", 110 "</DesignAxisRecord>", 111 "<!-- AxisValueCount=0 -->", 112] 113 114 115STAT_DATA_AXIS_VALUE_FORMAT3 = deHexStr( 116 "0001 0000 " # 0: Version=1.0 117 "0008 0001 " # 4: DesignAxisSize=8, DesignAxisCount=1 118 "0000 0012 " # 8: OffsetToDesignAxes=18 119 "0001 " # 12: AxisValueCount=1 120 "0000 001A " # 14: OffsetToAxisValueOffsets=26 121 "7767 6874 " # 18: DesignAxis[0].AxisTag='wght' 122 "0102 " # 22: DesignAxis[0].AxisNameID=258 'Weight' 123 "0000 " # 24: DesignAxis[0].AxisOrdering=0 124 "0002 " # 26: AxisValueOffsets=[2] (+26) 125 "0003 " # 28: AxisValue[0].Format=3 126 "0000 0002 " # 30: AxisValue[0].AxisIndex=0, .Flags=0x2 127 "0002 " # 34: AxisValue[0].ValueNameID=2 'Regular' 128 "0190 0000 " # 36: AxisValue[0].Value=400.0 129 "02BC 0000 " # 40: AxisValue[0].LinkedValue=700.0 130) # 44: <end> 131assert len(STAT_DATA_AXIS_VALUE_FORMAT3) == 44 132 133 134STAT_XML_AXIS_VALUE_FORMAT3 = [ 135 '<Version value="0x00010000"/>', 136 '<DesignAxisRecordSize value="8"/>', 137 "<!-- DesignAxisCount=1 -->", 138 "<DesignAxisRecord>", 139 ' <Axis index="0">', 140 ' <AxisTag value="wght"/>', 141 ' <AxisNameID value="258"/>', 142 ' <AxisOrdering value="0"/>', 143 " </Axis>", 144 "</DesignAxisRecord>", 145 "<!-- AxisValueCount=1 -->", 146 "<AxisValueArray>", 147 ' <AxisValue index="0" Format="3">', 148 ' <AxisIndex value="0"/>', 149 ' <Flags value="2"/> <!-- ElidableAxisValueName -->', 150 ' <ValueNameID value="2"/>', 151 ' <Value value="400.0"/>', 152 ' <LinkedValue value="700.0"/>', 153 " </AxisValue>", 154 "</AxisValueArray>", 155] 156 157 158STAT_DATA_VERSION_1_1 = deHexStr( 159 "0001 0001 " # 0: Version=1.1 160 "0008 0001 " # 4: DesignAxisSize=8, DesignAxisCount=1 161 "0000 0014 " # 8: OffsetToDesignAxes=20 162 "0001 " # 12: AxisValueCount=1 163 "0000 001C " # 14: OffsetToAxisValueOffsets=28 164 "0101 " # 18: ElidedFallbackNameID: 257 165 "7767 6874 " # 20: DesignAxis[0].AxisTag='wght' 166 "0102 " # 24: DesignAxis[0].AxisNameID=258 'Weight' 167 "0000 " # 26: DesignAxis[0].AxisOrdering=0 168 "0002 " # 28: AxisValueOffsets=[2] (+28) 169 "0003 " # 30: AxisValue[0].Format=3 170 "0000 0002 " # 32: AxisValue[0].AxisIndex=0, .Flags=0x2 171 "0002 " # 36: AxisValue[0].ValueNameID=2 'Regular' 172 "0190 0000 " # 38: AxisValue[0].Value=400.0 173 "02BC 0000 " # 42: AxisValue[0].LinkedValue=700.0 174) # 46: <end> 175assert len(STAT_DATA_VERSION_1_1) == 46 176 177 178STAT_XML_VERSION_1_1 = [ 179 '<Version value="0x00010001"/>', 180 '<DesignAxisRecordSize value="8"/>', 181 "<!-- DesignAxisCount=1 -->", 182 "<DesignAxisRecord>", 183 ' <Axis index="0">', 184 ' <AxisTag value="wght"/>', 185 ' <AxisNameID value="258"/>', 186 ' <AxisOrdering value="0"/>', 187 " </Axis>", 188 "</DesignAxisRecord>", 189 "<!-- AxisValueCount=1 -->", 190 "<AxisValueArray>", 191 ' <AxisValue index="0" Format="3">', 192 ' <AxisIndex value="0"/>', 193 ' <Flags value="2"/> <!-- ElidableAxisValueName -->', 194 ' <ValueNameID value="2"/>', 195 ' <Value value="400.0"/>', 196 ' <LinkedValue value="700.0"/>', 197 " </AxisValue>", 198 "</AxisValueArray>", 199 '<ElidedFallbackNameID value="257"/>', 200] 201 202 203class STATTest(unittest.TestCase): 204 @classmethod 205 def setUpClass(cls): 206 cls.maxDiff = None 207 208 def test_decompile_toXML(self): 209 table = newTable("STAT") 210 table.decompile(STAT_DATA, font=FakeFont([".notdef"])) 211 self.assertEqual(getXML(table.toXML), STAT_XML) 212 213 def test_decompile_toXML_withAxisJunk(self): 214 table = newTable("STAT") 215 table.decompile(STAT_DATA_WITH_AXIS_JUNK, font=FakeFont([".notdef"])) 216 self.assertEqual(getXML(table.toXML), STAT_XML_WITH_AXIS_JUNK) 217 218 def test_decompile_toXML_format3(self): 219 table = newTable("STAT") 220 table.decompile(STAT_DATA_AXIS_VALUE_FORMAT3, font=FakeFont([".notdef"])) 221 self.assertEqual(getXML(table.toXML), STAT_XML_AXIS_VALUE_FORMAT3) 222 223 def test_decompile_toXML_version_1_1(self): 224 table = newTable("STAT") 225 table.decompile(STAT_DATA_VERSION_1_1, font=FakeFont([".notdef"])) 226 self.assertEqual(getXML(table.toXML), STAT_XML_VERSION_1_1) 227 228 def test_compile_fromXML(self): 229 table = newTable("STAT") 230 font = FakeFont([".notdef"]) 231 for name, attrs, content in parseXML(STAT_XML): 232 table.fromXML(name, attrs, content, font=font) 233 self.assertEqual(table.compile(font), STAT_DATA) 234 235 def test_compile_fromXML_withAxisJunk(self): 236 table = newTable("STAT") 237 font = FakeFont([".notdef"]) 238 for name, attrs, content in parseXML(STAT_XML_WITH_AXIS_JUNK): 239 table.fromXML(name, attrs, content, font=font) 240 self.assertEqual(table.compile(font), STAT_DATA_WITH_AXIS_JUNK) 241 242 def test_compile_fromXML_format3(self): 243 table = newTable("STAT") 244 font = FakeFont([".notdef"]) 245 for name, attrs, content in parseXML(STAT_XML_AXIS_VALUE_FORMAT3): 246 table.fromXML(name, attrs, content, font=font) 247 self.assertEqual(table.compile(font), STAT_DATA_AXIS_VALUE_FORMAT3) 248 249 def test_compile_fromXML_version_1_1(self): 250 table = newTable("STAT") 251 font = FakeFont([".notdef"]) 252 for name, attrs, content in parseXML(STAT_XML_VERSION_1_1): 253 table.fromXML(name, attrs, content, font=font) 254 self.assertEqual(table.compile(font), STAT_DATA_VERSION_1_1) 255 256 257if __name__ == "__main__": 258 import sys 259 260 sys.exit(unittest.main()) 261