Merge pull request #2849 from fonttools/fix-division-by-zero

Fix ZeroDivisionErrors with normalizeLocation(extrapolate=True)
This commit is contained in:
Cosimo Lupo 2022-10-14 15:32:36 +01:00 committed by GitHub
commit bc03f09322
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 12 deletions

View File

@ -61,13 +61,17 @@ def normalizeValue(v, triple, extrapolate=False):
)
if not extrapolate:
v = max(min(v, upper), lower)
if v == default:
v = 0.0
elif v < default:
v = (v - default) / (default - lower)
if v == default or lower == upper:
return 0.0
if (v < default and lower != default) or (v > default and upper == default):
return (v - default) / (default - lower)
else:
v = (v - default) / (upper - default)
return v
assert (v > default and upper != default) or (
v < default and lower == default
), f"Ooops... v={v}, triple=({lower}, {default}, {upper})"
return (v - default) / (upper - default)
def normalizeLocation(location, axes, extrapolate=False):

View File

@ -31,19 +31,104 @@ def test_normalizeLocation():
assert normalizeLocation({"wght": 1001}, axes) == {"wght": 0.0}
@pytest.mark.parametrize(
"axes, location, expected",
[
# lower != default != upper
({"wght": (100, 400, 900)}, {"wght": 1000}, {"wght": 1.2}),
({"wght": (100, 400, 900)}, {"wght": 900}, {"wght": 1.0}),
({"wght": (100, 400, 900)}, {"wght": 650}, {"wght": 0.5}),
({"wght": (100, 400, 900)}, {"wght": 400}, {"wght": 0.0}),
({"wght": (100, 400, 900)}, {"wght": 250}, {"wght": -0.5}),
({"wght": (100, 400, 900)}, {"wght": 100}, {"wght": -1.0}),
({"wght": (100, 400, 900)}, {"wght": 25}, {"wght": -1.25}),
# lower == default != upper
(
{"wght": (400, 400, 900), "wdth": (100, 100, 150)},
{"wght": 1000, "wdth": 200},
{"wght": 1.2, "wdth": 2.0},
),
(
{"wght": (400, 400, 900), "wdth": (100, 100, 150)},
{"wght": 25, "wdth": 25},
{"wght": -0.75, "wdth": -1.5},
),
# lower != default == upper
(
{"wght": (100, 400, 400), "wdth": (50, 100, 100)},
{"wght": 700, "wdth": 150},
{"wght": 1.0, "wdth": 1.0},
),
(
{"wght": (100, 400, 400), "wdth": (50, 100, 100)},
{"wght": -50, "wdth": 25},
{"wght": -1.5, "wdth": -1.5},
),
# degenerate case with lower == default == upper, normalized location always 0
({"wght": (400, 400, 400)}, {"wght": 100}, {"wght": 0.0}),
({"wght": (400, 400, 400)}, {"wght": 400}, {"wght": 0.0}),
({"wght": (400, 400, 400)}, {"wght": 700}, {"wght": 0.0}),
],
)
def test_normalizeLocation_extrapolate(axes, location, expected):
assert normalizeLocation(location, axes, extrapolate=True) == expected
def test_supportScalar():
assert supportScalar({}, {}) == 1.0
assert supportScalar({"wght": 0.2}, {}) == 1.0
assert supportScalar({"wght": 0.2}, {"wght": (0, 2, 3)}) == 0.1
assert supportScalar({"wght": 2.5}, {"wght": (0, 2, 4)}) == 0.75
assert supportScalar({"wght": 3}, {"wght": (0, 2, 2)}) == 0.0
assert supportScalar({"wght": 3}, {"wght": (0, 2, 2)}, extrapolate=True, axisRanges={"wght": (0, 2)}) == 1.5
assert supportScalar({"wght": -1}, {"wght": (0, 2, 2)}, extrapolate=True, axisRanges={"wght": (0, 2)}) == -0.5
assert supportScalar({"wght": 3}, {"wght": (0, 1, 2)}, extrapolate=True, axisRanges={"wght": (0, 2)}) == -1.0
assert supportScalar({"wght": -1}, {"wght": (0, 1, 2)}, extrapolate=True, axisRanges={"wght": (0, 2)}) == -1.0
assert supportScalar({"wght": 2}, {"wght": (0, 0.75, 1)}, extrapolate=True, axisRanges={"wght": (0, 1)}) == -4.0
assert (
supportScalar(
{"wght": 3},
{"wght": (0, 2, 2)},
extrapolate=True,
axisRanges={"wght": (0, 2)},
)
== 1.5
)
assert (
supportScalar(
{"wght": -1},
{"wght": (0, 2, 2)},
extrapolate=True,
axisRanges={"wght": (0, 2)},
)
== -0.5
)
assert (
supportScalar(
{"wght": 3},
{"wght": (0, 1, 2)},
extrapolate=True,
axisRanges={"wght": (0, 2)},
)
== -1.0
)
assert (
supportScalar(
{"wght": -1},
{"wght": (0, 1, 2)},
extrapolate=True,
axisRanges={"wght": (0, 2)},
)
== -1.0
)
assert (
supportScalar(
{"wght": 2},
{"wght": (0, 0.75, 1)},
extrapolate=True,
axisRanges={"wght": (0, 1)},
)
== -4.0
)
with pytest.raises(TypeError):
supportScalar({"wght": 2}, {"wght": (0, 0.75, 1)}, extrapolate=True, axisRanges=None)
supportScalar(
{"wght": 2}, {"wght": (0, 0.75, 1)}, extrapolate=True, axisRanges=None
)
def test_model_extrapolate():