1from __future__ import print_function, division, absolute_import
2from fontTools.misc.py23 import *
3from fontTools.misc import sstruct
4from fontTools.misc.textTools import safeEval
5from . import DefaultTable
6
7
8hheaFormat = """
9		>  # big endian
10		tableVersion:           16.16F
11		ascent:                 h
12		descent:                h
13		lineGap:                h
14		advanceWidthMax:        H
15		minLeftSideBearing:     h
16		minRightSideBearing:    h
17		xMaxExtent:             h
18		caretSlopeRise:         h
19		caretSlopeRun:          h
20		caretOffset:            h
21		reserved0:              h
22		reserved1:              h
23		reserved2:              h
24		reserved3:              h
25		metricDataFormat:       h
26		numberOfHMetrics:       H
27"""
28
29
30class table__h_h_e_a(DefaultTable.DefaultTable):
31
32	dependencies = ['hmtx', 'glyf']
33
34	def decompile(self, data, ttFont):
35		sstruct.unpack(hheaFormat, data, self)
36
37	def compile(self, ttFont):
38		if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes:
39			self.recalc(ttFont)
40		return sstruct.pack(hheaFormat, self)
41
42	def recalc(self, ttFont):
43		hmtxTable = ttFont['hmtx']
44		if 'glyf' in ttFont:
45			glyfTable = ttFont['glyf']
46			INFINITY = 100000
47			advanceWidthMax = 0
48			minLeftSideBearing = +INFINITY  # arbitrary big number
49			minRightSideBearing = +INFINITY # arbitrary big number
50			xMaxExtent = -INFINITY          # arbitrary big negative number
51
52			for name in ttFont.getGlyphOrder():
53				width, lsb = hmtxTable[name]
54				advanceWidthMax = max(advanceWidthMax, width)
55				g = glyfTable[name]
56				if g.numberOfContours == 0:
57					continue
58				if g.numberOfContours < 0 and not hasattr(g, "xMax"):
59					# Composite glyph without extents set.
60					# Calculate those.
61					g.recalcBounds(glyfTable)
62				minLeftSideBearing = min(minLeftSideBearing, lsb)
63				rsb = width - lsb - (g.xMax - g.xMin)
64				minRightSideBearing = min(minRightSideBearing, rsb)
65				extent = lsb + (g.xMax - g.xMin)
66				xMaxExtent = max(xMaxExtent, extent)
67
68			if xMaxExtent == -INFINITY:
69				# No glyph has outlines.
70				minLeftSideBearing = 0
71				minRightSideBearing = 0
72				xMaxExtent = 0
73
74			self.advanceWidthMax = advanceWidthMax
75			self.minLeftSideBearing = minLeftSideBearing
76			self.minRightSideBearing = minRightSideBearing
77			self.xMaxExtent = xMaxExtent
78		else:
79			# XXX CFF recalc...
80			pass
81
82	def toXML(self, writer, ttFont):
83		formatstring, names, fixes = sstruct.getformat(hheaFormat)
84		for name in names:
85			value = getattr(self, name)
86			writer.simpletag(name, value=value)
87			writer.newline()
88
89	def fromXML(self, name, attrs, content, ttFont):
90		setattr(self, name, safeEval(attrs["value"]))
91
92