_h_m_t_x.py revision 30e691edd056ba22fa8970280e986747817bec3d
130e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom __future__ import print_function 230e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.py23 import * 330e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.textTools import safeEval 42b06aaa2a6bcd363c25fb0c43f6bb906906594bdBehdad Esfahbodfrom . import DefaultTable 530e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport sys 6035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbodimport array 7d3d7250fc3147b6333e365e5be4ff29aa92ee506pabsimport warnings 87842e56b97ce677b83bdab09cda48bc2d89ac75aJust 97842e56b97ce677b83bdab09cda48bc2d89ac75aJust 107842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__h_m_t_x(DefaultTable.DefaultTable): 117842e56b97ce677b83bdab09cda48bc2d89ac75aJust 127842e56b97ce677b83bdab09cda48bc2d89ac75aJust headerTag = 'hhea' 137842e56b97ce677b83bdab09cda48bc2d89ac75aJust advanceName = 'width' 147842e56b97ce677b83bdab09cda48bc2d89ac75aJust sideBearingName = 'lsb' 157842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetricsName = 'numberOfHMetrics' 167842e56b97ce677b83bdab09cda48bc2d89ac75aJust 177842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decompile(self, data, ttFont): 18035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod numGlyphs = ttFont['maxp'].numGlyphs 197842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 20035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod if numberOfMetrics > numGlyphs: 21035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod numberOfMetrics = numGlyphs # We warn later. 22035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod # Note: advanceWidth is unsigned, but we read/write as signed. 23035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod metrics = array.array("h", data[:4 * numberOfMetrics]) 24180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if sys.byteorder != "big": 25035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod metrics.byteswap() 267842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[4 * numberOfMetrics:] 27035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod numberOfSideBearings = numGlyphs - numberOfMetrics 28035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod sideBearings = array.array("h", data[:2 * numberOfSideBearings]) 29035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod data = data[2 * numberOfSideBearings:] 30035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod 31180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if sys.byteorder != "big": 32035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod sideBearings.byteswap() 337842e56b97ce677b83bdab09cda48bc2d89ac75aJust if data: 34731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just sys.stderr.write("too much data for hmtx/vmtx table\n") 357842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 36035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod for i in range(numberOfMetrics): 377842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphName = ttFont.getGlyphName(i) 38035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod self.metrics[glyphName] = list(metrics[i*2:i*2+2]) 39035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod lastAdvance = metrics[-2] 40035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod for i in range(numberOfSideBearings): 41035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod glyphName = ttFont.getGlyphName(i + numberOfMetrics) 42035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod self.metrics[glyphName] = [lastAdvance, sideBearings[i]] 437842e56b97ce677b83bdab09cda48bc2d89ac75aJust 447842e56b97ce677b83bdab09cda48bc2d89ac75aJust def compile(self, ttFont): 457842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = [] 467842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in ttFont.getGlyphOrder(): 477842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics.append(self.metrics[glyphName]) 487842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastAdvance = metrics[-1][0] 497842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastIndex = len(metrics) 507842e56b97ce677b83bdab09cda48bc2d89ac75aJust while metrics[lastIndex-2][0] == lastAdvance: 51035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod lastIndex -= 1 521288f8ad41b183ccdc3a8657b751ce53e03953a7jvr if lastIndex <= 1: 53ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr # all advances are equal 541288f8ad41b183ccdc3a8657b751ce53e03953a7jvr lastIndex = 1 55ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr break 567842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = metrics[lastIndex:] 57035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod additionalMetrics = [sb for advance, sb in additionalMetrics] 587842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics[:lastIndex] 597842e56b97ce677b83bdab09cda48bc2d89ac75aJust setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 607842e56b97ce677b83bdab09cda48bc2d89ac75aJust 614c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics = [] 624c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod for item in metrics: 634c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics.extend(item) 644c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics = array.array("h", allMetrics) 65180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if sys.byteorder != "big": 664c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics.byteswap() 674c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod data = allMetrics.tostring() 687842e56b97ce677b83bdab09cda48bc2d89ac75aJust 69035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod additionalMetrics = array.array("h", additionalMetrics) 70180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if sys.byteorder != "big": 71035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod additionalMetrics.byteswap() 727842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data + additionalMetrics.tostring() 737842e56b97ce677b83bdab09cda48bc2d89ac75aJust return data 747842e56b97ce677b83bdab09cda48bc2d89ac75aJust 757842e56b97ce677b83bdab09cda48bc2d89ac75aJust def toXML(self, writer, ttFont): 76ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod names = sorted(self.metrics.keys()) 777842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in names: 787842e56b97ce677b83bdab09cda48bc2d89ac75aJust advance, sb = self.metrics[glyphName] 797842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.simpletag("mtx", [ 807842e56b97ce677b83bdab09cda48bc2d89ac75aJust ("name", glyphName), 817842e56b97ce677b83bdab09cda48bc2d89ac75aJust (self.advanceName, advance), 827842e56b97ce677b83bdab09cda48bc2d89ac75aJust (self.sideBearingName, sb), 837842e56b97ce677b83bdab09cda48bc2d89ac75aJust ]) 847842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 857842e56b97ce677b83bdab09cda48bc2d89ac75aJust 863a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod def fromXML(self, name, attrs, content, ttFont): 877842e56b97ce677b83bdab09cda48bc2d89ac75aJust if not hasattr(self, "metrics"): 887842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 897842e56b97ce677b83bdab09cda48bc2d89ac75aJust if name == "mtx": 907842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 917842e56b97ce677b83bdab09cda48bc2d89ac75aJust safeEval(attrs[self.sideBearingName])] 927842e56b97ce677b83bdab09cda48bc2d89ac75aJust 937842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __getitem__(self, glyphName): 947842e56b97ce677b83bdab09cda48bc2d89ac75aJust return self.metrics[glyphName] 957842e56b97ce677b83bdab09cda48bc2d89ac75aJust 963a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod def __setitem__(self, glyphName, advance_sb_pair): 973a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod self.metrics[glyphName] = tuple(advance_sb_pair) 987842e56b97ce677b83bdab09cda48bc2d89ac75aJust 99