_h_m_t_x.py revision 4c2f1b6a2c2e4d85d4987606795097d592b1586a
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 allMetrics = [] 61 for item in metrics: 62 allMetrics.extend(item) 63 allMetrics = array.array("h", allMetrics) 64 if sys.byteorder <> "big": 65 allMetrics.byteswap() 66 data = allMetrics.tostring() 67 68 additionalMetrics = array.array("h", additionalMetrics) 69 if sys.byteorder <> "big": 70 additionalMetrics.byteswap() 71 data = data + additionalMetrics.tostring() 72 return data 73 74 def toXML(self, writer, ttFont): 75 names = self.metrics.keys() 76 names.sort() 77 for glyphName in names: 78 advance, sb = self.metrics[glyphName] 79 writer.simpletag("mtx", [ 80 ("name", glyphName), 81 (self.advanceName, advance), 82 (self.sideBearingName, sb), 83 ]) 84 writer.newline() 85 86 def fromXML(self, (name, attrs, content), ttFont): 87 if not hasattr(self, "metrics"): 88 self.metrics = {} 89 if name == "mtx": 90 self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 91 safeEval(attrs[self.sideBearingName])] 92 93 def __getitem__(self, glyphName): 94 return self.metrics[glyphName] 95 96 def __setitem__(self, glyphName, (advance, sb)): 97 self.metrics[glyphName] = advance, sb 98 99