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 13VHEA_DATA_VERSION_11 = deHexStr( 14 "0001 1000 " # 1.1 version 15 "01F4 " # 500 ascent 16 "FE0C " # -500 descent 17 "0000 " # 0 lineGap 18 "0BB8 " # 3000 advanceHeightMax 19 "FC16 " # -1002 minTopSideBearing 20 "FD5B " # -677 minBottomSideBearing 21 "0B70 " # 2928 yMaxExtent 22 "0000 " # 0 caretSlopeRise 23 "0001 " # 1 caretSlopeRun 24 "0000 " # 0 caretOffset 25 "0000 " # 0 reserved1 26 "0000 " # 0 reserved2 27 "0000 " # 0 reserved3 28 "0000 " # 0 reserved4 29 "0000 " # 0 metricDataFormat 30 "000C " # 12 numberOfVMetrics 31) 32 33VHEA_DATA_VERSION_10 = deHexStr("00010000") + VHEA_DATA_VERSION_11[4:] 34 35VHEA_VERSION_11_AS_DICT = { 36 "tableTag": "vhea", 37 "tableVersion": 0x00011000, 38 "ascent": 500, 39 "descent": -500, 40 "lineGap": 0, 41 "advanceHeightMax": 3000, 42 "minTopSideBearing": -1002, 43 "minBottomSideBearing": -677, 44 "yMaxExtent": 2928, 45 "caretSlopeRise": 0, 46 "caretSlopeRun": 1, 47 "caretOffset": 0, 48 "reserved1": 0, 49 "reserved2": 0, 50 "reserved3": 0, 51 "reserved4": 0, 52 "metricDataFormat": 0, 53 "numberOfVMetrics": 12, 54} 55 56VHEA_VERSION_10_AS_DICT = dict(VHEA_VERSION_11_AS_DICT) 57VHEA_VERSION_10_AS_DICT["tableVersion"] = 0x00010000 58 59VHEA_XML_VERSION_11 = [ 60 '<tableVersion value="0x00011000"/>', 61 '<ascent value="500"/>', 62 '<descent value="-500"/>', 63 '<lineGap value="0"/>', 64 '<advanceHeightMax value="3000"/>', 65 '<minTopSideBearing value="-1002"/>', 66 '<minBottomSideBearing value="-677"/>', 67 '<yMaxExtent value="2928"/>', 68 '<caretSlopeRise value="0"/>', 69 '<caretSlopeRun value="1"/>', 70 '<caretOffset value="0"/>', 71 '<reserved1 value="0"/>', 72 '<reserved2 value="0"/>', 73 '<reserved3 value="0"/>', 74 '<reserved4 value="0"/>', 75 '<metricDataFormat value="0"/>', 76 '<numberOfVMetrics value="12"/>', 77] 78 79VHEA_XML_VERSION_11_AS_FLOAT = [ 80 '<tableVersion value="1.0625"/>', 81] + VHEA_XML_VERSION_11[1:] 82 83VHEA_XML_VERSION_10 = [ 84 '<tableVersion value="0x00010000"/>', 85] + VHEA_XML_VERSION_11[1:] 86 87VHEA_XML_VERSION_10_AS_FLOAT = [ 88 '<tableVersion value="1.0"/>', 89] + VHEA_XML_VERSION_11[1:] 90 91 92class VheaCompileOrToXMLTest(unittest.TestCase): 93 def setUp(self): 94 vhea = newTable("vhea") 95 vhea.tableVersion = 0x00010000 96 vhea.ascent = 500 97 vhea.descent = -500 98 vhea.lineGap = 0 99 vhea.advanceHeightMax = 3000 100 vhea.minTopSideBearing = -1002 101 vhea.minBottomSideBearing = -677 102 vhea.yMaxExtent = 2928 103 vhea.caretSlopeRise = 0 104 vhea.caretSlopeRun = 1 105 vhea.caretOffset = 0 106 vhea.metricDataFormat = 0 107 vhea.numberOfVMetrics = 12 108 vhea.reserved1 = vhea.reserved2 = vhea.reserved3 = vhea.reserved4 = 0 109 self.font = TTFont(sfntVersion="OTTO") 110 self.font["vhea"] = vhea 111 112 def test_compile_caretOffset_as_reserved0(self): 113 vhea = self.font["vhea"] 114 del vhea.caretOffset 115 vhea.reserved0 = 0 116 self.assertEqual(VHEA_DATA_VERSION_10, vhea.compile(self.font)) 117 118 def test_compile_version_10(self): 119 vhea = self.font["vhea"] 120 vhea.tableVersion = 0x00010000 121 self.assertEqual(VHEA_DATA_VERSION_10, vhea.compile(self.font)) 122 123 def test_compile_version_10_as_float(self): 124 vhea = self.font["vhea"] 125 vhea.tableVersion = 1.0 126 with CapturingLogHandler(log, "WARNING") as captor: 127 self.assertEqual(VHEA_DATA_VERSION_10, vhea.compile(self.font)) 128 self.assertTrue( 129 len( 130 [r for r in captor.records if "Table version value is a float" in r.msg] 131 ) 132 == 1 133 ) 134 135 def test_compile_version_11(self): 136 vhea = self.font["vhea"] 137 vhea.tableVersion = 0x00011000 138 self.assertEqual(VHEA_DATA_VERSION_11, vhea.compile(self.font)) 139 140 def test_compile_version_11_as_float(self): 141 vhea = self.font["vhea"] 142 vhea.tableVersion = 1.0625 143 with CapturingLogHandler(log, "WARNING") as captor: 144 self.assertEqual(VHEA_DATA_VERSION_11, vhea.compile(self.font)) 145 self.assertTrue( 146 len( 147 [r for r in captor.records if "Table version value is a float" in r.msg] 148 ) 149 == 1 150 ) 151 152 def test_toXML_caretOffset_as_reserved0(self): 153 vhea = self.font["vhea"] 154 del vhea.caretOffset 155 vhea.reserved0 = 0 156 self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_10) 157 158 def test_toXML_version_10(self): 159 vhea = self.font["vhea"] 160 self.font["vhea"].tableVersion = 0x00010000 161 self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_10) 162 163 def test_toXML_version_10_as_float(self): 164 vhea = self.font["vhea"] 165 vhea.tableVersion = 1.0 166 with CapturingLogHandler(log, "WARNING") as captor: 167 self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_10) 168 self.assertTrue( 169 len( 170 [r for r in captor.records if "Table version value is a float" in r.msg] 171 ) 172 == 1 173 ) 174 175 def test_toXML_version_11(self): 176 vhea = self.font["vhea"] 177 self.font["vhea"].tableVersion = 0x00011000 178 self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_11) 179 180 def test_toXML_version_11_as_float(self): 181 vhea = self.font["vhea"] 182 vhea.tableVersion = 1.0625 183 with CapturingLogHandler(log, "WARNING") as captor: 184 self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_11) 185 self.assertTrue( 186 len( 187 [r for r in captor.records if "Table version value is a float" in r.msg] 188 ) 189 == 1 190 ) 191 192 193class VheaDecompileOrFromXMLTest(unittest.TestCase): 194 def setUp(self): 195 vhea = newTable("vhea") 196 self.font = TTFont(sfntVersion="OTTO") 197 self.font["vhea"] = vhea 198 199 def test_decompile_version_10(self): 200 vhea = self.font["vhea"] 201 vhea.decompile(VHEA_DATA_VERSION_10, self.font) 202 for key in vhea.__dict__: 203 self.assertEqual(getattr(vhea, key), VHEA_VERSION_10_AS_DICT[key]) 204 205 def test_decompile_version_11(self): 206 vhea = self.font["vhea"] 207 vhea.decompile(VHEA_DATA_VERSION_11, self.font) 208 for key in vhea.__dict__: 209 self.assertEqual(getattr(vhea, key), VHEA_VERSION_11_AS_DICT[key]) 210 211 def test_fromXML_version_10(self): 212 vhea = self.font["vhea"] 213 for name, attrs, content in parseXML(VHEA_XML_VERSION_10): 214 vhea.fromXML(name, attrs, content, self.font) 215 for key in vhea.__dict__: 216 self.assertEqual(getattr(vhea, key), VHEA_VERSION_10_AS_DICT[key]) 217 218 def test_fromXML_version_10_as_float(self): 219 vhea = self.font["vhea"] 220 with CapturingLogHandler(log, "WARNING") as captor: 221 for name, attrs, content in parseXML(VHEA_XML_VERSION_10_AS_FLOAT): 222 vhea.fromXML(name, attrs, content, self.font) 223 self.assertTrue( 224 len( 225 [r for r in captor.records if "Table version value is a float" in r.msg] 226 ) 227 == 1 228 ) 229 for key in vhea.__dict__: 230 self.assertEqual(getattr(vhea, key), VHEA_VERSION_10_AS_DICT[key]) 231 232 def test_fromXML_version_11(self): 233 vhea = self.font["vhea"] 234 for name, attrs, content in parseXML(VHEA_XML_VERSION_11): 235 vhea.fromXML(name, attrs, content, self.font) 236 for key in vhea.__dict__: 237 self.assertEqual(getattr(vhea, key), VHEA_VERSION_11_AS_DICT[key]) 238 239 def test_fromXML_version_11_as_float(self): 240 vhea = self.font["vhea"] 241 with CapturingLogHandler(log, "WARNING") as captor: 242 for name, attrs, content in parseXML(VHEA_XML_VERSION_11_AS_FLOAT): 243 vhea.fromXML(name, attrs, content, self.font) 244 self.assertTrue( 245 len( 246 [r for r in captor.records if "Table version value is a float" in r.msg] 247 ) 248 == 1 249 ) 250 for key in vhea.__dict__: 251 self.assertEqual(getattr(vhea, key), VHEA_VERSION_11_AS_DICT[key]) 252 253 254class VheaRecalcTest(unittest.TestCase): 255 def test_recalc_TTF(self): 256 font = TTFont() 257 font.importXML(os.path.join(DATA_DIR, "_v_h_e_a_recalc_TTF.ttx")) 258 vhea = font["vhea"] 259 vhea.recalc(font) 260 self.assertEqual(vhea.advanceHeightMax, 900) 261 self.assertEqual(vhea.minTopSideBearing, 200) 262 self.assertEqual(vhea.minBottomSideBearing, 377) 263 self.assertEqual(vhea.yMaxExtent, 312) 264 265 def test_recalc_OTF(self): 266 font = TTFont() 267 font.importXML(os.path.join(DATA_DIR, "_v_h_e_a_recalc_OTF.ttx")) 268 vhea = font["vhea"] 269 vhea.recalc(font) 270 self.assertEqual(vhea.advanceHeightMax, 900) 271 self.assertEqual(vhea.minTopSideBearing, 200) 272 self.assertEqual(vhea.minBottomSideBearing, 377) 273 self.assertEqual(vhea.yMaxExtent, 312) 274 275 def test_recalc_empty(self): 276 font = TTFont() 277 font.importXML(os.path.join(DATA_DIR, "_v_h_e_a_recalc_empty.ttx")) 278 vhea = font["vhea"] 279 vhea.recalc(font) 280 self.assertEqual(vhea.advanceHeightMax, 900) 281 self.assertEqual(vhea.minTopSideBearing, 0) 282 self.assertEqual(vhea.minBottomSideBearing, 0) 283 self.assertEqual(vhea.yMaxExtent, 0) 284 285 286if __name__ == "__main__": 287 import sys 288 289 sys.exit(unittest.main()) 290