Merge pull request #1230 from anthrotype/fix-coords-overflow

Fix GlyphCoordinates overflow
This commit is contained in:
Cosimo Lupo 2018-06-07 15:59:23 +01:00 committed by GitHub
commit 6bc44c8b05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 19 deletions

View File

@ -1220,6 +1220,9 @@ class GlyphCoordinates(object):
def _checkFloat(self, p): def _checkFloat(self, p):
if self.isFloat(): if self.isFloat():
return p return p
if any(v > 0x7FFF or v < -0x8000 for v in p):
self._ensureFloat()
return p
if any(isinstance(v, float) for v in p): if any(isinstance(v, float) for v in p):
p = [int(v) if int(v) == v else v for v in p] p = [int(v) if int(v) == v else v for v in p]
if any(isinstance(v, float) for v in p): if any(isinstance(v, float) for v in p):
@ -1259,7 +1262,6 @@ class GlyphCoordinates(object):
del self._a[i] del self._a[i]
del self._a[i] del self._a[i]
def __repr__(self): def __repr__(self):
return 'GlyphCoordinates(['+','.join(str(c) for c in self)+'])' return 'GlyphCoordinates(['+','.join(str(c) for c in self)+'])'
@ -1284,8 +1286,9 @@ class GlyphCoordinates(object):
a = self._a a = self._a
x,y = 0,0 x,y = 0,0
for i in range(len(a) // 2): for i in range(len(a) // 2):
a[2*i ] = x = a[2*i ] + x x = a[2*i ] + x
a[2*i+1] = y = a[2*i+1] + y y = a[2*i+1] + y
self[i] = (x, y)
def absoluteToRelative(self): def absoluteToRelative(self):
a = self._a a = self._a
@ -1295,8 +1298,7 @@ class GlyphCoordinates(object):
dy = a[2*i+1] - y dy = a[2*i+1] - y
x = a[2*i ] x = a[2*i ]
y = a[2*i+1] y = a[2*i+1]
a[2*i ] = dx self[i] = (dx, dy)
a[2*i+1] = dy
def translate(self, p): def translate(self, p):
""" """
@ -1305,8 +1307,7 @@ class GlyphCoordinates(object):
(x,y) = self._checkFloat(p) (x,y) = self._checkFloat(p)
a = self._a a = self._a
for i in range(len(a) // 2): for i in range(len(a) // 2):
a[2*i ] += x self[i] = (a[2*i] + x, a[2*i+1] + y)
a[2*i+1] += y
def scale(self, p): def scale(self, p):
""" """
@ -1315,8 +1316,7 @@ class GlyphCoordinates(object):
(x,y) = self._checkFloat(p) (x,y) = self._checkFloat(p)
a = self._a a = self._a
for i in range(len(a) // 2): for i in range(len(a) // 2):
a[2*i ] *= x self[i] = (a[2*i] * x, a[2*i+1] * y)
a[2*i+1] *= y
def transform(self, t): def transform(self, t):
""" """
@ -1432,8 +1432,8 @@ class GlyphCoordinates(object):
other = other._a other = other._a
a = self._a a = self._a
assert len(a) == len(other) assert len(a) == len(other)
for i in range(len(a)): for i in range(len(a) // 2):
a[i] += other[i] self[i] = (a[2*i] + other[2*i], a[2*i+1] + other[2*i+1])
return self return self
return NotImplemented return NotImplemented
@ -1457,8 +1457,8 @@ class GlyphCoordinates(object):
other = other._a other = other._a
a = self._a a = self._a
assert len(a) == len(other) assert len(a) == len(other)
for i in range(len(a)): for i in range(len(a) // 2):
a[i] -= other[i] self[i] = (a[2*i] - other[2*i], a[2*i+1] - other[2*i+1])
return self return self
return NotImplemented return NotImplemented

View File

@ -300,11 +300,6 @@ class VariationModel(object):
for i,weights in enumerate(self.deltaWeights): for i,weights in enumerate(self.deltaWeights):
delta = masterValues[mapping[i]] delta = masterValues[mapping[i]]
for j,weight in weights.items(): for j,weight in weights.items():
try:
delta -= out[j] * weight
except OverflowError:
# if it doesn't fit signed shorts, retry with doubles
delta._ensureFloat()
delta -= out[j] * weight delta -= out[j] * weight
out.append(delta) out.append(delta)
return out return out

View File

@ -2,6 +2,7 @@ from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import * from fontTools.misc.py23 import *
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
import sys import sys
import array
import pytest import pytest
@ -150,3 +151,9 @@ class GlyphCoordinatesTest(object):
# since the Python float is truncated to a C float. # since the Python float is truncated to a C float.
# when using typecode 'd' it should return the correct value 243 # when using typecode 'd' it should return the correct value 243
assert g[0][0] == round(afloat) assert g[0][0] == round(afloat)
def test__checkFloat_overflow(self):
g = GlyphCoordinates([(1, 1)], typecode="h")
g.append((0x8000, 0))
assert g.array.typecode == "d"
assert g.array == array.array("d", [1.0, 1.0, 32768.0, 0.0])