_h_m_t_x.py revision 32c10eecffb4923e0721c395e4b80fb732543f18
1081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom __future__ import print_function, division 2081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom fontTools.misc.py23 import * 3081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom fontTools.misc.textTools import safeEval 4081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom . import DefaultTable 5081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerimport sys 6081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerimport array 7081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerimport warnings 8081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 9081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 10081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerclass table__h_m_t_x(DefaultTable.DefaultTable): 11081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 12081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer headerTag = 'hhea' 13081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer advanceName = 'width' 14081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer sideBearingName = 'lsb' 15081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer numberOfMetricsName = 'numberOfHMetrics' 16081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 17081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer def decompile(self, data, ttFont): 18081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer numGlyphs = ttFont['maxp'].numGlyphs 19081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 20081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if numberOfMetrics > numGlyphs: 21081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer numberOfMetrics = numGlyphs # We warn later. 22081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer # Note: advanceWidth is unsigned, but we read/write as signed. 23081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer metrics = array.array("h", data[:4 * numberOfMetrics]) 24081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if sys.byteorder != "big": 25081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer metrics.byteswap() 26081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer data = data[4 * numberOfMetrics:] 27081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer numberOfSideBearings = numGlyphs - numberOfMetrics 28081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer sideBearings = array.array("h", data[:2 * numberOfSideBearings]) 29081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer data = data[2 * numberOfSideBearings:] 30081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 31081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if sys.byteorder != "big": 32081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer sideBearings.byteswap() 33081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if data: 34081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer sys.stderr.write("too much data for hmtx/vmtx table\n") 35081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer self.metrics = {} 36081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer for i in range(numberOfMetrics): 37081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer glyphName = ttFont.getGlyphName(i) 38081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer self.metrics[glyphName] = list(metrics[i*2:i*2+2]) 39081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer lastAdvance = metrics[-2] 40081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer for i in range(numberOfSideBearings): 41081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer glyphName = ttFont.getGlyphName(i + numberOfMetrics) 42081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer self.metrics[glyphName] = [lastAdvance, sideBearings[i]] 43081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 44081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer def compile(self, ttFont): 45081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer metrics = [] 46081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer for glyphName in ttFont.getGlyphOrder(): 47081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer metrics.append(self.metrics[glyphName]) 48081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer lastAdvance = metrics[-1][0] 49081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer lastIndex = len(metrics) 50081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer while metrics[lastIndex-2][0] == lastAdvance: 51081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer lastIndex -= 1 52081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if lastIndex <= 1: 53081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer # all advances are equal 54081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer lastIndex = 1 55081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer break 56081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer additionalMetrics = metrics[lastIndex:] 57081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer additionalMetrics = [sb for advance, sb in additionalMetrics] 58081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer metrics = metrics[:lastIndex] 59081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 60081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 61081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer allMetrics = [] 62081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer for item in metrics: 63081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer allMetrics.extend(item) 64081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer allMetrics = array.array("h", allMetrics) 65081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if sys.byteorder != "big": 66081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer allMetrics.byteswap() 67081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer data = allMetrics.tostring() 68081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 69081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer additionalMetrics = array.array("h", additionalMetrics) 70081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if sys.byteorder != "big": 71081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer additionalMetrics.byteswap() 72081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer data = data + additionalMetrics.tostring() 73081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer return data 74081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 75081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer def toXML(self, writer, ttFont): 76081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer names = sorted(self.metrics.keys()) 77081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer for glyphName in names: 78081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer advance, sb = self.metrics[glyphName] 79081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer writer.simpletag("mtx", [ 80081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer ("name", glyphName), 81081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer (self.advanceName, advance), 82081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer (self.sideBearingName, sb), 83081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer ]) 84081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer writer.newline() 85081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 86081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer def fromXML(self, name, attrs, content, ttFont): 87081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if not hasattr(self, "metrics"): 88081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer self.metrics = {} 89081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer if name == "mtx": 90081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 91081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer safeEval(attrs[self.sideBearingName])] 92081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 93081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer def __getitem__(self, glyphName): 94081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer return self.metrics[glyphName] 95081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 96081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer def __setitem__(self, glyphName, advance_sb_pair): 97081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer self.metrics[glyphName] = tuple(advance_sb_pair) 98081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer 99081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer