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