diff --git a/Lib/fontTools/varLib/models.py b/Lib/fontTools/varLib/models.py index 78086e8fc..6a9867c8a 100644 --- a/Lib/fontTools/varLib/models.py +++ b/Lib/fontTools/varLib/models.py @@ -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): diff --git a/Tests/varLib/models_test.py b/Tests/varLib/models_test.py index 58a047bb1..11ec1a1e8 100644 --- a/Tests/varLib/models_test.py +++ b/Tests/varLib/models_test.py @@ -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():