_h_m_t_x.py revision ca4c45681ef2ea9290c6845f8bf61dff281fc5c4
1import DefaultTable 2import Numeric 3from fontTools import ttLib 4from fontTools.misc.textTools import safeEval 5 6 7class table__h_m_t_x(DefaultTable.DefaultTable): 8 9 headerTag = 'hhea' 10 advanceName = 'width' 11 sideBearingName = 'lsb' 12 numberOfMetricsName = 'numberOfHMetrics' 13 14 def decompile(self, data, ttFont): 15 numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 16 metrics = Numeric.fromstring(data[:4 * numberOfMetrics], 17 Numeric.Int16) 18 if ttLib.endian <> "big": 19 metrics = metrics.byteswapped() 20 metrics.shape = (numberOfMetrics, 2) 21 data = data[4 * numberOfMetrics:] 22 numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics 23 numberOfSideBearings = int(numberOfSideBearings) 24 if numberOfSideBearings: 25 assert numberOfSideBearings > 0, "bad hmtx/vmtx table" 26 lastAdvance = metrics[-1][0] 27 advances = Numeric.array([lastAdvance] * numberOfSideBearings, 28 Numeric.Int16) 29 sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings], 30 Numeric.Int16) 31 if ttLib.endian <> "big": 32 sideBearings = sideBearings.byteswapped() 33 data = data[2 * numberOfSideBearings:] 34 additionalMetrics = Numeric.array([advances, sideBearings], 35 Numeric.Int16) 36 metrics = Numeric.concatenate((metrics, 37 Numeric.transpose(additionalMetrics))) 38 if data: 39 import sys 40 sys.stderr.write("too much data for hmtx/vmtx table\n") 41 metrics = metrics.tolist() 42 self.metrics = {} 43 for i in range(len(metrics)): 44 glyphName = ttFont.getGlyphName(i) 45 self.metrics[glyphName] = metrics[i] 46 47 def compile(self, ttFont): 48 metrics = [] 49 for glyphName in ttFont.getGlyphOrder(): 50 metrics.append(self.metrics[glyphName]) 51 lastAdvance = metrics[-1][0] 52 lastIndex = len(metrics) 53 while metrics[lastIndex-2][0] == lastAdvance: 54 lastIndex = lastIndex - 1 55 if lastIndex == 0: 56 # all advances are equal 57 break 58 additionalMetrics = metrics[lastIndex:] 59 additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) 60 metrics = metrics[:lastIndex] 61 setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 62 63 metrics = Numeric.array(metrics, Numeric.Int16) 64 if ttLib.endian <> "big": 65 metrics = metrics.byteswapped() 66 data = metrics.tostring() 67 68 additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16) 69 if ttLib.endian <> "big": 70 additionalMetrics = additionalMetrics.byteswapped() 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