fonttools/Tests/t1Lib/t1Lib_test.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

199 lines
6.4 KiB
Python
Raw Permalink Normal View History

import unittest
import os
import sys
from fontTools import t1Lib
from fontTools.pens.basePen import NullPen
from fontTools.misc.psCharStrings import T1CharString
import random
CWD = os.path.abspath(os.path.dirname(__file__))
DATADIR = os.path.join(CWD, "data")
# I used `tx` to convert PFA to LWFN (stored in the data fork)
LWFN = os.path.join(DATADIR, "TestT1-Regular.lwfn")
PFA = os.path.join(DATADIR, "TestT1-Regular.pfa")
PFB = os.path.join(DATADIR, "TestT1-Regular.pfb")
WEIRD_ZEROS = os.path.join(DATADIR, "TestT1-weird-zeros.pfa")
# ellipsis is hinted with 55 131 296 131 537 131 vstem3 0 122 hstem
ELLIPSIS_HINTED = os.path.join(DATADIR, "TestT1-ellipsis-hinted.pfa")
class FindEncryptedChunksTest(unittest.TestCase):
def test_findEncryptedChunks(self):
with open(PFA, "rb") as f:
data = f.read()
chunks = t1Lib.findEncryptedChunks(data)
self.assertEqual(len(chunks), 3)
self.assertFalse(chunks[0][0])
# the second chunk is encrypted
self.assertTrue(chunks[1][0])
self.assertFalse(chunks[2][0])
def test_findEncryptedChunks_weird_zeros(self):
with open(WEIRD_ZEROS, "rb") as f:
data = f.read()
# Just assert that this doesn't raise any exception for not finding the
# end of eexec
t1Lib.findEncryptedChunks(data)
class DecryptType1Test(unittest.TestCase):
def test_decryptType1(self):
with open(PFA, "rb") as f:
data = f.read()
decrypted = t1Lib.decryptType1(data)
self.assertNotEqual(decrypted, data)
class ReadWriteTest(unittest.TestCase):
def test_read_pfa_write_pfb(self):
font = t1Lib.T1Font(PFA)
data = self.write(font, "PFB")
self.assertEqual(font.getData(), data)
2022-12-13 11:26:36 +00:00
def test_read_and_parse_pfa_write_pfb(self):
font = t1Lib.T1Font(PFA)
font.parse()
saved_font = self.write(font, "PFB", dohex=False, doparse=True)
self.assertTrue(same_dicts(font.font, saved_font))
2022-12-13 11:26:36 +00:00
def test_read_pfb_write_pfa(self):
font = t1Lib.T1Font(PFB)
# 'OTHER' == 'PFA'
data = self.write(font, "OTHER", dohex=True)
self.assertEqual(font.getData(), data)
2022-12-13 11:26:36 +00:00
def test_read_and_parse_pfb_write_pfa(self):
font = t1Lib.T1Font(PFB)
font.parse()
# 'OTHER' == 'PFA'
saved_font = self.write(font, "OTHER", dohex=True, doparse=True)
self.assertTrue(same_dicts(font.font, saved_font))
2022-12-13 11:26:36 +00:00
def test_read_with_path(self):
import pathlib
2022-12-13 11:26:36 +00:00
font = t1Lib.T1Font(pathlib.Path(PFB))
2022-12-13 11:26:36 +00:00
@staticmethod
def write(font, outtype, dohex=False, doparse=False):
temp = os.path.join(DATADIR, "temp." + outtype.lower())
try:
font.saveAs(temp, outtype, dohex=dohex)
newfont = t1Lib.T1Font(temp)
if doparse:
newfont.parse()
data = newfont.font
else:
data = newfont.getData()
finally:
if os.path.exists(temp):
os.remove(temp)
return data
class T1FontTest(unittest.TestCase):
def test_parse_lwfn(self):
# the extended attrs are lost on git so we can't auto-detect 'LWFN'
font = t1Lib.T1Font(LWFN, kind="LWFN")
font.parse()
self.assertEqual(font["FontName"], "TestT1-Regular")
self.assertTrue("Subrs" in font["Private"])
2022-12-13 11:26:36 +00:00
def test_parse_pfa(self):
font = t1Lib.T1Font(PFA)
font.parse()
self.assertEqual(font["FontName"], "TestT1-Regular")
self.assertTrue("Subrs" in font["Private"])
2022-12-13 11:26:36 +00:00
def test_parse_pfb(self):
font = t1Lib.T1Font(PFB)
font.parse()
self.assertEqual(font["FontName"], "TestT1-Regular")
self.assertTrue("Subrs" in font["Private"])
2022-12-13 11:26:36 +00:00
def test_getGlyphSet(self):
font = t1Lib.T1Font(PFA)
glyphs = font.getGlyphSet()
i = random.randrange(len(glyphs))
aglyph = list(glyphs.values())[i]
self.assertTrue(hasattr(aglyph, "draw"))
self.assertFalse(hasattr(aglyph, "width"))
aglyph.draw(NullPen())
self.assertTrue(hasattr(aglyph, "width"))
class EditTest(unittest.TestCase):
def test_edit_pfa(self):
font = t1Lib.T1Font(PFA)
ellipsis = font.getGlyphSet()["ellipsis"]
ellipsis.decompile()
program = []
for v in ellipsis.program:
try:
program.append(int(v))
except:
program.append(v)
if v == "hsbw":
hints = [55, 131, 296, 131, 537, 131, "vstem3", 0, 122, "hstem"]
program.extend(hints)
ellipsis.program = program
# 'OTHER' == 'PFA'
saved_font = self.write(font, "OTHER", dohex=True, doparse=True)
hinted_font = t1Lib.T1Font(ELLIPSIS_HINTED)
hinted_font.parse()
self.assertTrue(same_dicts(hinted_font.font, saved_font))
2022-12-13 11:26:36 +00:00
@staticmethod
def write(font, outtype, dohex=False, doparse=False):
temp = os.path.join(DATADIR, "temp." + outtype.lower())
try:
font.saveAs(temp, outtype, dohex=dohex)
newfont = t1Lib.T1Font(temp)
if doparse:
newfont.parse()
data = newfont.font
else:
data = newfont.getData()
finally:
if os.path.exists(temp):
os.remove(temp)
return data
def same_dicts(dict1, dict2):
if dict1.keys() != dict2.keys():
return False
for key, value in dict1.items():
if isinstance(value, dict):
if not same_dicts(value, dict2[key]):
return False
elif isinstance(value, list):
if len(value) != len(dict2[key]):
return False
for elem1, elem2 in zip(value, dict2[key]):
if isinstance(elem1, T1CharString):
elem1.compile()
elem2.compile()
if elem1.bytecode != elem2.bytecode:
return False
else:
if elem1 != elem2:
return False
elif isinstance(value, T1CharString):
value.compile()
dict2[key].compile()
if value.bytecode != dict2[key].bytecode:
return False
else:
if value != dict2[key]:
return False
return True
2022-12-13 11:26:36 +00:00
if __name__ == "__main__":
import sys
2022-12-13 11:26:36 +00:00
sys.exit(unittest.main())