_h_m_t_x.py revision d3d7250fc3147b6333e365e5be4ff29aa92ee506
19be387c94ff8199f8031b7f11f06c52cce5ccf6djvrimport sys 27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable 31b7d54fedc29a9863250dc5486dcd86ed6f70a23jvrimport numpy 47842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools import ttLib 57842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval 6d3d7250fc3147b6333e365e5be4ff29aa92ee506pabsimport warnings 77842e56b97ce677b83bdab09cda48bc2d89ac75aJust 87842e56b97ce677b83bdab09cda48bc2d89ac75aJust 97842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__h_m_t_x(DefaultTable.DefaultTable): 107842e56b97ce677b83bdab09cda48bc2d89ac75aJust 117842e56b97ce677b83bdab09cda48bc2d89ac75aJust headerTag = 'hhea' 127842e56b97ce677b83bdab09cda48bc2d89ac75aJust advanceName = 'width' 137842e56b97ce677b83bdab09cda48bc2d89ac75aJust sideBearingName = 'lsb' 147842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetricsName = 'numberOfHMetrics' 157842e56b97ce677b83bdab09cda48bc2d89ac75aJust 167842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decompile(self, data, ttFont): 177842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 181b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr metrics = numpy.fromstring(data[:4 * numberOfMetrics], 191b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr numpy.int16) 209be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 211b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr metrics = metrics.byteswap() 227842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics.shape = (numberOfMetrics, 2) 237842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[4 * numberOfMetrics:] 247842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics 257842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfSideBearings = int(numberOfSideBearings) 267842e56b97ce677b83bdab09cda48bc2d89ac75aJust if numberOfSideBearings: 277842e56b97ce677b83bdab09cda48bc2d89ac75aJust assert numberOfSideBearings > 0, "bad hmtx/vmtx table" 287842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastAdvance = metrics[-1][0] 291b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr advances = numpy.array([lastAdvance] * numberOfSideBearings, 301b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr numpy.int16) 311b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr sideBearings = numpy.fromstring(data[:2 * numberOfSideBearings], 321b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr numpy.int16) 339be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 341b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr sideBearings = sideBearings.byteswap() 357842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[2 * numberOfSideBearings:] 36d3d7250fc3147b6333e365e5be4ff29aa92ee506pabs if advances and sideBearings: 37d3d7250fc3147b6333e365e5be4ff29aa92ee506pabs additionalMetrics = numpy.array([advances, sideBearings], numpy.int16) 38d3d7250fc3147b6333e365e5be4ff29aa92ee506pabs metrics = numpy.concatenate((metrics, numpy.transpose(additionalMetrics))) 39d3d7250fc3147b6333e365e5be4ff29aa92ee506pabs else: 40d3d7250fc3147b6333e365e5be4ff29aa92ee506pabs warnings.warn('Unable to include additional metrics') 417842e56b97ce677b83bdab09cda48bc2d89ac75aJust if data: 42731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just sys.stderr.write("too much data for hmtx/vmtx table\n") 437842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics.tolist() 447842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 457842e56b97ce677b83bdab09cda48bc2d89ac75aJust for i in range(len(metrics)): 467842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphName = ttFont.getGlyphName(i) 477842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[glyphName] = metrics[i] 487842e56b97ce677b83bdab09cda48bc2d89ac75aJust 497842e56b97ce677b83bdab09cda48bc2d89ac75aJust def compile(self, ttFont): 507842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = [] 517842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in ttFont.getGlyphOrder(): 527842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics.append(self.metrics[glyphName]) 537842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastAdvance = metrics[-1][0] 547842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastIndex = len(metrics) 557842e56b97ce677b83bdab09cda48bc2d89ac75aJust while metrics[lastIndex-2][0] == lastAdvance: 567842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastIndex = lastIndex - 1 571288f8ad41b183ccdc3a8657b751ce53e03953a7jvr if lastIndex <= 1: 58ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr # all advances are equal 591288f8ad41b183ccdc3a8657b751ce53e03953a7jvr lastIndex = 1 60ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr break 617842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = metrics[lastIndex:] 627842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) 637842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics[:lastIndex] 647842e56b97ce677b83bdab09cda48bc2d89ac75aJust setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 657842e56b97ce677b83bdab09cda48bc2d89ac75aJust 661b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr metrics = numpy.array(metrics, numpy.int16) 679be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 681b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr metrics = metrics.byteswap() 697842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = metrics.tostring() 707842e56b97ce677b83bdab09cda48bc2d89ac75aJust 711b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr additionalMetrics = numpy.array(additionalMetrics, numpy.int16) 729be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 731b7d54fedc29a9863250dc5486dcd86ed6f70a23jvr additionalMetrics = additionalMetrics.byteswap() 747842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data + additionalMetrics.tostring() 757842e56b97ce677b83bdab09cda48bc2d89ac75aJust return data 767842e56b97ce677b83bdab09cda48bc2d89ac75aJust 777842e56b97ce677b83bdab09cda48bc2d89ac75aJust def toXML(self, writer, ttFont): 787842e56b97ce677b83bdab09cda48bc2d89ac75aJust names = self.metrics.keys() 797842e56b97ce677b83bdab09cda48bc2d89ac75aJust names.sort() 807842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in names: 817842e56b97ce677b83bdab09cda48bc2d89ac75aJust advance, sb = self.metrics[glyphName] 827842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.simpletag("mtx", [ 837842e56b97ce677b83bdab09cda48bc2d89ac75aJust ("name", glyphName), 847842e56b97ce677b83bdab09cda48bc2d89ac75aJust (self.advanceName, advance), 857842e56b97ce677b83bdab09cda48bc2d89ac75aJust (self.sideBearingName, sb), 867842e56b97ce677b83bdab09cda48bc2d89ac75aJust ]) 877842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 887842e56b97ce677b83bdab09cda48bc2d89ac75aJust 897842e56b97ce677b83bdab09cda48bc2d89ac75aJust def fromXML(self, (name, attrs, content), ttFont): 907842e56b97ce677b83bdab09cda48bc2d89ac75aJust if not hasattr(self, "metrics"): 917842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 927842e56b97ce677b83bdab09cda48bc2d89ac75aJust if name == "mtx": 937842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 947842e56b97ce677b83bdab09cda48bc2d89ac75aJust safeEval(attrs[self.sideBearingName])] 957842e56b97ce677b83bdab09cda48bc2d89ac75aJust 967842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __getitem__(self, glyphName): 977842e56b97ce677b83bdab09cda48bc2d89ac75aJust return self.metrics[glyphName] 987842e56b97ce677b83bdab09cda48bc2d89ac75aJust 997842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __setitem__(self, glyphName, (advance, sb)): 1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[glyphName] = advance, sb 1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust 102