_h_m_t_x.py revision 3a9fd301808f5a8991ca9ac44028d1ecb22d307f
1ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerimport sys 2ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerfrom . import DefaultTable 3ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerimport array 4ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerfrom fontTools import ttLib 5ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerfrom fontTools.misc.textTools import safeEval 6ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerimport warnings 7ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 8ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 9ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerclass table__h_m_t_x(DefaultTable.DefaultTable): 10ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 11ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner headerTag = 'hhea' 12ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner advanceName = 'width' 13ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner sideBearingName = 'lsb' 14ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner numberOfMetricsName = 'numberOfHMetrics' 15ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 16ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner def decompile(self, data, ttFont): 17ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner numGlyphs = ttFont['maxp'].numGlyphs 18ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 19ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner if numberOfMetrics > numGlyphs: 20ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner numberOfMetrics = numGlyphs # We warn later. 21ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner # Note: advanceWidth is unsigned, but we read/write as signed. 22ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner metrics = array.array("h", data[:4 * numberOfMetrics]) 23ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner if sys.byteorder != "big": 24ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner metrics.byteswap() 25ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner data = data[4 * numberOfMetrics:] 26ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner numberOfSideBearings = numGlyphs - numberOfMetrics 27ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner sideBearings = array.array("h", data[:2 * numberOfSideBearings]) 28ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner data = data[2 * numberOfSideBearings:] 29ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 30ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner if sys.byteorder != "big": 31ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner sideBearings.byteswap() 32ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner if data: 33ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner sys.stderr.write("too much data for hmtx/vmtx table\n") 34ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner self.metrics = {} 35ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner for i in range(numberOfMetrics): 36ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner glyphName = ttFont.getGlyphName(i) 37ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner self.metrics[glyphName] = list(metrics[i*2:i*2+2]) 38ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner lastAdvance = metrics[-2] 39ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner for i in range(numberOfSideBearings): 40ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner glyphName = ttFont.getGlyphName(i + numberOfMetrics) 41ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner self.metrics[glyphName] = [lastAdvance, sideBearings[i]] 42ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 43ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner def compile(self, ttFont): 44ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner metrics = [] 45ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner for glyphName in ttFont.getGlyphOrder(): 46ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner metrics.append(self.metrics[glyphName]) 47ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner lastAdvance = metrics[-1][0] 48ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner lastIndex = len(metrics) 49ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner while metrics[lastIndex-2][0] == lastAdvance: 50ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner lastIndex -= 1 51ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner if lastIndex <= 1: 52ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner # all advances are equal 53ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner 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_pair): 97 self.metrics[glyphName] = tuple(advance_sb_pair) 98 99