_h_m_t_x.py revision 212ea147062ac1ba9c914836b25bb4a8a8463522
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import sys 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import DefaultTable 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import Numeric 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from fontTools import ttLib 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from fontTools.misc.textTools import safeEval 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class table__h_m_t_x(DefaultTable.DefaultTable): 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) headerTag = 'hhea' 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) advanceName = 'width' 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sideBearingName = 'lsb' 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) numberOfMetricsName = 'numberOfHMetrics' 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 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 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 <= 1: 56 # all advances are equal 57 lastIndex = 1 58 break 59 additionalMetrics = metrics[lastIndex:] 60 additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) 61 metrics = metrics[:lastIndex] 62 setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 63 64 metrics = Numeric.array(metrics, Numeric.Int16) 65 if sys.byteorder <> "big": 66 metrics = metrics.byteswapped() 67 data = metrics.tostring() 68 69 additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16) 70 if sys.byteorder <> "big": 71 additionalMetrics = additionalMetrics.byteswapped() 72 data = data + additionalMetrics.tostring() 73 return data 74 75 def toXML(self, writer, ttFont): 76 names = self.metrics.keys() 77 names.sort() 78 for glyphName in names: 79 advance, sb = self.metrics[glyphName] 80 writer.simpletag("mtx", [ 81 ("name", glyphName), 82 (self.advanceName, advance), 83 (self.sideBearingName, sb), 84 ]) 85 writer.newline() 86 87 def fromXML(self, (name, attrs, content), ttFont): 88 if not hasattr(self, "metrics"): 89 self.metrics = {} 90 if name == "mtx": 91 self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 92 safeEval(attrs[self.sideBearingName])] 93 94 def __getitem__(self, glyphName): 95 return self.metrics[glyphName] 96 97 def __setitem__(self, glyphName, (advance, sb)): 98 self.metrics[glyphName] = advance, sb 99 100