_h_m_t_x.py revision 1b7d54fedc29a9863250dc5486dcd86ed6f70a23
1import sys 2import DefaultTable 3import numpy 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 = numpy.fromstring(data[:4 * numberOfMetrics], 18 numpy.int16) 19 if sys.byteorder <> "big": 20 metrics = metrics.byteswap() 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 = numpy.array([lastAdvance] * numberOfSideBearings, 29 numpy.int16) 30 sideBearings = numpy.fromstring(data[:2 * numberOfSideBearings], 31 numpy.int16) 32 if sys.byteorder <> "big": 33 sideBearings = sideBearings.byteswap() 34 data = data[2 * numberOfSideBearings:] 35 additionalMetrics = numpy.array([advances, sideBearings], 36 numpy.int16) 37 metrics = numpy.concatenate((metrics, 38 numpy.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 = numpy.array(metrics, numpy.int16) 65 if sys.byteorder <> "big": 66 metrics = metrics.byteswap() 67 data = metrics.tostring() 68 69 additionalMetrics = numpy.array(additionalMetrics, numpy.int16) 70 if sys.byteorder <> "big": 71 additionalMetrics = additionalMetrics.byteswap() 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