_h_m_t_x.py revision 4c2f1b6a2c2e4d85d4987606795097d592b1586a
19be387c94ff8199f8031b7f11f06c52cce5ccf6djvrimport sys 27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable 3035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbodimport array 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): 17035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod numGlyphs = ttFont['maxp'].numGlyphs 187842e56b97ce677b83bdab09cda48bc2d89ac75aJust numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 19035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod if numberOfMetrics > numGlyphs: 20035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod numberOfMetrics = numGlyphs # We warn later. 21035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod # Note: advanceWidth is unsigned, but we read/write as signed. 22035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod metrics = array.array("h", data[:4 * numberOfMetrics]) 239be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 24035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod metrics.byteswap() 257842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[4 * numberOfMetrics:] 26035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod numberOfSideBearings = numGlyphs - numberOfMetrics 27035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod sideBearings = array.array("h", data[:2 * numberOfSideBearings]) 28035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod data = data[2 * numberOfSideBearings:] 29035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod 30035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod if sys.byteorder <> "big": 31035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod sideBearings.byteswap() 327842e56b97ce677b83bdab09cda48bc2d89ac75aJust if data: 33731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just sys.stderr.write("too much data for hmtx/vmtx table\n") 347842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics = {} 35035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod for i in range(numberOfMetrics): 367842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphName = ttFont.getGlyphName(i) 37035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod self.metrics[glyphName] = list(metrics[i*2:i*2+2]) 38035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod lastAdvance = metrics[-2] 39035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod for i in range(numberOfSideBearings): 40035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod glyphName = ttFont.getGlyphName(i + numberOfMetrics) 41035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod self.metrics[glyphName] = [lastAdvance, sideBearings[i]] 427842e56b97ce677b83bdab09cda48bc2d89ac75aJust 437842e56b97ce677b83bdab09cda48bc2d89ac75aJust def compile(self, ttFont): 447842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = [] 457842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphName in ttFont.getGlyphOrder(): 467842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics.append(self.metrics[glyphName]) 477842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastAdvance = metrics[-1][0] 487842e56b97ce677b83bdab09cda48bc2d89ac75aJust lastIndex = len(metrics) 497842e56b97ce677b83bdab09cda48bc2d89ac75aJust while metrics[lastIndex-2][0] == lastAdvance: 50035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod lastIndex -= 1 511288f8ad41b183ccdc3a8657b751ce53e03953a7jvr if lastIndex <= 1: 52ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr # all advances are equal 531288f8ad41b183ccdc3a8657b751ce53e03953a7jvr lastIndex = 1 54ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr break 557842e56b97ce677b83bdab09cda48bc2d89ac75aJust additionalMetrics = metrics[lastIndex:] 56035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod additionalMetrics = [sb for advance, sb in additionalMetrics] 577842e56b97ce677b83bdab09cda48bc2d89ac75aJust metrics = metrics[:lastIndex] 587842e56b97ce677b83bdab09cda48bc2d89ac75aJust setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 597842e56b97ce677b83bdab09cda48bc2d89ac75aJust 604c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics = [] 614c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod for item in metrics: 624c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics.extend(item) 634c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics = array.array("h", allMetrics) 649be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 654c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod allMetrics.byteswap() 664c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod data = allMetrics.tostring() 677842e56b97ce677b83bdab09cda48bc2d89ac75aJust 68035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod additionalMetrics = array.array("h", additionalMetrics) 699be387c94ff8199f8031b7f11f06c52cce5ccf6djvr if sys.byteorder <> "big": 70035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod additionalMetrics.byteswap() 717842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data + additionalMetrics.tostring() 727842e56b97ce677b83bdab09cda48bc2d89ac75aJust return data 737842e56b97ce677b83bdab09cda48bc2d89ac75aJust 747842e56b97ce677b83bdab09cda48bc2d89ac75aJust def toXML(self, writer, ttFont): 757842e56b97ce677b83bdab09cda48bc2d89ac75aJust names = self.metrics.keys() 767842e56b97ce677b83bdab09cda48bc2d89ac75aJust names.sort() 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 867842e56b97ce677b83bdab09cda48bc2d89ac75aJust 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 967842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __setitem__(self, glyphName, (advance, sb)): 977842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.metrics[glyphName] = advance, sb 987842e56b97ce677b83bdab09cda48bc2d89ac75aJust 99