xref: /aosp_15_r20/external/harfbuzz_ng/src/test-subset-instancer-solver.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1 /*
2  * Copyright © 2023  Google, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Google Author(s): Qunxin Liu
25  */
26 
27 #include <math.h>
28 #include "hb-subset-instancer-solver.hh"
29 
approx(Triple a,Triple b)30 static inline bool approx (Triple a, Triple b)
31 {
32   return abs (a.minimum - b.minimum) < 0.000001 &&
33          abs (a.middle - b.middle) < 0.000001 &&
34          abs (a.maximum - b.maximum) < 0.000001;
35 }
36 
approx(double a,double b)37 static inline bool approx (double a, double b)
38 { return abs (a - b) < 0.000001; }
39 
40 /* tests ported from
41  * https://github.com/fonttools/fonttools/blob/main/Tests/varLib/instancer/solver_test.py */
42 int
main(int argc,char ** argv)43 main (int argc, char **argv)
44 {
45   TripleDistances default_axis_distances{1.0, 1.0};
46   /* Case 1 */
47   {
48     /* pin axis*/
49     Triple tent (0.0, 1.0, 1.0);
50     Triple axis_range (0.0, 0.0, 0.0);
51     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
52     assert (out.length == 0);
53   }
54 
55   {
56     /* pin axis*/
57     Triple tent (0.0, 1.0, 1.0);
58     Triple axis_range (0.5, 0.5, 0.5);
59     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
60     assert (out.length == 1);
61     assert (out[0].first == 0.5);
62     assert (out[0].second == Triple ());
63   }
64 
65   {
66     /* tent falls outside the new axis range */
67     Triple tent (0.3, 0.5, 0.8);
68     Triple axis_range (0.1, 0.2, 0.3);
69     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
70     assert (out.length == 0);
71   }
72 
73   /* Case 2 */
74   {
75     Triple tent (0.0, 1.0, 1.0);
76     Triple axis_range (-1.0, 0.0, 0.5);
77     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
78     assert (out.length == 1);
79     assert (out[0].first == 0.5);
80     assert (out[0].second == Triple (0.0, 1.0, 1.0));
81   }
82 
83   /* Case 2 */
84   {
85     Triple tent (0.0, 1.0, 1.0);
86     Triple axis_range (-1.0, 0.0, 0.75);
87     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
88     assert (out.length == 1);
89     assert (out[0].first == 0.75);
90     assert (out[0].second == Triple (0.0, 1.0, 1.0));
91   }
92 
93   /* Without gain: */
94   /* Case 3 */
95   {
96     Triple tent (0.0, 0.2, 1.0);
97     Triple axis_range (-1.0, 0.0, 0.8);
98     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
99     assert (out.length == 2);
100     assert (out[0].first == 1.0);
101     assert (out[0].second == Triple (0.0, 0.25, 1.0));
102     assert (approx (out[1].first, 0.250));
103     assert (out[1].second == Triple (0.25, 1.0, 1.0));
104   }
105 
106   /* Case 3 boundary */
107   {
108     Triple tent (0.0, 0.4, 1.0);
109     Triple axis_range (-1.0, 0.0, 0.5);
110     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
111     assert (out.length == 2);
112     assert (out[0].first == 1.0);
113     assert (out[0].second == Triple (0.0, 0.8, 1.0));
114     assert (approx (out[1].first, 2.5/3));
115     assert (out[1].second == Triple (0.8, 1.0, 1.0));
116   }
117 
118   /* Case 4 */
119   {
120     Triple tent (0.0, 0.25, 1.0);
121     Triple axis_range (-1.0, 0.0, 0.4);
122     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
123     assert (out.length == 2);
124     assert (out[0].first == 1.0);
125     assert (out[0].second == Triple (0.0, 0.625, 1.0));
126     assert (approx (out[1].first, 0.80));
127     assert (out[1].second == Triple (0.625, 1.0, 1.0));
128   }
129 
130   /* Case 4 */
131   {
132     Triple tent (0.25, 0.3, 1.05);
133     Triple axis_range (0.0, 0.2, 0.4);
134     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
135     assert (out.length == 2);
136     assert (out[0].first == 1.0);
137     assert (approx (out[0].second, Triple (0.25, 0.5, 1.0)));
138     assert (approx (out[1].first, 2.6 / 3));
139     assert (approx (out[1].second, Triple (0.5, 1.0, 1.0)));
140   }
141 
142   /* Case 4 boundary */
143   {
144     Triple tent (0.25, 0.5, 1.0);
145     Triple axis_range (0.0, 0.25, 0.5);
146     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
147     assert (out.length == 1);
148     assert (out[0].first == 1.0);
149     assert (out[0].second == Triple (0.0, 1.0, 1.0));
150   }
151 
152   /* With gain */
153   /* Case 3a/1neg */
154   {
155     Triple tent (0.0, 0.5, 1.0);
156     Triple axis_range (0.0, 0.5, 1.0);
157     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
158     assert (out.length == 3);
159     assert (out[0].first == 1.0);
160     assert (out[0].second == Triple ());
161     assert (out[1].first == -1.0);
162     assert (out[1].second == Triple (0.0, 1.0, 1.0));
163     assert (out[2].first == -1.0);
164     assert (out[2].second == Triple (-1.0, -1.0, 0.0));
165   }
166 
167   {
168     Triple tent (0.0, 0.5, 1.0);
169     Triple axis_range (0.0, 0.5, 0.75);
170     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
171     assert (out.length == 3);
172     assert (out[0].first == 1.0);
173     assert (out[0].second == Triple ());
174     assert (out[1].first == -0.5);
175     assert (out[1].second == Triple (0.0, 1.0, 1.0));
176     assert (out[2].first == -1.0);
177     assert (out[2].second == Triple (-1.0, -1.0, 0.0));
178   }
179 
180   {
181     Triple tent (0.0, 0.50, 1.0);
182     Triple axis_range (0.0, 0.25, 0.8);
183     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
184     assert (out.length == 4);
185     assert (out[0].first == 0.5);
186     assert (out[0].second == Triple ());
187     assert (out[1].first == 0.5);
188     assert (approx (out[1].second, Triple (0.0, 0.454545, 0.909091)));
189     assert (approx (out[2].first, -0.1));
190     assert (approx (out[2].second, Triple (0.909091, 1.0, 1.0)));
191     assert (out[3].first == -0.5);
192     assert (out[3].second == Triple (-1.0, -1.0, 0.0));
193   }
194 
195   /* Case 3a/1neg */
196   {
197     Triple tent (0.0, 0.5, 2.0);
198     Triple axis_range (0.2, 0.5, 0.8);
199     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
200     assert (out.length == 3);
201     assert (out[0].first == 1.0);
202     assert (out[0].second == Triple ());
203     assert (approx (out[1].first, -0.2));
204     assert (out[1].second == Triple (0.0, 1.0, 1.0));
205     assert (approx (out[2].first, -0.6));
206     assert (out[2].second == Triple (-1.0, -1.0, 0.0));
207   }
208 
209   /* Case 3a/1neg */
210   {
211     Triple tent (0.0, 0.5, 2.0);
212     Triple axis_range (0.2, 0.5, 1.0);
213     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
214     assert (out.length == 3);
215     assert (out[0].first == 1.0);
216     assert (out[0].second == Triple ());
217     assert (approx (out[1].first, -1.0/3));
218     assert (out[1].second == Triple (0.0, 1.0, 1.0));
219     assert (approx (out[2].first, -0.6));
220     assert (out[2].second == Triple (-1.0, -1.0, 0.0));
221   }
222 
223   /* Case 3 */
224   {
225     Triple tent (0.0, 0.5, 1.0);
226     Triple axis_range (0.25, 0.25, 0.75);
227     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
228     assert (out.length == 2);
229     assert (out[0].first == 0.5);
230     assert (out[0].second == Triple ());
231     assert (out[1].first == 0.5);
232     assert (out[1].second == Triple (0.0, 0.5, 1.0));
233   }
234 
235   /* Case 1neg */
236   {
237     Triple tent (0.0, 0.5, 1.0);
238     Triple axis_range (0.0, 0.25, 0.5);
239     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
240     assert (out.length == 3);
241     assert (out[0].first == 0.5);
242     assert (out[0].second == Triple ());
243     assert (out[1].first == 0.5);
244     assert (out[1].second == Triple (0.0, 1.0, 1.0));
245     assert (out[2].first == -0.5);
246     assert (out[2].second == Triple (-1.0, -1.0, 0.0));
247   }
248 
249   /* Case 2neg */
250   {
251     Triple tent (0.05, 0.55, 1.0);
252     Triple axis_range (0.0, 0.25, 0.5);
253     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
254     assert (out.length == 4);
255     assert (approx (out[0].first, 0.4));
256     assert (out[0].second == Triple ());
257     assert (approx (out[1].first, 0.5));
258     assert (out[1].second == Triple (0.0, 1.0, 1.0));
259     assert (approx (out[2].first, -0.4));
260     assert (out[2].second == Triple (-1.0, -0.8, 0.0));
261     assert (approx (out[3].first, -0.4));
262     assert (out[3].second == Triple (-1.0, -1.0, -0.8));
263   }
264 
265   /* Case 2neg, other side */
266   {
267     Triple tent (-1.0, -0.55, -0.05);
268     Triple axis_range (-0.5, -0.25, 0.0);
269     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
270     assert (out.length == 4);
271     assert (approx (out[0].first, 0.4));
272     assert (out[0].second == Triple ());
273     assert (approx (out[1].first, 0.5));
274     assert (out[1].second == Triple (-1.0, -1.0, 0.0));
275     assert (approx (out[2].first, -0.4));
276     assert (out[2].second == Triple (0.0, 0.8, 1.0));
277     assert (approx (out[3].first, -0.4));
278     assert (out[3].second == Triple (0.8, 1.0, 1.0));
279   }
280 
281   /* Misc corner cases */
282   {
283     Triple tent (0.5, 0.5, 0.5);
284     Triple axis_range (0.5, 0.5, 0.5);
285     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
286     assert (out.length == 1);
287     assert (out[0].first == 1.0);
288     assert (out[0].second == Triple ());
289   }
290 
291   {
292     Triple tent (0.3, 0.5, 0.7);
293     Triple axis_range (0.1, 0.5, 0.9);
294     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
295     assert (out.length == 5);
296     assert (out[0].first == 1.0);
297     assert (out[0].second == Triple ());
298     assert (out[1].first == -1.0);
299     assert (approx(out[1].second, Triple (0.0, 0.5, 1.0)));
300     assert (out[2].first == -1.0);
301     assert (approx(out[2].second, Triple (0.5, 1.0, 1.0)));
302     assert (out[3].first == -1.0);
303     assert (approx (out[3].second, Triple (-1.0, -0.5, 0.0)));
304     assert (out[4].first == -1.0);
305     assert (approx (out[4].second, Triple (-1.0, -1.0, -0.5)));
306   }
307 
308   {
309     Triple tent (0.5, 0.5, 0.5);
310     Triple axis_range (0.25, 0.25, 0.5);
311     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
312     assert (out.length == 1);
313     assert (out[0].first == 1.0);
314     assert (out[0].second == Triple (1.0, 1.0, 1.0));
315   }
316 
317   {
318     Triple tent (0.5, 0.5, 0.5);
319     Triple axis_range (0.25, 0.35, 0.5);
320     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
321     assert (out.length == 1);
322     assert (out[0].first == 1.0);
323     assert (out[0].second == Triple (1.0, 1.0, 1.0));
324   }
325 
326   {
327     Triple tent (0.5, 0.5, 0.55);
328     Triple axis_range (0.25, 0.35, 0.5);
329     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
330     assert (out.length == 1);
331     assert (out[0].first == 1.0);
332     assert (out[0].second == Triple (1.0, 1.0, 1.0));
333   }
334 
335   {
336     Triple tent (0.5, 0.5, 1.0);
337     Triple axis_range (0.5, 0.5, 1.0);
338     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
339     assert (out.length == 2);
340     assert (out[0].first == 1.0);
341     assert (out[0].second == Triple ());
342     assert (out[1].first == -1.0);
343     assert (out[1].second == Triple (0.0, 1.0, 1.0));
344   }
345 
346   {
347     Triple tent (0.25, 0.5, 1.0);
348     Triple axis_range (0.5, 0.5, 1.0);
349     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
350     assert (out.length == 2);
351     assert (out[0].first == 1.0);
352     assert (out[0].second == Triple ());
353     assert (out[1].first == -1.0);
354     assert (out[1].second == Triple (0.0, 1.0, 1.0));
355   }
356 
357   {
358     Triple tent (0.0, 0.2, 1.0);
359     Triple axis_range (0.0, 0.0, 0.5);
360     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
361     assert (out.length == 2);
362     assert (out[0].first == 1.0);
363     assert (out[0].second == Triple (0.0, 0.4, 1.0));
364     assert (out[1].first == 0.625);
365     assert (out[1].second == Triple (0.4, 1.0, 1.0));
366   }
367 
368 
369   {
370     Triple tent (0.0, 0.5, 1.0);
371     Triple axis_range (-1.0, 0.25, 1.0);
372     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
373     assert (out.length == 5);
374     assert (out[0].first == 0.5);
375     assert (out[0].second == Triple ());
376     assert (out[1].first == 0.5);
377     assert (out[1].second == Triple (0.0, 1.0/3, 2.0/3));
378     assert (out[2].first == -0.5);
379     assert (out[2].second == Triple (2.0/3, 1.0, 1.0));
380     assert (out[3].first == -0.5);
381     assert (out[3].second == Triple (-1.0, -0.2, 0.0));
382     assert (out[4].first == -0.5);
383     assert (out[4].second == Triple (-1.0, -1.0, -0.2));
384   }
385 
386   {
387     Triple tent (0.5, 0.5, 0.5);
388     Triple axis_range (0.0, 0.5, 1.0);
389     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
390     assert (out.length == 5);
391     assert (out[0].first == 1.0);
392     assert (out[0].second == Triple ());
393     assert (out[1].first == -1.0);
394     assert (out[1].second == Triple (0.0, 2/(double) (1 << 14), 1.0));
395     assert (out[2].first == -1.0);
396     assert (out[2].second == Triple (2/(double) (1 << 14), 1.0, 1.0));
397     assert (out[3].first == -1.0);
398     assert (out[3].second == Triple (-1.0, -2/(double) (1 << 14), 0.0));
399     assert (out[4].first == -1.0);
400     assert (out[4].second == Triple (-1.0, -1.0, -2/(double) (1 << 14)));
401   }
402 
403   {
404     Triple tent (0.0, 1.0, 1.0);
405     Triple axis_range (-1.0, -0.5, 1.0);
406     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
407     assert (out.length == 1);
408     assert (out[0].first == 1.0);
409     assert (out[0].second == Triple (1.0/3, 1.0, 1.0));
410   }
411 
412   {
413     Triple tent (0.0, 1.0, 1.0);
414     Triple axis_range (-1.0, -0.5, 1.0);
415     TripleDistances axis_distances{2.0, 1.0};
416     rebase_tent_result_t out = rebase_tent (tent, axis_range, axis_distances);
417     assert (out.length == 1);
418     assert (out[0].first == 1.0);
419     assert (out[0].second == Triple (0.5, 1.0, 1.0));
420   }
421 
422   {
423     Triple tent (0.6, 0.7, 0.8);
424     Triple axis_range (-1.0, 0.2, 1.0);
425     TripleDistances axis_distances{1.0, 1.0};
426     rebase_tent_result_t out = rebase_tent (tent, axis_range, axis_distances);
427     assert (out.length == 1);
428     assert (out[0].first == 1.0);
429     assert (approx (out[0].second, Triple (0.5, 0.625, 0.75)));
430   }
431 }
432