_h_m_t_x.py revision 1288f8ad41b183ccdc3a8657b751ce53e03953a7
17842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable 27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport Numeric 37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools import ttLib 47842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval 57842e56b97ce677b83bdab09cda48bc2d89ac75aJust 67842e56b97ce677b83bdab09cda48bc2d89ac75aJust 77842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__h_m_t_x(DefaultTable.DefaultTable): 87842e56b97ce677b83bdab09cda48bc2d89ac75aJust 97842e56b97ce677b83bdab09cda48bc2d89ac75aJust headerTag = 'hhea' 107842e56b97ce677b83bdab09cda48bc2d89ac75aJust advanceName = 'width' 117842e56b97ce677b83bdab09cda48bc2d89ac75aJust sideBearingName = 'lsb' 127842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetricsName = 'numberOfHMetrics' 137842e56b97ce677b83bdab09cda48bc2d89ac75aJust 147842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decompile(self, data, ttFont): 157842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 167842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = Numeric.fromstring(data[:4 * numberOfMetrics], 177842e56b97ce677b83bdab09cda48bc2d89ac75aJust Numeric.Int16) 187842e56b97ce677b83bdab09cda48bc2d89ac75aJust if ttLib.endian <> "big": 197842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics.byteswapped() 207842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics.shape = (numberOfMetrics, 2) 217842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[4 * numberOfMetrics:] 227842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics 237842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfSideBearings = int(numberOfSideBearings) 247842e56b97ce677b83bdab09cda48bc2d89ac75aJust if numberOfSideBearings: 257842e56b97ce677b83bdab09cda48bc2d89ac75aJust assert numberOfSideBearings > 0, "bad hmtx/vmtx table" 267842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastAdvance = metrics[-1][0] 277842e56b97ce677b83bdab09cda48bc2d89ac75aJust advances = Numeric.array([lastAdvance] * numberOfSideBearings, 287842e56b97ce677b83bdab09cda48bc2d89ac75aJust Numeric.Int16) 297842e56b97ce677b83bdab09cda48bc2d89ac75aJust sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings], 307842e56b97ce677b83bdab09cda48bc2d89ac75aJust Numeric.Int16) 317842e56b97ce677b83bdab09cda48bc2d89ac75aJust if ttLib.endian <> "big": 327842e56b97ce677b83bdab09cda48bc2d89ac75aJust sideBearings = sideBearings.byteswapped() 337842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[2 * numberOfSideBearings:] 347842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = Numeric.array([advances, sideBearings], 357842e56b97ce677b83bdab09cda48bc2d89ac75aJust Numeric.Int16) 367842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = Numeric.concatenate((metrics, 377842e56b97ce677b83bdab09cda48bc2d89ac75aJust Numeric.transpose(additionalMetrics))) 387842e56b97ce677b83bdab09cda48bc2d89ac75aJust if data: 39731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just import sys 40731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just sys.stderr.write("too much data for hmtx/vmtx table\n") 417842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics.tolist() 427842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 437842e56b97ce677b83bdab09cda48bc2d89ac75aJust for i in range(len(metrics)): 447842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphName = ttFont.getGlyphName(i) 457842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[glyphName] = metrics[i] 467842e56b97ce677b83bdab09cda48bc2d89ac75aJust 477842e56b97ce677b83bdab09cda48bc2d89ac75aJust def compile(self, ttFont): 487842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = [] 497842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in ttFont.getGlyphOrder(): 507842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics.append(self.metrics[glyphName]) 517842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastAdvance = metrics[-1][0] 527842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastIndex = len(metrics) 537842e56b97ce677b83bdab09cda48bc2d89ac75aJust while metrics[lastIndex-2][0] == lastAdvance: 547842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastIndex = lastIndex - 1 551288f8ad41b183ccdc3a8657b751ce53e03953a7jvr if lastIndex <= 1: 56ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr # all advances are equal 571288f8ad41b183ccdc3a8657b751ce53e03953a7jvr lastIndex = 1 58ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr break 597842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = metrics[lastIndex:] 607842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) 617842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics[:lastIndex] 627842e56b97ce677b83bdab09cda48bc2d89ac75aJust setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 637842e56b97ce677b83bdab09cda48bc2d89ac75aJust 647842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = Numeric.array(metrics, Numeric.Int16) 657842e56b97ce677b83bdab09cda48bc2d89ac75aJust if ttLib.endian <> "big": 667842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics.byteswapped() 677842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = metrics.tostring() 687842e56b97ce677b83bdab09cda48bc2d89ac75aJust 697842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16) 707842e56b97ce677b83bdab09cda48bc2d89ac75aJust if ttLib.endian <> "big": 717842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = additionalMetrics.byteswapped() 727842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data + additionalMetrics.tostring() 737842e56b97ce677b83bdab09cda48bc2d89ac75aJust return data 747842e56b97ce677b83bdab09cda48bc2d89ac75aJust 757842e56b97ce677b83bdab09cda48bc2d89ac75aJust def toXML(self, writer, ttFont): 767842e56b97ce677b83bdab09cda48bc2d89ac75aJust names = self.metrics.keys() 777842e56b97ce677b83bdab09cda48bc2d89ac75aJust names.sort() 787842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in names: 797842e56b97ce677b83bdab09cda48bc2d89ac75aJust advance, sb = self.metrics[glyphName] 807842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.simpletag("mtx", [ 817842e56b97ce677b83bdab09cda48bc2d89ac75aJust ("name", glyphName), 827842e56b97ce677b83bdab09cda48bc2d89ac75aJust (self.advanceName, advance), 837842e56b97ce677b83bdab09cda48bc2d89ac75aJust (self.sideBearingName, sb), 847842e56b97ce677b83bdab09cda48bc2d89ac75aJust ]) 857842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 867842e56b97ce677b83bdab09cda48bc2d89ac75aJust 877842e56b97ce677b83bdab09cda48bc2d89ac75aJust def fromXML(self, (name, attrs, content), ttFont): 887842e56b97ce677b83bdab09cda48bc2d89ac75aJust if not hasattr(self, "metrics"): 897842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 907842e56b97ce677b83bdab09cda48bc2d89ac75aJust if name == "mtx": 917842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 927842e56b97ce677b83bdab09cda48bc2d89ac75aJust safeEval(attrs[self.sideBearingName])] 937842e56b97ce677b83bdab09cda48bc2d89ac75aJust 947842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __getitem__(self, glyphName): 957842e56b97ce677b83bdab09cda48bc2d89ac75aJust return self.metrics[glyphName] 967842e56b97ce677b83bdab09cda48bc2d89ac75aJust 977842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __setitem__(self, glyphName, (advance, sb)): 987842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[glyphName] = advance, sb 997842e56b97ce677b83bdab09cda48bc2d89ac75aJust 100