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