xref: /aosp_15_r20/external/harfbuzz_ng/test/shape/data/aots/hb-aots-tester.cpp (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1 /*____________________________________________________________________________
2 
3     Copyright 2000-2016 Adobe Systems Incorporated. All Rights Reserved.
4 
5     Licensed under the Apache License, Version 2.0 (the "License");
6     you may not use these files except in compliance with the License.
7     You may obtain a copy of the License at
8 
9     http://www.apache.org/licenses/LICENSE-2.0
10 
11     Unless required by applicable law or agreed to in writing, software
12     distributed under the License is distributed on an "AS IS" BASIS,
13     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14     See the License for the specific language governing permissions and
15     limitations under the License.
16 ____________________________________________________________________________*/
17 
18 #include "stdlib.h"
19 #include "stdio.h"
20 #include "string.h"
21 #include "hb.h"
22 #include "hb-ot.h"
23 
24 static const bool verbose = true;
25 
26 struct TestData
27 {
TestDataTestData28     TestData(hb_buffer_t  *buffer_,
29              hb_face_t    *face_,
30              hb_font_t    *font_,
31              hb_feature_t *features_,
32              int           num_features_)
33         : buffer(buffer_), face(face_), font(font_),
34           features(features_), num_features(num_features_)
35     { }
~TestDataTestData36     ~TestData()
37     {
38         free (features);
39         hb_face_destroy (face);
40         hb_font_destroy (font);
41         hb_buffer_destroy (buffer);
42     }
43 
44     hb_buffer_t  *buffer;
45     hb_face_t    *face;
46     hb_font_t    *font;
47     hb_feature_t *features;
48     int           num_features;
49 };
50 
51 TestData
runTest(const char * testName,const char * fontfileName,unsigned int * in,int nbIn,unsigned int * select,int nbSelect)52 runTest(const char *testName,
53         const char *fontfileName,
54         unsigned int *in, int nbIn,
55         unsigned int *select, int nbSelect)
56 {
57     FILE *f = fopen (fontfileName, "rb");
58     fseek(f, 0, SEEK_END);
59     long fontsize = ftell(f);
60     fseek(f, 0, SEEK_SET);
61     char *fontdata = (char *)malloc (fontsize);
62     fread(fontdata, fontsize, 1, f);
63     fclose(f);
64 
65     if (verbose) {
66         printf ("------------------------------- %s\n", testName);
67     }
68 
69     // setup font
70     hb_blob_t *blob = hb_blob_create(fontdata, fontsize,
71                                      HB_MEMORY_MODE_WRITABLE,
72                                      0, 0);
73     hb_face_t *face = hb_face_create(blob, 0);
74     hb_font_t *font = hb_font_create(face);
75     unsigned int upem = hb_face_get_upem (face);
76 
77     hb_font_set_scale(font, upem, upem);
78     hb_ot_font_set_funcs (font);
79 
80     // setup buffer
81     hb_buffer_t *buffer = hb_buffer_create();
82     hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
83     hb_buffer_set_script(buffer, HB_SCRIPT_LATIN);
84     hb_buffer_set_language(buffer, hb_language_from_string("en", 2));
85 
86     hb_buffer_add_utf32(buffer, in, nbIn, 0, nbIn);
87 
88     // setup features
89     hb_feature_t *features;
90     int nbFeatures;
91 
92     if (nbSelect == 0)
93     {
94         nbFeatures = 1;
95 
96         features = (hb_feature_t *) malloc (sizeof (*features));
97         features[0].tag = HB_TAG('t', 'e', 's', 't');
98         features[0].value = 1;
99         features[0].start = HB_FEATURE_GLOBAL_START;
100         features[0].end = HB_FEATURE_GLOBAL_END;
101     }
102     else
103     {
104         nbFeatures = 0;
105 
106         features = (hb_feature_t *) malloc (sizeof (*features) * nbSelect);
107         for (int i = 0; i < nbSelect; i++) {
108             if (select[i] != -1) {
109                 features[nbFeatures].tag = HB_TAG('t', 'e', 's', 't');
110                 features[nbFeatures].value = select[i];
111                 features[nbFeatures].start = i;
112                 features[nbFeatures].end = i + 1;
113                 nbFeatures++;
114             }
115         }
116     }
117 
118     // shape
119     hb_shape(font, buffer, features, nbFeatures);
120 
121     hb_blob_destroy(blob);
122 
123     return TestData(buffer, face, font, features, nbFeatures);
124 }
125 
126 
printArray(const char * s,int * a,int n)127 void printArray (const char* s, int *a, int n)
128 {
129     printf ("%s  %d : ", s, n);
130     for (int i = 0; i < n; i++) {
131         printf (" %d", a[i]);
132     }
133     printf ("\n");
134 }
135 
printUArray(const char * s,unsigned int * a,int n)136 void printUArray (const char* s, unsigned int *a, int n)
137 {
138     printArray (s, (int *) a, n);
139 }
140 
gsub_test(const char * testName,const char * fontfileName,int nbIn,unsigned int * in,int nbSelect,unsigned int * select,int nbExpected,unsigned int * expected)141 bool gsub_test(const char *testName,
142                const char *fontfileName,
143                int nbIn, unsigned int *in,
144                int nbSelect, unsigned int *select,
145                int nbExpected, unsigned int *expected)
146 {
147     TestData data = runTest(testName,
148                             fontfileName,
149                             in, nbIn,
150                             select, nbSelect);
151 
152     // verify
153     hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(data.buffer, 0);
154     unsigned int nbActual = hb_buffer_get_length(data.buffer);
155 
156     bool ok = true;
157 
158     if (nbActual != nbExpected)
159         ok = false;
160     else {
161         for (int i = 0; i < nbActual; i++) {
162             if (actual[i].codepoint != expected [i]) {
163                 ok = false;
164                 break;
165             }
166         }
167     }
168 
169 
170     char test_name[255];
171     sprintf (test_name, "../../tests/%.*s.tests", (int) (strrchr (testName, '_') - testName), testName);
172     FILE *tests_file = fopen (test_name, "a+");
173     if (!ok) fprintf (tests_file, "#");
174     fprintf (tests_file, "../fonts/%s;--features=\"", fontfileName + 9);
175     for (unsigned int i = 0; i < data.num_features; i++)
176     {
177         if (i != 0) fprintf (tests_file, ",");
178         char buf[255];
179         hb_feature_to_string (&data.features[i], buf, sizeof (buf));
180         fprintf (tests_file, "%s", buf);
181     }
182     fprintf (tests_file, "\" --single-par --no-clusters --no-glyph-names --no-positions;");
183 
184     for (unsigned int i = 0; i < nbIn; i++)
185     {
186         if (i != 0) fprintf (tests_file, ",");
187         fprintf (tests_file, "U+%04X", in[i]);
188     }
189 
190     fprintf (tests_file, ";[");
191     for (unsigned int i = 0; i < nbActual; i++)
192     {
193         if (i != 0) fprintf (tests_file, "|");
194         fprintf (tests_file, "%d", expected[i]);
195     }
196     fprintf (tests_file, "]");
197 
198     fprintf (tests_file, "\n");
199     fclose (tests_file);
200 
201 
202     if (! ok) {
203         printf ("******* GSUB %s\n", testName);
204 
205         printf ("expected %d:", nbExpected);
206         for (int i = 0; i < nbExpected; i++) {
207             printf (" %d", expected[i]); }
208         printf ("\n");
209 
210         printf ("  actual %d:", nbActual);
211         for (int i = 0; i < nbActual; i++) {
212             printf (" %d", actual[i].codepoint); }
213         printf ("\n");
214 
215     }
216 
217     return ok;
218 }
219 
cmap_test(const char * testName,const char * fontfileName,int nbIn,unsigned int * in,int nbSelect,unsigned int * select,int nbExpected,unsigned int * expected)220 bool cmap_test(const char *testName,
221                const char *fontfileName,
222                int nbIn, unsigned int *in,
223                int nbSelect, unsigned int *select,
224                int nbExpected, unsigned int *expected)
225 {
226     TestData data = runTest(testName,
227                             fontfileName,
228                             in, nbIn,
229                             select, nbSelect);
230 
231     // verify
232     hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(data.buffer, 0);
233     unsigned int nbActual = hb_buffer_get_length(data.buffer);
234 
235     bool ok = true;
236 
237     if (nbActual != nbExpected)
238         ok = false;
239     else {
240         for (int i = 0; i < nbActual; i++) {
241             if (actual[i].codepoint != expected [i]) {
242                 ok = false;
243                 break;
244             }
245         }
246     }
247 
248 
249     char test_name[255];
250     sprintf (test_name, "../../tests/%.*s.tests", (int) (strrchr (testName, '_') - testName), testName);
251     FILE *tests_file = fopen (test_name, "a+");
252     if (!ok) fprintf (tests_file, "#");
253     fprintf (tests_file, "../fonts/%s;--features=\"", fontfileName + 9);
254     for (unsigned int i = 0; i < data.num_features; i++)
255     {
256         if (i != 0) fprintf (tests_file, ",");
257         char buf[255];
258         hb_feature_to_string (&data.features[i], buf, sizeof (buf));
259         fprintf (tests_file, "%s", buf);
260     }
261     fprintf (tests_file, "\" --single-par --no-clusters --no-glyph-names --no-positions --font-funcs=ot;");
262 
263     for (unsigned int i = 0; i < nbIn; i++)
264     {
265         if (i != 0) fprintf (tests_file, ",");
266         fprintf (tests_file, "U+%04X", in[i]);
267     }
268 
269     fprintf (tests_file, ";[");
270     for (unsigned int i = 0; i < nbActual; i++)
271     {
272         if (i != 0) fprintf (tests_file, "|");
273         fprintf (tests_file, "%d", expected[i]);
274     }
275     fprintf (tests_file, "]");
276 
277     fprintf (tests_file, "\n");
278     fclose (tests_file);
279 
280 
281     if (! ok) {
282         printf ("******* cmap %s\n", testName);
283 
284         printf ("expected %d:", nbExpected);
285         for (int i = 0; i < nbExpected; i++) {
286             printf (" %d", expected[i]); }
287         printf ("\n");
288 
289         printf ("  actual %d:", nbActual);
290         for (int i = 0; i < nbActual; i++) {
291             printf (" %d", actual[i].codepoint); }
292         printf ("\n");
293 
294     }
295 
296     return ok;
297 }
298 
gpos_test(const char * testName,const char * fontfileName,int nbIn,unsigned int * in,int nbOut,unsigned int * out,int * x,int * y)299 bool gpos_test(const char *testName,
300                const char *fontfileName,
301                int nbIn,
302                unsigned int *in,
303                int nbOut,
304                unsigned int *out,
305                int *x,
306                int *y)
307 {
308     TestData data = runTest(testName,
309                             fontfileName,
310                             in, nbIn,
311                             0, 0);
312 
313     // verify
314     unsigned int nbActual;
315     hb_glyph_info_t *actual = hb_buffer_get_glyph_infos(data.buffer, &nbActual);
316     hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (data.buffer, NULL);
317 
318     unsigned int *actualG = (unsigned int *) malloc(sizeof(*actualG) * nbActual);
319     int *actualX = (int *) malloc(sizeof(*actualX) * nbActual);
320     int *actualY = (int *) malloc(sizeof(*actualY) * nbActual);
321     int curX = 0;
322     int curY = 0;
323     for (int i = 0; i < nbActual; i++) {
324         actualG[i] = actual[i].codepoint;
325         actualX[i] = curX + pos[i].x_offset;
326         actualY[i] = curY + pos[i].y_offset;
327 
328         curX += pos[i].x_advance;
329         if (hb_ot_layout_get_glyph_class (data.face, actualG[i]) != HB_OT_LAYOUT_GLYPH_CLASS_MARK)
330             curX -= 1500;
331         curY += pos[i].y_advance;
332     }
333 
334     bool nbOk = true;
335     bool xOk = true;
336     bool yOk = true;
337 
338     if (nbActual != nbOut)
339         nbOk = false;
340     else {
341         for (int i = 0; i < nbActual; i++) {
342             if (actualX[i] != x[i]) {
343                 xOk = false;
344             }
345             if (actualY[i] != y[i]) {
346                 yOk = false;
347             }
348         }
349     }
350 
351     bool ok = (nbOk && xOk && yOk);
352     if (! ok) {
353         printf ("******* GPOS %s\n", testName);
354 
355         if (! (nbOk && xOk)) {
356             printArray ("expectedX", x, nbOut);
357             printArray ("actualX  ", actualX, nbActual);
358 
359             printf ("xadv/pos:");
360             for (int i = 0; i < nbOut; i++) {
361                 printf (" %d/%d", pos[i].x_advance, pos[i].x_offset);
362             }
363             printf ("\n");
364         }
365 
366         if (! (nbOk && yOk)) {
367             printArray ("expectedY", y, nbOut);
368             printArray ("actualY  ", actualY, nbActual);
369 
370             printf ("yadv/pos:");
371             for (int i = 0; i < nbOut; i++) {
372                 printf (" %d/%d", pos[i].y_advance, pos[i].y_offset);
373             }
374             printf ("\n");
375         }
376     }
377 
378 
379     char test_name[255];
380     sprintf (test_name, "../../tests/%.*s.tests", (int) (strrchr (testName, '_') - testName), testName);
381     FILE *tests_file = fopen (test_name, "a+");
382     if (!ok) fprintf (tests_file, "#");
383     fprintf (tests_file, "../fonts/%s;--features=\"", fontfileName + 9);
384     for (unsigned int i = 0; i < data.num_features; i++)
385     {
386         if (i != 0) fprintf (tests_file, ",");
387         char buf[255];
388         hb_feature_to_string (&data.features[i], buf, sizeof (buf));
389         fprintf (tests_file, "%s", buf);
390     }
391     fprintf (tests_file, "\" --single-par --no-clusters --no-glyph-names --ned;");
392 
393     for (unsigned int i = 0; i < nbIn; i++)
394     {
395         if (i != 0) fprintf (tests_file, ",");
396         fprintf (tests_file, "U+%04X", in[i]);
397     }
398 
399     fprintf (tests_file, ";[");
400     int accumlatedAdvance = 0;
401     for (unsigned int i = 0; i < nbActual; i++)
402     {
403         if (i != 0) fprintf (tests_file, "|");
404         fprintf (tests_file, "%d", /*it should be "out[i]"*/ actualG[i]);
405 
406         int expected_x = x[i] + accumlatedAdvance;
407         int expected_y = y[i];
408         if (expected_x || expected_y) fprintf (tests_file, "@%d,%d", expected_x, expected_y);
409         if (hb_ot_layout_get_glyph_class (data.face, actualG[i]) != HB_OT_LAYOUT_GLYPH_CLASS_MARK)
410             accumlatedAdvance += 1500;
411     }
412     fprintf (tests_file, "]");
413 
414     fprintf (tests_file, "\n");
415     fclose (tests_file);
416 
417 
418     free(actualG);
419     free(actualX);
420     free(actualY);
421 
422     return ok;
423 }
424 
425 
main(int argc,char ** argv)426 int main(int argc, char **argv)
427 {
428     int failures = 0;
429     int pass = 0;
430 
431 #include "hb-aots-tester.h"
432 
433     printf ("%d failures, %d pass\n", failures, pass);
434 }
435 
436 
437 
438