_h_m_t_x.py revision ca4c45681ef2ea9290c6845f8bf61dff281fc5c4
140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsimport DefaultTable 240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsimport Numeric 340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsfrom fontTools import ttLib 440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsfrom fontTools.misc.textTools import safeEval 540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsclass table__h_m_t_x(DefaultTable.DefaultTable): 840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams headerTag = 'hhea' 1040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams advanceName = 'width' 1140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams sideBearingName = 'lsb' 1240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams numberOfMetricsName = 'numberOfHMetrics' 1340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 1440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams def decompile(self, data, ttFont): 1540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) 1640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics = Numeric.fromstring(data[:4 * numberOfMetrics], 1740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams Numeric.Int16) 1840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams if ttLib.endian <> "big": 1940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics = metrics.byteswapped() 2040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics.shape = (numberOfMetrics, 2) 2102d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams data = data[4 * numberOfMetrics:] 2202d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics 2302d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams numberOfSideBearings = int(numberOfSideBearings) 2402d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams if numberOfSideBearings: 2502d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams assert numberOfSideBearings > 0, "bad hmtx/vmtx table" 2640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams lastAdvance = metrics[-1][0] 2740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams advances = Numeric.array([lastAdvance] * numberOfSideBearings, 2840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams Numeric.Int16) 2940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings], 3040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams Numeric.Int16) 31460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray if ttLib.endian <> "big": 3240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams sideBearings = sideBearings.byteswapped() 3340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams data = data[2 * numberOfSideBearings:] 3440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams additionalMetrics = Numeric.array([advances, sideBearings], 3540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams Numeric.Int16) 3640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics = Numeric.concatenate((metrics, 3740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams Numeric.transpose(additionalMetrics))) 3840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams if data: 3940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams import sys 4040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams sys.stderr.write("too much data for hmtx/vmtx table\n") 41c11e25c4e653124def1fb18e203b894f42106cbeTim Murray metrics = metrics.tolist() 4240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams self.metrics = {} 4340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams for i in range(len(metrics)): 4440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams glyphName = ttFont.getGlyphName(i) 4540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams self.metrics[glyphName] = metrics[i] 4640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 47460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray def compile(self, ttFont): 4840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics = [] 4940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams for glyphName in ttFont.getGlyphOrder(): 501e645d29250731c6e34040940c59f1033213ad3eJason Sams metrics.append(self.metrics[glyphName]) 5140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams lastAdvance = metrics[-1][0] 5240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams lastIndex = len(metrics) 5340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams while metrics[lastIndex-2][0] == lastAdvance: 5440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams lastIndex = lastIndex - 1 5540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams if lastIndex == 0: 56c11e25c4e653124def1fb18e203b894f42106cbeTim Murray # all advances are equal 57c11e25c4e653124def1fb18e203b894f42106cbeTim Murray break 58c11e25c4e653124def1fb18e203b894f42106cbeTim Murray additionalMetrics = metrics[lastIndex:] 59c11e25c4e653124def1fb18e203b894f42106cbeTim Murray additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) 60c11e25c4e653124def1fb18e203b894f42106cbeTim Murray metrics = metrics[:lastIndex] 61c11e25c4e653124def1fb18e203b894f42106cbeTim Murray setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) 62c11e25c4e653124def1fb18e203b894f42106cbeTim Murray 6340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics = Numeric.array(metrics, Numeric.Int16) 6440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams if ttLib.endian <> "big": 6540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams metrics = metrics.byteswapped() 6640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams data = metrics.tostring() 6740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 6840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16) 6940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams if ttLib.endian <> "big": 7040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams additionalMetrics = additionalMetrics.byteswapped() 7140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams data = data + additionalMetrics.tostring() 7240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams return data 7340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 7440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams def toXML(self, writer, ttFont): 7540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams names = self.metrics.keys() 7640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams names.sort() 7740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams for glyphName in names: 7840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams advance, sb = self.metrics[glyphName] 7940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams writer.simpletag("mtx", [ 8040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams ("name", glyphName), 8140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams (self.advanceName, advance), 8240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams (self.sideBearingName, sb), 8340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams ]) 8440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams writer.newline() 8540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams 8640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams def fromXML(self, (name, attrs, content), ttFont): 876f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray if not hasattr(self, "metrics"): 8840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams self.metrics = {} 8940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams if name == "mtx": 9040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 916f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray safeEval(attrs[self.sideBearingName])] 926f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray 936f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray def __getitem__(self, glyphName): 946f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray return self.metrics[glyphName] 956f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray 966f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray def __setitem__(self, glyphName, (advance, sb)): 976f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray self.metrics[glyphName] = advance, sb 986f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray 996f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray