blob: 3e639a5828c7ee544643f1788f96483c94a6d408 [file] [log] [blame]
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)
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))
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)
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))
def test_read_with_path(self):
import pathlib
font = t1Lib.T1Font(pathlib.Path(PFB))
@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'])
def test_parse_pfa(self):
font = t1Lib.T1Font(PFA)
font.parse()
self.assertEqual(font['FontName'], 'TestT1-Regular')
self.assertTrue('Subrs' in font['Private'])
def test_parse_pfb(self):
font = t1Lib.T1Font(PFB)
font.parse()
self.assertEqual(font['FontName'], 'TestT1-Regular')
self.assertTrue('Subrs' in font['Private'])
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))
@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
if __name__ == '__main__':
import sys
sys.exit(unittest.main())