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