_h_m_t_x.py revision 035bc7da2318f0dcacecba2e1e24c0a4bf3cf80c
1import sys 2import DefaultTable 3import array 4from fontTools import ttLib 5from fontTools.misc.textTools import safeEval 6import warnings 7 8 9class table__h_m_t_x(DefaultTable.DefaultTable): 10 11 headerTag = 'hhea' 12 advanceName = 'width' 13 sideBearingName = 'lsb' 14 numberOfMetricsName = 'numberOfHMetrics' 15 16 def decompile(self, data, ttFont): 17 numGlyphs = ttFont['maxp'].numGlyphs 18 numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 19 if numberOfMetrics > numGlyphs: 20 numberOfMetrics = numGlyphs # We warn later. 21 # Note: advanceWidth is unsigned, but we read/write as signed. 22 metrics = array.array("h", data[:4 * numberOfMetrics]) 23 if sys.byteorder <> "big": 24 metrics.byteswap() 25 data = data[4 * numberOfMetrics:] 26 numberOfSideBearings = numGlyphs - numberOfMetrics 27 sideBearings = array.array("h", data[:2 * numberOfSideBearings]) 28 data = data[2 * numberOfSideBearings:] 29 30 if sys.byteorder <> "big": 31 sideBearings.byteswap() 32 if data: 33 sys.stderr.write("too much data for hmtx/vmtx table\n") 34 self.metrics = {} 35 for i in range(numberOfMetrics): 36 glyphName = ttFont.getGlyphName(i) 37 self.metrics[glyphName] = list(metrics[i*2:i*2+2]) 38 lastAdvance = metrics[-2] 39 for i in range(numberOfSideBearings): 40 glyphName = ttFont.getGlyphName(i + numberOfMetrics) 41 self.metrics[glyphName] = [lastAdvance, sideBearings[i]] 42 43 def compile(self, ttFont): 44 metrics = [] 45 for glyphName in ttFont.getGlyphOrder(): 46 metrics.append(self.metrics[glyphName]) 47 lastAdvance = metrics[-1][0] 48 lastIndex = len(metrics) 49 while metrics[lastIndex-2][0] == lastAdvance: 50 lastIndex -= 1 51 if lastIndex <= 1: 52 # all advances are equal 53 lastIndex = 1 54 break 55 additionalMetrics = metrics[lastIndex:] 56 additionalMetrics = [sb for advance, sb in additionalMetrics] 57 metrics = metrics[:lastIndex] 58 setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 59 60 metrics = sum(metrics,[]) 61 metrics = array.array("h", metrics) 62 if sys.byteorder <> "big": 63 metrics.byteswap() 64 data = metrics.tostring() 65 66 additionalMetrics = array.array("h", additionalMetrics) 67 if sys.byteorder <> "big": 68 additionalMetrics.byteswap() 69 data = data + additionalMetrics.tostring() 70 return data 71 72 def toXML(self, writer, ttFont): 73 names = self.metrics.keys() 74 names.sort() 75 for glyphName in names: 76 advance, sb = self.metrics[glyphName] 77 writer.simpletag("mtx", [ 78 ("name", glyphName), 79 (self.advanceName, advance), 80 (self.sideBearingName, sb), 81 ]) 82 writer.newline() 83 84 def fromXML(self, (name, attrs, content), ttFont): 85 if not hasattr(self, "metrics"): 86 self.metrics = {} 87 if name == "mtx": 88 self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 89 safeEval(attrs[self.sideBearingName])] 90 91 def __getitem__(self, glyphName): 92 return self.metrics[glyphName] 93 94 def __setitem__(self, glyphName, (advance, sb)): 95 self.metrics[glyphName] = advance, sb 96 97