from fontTools.misc.loggingTools import CapturingLogHandler
from fontTools.misc.testTools import parseXML, getXML
from fontTools.misc.textTools import deHexStr
from fontTools.ttLib import TTFont, newTable
from fontTools.misc.fixedTools import log
import os
import unittest


CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
DATA_DIR = os.path.join(CURR_DIR, 'data')

HHEA_DATA = deHexStr(
    '0001 0000 '  # 1.0   version
    '02EE '       # 750   ascent
    'FF06 '       # -250  descent
    '00C8 '       # 200   lineGap
    '03E8 '       # 1000  advanceWidthMax
    'FFE7 '       # -25   minLeftSideBearing
    'FFEC '       # -20   minRightSideBearing
    '03D1 '       # 977   xMaxExtent
    '0000 '       # 0     caretSlopeRise
    '0001 '       # 1     caretSlopeRun
    '0010 '       # 16    caretOffset
    '0000 '       # 0     reserved0
    '0000 '       # 0     reserved1
    '0000 '       # 0     reserved2
    '0000 '       # 0     reserved3
    '0000 '       # 0     metricDataFormat
    '002A '       # 42    numberOfHMetrics
)

HHEA_AS_DICT = {
    'tableTag': 'hhea',
    'tableVersion': 0x00010000,
    'ascent': 750,
    'descent': -250,
    'lineGap': 200,
    'advanceWidthMax': 1000,
    'minLeftSideBearing': -25,
    'minRightSideBearing': -20,
    'xMaxExtent': 977,
    'caretSlopeRise': 0,
    'caretSlopeRun': 1,
    'caretOffset': 16,
    'reserved0': 0,
    'reserved1': 0,
    'reserved2': 0,
    'reserved3': 0,
    'metricDataFormat': 0,
    'numberOfHMetrics': 42,
}

HHEA_XML = [
    '<tableVersion value="0x00010000"/>',
    '<ascent value="750"/>',
    '<descent value="-250"/>',
    '<lineGap value="200"/>',
    '<advanceWidthMax value="1000"/>',
    '<minLeftSideBearing value="-25"/>',
    '<minRightSideBearing value="-20"/>',
    '<xMaxExtent value="977"/>',
    '<caretSlopeRise value="0"/>',
    '<caretSlopeRun value="1"/>',
    '<caretOffset value="16"/>',
    '<reserved0 value="0"/>',
    '<reserved1 value="0"/>',
    '<reserved2 value="0"/>',
    '<reserved3 value="0"/>',
    '<metricDataFormat value="0"/>',
    '<numberOfHMetrics value="42"/>',
]

HHEA_XML_VERSION_AS_FLOAT = [
    '<tableVersion value="1.0"/>',
] + HHEA_XML[1:]


class HheaCompileOrToXMLTest(unittest.TestCase):

    def setUp(self):
        hhea = newTable('hhea')
        hhea.tableVersion = 0x00010000
        hhea.ascent = 750
        hhea.descent = -250
        hhea.lineGap = 200
        hhea.advanceWidthMax = 1000
        hhea.minLeftSideBearing = -25
        hhea.minRightSideBearing = -20
        hhea.xMaxExtent = 977
        hhea.caretSlopeRise = 0
        hhea.caretSlopeRun = 1
        hhea.caretOffset = 16
        hhea.metricDataFormat = 0
        hhea.numberOfHMetrics = 42
        hhea.reserved0 = hhea.reserved1 = hhea.reserved2 = hhea.reserved3 = 0
        self.font = TTFont(sfntVersion='OTTO')
        self.font['hhea'] = hhea

    def test_compile(self):
        hhea = self.font['hhea']
        hhea.tableVersion = 0x00010000
        self.assertEqual(HHEA_DATA, hhea.compile(self.font))

    def test_compile_version_10_as_float(self):
        hhea = self.font['hhea']
        hhea.tableVersion = 1.0
        with CapturingLogHandler(log, "WARNING") as captor:
            self.assertEqual(HHEA_DATA, hhea.compile(self.font))
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)

    def test_toXML(self):
        hhea = self.font['hhea']
        self.font['hhea'].tableVersion = 0x00010000
        self.assertEqual(getXML(hhea.toXML), HHEA_XML)

    def test_toXML_version_as_float(self):
        hhea = self.font['hhea']
        hhea.tableVersion = 1.0
        with CapturingLogHandler(log, "WARNING") as captor:
            self.assertEqual(getXML(hhea.toXML), HHEA_XML)
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)

    def test_aliases(self):
        hhea = self.font['hhea']
        self.assertEqual(hhea.ascent, hhea.ascender)
        self.assertEqual(hhea.descent, hhea.descender)
        hhea.ascender = 800
        self.assertEqual(hhea.ascent, 800)
        hhea.ascent = 750
        self.assertEqual(hhea.ascender, 750)
        hhea.descender = -300
        self.assertEqual(hhea.descent, -300)
        hhea.descent = -299
        self.assertEqual(hhea.descender, -299)

class HheaDecompileOrFromXMLTest(unittest.TestCase):

    def setUp(self):
        hhea = newTable('hhea')
        self.font = TTFont(sfntVersion='OTTO')
        self.font['hhea'] = hhea

    def test_decompile(self):
        hhea = self.font['hhea']
        hhea.decompile(HHEA_DATA, self.font)
        for key in hhea.__dict__:
            self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key])

    def test_fromXML(self):
        hhea = self.font['hhea']
        for name, attrs, content in parseXML(HHEA_XML):
            hhea.fromXML(name, attrs, content, self.font)
        for key in hhea.__dict__:
            self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key])

    def test_fromXML_version_as_float(self):
        hhea = self.font['hhea']
        with CapturingLogHandler(log, "WARNING") as captor:
            for name, attrs, content in parseXML(HHEA_XML_VERSION_AS_FLOAT):
                hhea.fromXML(name, attrs, content, self.font)
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)
        for key in hhea.__dict__:
            self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key])


class HheaRecalcTest(unittest.TestCase):

    def test_recalc_TTF(self):
        font = TTFont()
        font.importXML(os.path.join(DATA_DIR, '_h_h_e_a_recalc_TTF.ttx'))
        hhea = font['hhea']
        hhea.recalc(font)
        self.assertEqual(hhea.advanceWidthMax, 600)
        self.assertEqual(hhea.minLeftSideBearing, -56)
        self.assertEqual(hhea.minRightSideBearing, 100)
        self.assertEqual(hhea.xMaxExtent, 400)

    def test_recalc_OTF(self):
        font = TTFont()
        font.importXML(os.path.join(DATA_DIR, '_h_h_e_a_recalc_OTF.ttx'))
        hhea = font['hhea']
        hhea.recalc(font)
        self.assertEqual(hhea.advanceWidthMax, 600)
        self.assertEqual(hhea.minLeftSideBearing, -56)
        self.assertEqual(hhea.minRightSideBearing, 100)
        self.assertEqual(hhea.xMaxExtent, 400)

    def test_recalc_empty(self):
        font = TTFont()
        font.importXML(os.path.join(DATA_DIR, '_h_h_e_a_recalc_empty.ttx'))
        hhea = font['hhea']
        hhea.recalc(font)
        self.assertEqual(hhea.advanceWidthMax, 600)
        self.assertEqual(hhea.minLeftSideBearing, 0)
        self.assertEqual(hhea.minRightSideBearing, 0)
        self.assertEqual(hhea.xMaxExtent, 0)


if __name__ == "__main__":
    import sys
    sys.exit(unittest.main())
