import sys import DefaultTable import numpy from fontTools import ttLib from fontTools.misc.textTools import safeEval class table__h_m_t_x(DefaultTable.DefaultTable): headerTag = 'hhea' advanceName = 'width' sideBearingName = 'lsb' numberOfMetricsName = 'numberOfHMetrics' def decompile(self, data, ttFont): numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) metrics = numpy.fromstring(data[:4 * numberOfMetrics], numpy.int16) if sys.byteorder <> "big": metrics = metrics.byteswap() metrics.shape = (numberOfMetrics, 2) data = data[4 * numberOfMetrics:] numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics numberOfSideBearings = int(numberOfSideBearings) if numberOfSideBearings: assert numberOfSideBearings > 0, "bad hmtx/vmtx table" lastAdvance = metrics[-1][0] advances = numpy.array([lastAdvance] * numberOfSideBearings, numpy.int16) sideBearings = numpy.fromstring(data[:2 * numberOfSideBearings], numpy.int16) if sys.byteorder <> "big": sideBearings = sideBearings.byteswap() data = data[2 * numberOfSideBearings:] additionalMetrics = numpy.array([advances, sideBearings], numpy.int16) metrics = numpy.concatenate((metrics, numpy.transpose(additionalMetrics))) if data: sys.stderr.write("too much data for hmtx/vmtx table\n") metrics = metrics.tolist() self.metrics = {} for i in range(len(metrics)): glyphName = ttFont.getGlyphName(i) self.metrics[glyphName] = metrics[i] def compile(self, ttFont): metrics = [] for glyphName in ttFont.getGlyphOrder(): metrics.append(self.metrics[glyphName]) lastAdvance = metrics[-1][0] lastIndex = len(metrics) while metrics[lastIndex-2][0] == lastAdvance: lastIndex = lastIndex - 1 if lastIndex <= 1: # all advances are equal lastIndex = 1 break additionalMetrics = metrics[lastIndex:] additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) metrics = metrics[:lastIndex] setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) metrics = numpy.array(metrics, numpy.int16) if sys.byteorder <> "big": metrics = metrics.byteswap() data = metrics.tostring() additionalMetrics = numpy.array(additionalMetrics, numpy.int16) if sys.byteorder <> "big": additionalMetrics = additionalMetrics.byteswap() data = data + additionalMetrics.tostring() return data def toXML(self, writer, ttFont): names = self.metrics.keys() names.sort() for glyphName in names: advance, sb = self.metrics[glyphName] writer.simpletag("mtx", [ ("name", glyphName), (self.advanceName, advance), (self.sideBearingName, sb), ]) writer.newline() def fromXML(self, (name, attrs, content), ttFont): if not hasattr(self, "metrics"): self.metrics = {} if name == "mtx": self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), safeEval(attrs[self.sideBearingName])] def __getitem__(self, glyphName): return self.metrics[glyphName] def __setitem__(self, glyphName, (advance, sb)): self.metrics[glyphName] = advance, sb