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