_h_m_t_x.py revision f4e39bf3637499c00c8e7a55866988699dcac97f
1from __future__ import print_function, division 2from fontTools.misc.py23 import * 3from fontTools.misc.textTools import safeEval 4from . import DefaultTable 5import sys 6import array 7import warnings 8 9 10class table__h_m_t_x(DefaultTable.DefaultTable): 11 12 headerTag = 'hhea' 13 advanceName = 'width' 14 sideBearingName = 'lsb' 15 numberOfMetricsName = 'numberOfHMetrics' 16 17 def decompile(self, data, ttFont): 18 numGlyphs = ttFont['maxp'].numGlyphs 19 numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 20 if numberOfMetrics > numGlyphs: 21 numberOfMetrics = numGlyphs # We warn later. 22 # Note: advanceWidth is unsigned, but we read/write as signed. 23 metrics = array.array("h", data[:4 * numberOfMetrics]) 24 if sys.byteorder != "big": 25 metrics.byteswap() 26 data = data[4 * numberOfMetrics:] 27 numberOfSideBearings = numGlyphs - numberOfMetrics 28 sideBearings = array.array("h", data[:2 * numberOfSideBearings]) 29 data = data[2 * numberOfSideBearings:] 30 31 if sys.byteorder != "big": 32 sideBearings.byteswap() 33 if data: 34 warnings.warn("too much 'hmtx'/'vmtx' table data") 35 self.metrics = {} 36 for i in range(numberOfMetrics): 37 glyphName = ttFont.getGlyphName(i) 38 self.metrics[glyphName] = list(metrics[i*2:i*2+2]) 39 lastAdvance = metrics[-2] 40 for i in range(numberOfSideBearings): 41 glyphName = ttFont.getGlyphName(i + numberOfMetrics) 42 self.metrics[glyphName] = [lastAdvance, sideBearings[i]] 43 44 def compile(self, ttFont): 45 metrics = [] 46 for glyphName in ttFont.getGlyphOrder(): 47 metrics.append(self.metrics[glyphName]) 48 lastAdvance = metrics[-1][0] 49 lastIndex = len(metrics) 50 while metrics[lastIndex-2][0] == lastAdvance: 51 lastIndex -= 1 52 if lastIndex <= 1: 53 # all advances are equal 54 lastIndex = 1 55 break 56 additionalMetrics = metrics[lastIndex:] 57 additionalMetrics = [sb for advance, sb in additionalMetrics] 58 metrics = metrics[:lastIndex] 59 setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 60 61 allMetrics = [] 62 for item in metrics: 63 allMetrics.extend(item) 64 allMetrics = array.array("h", allMetrics) 65 if sys.byteorder != "big": 66 allMetrics.byteswap() 67 data = allMetrics.tostring() 68 69 additionalMetrics = array.array("h", additionalMetrics) 70 if sys.byteorder != "big": 71 additionalMetrics.byteswap() 72 data = data + additionalMetrics.tostring() 73 return data 74 75 def toXML(self, writer, ttFont): 76 names = sorted(self.metrics.keys()) 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