1*e1fe3e4aSElliott Hughesfrom fontTools.misc.loggingTools import CapturingLogHandler 2*e1fe3e4aSElliott Hughesfrom fontTools.misc.testTools import FakeFont, makeXMLWriter 3*e1fe3e4aSElliott Hughesfrom fontTools.misc.textTools import deHexStr 4*e1fe3e4aSElliott Hughesimport fontTools.ttLib.tables.otConverters as otConverters 5*e1fe3e4aSElliott Hughesfrom fontTools.ttLib import newTable 6*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables.otBase import OTTableReader, OTTableWriter 7*e1fe3e4aSElliott Hughesimport unittest 8*e1fe3e4aSElliott Hughes 9*e1fe3e4aSElliott Hughes 10*e1fe3e4aSElliott Hughesclass Char64Test(unittest.TestCase): 11*e1fe3e4aSElliott Hughes font = FakeFont([]) 12*e1fe3e4aSElliott Hughes converter = otConverters.Char64("char64", 0, None, None) 13*e1fe3e4aSElliott Hughes 14*e1fe3e4aSElliott Hughes def test_read(self): 15*e1fe3e4aSElliott Hughes reader = OTTableReader(b"Hello\0junk after zero byte" + 100 * b"\0") 16*e1fe3e4aSElliott Hughes self.assertEqual(self.converter.read(reader, self.font, {}), "Hello") 17*e1fe3e4aSElliott Hughes self.assertEqual(reader.pos, 64) 18*e1fe3e4aSElliott Hughes 19*e1fe3e4aSElliott Hughes def test_read_replace_not_ascii(self): 20*e1fe3e4aSElliott Hughes reader = OTTableReader(b"Hello \xE4 world" + 100 * b"\0") 21*e1fe3e4aSElliott Hughes with CapturingLogHandler(otConverters.log, "WARNING") as captor: 22*e1fe3e4aSElliott Hughes data = self.converter.read(reader, self.font, {}) 23*e1fe3e4aSElliott Hughes self.assertEqual(data, "Hello � world") 24*e1fe3e4aSElliott Hughes self.assertEqual(reader.pos, 64) 25*e1fe3e4aSElliott Hughes self.assertIn( 26*e1fe3e4aSElliott Hughes 'replaced non-ASCII characters in "Hello � world"', 27*e1fe3e4aSElliott Hughes [r.msg for r in captor.records], 28*e1fe3e4aSElliott Hughes ) 29*e1fe3e4aSElliott Hughes 30*e1fe3e4aSElliott Hughes def test_write(self): 31*e1fe3e4aSElliott Hughes writer = OTTableWriter() 32*e1fe3e4aSElliott Hughes self.converter.write(writer, self.font, {}, "Hello world") 33*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), b"Hello world" + 53 * b"\0") 34*e1fe3e4aSElliott Hughes 35*e1fe3e4aSElliott Hughes def test_write_replace_not_ascii(self): 36*e1fe3e4aSElliott Hughes writer = OTTableWriter() 37*e1fe3e4aSElliott Hughes with CapturingLogHandler(otConverters.log, "WARNING") as captor: 38*e1fe3e4aSElliott Hughes self.converter.write(writer, self.font, {}, "Hello ☃") 39*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), b"Hello ?" + 57 * b"\0") 40*e1fe3e4aSElliott Hughes self.assertIn( 41*e1fe3e4aSElliott Hughes 'replacing non-ASCII characters in "Hello ☃"', 42*e1fe3e4aSElliott Hughes [r.msg for r in captor.records], 43*e1fe3e4aSElliott Hughes ) 44*e1fe3e4aSElliott Hughes 45*e1fe3e4aSElliott Hughes def test_write_truncated(self): 46*e1fe3e4aSElliott Hughes writer = OTTableWriter() 47*e1fe3e4aSElliott Hughes with CapturingLogHandler(otConverters.log, "WARNING") as captor: 48*e1fe3e4aSElliott Hughes self.converter.write(writer, self.font, {}, "A" * 80) 49*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), b"A" * 64) 50*e1fe3e4aSElliott Hughes self.assertIn( 51*e1fe3e4aSElliott Hughes 'truncating overlong "' + "A" * 80 + '" to 64 bytes', 52*e1fe3e4aSElliott Hughes [r.msg for r in captor.records], 53*e1fe3e4aSElliott Hughes ) 54*e1fe3e4aSElliott Hughes 55*e1fe3e4aSElliott Hughes def test_xmlRead(self): 56*e1fe3e4aSElliott Hughes value = self.converter.xmlRead({"value": "Foo"}, [], self.font) 57*e1fe3e4aSElliott Hughes self.assertEqual(value, "Foo") 58*e1fe3e4aSElliott Hughes 59*e1fe3e4aSElliott Hughes def test_xmlWrite(self): 60*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 61*e1fe3e4aSElliott Hughes self.converter.xmlWrite( 62*e1fe3e4aSElliott Hughes writer, self.font, "Hello world", "Element", [("attr", "v")] 63*e1fe3e4aSElliott Hughes ) 64*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").rstrip() 65*e1fe3e4aSElliott Hughes self.assertEqual(xml, '<Element attr="v" value="Hello world"/>') 66*e1fe3e4aSElliott Hughes 67*e1fe3e4aSElliott Hughes 68*e1fe3e4aSElliott Hughesclass GlyphIDTest(unittest.TestCase): 69*e1fe3e4aSElliott Hughes font = FakeFont(".notdef A B C".split()) 70*e1fe3e4aSElliott Hughes converter = otConverters.GlyphID("GlyphID", 0, None, None) 71*e1fe3e4aSElliott Hughes 72*e1fe3e4aSElliott Hughes def test_readArray(self): 73*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("0002 0001 DEAD 0002")) 74*e1fe3e4aSElliott Hughes self.assertEqual( 75*e1fe3e4aSElliott Hughes self.converter.readArray(reader, self.font, {}, 4), 76*e1fe3e4aSElliott Hughes ["B", "A", "glyph57005", "B"], 77*e1fe3e4aSElliott Hughes ) 78*e1fe3e4aSElliott Hughes self.assertEqual(reader.pos, 8) 79*e1fe3e4aSElliott Hughes 80*e1fe3e4aSElliott Hughes def test_read(self): 81*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("0003")) 82*e1fe3e4aSElliott Hughes self.assertEqual(self.converter.read(reader, self.font, {}), "C") 83*e1fe3e4aSElliott Hughes self.assertEqual(reader.pos, 2) 84*e1fe3e4aSElliott Hughes 85*e1fe3e4aSElliott Hughes def test_write(self): 86*e1fe3e4aSElliott Hughes writer = OTTableWriter() 87*e1fe3e4aSElliott Hughes self.converter.write(writer, self.font, {}, "B") 88*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), deHexStr("0002")) 89*e1fe3e4aSElliott Hughes 90*e1fe3e4aSElliott Hughes 91*e1fe3e4aSElliott Hughesclass LongTest(unittest.TestCase): 92*e1fe3e4aSElliott Hughes font = FakeFont([]) 93*e1fe3e4aSElliott Hughes converter = otConverters.Long("Long", 0, None, None) 94*e1fe3e4aSElliott Hughes 95*e1fe3e4aSElliott Hughes def test_read(self): 96*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("FF0000EE")) 97*e1fe3e4aSElliott Hughes self.assertEqual(self.converter.read(reader, self.font, {}), -16776978) 98*e1fe3e4aSElliott Hughes self.assertEqual(reader.pos, 4) 99*e1fe3e4aSElliott Hughes 100*e1fe3e4aSElliott Hughes def test_write(self): 101*e1fe3e4aSElliott Hughes writer = OTTableWriter() 102*e1fe3e4aSElliott Hughes self.converter.write(writer, self.font, {}, -16777213) 103*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), deHexStr("FF000003")) 104*e1fe3e4aSElliott Hughes 105*e1fe3e4aSElliott Hughes def test_xmlRead(self): 106*e1fe3e4aSElliott Hughes value = self.converter.xmlRead({"value": "314159"}, [], self.font) 107*e1fe3e4aSElliott Hughes self.assertEqual(value, 314159) 108*e1fe3e4aSElliott Hughes 109*e1fe3e4aSElliott Hughes def test_xmlWrite(self): 110*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 111*e1fe3e4aSElliott Hughes self.converter.xmlWrite(writer, self.font, 291, "Foo", [("attr", "v")]) 112*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").rstrip() 113*e1fe3e4aSElliott Hughes self.assertEqual(xml, '<Foo attr="v" value="291"/>') 114*e1fe3e4aSElliott Hughes 115*e1fe3e4aSElliott Hughes 116*e1fe3e4aSElliott Hughesclass NameIDTest(unittest.TestCase): 117*e1fe3e4aSElliott Hughes converter = otConverters.NameID("NameID", 0, None, None) 118*e1fe3e4aSElliott Hughes 119*e1fe3e4aSElliott Hughes def makeFont(self): 120*e1fe3e4aSElliott Hughes nameTable = newTable("name") 121*e1fe3e4aSElliott Hughes nameTable.setName("Demibold Condensed", 0x123, 3, 0, 0x409) 122*e1fe3e4aSElliott Hughes nameTable.setName("Copyright 2018", 0, 3, 0, 0x409) 123*e1fe3e4aSElliott Hughes return {"name": nameTable} 124*e1fe3e4aSElliott Hughes 125*e1fe3e4aSElliott Hughes def test_read(self): 126*e1fe3e4aSElliott Hughes font = self.makeFont() 127*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("0123")) 128*e1fe3e4aSElliott Hughes self.assertEqual(self.converter.read(reader, font, {}), 0x123) 129*e1fe3e4aSElliott Hughes 130*e1fe3e4aSElliott Hughes def test_write(self): 131*e1fe3e4aSElliott Hughes writer = OTTableWriter() 132*e1fe3e4aSElliott Hughes self.converter.write(writer, self.makeFont(), {}, 0x123) 133*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), deHexStr("0123")) 134*e1fe3e4aSElliott Hughes 135*e1fe3e4aSElliott Hughes def test_xmlWrite(self): 136*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 137*e1fe3e4aSElliott Hughes self.converter.xmlWrite( 138*e1fe3e4aSElliott Hughes writer, self.makeFont(), 291, "FooNameID", [("attr", "val")] 139*e1fe3e4aSElliott Hughes ) 140*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").rstrip() 141*e1fe3e4aSElliott Hughes self.assertEqual( 142*e1fe3e4aSElliott Hughes xml, '<FooNameID attr="val" value="291"/> <!-- Demibold Condensed -->' 143*e1fe3e4aSElliott Hughes ) 144*e1fe3e4aSElliott Hughes 145*e1fe3e4aSElliott Hughes def test_xmlWrite_missingID(self): 146*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 147*e1fe3e4aSElliott Hughes with CapturingLogHandler(otConverters.log, "WARNING") as captor: 148*e1fe3e4aSElliott Hughes self.converter.xmlWrite( 149*e1fe3e4aSElliott Hughes writer, self.makeFont(), 666, "Entity", [("attrib", "val")] 150*e1fe3e4aSElliott Hughes ) 151*e1fe3e4aSElliott Hughes self.assertIn( 152*e1fe3e4aSElliott Hughes "name id 666 missing from name table", [r.msg for r in captor.records] 153*e1fe3e4aSElliott Hughes ) 154*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").rstrip() 155*e1fe3e4aSElliott Hughes self.assertEqual( 156*e1fe3e4aSElliott Hughes xml, 157*e1fe3e4aSElliott Hughes '<Entity attrib="val"' ' value="666"/> <!-- missing from name table -->', 158*e1fe3e4aSElliott Hughes ) 159*e1fe3e4aSElliott Hughes 160*e1fe3e4aSElliott Hughes def test_xmlWrite_NULL(self): 161*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 162*e1fe3e4aSElliott Hughes self.converter.xmlWrite( 163*e1fe3e4aSElliott Hughes writer, self.makeFont(), 0, "FooNameID", [("attr", "val")] 164*e1fe3e4aSElliott Hughes ) 165*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").rstrip() 166*e1fe3e4aSElliott Hughes self.assertEqual(xml, '<FooNameID attr="val" value="0"/>') 167*e1fe3e4aSElliott Hughes 168*e1fe3e4aSElliott Hughes 169*e1fe3e4aSElliott Hughesclass UInt8Test(unittest.TestCase): 170*e1fe3e4aSElliott Hughes font = FakeFont([]) 171*e1fe3e4aSElliott Hughes converter = otConverters.UInt8("UInt8", 0, None, None) 172*e1fe3e4aSElliott Hughes 173*e1fe3e4aSElliott Hughes def test_read(self): 174*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("FE")) 175*e1fe3e4aSElliott Hughes self.assertEqual(self.converter.read(reader, self.font, {}), 254) 176*e1fe3e4aSElliott Hughes self.assertEqual(reader.pos, 1) 177*e1fe3e4aSElliott Hughes 178*e1fe3e4aSElliott Hughes def test_write(self): 179*e1fe3e4aSElliott Hughes writer = OTTableWriter() 180*e1fe3e4aSElliott Hughes self.converter.write(writer, self.font, {}, 253) 181*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), deHexStr("FD")) 182*e1fe3e4aSElliott Hughes 183*e1fe3e4aSElliott Hughes def test_xmlRead(self): 184*e1fe3e4aSElliott Hughes value = self.converter.xmlRead({"value": "254"}, [], self.font) 185*e1fe3e4aSElliott Hughes self.assertEqual(value, 254) 186*e1fe3e4aSElliott Hughes 187*e1fe3e4aSElliott Hughes def test_xmlWrite(self): 188*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 189*e1fe3e4aSElliott Hughes self.converter.xmlWrite(writer, self.font, 251, "Foo", [("attr", "v")]) 190*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").rstrip() 191*e1fe3e4aSElliott Hughes self.assertEqual(xml, '<Foo attr="v" value="251"/>') 192*e1fe3e4aSElliott Hughes 193*e1fe3e4aSElliott Hughes 194*e1fe3e4aSElliott Hughesclass AATLookupTest(unittest.TestCase): 195*e1fe3e4aSElliott Hughes font = FakeFont(".notdef A B C D E F G H A.alt B.alt".split()) 196*e1fe3e4aSElliott Hughes converter = otConverters.AATLookup( 197*e1fe3e4aSElliott Hughes "AATLookup", 0, None, tableClass=otConverters.GlyphID 198*e1fe3e4aSElliott Hughes ) 199*e1fe3e4aSElliott Hughes 200*e1fe3e4aSElliott Hughes def __init__(self, methodName): 201*e1fe3e4aSElliott Hughes unittest.TestCase.__init__(self, methodName) 202*e1fe3e4aSElliott Hughes # Python 3 renamed assertRaisesRegexp to assertRaisesRegex, 203*e1fe3e4aSElliott Hughes # and fires deprecation warnings if a program uses the old name. 204*e1fe3e4aSElliott Hughes if not hasattr(self, "assertRaisesRegex"): 205*e1fe3e4aSElliott Hughes self.assertRaisesRegex = self.assertRaisesRegexp 206*e1fe3e4aSElliott Hughes 207*e1fe3e4aSElliott Hughes def test_readFormat0(self): 208*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("0000 0000 0001 0002 0000 7D00 0001")) 209*e1fe3e4aSElliott Hughes self.assertEqual( 210*e1fe3e4aSElliott Hughes self.converter.read(reader, self.font, None), 211*e1fe3e4aSElliott Hughes { 212*e1fe3e4aSElliott Hughes ".notdef": ".notdef", 213*e1fe3e4aSElliott Hughes "A": "A", 214*e1fe3e4aSElliott Hughes "B": "B", 215*e1fe3e4aSElliott Hughes "C": ".notdef", 216*e1fe3e4aSElliott Hughes "D": "glyph32000", 217*e1fe3e4aSElliott Hughes "E": "A", 218*e1fe3e4aSElliott Hughes }, 219*e1fe3e4aSElliott Hughes ) 220*e1fe3e4aSElliott Hughes 221*e1fe3e4aSElliott Hughes def test_readFormat2(self): 222*e1fe3e4aSElliott Hughes reader = OTTableReader( 223*e1fe3e4aSElliott Hughes deHexStr( 224*e1fe3e4aSElliott Hughes "0002 0006 0002 000C 0001 0006 " 225*e1fe3e4aSElliott Hughes "0002 0001 0003 " # glyph A..B: map to C 226*e1fe3e4aSElliott Hughes "0007 0005 0008 " # glyph E..G: map to H 227*e1fe3e4aSElliott Hughes "FFFF FFFF FFFF" 228*e1fe3e4aSElliott Hughes ) 229*e1fe3e4aSElliott Hughes ) # end of search table 230*e1fe3e4aSElliott Hughes self.assertEqual( 231*e1fe3e4aSElliott Hughes self.converter.read(reader, self.font, None), 232*e1fe3e4aSElliott Hughes { 233*e1fe3e4aSElliott Hughes "A": "C", 234*e1fe3e4aSElliott Hughes "B": "C", 235*e1fe3e4aSElliott Hughes "E": "H", 236*e1fe3e4aSElliott Hughes "F": "H", 237*e1fe3e4aSElliott Hughes "G": "H", 238*e1fe3e4aSElliott Hughes }, 239*e1fe3e4aSElliott Hughes ) 240*e1fe3e4aSElliott Hughes 241*e1fe3e4aSElliott Hughes def test_readFormat4(self): 242*e1fe3e4aSElliott Hughes reader = OTTableReader( 243*e1fe3e4aSElliott Hughes deHexStr( 244*e1fe3e4aSElliott Hughes "0004 0006 0003 000C 0001 0006 " 245*e1fe3e4aSElliott Hughes "0002 0001 001E " # glyph 1..2: mapping at offset 0x1E 246*e1fe3e4aSElliott Hughes "0005 0004 001E " # glyph 4..5: mapping at offset 0x1E 247*e1fe3e4aSElliott Hughes "FFFF FFFF FFFF " # end of search table 248*e1fe3e4aSElliott Hughes "0007 0008" 249*e1fe3e4aSElliott Hughes ) 250*e1fe3e4aSElliott Hughes ) # offset 0x18: glyphs [7, 8] = [G, H] 251*e1fe3e4aSElliott Hughes self.assertEqual( 252*e1fe3e4aSElliott Hughes self.converter.read(reader, self.font, None), 253*e1fe3e4aSElliott Hughes { 254*e1fe3e4aSElliott Hughes "A": "G", 255*e1fe3e4aSElliott Hughes "B": "H", 256*e1fe3e4aSElliott Hughes "D": "G", 257*e1fe3e4aSElliott Hughes "E": "H", 258*e1fe3e4aSElliott Hughes }, 259*e1fe3e4aSElliott Hughes ) 260*e1fe3e4aSElliott Hughes 261*e1fe3e4aSElliott Hughes def test_readFormat6(self): 262*e1fe3e4aSElliott Hughes reader = OTTableReader( 263*e1fe3e4aSElliott Hughes deHexStr( 264*e1fe3e4aSElliott Hughes "0006 0004 0002 0008 0001 0004 " 265*e1fe3e4aSElliott Hughes "0003 0001 " # C --> A 266*e1fe3e4aSElliott Hughes "0005 0002 " # E --> B 267*e1fe3e4aSElliott Hughes "FFFF FFFF" 268*e1fe3e4aSElliott Hughes ) 269*e1fe3e4aSElliott Hughes ) # end of search table 270*e1fe3e4aSElliott Hughes self.assertEqual( 271*e1fe3e4aSElliott Hughes self.converter.read(reader, self.font, None), 272*e1fe3e4aSElliott Hughes { 273*e1fe3e4aSElliott Hughes "C": "A", 274*e1fe3e4aSElliott Hughes "E": "B", 275*e1fe3e4aSElliott Hughes }, 276*e1fe3e4aSElliott Hughes ) 277*e1fe3e4aSElliott Hughes 278*e1fe3e4aSElliott Hughes def test_readFormat8(self): 279*e1fe3e4aSElliott Hughes reader = OTTableReader( 280*e1fe3e4aSElliott Hughes deHexStr("0008 " "0003 0003 " "0007 0001 0002") # first: C, count: 3 281*e1fe3e4aSElliott Hughes ) # [G, A, B] 282*e1fe3e4aSElliott Hughes self.assertEqual( 283*e1fe3e4aSElliott Hughes self.converter.read(reader, self.font, None), 284*e1fe3e4aSElliott Hughes { 285*e1fe3e4aSElliott Hughes "C": "G", 286*e1fe3e4aSElliott Hughes "D": "A", 287*e1fe3e4aSElliott Hughes "E": "B", 288*e1fe3e4aSElliott Hughes }, 289*e1fe3e4aSElliott Hughes ) 290*e1fe3e4aSElliott Hughes 291*e1fe3e4aSElliott Hughes def test_readUnknownFormat(self): 292*e1fe3e4aSElliott Hughes reader = OTTableReader(deHexStr("0009")) 293*e1fe3e4aSElliott Hughes self.assertRaisesRegex( 294*e1fe3e4aSElliott Hughes AssertionError, 295*e1fe3e4aSElliott Hughes "unsupported lookup format: 9", 296*e1fe3e4aSElliott Hughes self.converter.read, 297*e1fe3e4aSElliott Hughes reader, 298*e1fe3e4aSElliott Hughes self.font, 299*e1fe3e4aSElliott Hughes None, 300*e1fe3e4aSElliott Hughes ) 301*e1fe3e4aSElliott Hughes 302*e1fe3e4aSElliott Hughes def test_writeFormat0(self): 303*e1fe3e4aSElliott Hughes writer = OTTableWriter() 304*e1fe3e4aSElliott Hughes font = FakeFont(".notdef A B C".split()) 305*e1fe3e4aSElliott Hughes self.converter.write( 306*e1fe3e4aSElliott Hughes writer, font, {}, {".notdef": ".notdef", "A": "C", "B": "C", "C": "A"} 307*e1fe3e4aSElliott Hughes ) 308*e1fe3e4aSElliott Hughes self.assertEqual(writer.getData(), deHexStr("0000 0000 0003 0003 0001")) 309*e1fe3e4aSElliott Hughes 310*e1fe3e4aSElliott Hughes def test_writeFormat2(self): 311*e1fe3e4aSElliott Hughes writer = OTTableWriter() 312*e1fe3e4aSElliott Hughes font = FakeFont(".notdef A B C D E F G H".split()) 313*e1fe3e4aSElliott Hughes self.converter.write( 314*e1fe3e4aSElliott Hughes writer, 315*e1fe3e4aSElliott Hughes font, 316*e1fe3e4aSElliott Hughes {}, 317*e1fe3e4aSElliott Hughes { 318*e1fe3e4aSElliott Hughes "B": "C", 319*e1fe3e4aSElliott Hughes "C": "C", 320*e1fe3e4aSElliott Hughes "D": "C", 321*e1fe3e4aSElliott Hughes "E": "C", 322*e1fe3e4aSElliott Hughes "G": "A", 323*e1fe3e4aSElliott Hughes "H": "A", 324*e1fe3e4aSElliott Hughes }, 325*e1fe3e4aSElliott Hughes ) 326*e1fe3e4aSElliott Hughes self.assertEqual( 327*e1fe3e4aSElliott Hughes writer.getData(), 328*e1fe3e4aSElliott Hughes deHexStr( 329*e1fe3e4aSElliott Hughes "0002 " # format=2 330*e1fe3e4aSElliott Hughes "0006 " # binSrchHeader.unitSize=6 331*e1fe3e4aSElliott Hughes "0002 " # binSrchHeader.nUnits=2 332*e1fe3e4aSElliott Hughes "000C " # binSrchHeader.searchRange=12 333*e1fe3e4aSElliott Hughes "0001 " # binSrchHeader.entrySelector=1 334*e1fe3e4aSElliott Hughes "0000 " # binSrchHeader.rangeShift=0 335*e1fe3e4aSElliott Hughes "0005 0002 0003 " # segments[0].lastGlyph=E, firstGlyph=B, value=C 336*e1fe3e4aSElliott Hughes "0008 0007 0001 " # segments[1].lastGlyph=H, firstGlyph=G, value=A 337*e1fe3e4aSElliott Hughes "FFFF FFFF 0000 " # segments[2]=<END> 338*e1fe3e4aSElliott Hughes ), 339*e1fe3e4aSElliott Hughes ) 340*e1fe3e4aSElliott Hughes 341*e1fe3e4aSElliott Hughes def test_writeFormat6(self): 342*e1fe3e4aSElliott Hughes writer = OTTableWriter() 343*e1fe3e4aSElliott Hughes font = FakeFont(".notdef A B C D E".split()) 344*e1fe3e4aSElliott Hughes self.converter.write( 345*e1fe3e4aSElliott Hughes writer, 346*e1fe3e4aSElliott Hughes font, 347*e1fe3e4aSElliott Hughes {}, 348*e1fe3e4aSElliott Hughes { 349*e1fe3e4aSElliott Hughes "A": "C", 350*e1fe3e4aSElliott Hughes "C": "B", 351*e1fe3e4aSElliott Hughes "D": "D", 352*e1fe3e4aSElliott Hughes "E": "E", 353*e1fe3e4aSElliott Hughes }, 354*e1fe3e4aSElliott Hughes ) 355*e1fe3e4aSElliott Hughes self.assertEqual( 356*e1fe3e4aSElliott Hughes writer.getData(), 357*e1fe3e4aSElliott Hughes deHexStr( 358*e1fe3e4aSElliott Hughes "0006 " # format=6 359*e1fe3e4aSElliott Hughes "0004 " # binSrchHeader.unitSize=4 360*e1fe3e4aSElliott Hughes "0004 " # binSrchHeader.nUnits=4 361*e1fe3e4aSElliott Hughes "0010 " # binSrchHeader.searchRange=16 362*e1fe3e4aSElliott Hughes "0002 " # binSrchHeader.entrySelector=2 363*e1fe3e4aSElliott Hughes "0000 " # binSrchHeader.rangeShift=0 364*e1fe3e4aSElliott Hughes "0001 0003 " # entries[0].glyph=A, .value=C 365*e1fe3e4aSElliott Hughes "0003 0002 " # entries[1].glyph=C, .value=B 366*e1fe3e4aSElliott Hughes "0004 0004 " # entries[2].glyph=D, .value=D 367*e1fe3e4aSElliott Hughes "0005 0005 " # entries[3].glyph=E, .value=E 368*e1fe3e4aSElliott Hughes "FFFF 0000 " # entries[4]=<END> 369*e1fe3e4aSElliott Hughes ), 370*e1fe3e4aSElliott Hughes ) 371*e1fe3e4aSElliott Hughes 372*e1fe3e4aSElliott Hughes def test_writeFormat8(self): 373*e1fe3e4aSElliott Hughes writer = OTTableWriter() 374*e1fe3e4aSElliott Hughes font = FakeFont(".notdef A B C D E F G H".split()) 375*e1fe3e4aSElliott Hughes self.converter.write( 376*e1fe3e4aSElliott Hughes writer, 377*e1fe3e4aSElliott Hughes font, 378*e1fe3e4aSElliott Hughes {}, 379*e1fe3e4aSElliott Hughes { 380*e1fe3e4aSElliott Hughes "B": "B", 381*e1fe3e4aSElliott Hughes "C": "A", 382*e1fe3e4aSElliott Hughes "D": "B", 383*e1fe3e4aSElliott Hughes "E": "C", 384*e1fe3e4aSElliott Hughes "F": "B", 385*e1fe3e4aSElliott Hughes "G": "A", 386*e1fe3e4aSElliott Hughes }, 387*e1fe3e4aSElliott Hughes ) 388*e1fe3e4aSElliott Hughes self.assertEqual( 389*e1fe3e4aSElliott Hughes writer.getData(), 390*e1fe3e4aSElliott Hughes deHexStr( 391*e1fe3e4aSElliott Hughes "0008 " # format=8 392*e1fe3e4aSElliott Hughes "0002 " # firstGlyph=B 393*e1fe3e4aSElliott Hughes "0006 " # glyphCount=6 394*e1fe3e4aSElliott Hughes "0002 0001 0002 0003 0002 0001" # valueArray=[B, A, B, C, B, A] 395*e1fe3e4aSElliott Hughes ), 396*e1fe3e4aSElliott Hughes ) 397*e1fe3e4aSElliott Hughes 398*e1fe3e4aSElliott Hughes def test_xmlRead(self): 399*e1fe3e4aSElliott Hughes value = self.converter.xmlRead( 400*e1fe3e4aSElliott Hughes {}, 401*e1fe3e4aSElliott Hughes [ 402*e1fe3e4aSElliott Hughes ("Lookup", {"glyph": "A", "value": "A.alt"}, []), 403*e1fe3e4aSElliott Hughes ("Lookup", {"glyph": "B", "value": "B.alt"}, []), 404*e1fe3e4aSElliott Hughes ], 405*e1fe3e4aSElliott Hughes self.font, 406*e1fe3e4aSElliott Hughes ) 407*e1fe3e4aSElliott Hughes self.assertEqual(value, {"A": "A.alt", "B": "B.alt"}) 408*e1fe3e4aSElliott Hughes 409*e1fe3e4aSElliott Hughes def test_xmlWrite(self): 410*e1fe3e4aSElliott Hughes writer = makeXMLWriter() 411*e1fe3e4aSElliott Hughes self.converter.xmlWrite( 412*e1fe3e4aSElliott Hughes writer, 413*e1fe3e4aSElliott Hughes self.font, 414*e1fe3e4aSElliott Hughes value={"A": "A.alt", "B": "B.alt"}, 415*e1fe3e4aSElliott Hughes name="Foo", 416*e1fe3e4aSElliott Hughes attrs=[("attr", "val")], 417*e1fe3e4aSElliott Hughes ) 418*e1fe3e4aSElliott Hughes xml = writer.file.getvalue().decode("utf-8").splitlines() 419*e1fe3e4aSElliott Hughes self.assertEqual( 420*e1fe3e4aSElliott Hughes xml, 421*e1fe3e4aSElliott Hughes [ 422*e1fe3e4aSElliott Hughes '<Foo attr="val">', 423*e1fe3e4aSElliott Hughes ' <Lookup glyph="A" value="A.alt"/>', 424*e1fe3e4aSElliott Hughes ' <Lookup glyph="B" value="B.alt"/>', 425*e1fe3e4aSElliott Hughes "</Foo>", 426*e1fe3e4aSElliott Hughes ], 427*e1fe3e4aSElliott Hughes ) 428*e1fe3e4aSElliott Hughes 429*e1fe3e4aSElliott Hughes 430*e1fe3e4aSElliott Hughesclass LazyListTest(unittest.TestCase): 431*e1fe3e4aSElliott Hughes def test_slice(self): 432*e1fe3e4aSElliott Hughes ll = otConverters._LazyList([10, 11, 12, 13]) 433*e1fe3e4aSElliott Hughes sl = ll[:] 434*e1fe3e4aSElliott Hughes 435*e1fe3e4aSElliott Hughes self.assertIsNot(sl, ll) 436*e1fe3e4aSElliott Hughes self.assertIsInstance(sl, list) 437*e1fe3e4aSElliott Hughes self.assertEqual([10, 11, 12, 13], sl) 438*e1fe3e4aSElliott Hughes 439*e1fe3e4aSElliott Hughes self.assertEqual([11, 12], ll[1:3]) 440*e1fe3e4aSElliott Hughes 441*e1fe3e4aSElliott Hughes def test_getitem(self): 442*e1fe3e4aSElliott Hughes count = 2 443*e1fe3e4aSElliott Hughes reader = OTTableReader(b"\x00\xFE\xFF\x00\x00\x00", offset=1) 444*e1fe3e4aSElliott Hughes converter = otConverters.UInt8("UInt8", 0, None, None) 445*e1fe3e4aSElliott Hughes recordSize = converter.staticSize 446*e1fe3e4aSElliott Hughes l = otConverters._LazyList() 447*e1fe3e4aSElliott Hughes l.reader = reader 448*e1fe3e4aSElliott Hughes l.pos = l.reader.pos 449*e1fe3e4aSElliott Hughes l.font = None 450*e1fe3e4aSElliott Hughes l.conv = converter 451*e1fe3e4aSElliott Hughes l.recordSize = recordSize 452*e1fe3e4aSElliott Hughes l.extend(otConverters._MissingItem([i]) for i in range(count)) 453*e1fe3e4aSElliott Hughes reader.advance(count * recordSize) 454*e1fe3e4aSElliott Hughes 455*e1fe3e4aSElliott Hughes self.assertEqual(l[0], 254) 456*e1fe3e4aSElliott Hughes self.assertEqual(l[1], 255) 457*e1fe3e4aSElliott Hughes 458*e1fe3e4aSElliott Hughes def test_add_both_LazyList(self): 459*e1fe3e4aSElliott Hughes ll1 = otConverters._LazyList([1]) 460*e1fe3e4aSElliott Hughes ll2 = otConverters._LazyList([2]) 461*e1fe3e4aSElliott Hughes 462*e1fe3e4aSElliott Hughes l3 = ll1 + ll2 463*e1fe3e4aSElliott Hughes 464*e1fe3e4aSElliott Hughes self.assertIsInstance(l3, list) 465*e1fe3e4aSElliott Hughes self.assertEqual([1, 2], l3) 466*e1fe3e4aSElliott Hughes 467*e1fe3e4aSElliott Hughes def test_add_LazyList_and_list(self): 468*e1fe3e4aSElliott Hughes ll1 = otConverters._LazyList([1]) 469*e1fe3e4aSElliott Hughes l2 = [2] 470*e1fe3e4aSElliott Hughes 471*e1fe3e4aSElliott Hughes l3 = ll1 + l2 472*e1fe3e4aSElliott Hughes 473*e1fe3e4aSElliott Hughes self.assertIsInstance(l3, list) 474*e1fe3e4aSElliott Hughes self.assertEqual([1, 2], l3) 475*e1fe3e4aSElliott Hughes 476*e1fe3e4aSElliott Hughes def test_add_not_implemented(self): 477*e1fe3e4aSElliott Hughes with self.assertRaises(TypeError): 478*e1fe3e4aSElliott Hughes otConverters._LazyList() + 0 479*e1fe3e4aSElliott Hughes with self.assertRaises(TypeError): 480*e1fe3e4aSElliott Hughes otConverters._LazyList() + tuple() 481*e1fe3e4aSElliott Hughes 482*e1fe3e4aSElliott Hughes def test_radd_list_and_LazyList(self): 483*e1fe3e4aSElliott Hughes l1 = [1] 484*e1fe3e4aSElliott Hughes ll2 = otConverters._LazyList([2]) 485*e1fe3e4aSElliott Hughes 486*e1fe3e4aSElliott Hughes l3 = l1 + ll2 487*e1fe3e4aSElliott Hughes 488*e1fe3e4aSElliott Hughes self.assertIsInstance(l3, list) 489*e1fe3e4aSElliott Hughes self.assertEqual([1, 2], l3) 490*e1fe3e4aSElliott Hughes 491*e1fe3e4aSElliott Hughes def test_radd_not_implemented(self): 492*e1fe3e4aSElliott Hughes with self.assertRaises(TypeError): 493*e1fe3e4aSElliott Hughes 0 + otConverters._LazyList() 494*e1fe3e4aSElliott Hughes with self.assertRaises(TypeError): 495*e1fe3e4aSElliott Hughes tuple() + otConverters._LazyList() 496*e1fe3e4aSElliott Hughes 497*e1fe3e4aSElliott Hughes 498*e1fe3e4aSElliott Hughesif __name__ == "__main__": 499*e1fe3e4aSElliott Hughes import sys 500*e1fe3e4aSElliott Hughes 501*e1fe3e4aSElliott Hughes sys.exit(unittest.main()) 502