1from fontTools.misc.loggingTools import CapturingLogHandler 2from fontTools.misc.testTools import parseXML, getXML 3from fontTools.misc.textTools import deHexStr 4from fontTools.ttLib import TTFont, newTable 5from fontTools.misc.fixedTools import log 6import os 7import unittest 8 9 10CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__))) 11DATA_DIR = os.path.join(CURR_DIR, 'data') 12 13HHEA_DATA = deHexStr( 14 '0001 0000 ' # 1.0 version 15 '02EE ' # 750 ascent 16 'FF06 ' # -250 descent 17 '00C8 ' # 200 lineGap 18 '03E8 ' # 1000 advanceWidthMax 19 'FFE7 ' # -25 minLeftSideBearing 20 'FFEC ' # -20 minRightSideBearing 21 '03D1 ' # 977 xMaxExtent 22 '0000 ' # 0 caretSlopeRise 23 '0001 ' # 1 caretSlopeRun 24 '0010 ' # 16 caretOffset 25 '0000 ' # 0 reserved0 26 '0000 ' # 0 reserved1 27 '0000 ' # 0 reserved2 28 '0000 ' # 0 reserved3 29 '0000 ' # 0 metricDataFormat 30 '002A ' # 42 numberOfHMetrics 31) 32 33HHEA_AS_DICT = { 34 'tableTag': 'hhea', 35 'tableVersion': 0x00010000, 36 'ascent': 750, 37 'descent': -250, 38 'lineGap': 200, 39 'advanceWidthMax': 1000, 40 'minLeftSideBearing': -25, 41 'minRightSideBearing': -20, 42 'xMaxExtent': 977, 43 'caretSlopeRise': 0, 44 'caretSlopeRun': 1, 45 'caretOffset': 16, 46 'reserved0': 0, 47 'reserved1': 0, 48 'reserved2': 0, 49 'reserved3': 0, 50 'metricDataFormat': 0, 51 'numberOfHMetrics': 42, 52} 53 54HHEA_XML = [ 55 '<tableVersion value="0x00010000"/>', 56 '<ascent value="750"/>', 57 '<descent value="-250"/>', 58 '<lineGap value="200"/>', 59 '<advanceWidthMax value="1000"/>', 60 '<minLeftSideBearing value="-25"/>', 61 '<minRightSideBearing value="-20"/>', 62 '<xMaxExtent value="977"/>', 63 '<caretSlopeRise value="0"/>', 64 '<caretSlopeRun value="1"/>', 65 '<caretOffset value="16"/>', 66 '<reserved0 value="0"/>', 67 '<reserved1 value="0"/>', 68 '<reserved2 value="0"/>', 69 '<reserved3 value="0"/>', 70 '<metricDataFormat value="0"/>', 71 '<numberOfHMetrics value="42"/>', 72] 73 74HHEA_XML_VERSION_AS_FLOAT = [ 75 '<tableVersion value="1.0"/>', 76] + HHEA_XML[1:] 77 78 79class HheaCompileOrToXMLTest(unittest.TestCase): 80 81 def setUp(self): 82 hhea = newTable('hhea') 83 hhea.tableVersion = 0x00010000 84 hhea.ascent = 750 85 hhea.descent = -250 86 hhea.lineGap = 200 87 hhea.advanceWidthMax = 1000 88 hhea.minLeftSideBearing = -25 89 hhea.minRightSideBearing = -20 90 hhea.xMaxExtent = 977 91 hhea.caretSlopeRise = 0 92 hhea.caretSlopeRun = 1 93 hhea.caretOffset = 16 94 hhea.metricDataFormat = 0 95 hhea.numberOfHMetrics = 42 96 hhea.reserved0 = hhea.reserved1 = hhea.reserved2 = hhea.reserved3 = 0 97 self.font = TTFont(sfntVersion='OTTO') 98 self.font['hhea'] = hhea 99 100 def test_compile(self): 101 hhea = self.font['hhea'] 102 hhea.tableVersion = 0x00010000 103 self.assertEqual(HHEA_DATA, hhea.compile(self.font)) 104 105 def test_compile_version_10_as_float(self): 106 hhea = self.font['hhea'] 107 hhea.tableVersion = 1.0 108 with CapturingLogHandler(log, "WARNING") as captor: 109 self.assertEqual(HHEA_DATA, hhea.compile(self.font)) 110 self.assertTrue( 111 len([r for r in captor.records 112 if "Table version value is a float" in r.msg]) == 1) 113 114 def test_toXML(self): 115 hhea = self.font['hhea'] 116 self.font['hhea'].tableVersion = 0x00010000 117 self.assertEqual(getXML(hhea.toXML), HHEA_XML) 118 119 def test_toXML_version_as_float(self): 120 hhea = self.font['hhea'] 121 hhea.tableVersion = 1.0 122 with CapturingLogHandler(log, "WARNING") as captor: 123 self.assertEqual(getXML(hhea.toXML), HHEA_XML) 124 self.assertTrue( 125 len([r for r in captor.records 126 if "Table version value is a float" in r.msg]) == 1) 127 128 def test_aliases(self): 129 hhea = self.font['hhea'] 130 self.assertEqual(hhea.ascent, hhea.ascender) 131 self.assertEqual(hhea.descent, hhea.descender) 132 hhea.ascender = 800 133 self.assertEqual(hhea.ascent, 800) 134 hhea.ascent = 750 135 self.assertEqual(hhea.ascender, 750) 136 hhea.descender = -300 137 self.assertEqual(hhea.descent, -300) 138 hhea.descent = -299 139 self.assertEqual(hhea.descender, -299) 140 141class HheaDecompileOrFromXMLTest(unittest.TestCase): 142 143 def setUp(self): 144 hhea = newTable('hhea') 145 self.font = TTFont(sfntVersion='OTTO') 146 self.font['hhea'] = hhea 147 148 def test_decompile(self): 149 hhea = self.font['hhea'] 150 hhea.decompile(HHEA_DATA, self.font) 151 for key in hhea.__dict__: 152 self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key]) 153 154 def test_fromXML(self): 155 hhea = self.font['hhea'] 156 for name, attrs, content in parseXML(HHEA_XML): 157 hhea.fromXML(name, attrs, content, self.font) 158 for key in hhea.__dict__: 159 self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key]) 160 161 def test_fromXML_version_as_float(self): 162 hhea = self.font['hhea'] 163 with CapturingLogHandler(log, "WARNING") as captor: 164 for name, attrs, content in parseXML(HHEA_XML_VERSION_AS_FLOAT): 165 hhea.fromXML(name, attrs, content, self.font) 166 self.assertTrue( 167 len([r for r in captor.records 168 if "Table version value is a float" in r.msg]) == 1) 169 for key in hhea.__dict__: 170 self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key]) 171 172 173class HheaRecalcTest(unittest.TestCase): 174 175 def test_recalc_TTF(self): 176 font = TTFont() 177 font.importXML(os.path.join(DATA_DIR, '_h_h_e_a_recalc_TTF.ttx')) 178 hhea = font['hhea'] 179 hhea.recalc(font) 180 self.assertEqual(hhea.advanceWidthMax, 600) 181 self.assertEqual(hhea.minLeftSideBearing, -56) 182 self.assertEqual(hhea.minRightSideBearing, 100) 183 self.assertEqual(hhea.xMaxExtent, 400) 184 185 def test_recalc_OTF(self): 186 font = TTFont() 187 font.importXML(os.path.join(DATA_DIR, '_h_h_e_a_recalc_OTF.ttx')) 188 hhea = font['hhea'] 189 hhea.recalc(font) 190 self.assertEqual(hhea.advanceWidthMax, 600) 191 self.assertEqual(hhea.minLeftSideBearing, -56) 192 self.assertEqual(hhea.minRightSideBearing, 100) 193 self.assertEqual(hhea.xMaxExtent, 400) 194 195 def test_recalc_empty(self): 196 font = TTFont() 197 font.importXML(os.path.join(DATA_DIR, '_h_h_e_a_recalc_empty.ttx')) 198 hhea = font['hhea'] 199 hhea.recalc(font) 200 self.assertEqual(hhea.advanceWidthMax, 600) 201 self.assertEqual(hhea.minLeftSideBearing, 0) 202 self.assertEqual(hhea.minRightSideBearing, 0) 203 self.assertEqual(hhea.xMaxExtent, 0) 204 205 206if __name__ == "__main__": 207 import sys 208 sys.exit(unittest.main()) 209