1*e1fe3e4aSElliott Hughesimport io 2*e1fe3e4aSElliott Hughesimport copy 3*e1fe3e4aSElliott Hughesimport pickle 4*e1fe3e4aSElliott Hughesimport tempfile 5*e1fe3e4aSElliott Hughesfrom fontTools.ttLib import TTFont 6*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.sfnt import calcChecksum, SFNTReader, WOFFFlavorData 7*e1fe3e4aSElliott Hughesfrom pathlib import Path 8*e1fe3e4aSElliott Hughesimport pytest 9*e1fe3e4aSElliott Hughes 10*e1fe3e4aSElliott HughesTEST_DATA = Path(__file__).parent / "data" 11*e1fe3e4aSElliott Hughes 12*e1fe3e4aSElliott Hughes 13*e1fe3e4aSElliott Hughes@pytest.fixture 14*e1fe3e4aSElliott Hughesdef ttfont_path(): 15*e1fe3e4aSElliott Hughes font = TTFont() 16*e1fe3e4aSElliott Hughes font.importXML(TEST_DATA / "TestTTF-Regular.ttx") 17*e1fe3e4aSElliott Hughes with tempfile.NamedTemporaryFile(suffix=".ttf", delete=False) as fp: 18*e1fe3e4aSElliott Hughes font_path = Path(fp.name) 19*e1fe3e4aSElliott Hughes font.save(font_path) 20*e1fe3e4aSElliott Hughes yield font_path 21*e1fe3e4aSElliott Hughes font_path.unlink() 22*e1fe3e4aSElliott Hughes 23*e1fe3e4aSElliott Hughes 24*e1fe3e4aSElliott Hughesdef test_calcChecksum(): 25*e1fe3e4aSElliott Hughes assert calcChecksum(b"abcd") == 1633837924 26*e1fe3e4aSElliott Hughes assert calcChecksum(b"abcdxyz") == 3655064932 27*e1fe3e4aSElliott Hughes 28*e1fe3e4aSElliott Hughes 29*e1fe3e4aSElliott HughesEMPTY_SFNT = b"\x00\x01\x00\x00" + b"\x00" * 8 30*e1fe3e4aSElliott Hughes 31*e1fe3e4aSElliott Hughes 32*e1fe3e4aSElliott Hughesdef pickle_unpickle(obj): 33*e1fe3e4aSElliott Hughes return pickle.loads(pickle.dumps(obj)) 34*e1fe3e4aSElliott Hughes 35*e1fe3e4aSElliott Hughes 36*e1fe3e4aSElliott Hughesclass SFNTReaderTest: 37*e1fe3e4aSElliott Hughes @pytest.mark.parametrize("deepcopy", [copy.deepcopy, pickle_unpickle]) 38*e1fe3e4aSElliott Hughes def test_pickle_protocol_FileIO(self, deepcopy, tmp_path): 39*e1fe3e4aSElliott Hughes fontfile = tmp_path / "test.ttf" 40*e1fe3e4aSElliott Hughes fontfile.write_bytes(EMPTY_SFNT) 41*e1fe3e4aSElliott Hughes reader = SFNTReader(fontfile.open("rb")) 42*e1fe3e4aSElliott Hughes 43*e1fe3e4aSElliott Hughes reader2 = deepcopy(reader) 44*e1fe3e4aSElliott Hughes 45*e1fe3e4aSElliott Hughes assert reader2 is not reader 46*e1fe3e4aSElliott Hughes assert reader2.file is not reader.file 47*e1fe3e4aSElliott Hughes 48*e1fe3e4aSElliott Hughes assert isinstance(reader2.file, io.BufferedReader) 49*e1fe3e4aSElliott Hughes assert isinstance(reader2.file.raw, io.FileIO) 50*e1fe3e4aSElliott Hughes assert reader2.file.name == reader.file.name 51*e1fe3e4aSElliott Hughes assert reader2.file.tell() == reader.file.tell() 52*e1fe3e4aSElliott Hughes 53*e1fe3e4aSElliott Hughes for k, v in reader.__dict__.items(): 54*e1fe3e4aSElliott Hughes if k == "file": 55*e1fe3e4aSElliott Hughes continue 56*e1fe3e4aSElliott Hughes assert getattr(reader2, k) == v 57*e1fe3e4aSElliott Hughes 58*e1fe3e4aSElliott Hughes @pytest.mark.parametrize("deepcopy", [copy.deepcopy, pickle_unpickle]) 59*e1fe3e4aSElliott Hughes def test_pickle_protocol_BytesIO(self, deepcopy, tmp_path): 60*e1fe3e4aSElliott Hughes buf = io.BytesIO(EMPTY_SFNT) 61*e1fe3e4aSElliott Hughes reader = SFNTReader(buf) 62*e1fe3e4aSElliott Hughes 63*e1fe3e4aSElliott Hughes reader2 = deepcopy(reader) 64*e1fe3e4aSElliott Hughes 65*e1fe3e4aSElliott Hughes assert reader2 is not reader 66*e1fe3e4aSElliott Hughes assert reader2.file is not reader.file 67*e1fe3e4aSElliott Hughes 68*e1fe3e4aSElliott Hughes assert isinstance(reader2.file, io.BytesIO) 69*e1fe3e4aSElliott Hughes assert reader2.file.tell() == reader.file.tell() 70*e1fe3e4aSElliott Hughes assert reader2.file.getvalue() == reader.file.getvalue() 71*e1fe3e4aSElliott Hughes 72*e1fe3e4aSElliott Hughes for k, v in reader.__dict__.items(): 73*e1fe3e4aSElliott Hughes if k == "file": 74*e1fe3e4aSElliott Hughes continue 75*e1fe3e4aSElliott Hughes assert getattr(reader2, k) == v 76*e1fe3e4aSElliott Hughes 77*e1fe3e4aSElliott Hughes 78*e1fe3e4aSElliott Hughesdef test_ttLib_sfnt_write_privData(tmp_path, ttfont_path): 79*e1fe3e4aSElliott Hughes output_path = tmp_path / "TestTTF-Regular.woff" 80*e1fe3e4aSElliott Hughes font = TTFont(ttfont_path) 81*e1fe3e4aSElliott Hughes 82*e1fe3e4aSElliott Hughes privData = "Private Eyes".encode() 83*e1fe3e4aSElliott Hughes 84*e1fe3e4aSElliott Hughes data = WOFFFlavorData() 85*e1fe3e4aSElliott Hughes head = font["head"] 86*e1fe3e4aSElliott Hughes data.majorVersion, data.minorVersion = map( 87*e1fe3e4aSElliott Hughes int, format(head.fontRevision, ".3f").split(".") 88*e1fe3e4aSElliott Hughes ) 89*e1fe3e4aSElliott Hughes 90*e1fe3e4aSElliott Hughes data.privData = privData 91*e1fe3e4aSElliott Hughes font.flavor = "woff" 92*e1fe3e4aSElliott Hughes font.flavorData = data 93*e1fe3e4aSElliott Hughes font.save(output_path) 94*e1fe3e4aSElliott Hughes 95*e1fe3e4aSElliott Hughes assert output_path.exists() 96*e1fe3e4aSElliott Hughes assert TTFont(output_path).flavorData.privData == privData 97