• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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