diff --git a/Lib/fontTools/ttLib/tables/_h_m_t_x.py b/Lib/fontTools/ttLib/tables/_h_m_t_x.py index a87e8d177..475a93f2a 100644 --- a/Lib/fontTools/ttLib/tables/_h_m_t_x.py +++ b/Lib/fontTools/ttLib/tables/_h_m_t_x.py @@ -1,6 +1,6 @@ import sys import DefaultTable -import numpy +import array from fontTools import ttLib from fontTools.misc.textTools import safeEval import warnings @@ -14,37 +14,31 @@ class table__h_m_t_x(DefaultTable.DefaultTable): numberOfMetricsName = 'numberOfHMetrics' def decompile(self, data, ttFont): + numGlyphs = ttFont['maxp'].numGlyphs numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName)) - metrics = numpy.fromstring(data[:4 * numberOfMetrics], - numpy.int16) + if numberOfMetrics > numGlyphs: + numberOfMetrics = numGlyphs # We warn later. + # Note: advanceWidth is unsigned, but we read/write as signed. + metrics = array.array("h", data[:4 * numberOfMetrics]) if sys.byteorder <> "big": - metrics = metrics.byteswap() - metrics.shape = (numberOfMetrics, 2) + metrics.byteswap() 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:] - if len(advances) and len(sideBearings): - additionalMetrics = numpy.array([advances, sideBearings], numpy.int16) - metrics = numpy.concatenate((metrics, numpy.transpose(additionalMetrics))) - else: - warnings.warn('Unable to include additional metrics') + numberOfSideBearings = numGlyphs - numberOfMetrics + sideBearings = array.array("h", data[:2 * numberOfSideBearings]) + data = data[2 * numberOfSideBearings:] + + if sys.byteorder <> "big": + sideBearings.byteswap() if data: sys.stderr.write("too much data for hmtx/vmtx table\n") - metrics = metrics.tolist() self.metrics = {} - for i in range(len(metrics)): + for i in range(numberOfMetrics): glyphName = ttFont.getGlyphName(i) - self.metrics[glyphName] = metrics[i] + self.metrics[glyphName] = list(metrics[i*2:i*2+2]) + lastAdvance = metrics[-2] + for i in range(numberOfSideBearings): + glyphName = ttFont.getGlyphName(i + numberOfMetrics) + self.metrics[glyphName] = [lastAdvance, sideBearings[i]] def compile(self, ttFont): metrics = [] @@ -53,24 +47,25 @@ class table__h_m_t_x(DefaultTable.DefaultTable): lastAdvance = metrics[-1][0] lastIndex = len(metrics) while metrics[lastIndex-2][0] == lastAdvance: - lastIndex = lastIndex - 1 + lastIndex -= 1 if lastIndex <= 1: # all advances are equal lastIndex = 1 break additionalMetrics = metrics[lastIndex:] - additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics) + additionalMetrics = [sb for advance, sb in additionalMetrics] metrics = metrics[:lastIndex] setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics)) - metrics = numpy.array(metrics, numpy.int16) + metrics = sum(metrics,[]) + metrics = array.array("h", metrics) if sys.byteorder <> "big": - metrics = metrics.byteswap() + metrics.byteswap() data = metrics.tostring() - additionalMetrics = numpy.array(additionalMetrics, numpy.int16) + additionalMetrics = array.array("h", additionalMetrics) if sys.byteorder <> "big": - additionalMetrics = additionalMetrics.byteswap() + additionalMetrics.byteswap() data = data + additionalMetrics.tostring() return data