xref: /aosp_15_r20/external/fonttools/Tests/varLib/instancer/solver_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1from fontTools.varLib.instancer import solver
2from fontTools.varLib.instancer import NormalizedAxisTripleAndDistances
3import pytest
4
5
6class RebaseTentTest(object):
7    @pytest.mark.parametrize(
8        "tent, axisRange, expected",
9        [
10            # Case 1: # Pin at default
11            pytest.param((0, 1, 1), (0.0, 0.0, 0.0), []),
12            # Case 1:
13            pytest.param((0.3, 0.5, 0.8), (0.1, 0.2, 0.3), []),
14            # Pin axis
15            pytest.param(
16                (0, 1, 1),
17                (0.5, 0.5, 0.5),
18                [
19                    (0.5, None),
20                ],
21            ),
22            # Case 2:
23            pytest.param(
24                (0, 1, 1),
25                (-1, 0, 0.5),
26                [
27                    (0.5, (0, 1, 1)),
28                ],
29            ),
30            # Case 2:
31            pytest.param(
32                (0, 1, 1),
33                (-1, 0, 0.75),
34                [
35                    (0.75, (0, 1, 1)),
36                ],
37            ),
38            #
39            # Without gain:
40            #
41            # Case 3
42            pytest.param(
43                (0, 0.2, 1),
44                (-1, 0, 0.8),
45                [
46                    (1, (0, 0.25, 1)),
47                    (0.25, (0.25, 1, 1)),
48                ],
49            ),
50            # Case 3 boundary
51            pytest.param(
52                (0, 0.4, 1),
53                (-1, 0, 0.5),
54                [
55                    (1, (0, 0.8, 1)),
56                    (2.5 / 3, (0.8, 1, 1)),
57                ],
58            ),
59            # Case 4
60            pytest.param(
61                (0, 0.25, 1),
62                (-1, 0, 0.4),
63                [
64                    (1, (0, 0.625, 1)),
65                    (0.8, (0.625, 1, 1)),
66                ],
67            ),
68            pytest.param(
69                (0.25, 0.3, 1.05),
70                (0, 0.2, 0.4),
71                [
72                    (1, (0.25, 0.5, 1)),
73                    (2.6 / 3, (0.5, 1, 1)),
74                ],
75            ),
76            # Case 4 boundary
77            pytest.param(
78                (0.25, 0.5, 1),
79                (0, 0.25, 0.5),
80                [
81                    (1, (0, 1, 1)),
82                ],
83            ),
84            #
85            # With gain:
86            #
87            # Case 3a/1neg
88            pytest.param(
89                (0.0, 0.5, 1),
90                (0, 0.5, 1),
91                [
92                    (1, None),
93                    (-1, (0, 1, 1)),
94                    (-1, (-1, -1, 0)),
95                ],
96            ),
97            pytest.param(
98                (0.0, 0.5, 1),
99                (0, 0.5, 0.75),
100                [
101                    (1, None),
102                    (-0.5, (0, 1, 1)),
103                    (-1, (-1, -1, 0)),
104                ],
105            ),
106            pytest.param(
107                (0.0, 0.5, 1),
108                (0, 0.25, 0.8),
109                [
110                    (0.5, None),
111                    (0.5, (0, 0.45454545, 0.9090909090)),
112                    (-0.1, (0.9090909090, 1.0, 1.0)),
113                    (-0.5, (-1, -1, 0)),
114                ],
115            ),
116            # Case 3a/1neg
117            pytest.param(
118                (0.0, 0.5, 2),
119                (0.2, 0.5, 0.8),
120                [
121                    (1, None),
122                    (-0.2, (0, 1, 1)),
123                    (-0.6, (-1, -1, 0)),
124                ],
125            ),
126            # Case 3a/1neg
127            pytest.param(
128                (0.0, 0.5, 2),
129                (0.2, 0.5, 1),
130                [
131                    (1, None),
132                    (-1 / 3, (0, 1, 1)),
133                    (-0.6, (-1, -1, 0)),
134                ],
135            ),
136            # Case 3
137            pytest.param(
138                (0, 0.5, 1),
139                (0.25, 0.25, 0.75),
140                [
141                    (0.5, None),
142                    (0.5, (0, 0.5, 1.0)),
143                ],
144            ),
145            # Case 1neg
146            pytest.param(
147                (0.0, 0.5, 1),
148                (0, 0.25, 0.5),
149                [
150                    (0.5, None),
151                    (0.5, (0, 1, 1)),
152                    (-0.5, (-1, -1, 0)),
153                ],
154            ),
155            # Case 2neg
156            pytest.param(
157                (0.05, 0.55, 1),
158                (0, 0.25, 0.5),
159                [
160                    (0.4, None),
161                    (0.5, (0, 1, 1)),
162                    (-0.4, (-1, -0.8, 0)),
163                    (-0.4, (-1, -1, -0.8)),
164                ],
165            ),
166            # Case 2neg, other side
167            pytest.param(
168                (-1, -0.55, -0.05),
169                (-0.5, -0.25, 0),
170                [
171                    (0.4, None),
172                    (0.5, (-1, -1, 0)),
173                    (-0.4, (0, 0.8, 1)),
174                    (-0.4, (0.8, 1, 1)),
175                ],
176            ),
177            #
178            # Misc corner cases
179            #
180            pytest.param(
181                (0.5, 0.5, 0.5),
182                (0.5, 0.5, 0.5),
183                [
184                    (1, None),
185                ],
186            ),
187            pytest.param(
188                (0.3, 0.5, 0.7),
189                (0.1, 0.5, 0.9),
190                [
191                    (1, None),
192                    (-1, (0, 0.5, 1)),
193                    (-1, (0.5, 1, 1)),
194                    (-1, (-1, -0.5, 0)),
195                    (-1, (-1, -1, -0.5)),
196                ],
197            ),
198            pytest.param(
199                (0.5, 0.5, 0.5),
200                (0.25, 0.25, 0.5),
201                [
202                    (1, (1, 1, 1)),
203                ],
204            ),
205            pytest.param(
206                (0.5, 0.5, 0.5),
207                (0.25, 0.35, 0.5),
208                [
209                    (1, (1, 1, 1)),
210                ],
211            ),
212            pytest.param(
213                (0.5, 0.5, 0.55),
214                (0.25, 0.35, 0.5),
215                [
216                    (1, (1, 1, 1)),
217                ],
218            ),
219            pytest.param(
220                (0.5, 0.5, 1),
221                (0.5, 0.5, 1),
222                [
223                    (1, None),
224                    (-1, (0, 1, 1)),
225                ],
226            ),
227            pytest.param(
228                (0.25, 0.5, 1),
229                (0.5, 0.5, 1),
230                [
231                    (1, None),
232                    (-1, (0, 1, 1)),
233                ],
234            ),
235            pytest.param(
236                (0, 0.2, 1),
237                (0, 0, 0.5),
238                [
239                    (1, (0, 0.4, 1)),
240                    (0.625, (0.4, 1, 1)),
241                ],
242            ),
243            # https://github.com/fonttools/fonttools/issues/3139
244            pytest.param(
245                (0, 0.5, 1),
246                (-1, 0.25, 1),
247                [
248                    (0.5, None),
249                    (0.5, (0.0, 1 / 3, 2 / 3)),
250                    (-0.5, (2 / 3, 1, 1)),
251                    (-0.5, (-1, -0.2, 0)),
252                    (-0.5, (-1, -1, -0.2)),
253                ],
254            ),
255            # Dirac delta at new default. Fancy!
256            pytest.param(
257                (0.5, 0.5, 0.5),
258                (0, 0.5, 1),
259                [
260                    (1, None),
261                    (-1, (0, 0.0001220703, 1)),
262                    (-1, (0.0001220703, 1, 1)),
263                    (-1, (-1, -0.0001220703, 0)),
264                    (-1, (-1, -1, -0.0001220703)),
265                ],
266            ),
267            # https://github.com/fonttools/fonttools/issues/3177
268            pytest.param(
269                (0, 1, 1),
270                (-1, -0.5, +1, 1, 1),
271                [
272                    (1.0, (1 / 3, 1.0, 1.0)),
273                ],
274            ),
275            pytest.param(
276                (0, 1, 1),
277                (-1, -0.5, +1, 2, 1),
278                [
279                    (1.0, (0.5, 1.0, 1.0)),
280                ],
281            ),
282            # https://github.com/fonttools/fonttools/issues/3291
283            pytest.param(
284                (0.6, 0.7, 0.8),
285                (-1, 0.2, +1, 1, 1),
286                [
287                    (1.0, (0.5, 0.625, 0.75)),
288                ],
289            ),
290        ],
291    )
292    def test_rebaseTent(self, tent, axisRange, expected):
293        axisRange = NormalizedAxisTripleAndDistances(*axisRange)
294
295        sol = solver.rebaseTent(tent, axisRange)
296
297        a = pytest.approx
298        expected = [
299            (a(scalar), (a(v[0]), a(v[1]), a(v[2])) if v is not None else None)
300            for scalar, v in expected
301        ]
302
303        assert sol == expected, (tent, axisRange)
304