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 def setUp(self): 81 hhea = newTable("hhea") 82 hhea.tableVersion = 0x00010000 83 hhea.ascent = 750 84 hhea.descent = -250 85 hhea.lineGap = 200 86 hhea.advanceWidthMax = 1000 87 hhea.minLeftSideBearing = -25 88 hhea.minRightSideBearing = -20 89 hhea.xMaxExtent = 977 90 hhea.caretSlopeRise = 0 91 hhea.caretSlopeRun = 1 92 hhea.caretOffset = 16 93 hhea.metricDataFormat = 0 94 hhea.numberOfHMetrics = 42 95 hhea.reserved0 = hhea.reserved1 = hhea.reserved2 = hhea.reserved3 = 0 96 self.font = TTFont(sfntVersion="OTTO") 97 self.font["hhea"] = hhea 98 99 def test_compile(self): 100 hhea = self.font["hhea"] 101 hhea.tableVersion = 0x00010000 102 self.assertEqual(HHEA_DATA, hhea.compile(self.font)) 103 104 def test_compile_version_10_as_float(self): 105 hhea = self.font["hhea"] 106 hhea.tableVersion = 1.0 107 with CapturingLogHandler(log, "WARNING") as captor: 108 self.assertEqual(HHEA_DATA, hhea.compile(self.font)) 109 self.assertTrue( 110 len( 111 [r for r in captor.records if "Table version value is a float" in r.msg] 112 ) 113 == 1 114 ) 115 116 def test_toXML(self): 117 hhea = self.font["hhea"] 118 self.font["hhea"].tableVersion = 0x00010000 119 self.assertEqual(getXML(hhea.toXML), HHEA_XML) 120 121 def test_toXML_version_as_float(self): 122 hhea = self.font["hhea"] 123 hhea.tableVersion = 1.0 124 with CapturingLogHandler(log, "WARNING") as captor: 125 self.assertEqual(getXML(hhea.toXML), HHEA_XML) 126 self.assertTrue( 127 len( 128 [r for r in captor.records if "Table version value is a float" in r.msg] 129 ) 130 == 1 131 ) 132 133 def test_aliases(self): 134 hhea = self.font["hhea"] 135 self.assertEqual(hhea.ascent, hhea.ascender) 136 self.assertEqual(hhea.descent, hhea.descender) 137 hhea.ascender = 800 138 self.assertEqual(hhea.ascent, 800) 139 hhea.ascent = 750 140 self.assertEqual(hhea.ascender, 750) 141 hhea.descender = -300 142 self.assertEqual(hhea.descent, -300) 143 hhea.descent = -299 144 self.assertEqual(hhea.descender, -299) 145 146 147class HheaDecompileOrFromXMLTest(unittest.TestCase): 148 def setUp(self): 149 hhea = newTable("hhea") 150 self.font = TTFont(sfntVersion="OTTO") 151 self.font["hhea"] = hhea 152 153 def test_decompile(self): 154 hhea = self.font["hhea"] 155 hhea.decompile(HHEA_DATA, self.font) 156 for key in hhea.__dict__: 157 self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key]) 158 159 def test_fromXML(self): 160 hhea = self.font["hhea"] 161 for name, attrs, content in parseXML(HHEA_XML): 162 hhea.fromXML(name, attrs, content, self.font) 163 for key in hhea.__dict__: 164 self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key]) 165 166 def test_fromXML_version_as_float(self): 167 hhea = self.font["hhea"] 168 with CapturingLogHandler(log, "WARNING") as captor: 169 for name, attrs, content in parseXML(HHEA_XML_VERSION_AS_FLOAT): 170 hhea.fromXML(name, attrs, content, self.font) 171 self.assertTrue( 172 len( 173 [r for r in captor.records if "Table version value is a float" in r.msg] 174 ) 175 == 1 176 ) 177 for key in hhea.__dict__: 178 self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key]) 179 180 181class HheaRecalcTest(unittest.TestCase): 182 def test_recalc_TTF(self): 183 font = TTFont() 184 font.importXML(os.path.join(DATA_DIR, "_h_h_e_a_recalc_TTF.ttx")) 185 hhea = font["hhea"] 186 hhea.recalc(font) 187 self.assertEqual(hhea.advanceWidthMax, 600) 188 self.assertEqual(hhea.minLeftSideBearing, -56) 189 self.assertEqual(hhea.minRightSideBearing, 100) 190 self.assertEqual(hhea.xMaxExtent, 400) 191 192 def test_recalc_OTF(self): 193 font = TTFont() 194 font.importXML(os.path.join(DATA_DIR, "_h_h_e_a_recalc_OTF.ttx")) 195 hhea = font["hhea"] 196 hhea.recalc(font) 197 self.assertEqual(hhea.advanceWidthMax, 600) 198 self.assertEqual(hhea.minLeftSideBearing, -56) 199 self.assertEqual(hhea.minRightSideBearing, 100) 200 self.assertEqual(hhea.xMaxExtent, 400) 201 202 def test_recalc_empty(self): 203 font = TTFont() 204 font.importXML(os.path.join(DATA_DIR, "_h_h_e_a_recalc_empty.ttx")) 205 hhea = font["hhea"] 206 hhea.recalc(font) 207 self.assertEqual(hhea.advanceWidthMax, 600) 208 self.assertEqual(hhea.minLeftSideBearing, 0) 209 self.assertEqual(hhea.minRightSideBearing, 0) 210 self.assertEqual(hhea.xMaxExtent, 0) 211 212 213if __name__ == "__main__": 214 import sys 215 216 sys.exit(unittest.main()) 217