Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / test / api / test-draw.c
1 /*
2  * Copyright © 2020  Ebrahim Byagowi
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
25 #include "hb-test.h"
26 #include <math.h>
27
28 #include <hb.h>
29 #ifdef HAVE_FREETYPE
30 #include <hb-ft.h>
31 #endif
32
33 typedef struct draw_data_t
34 {
35   char *str;
36   unsigned size;
37   unsigned consumed;
38 } draw_data_t;
39
40 /* Our modified itoa, why not using libc's? it is going to be used
41    in harfbuzzjs where libc isn't available */
42 static void _hb_reverse (char *buf, unsigned int len)
43 {
44   unsigned start = 0, end = len - 1;
45   while (start < end)
46   {
47     char c = buf[end];
48     buf[end] = buf[start];
49     buf[start] = c;
50     start++; end--;
51   }
52 }
53 static unsigned _hb_itoa (float fnum, char *buf)
54 {
55   int32_t num = (int32_t) floorf (fnum + .5f);
56   unsigned int i = 0;
57   hb_bool_t is_negative = num < 0;
58   if (is_negative) num = -num;
59   do
60   {
61     buf[i++] = '0' + num % 10;
62     num /= 10;
63   } while (num);
64   if (is_negative) buf[i++] = '-';
65   _hb_reverse (buf, i);
66   buf[i] = '\0';
67   return i;
68 }
69
70 #define ITOA_BUF_SIZE 12 // 10 digits in int32, 1 for negative sign, 1 for \0
71
72 static void
73 test_itoa (void)
74 {
75   char s[] = "12345";
76   _hb_reverse (s, 5);
77   g_assert_cmpmem (s, 5, "54321", 5);
78
79   {
80     unsigned num = 12345;
81     char buf[ITOA_BUF_SIZE];
82     unsigned len = _hb_itoa (num, buf);
83     g_assert_cmpmem (buf, len, "12345", 5);
84   }
85
86   {
87     unsigned num = 3152;
88     char buf[ITOA_BUF_SIZE];
89     unsigned len = _hb_itoa (num, buf);
90     g_assert_cmpmem (buf, len, "3152", 4);
91   }
92
93   {
94     int num = -6457;
95     char buf[ITOA_BUF_SIZE];
96     unsigned len = _hb_itoa (num, buf);
97     g_assert_cmpmem (buf, len, "-6457", 5);
98   }
99 }
100
101 static void
102 move_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
103          hb_draw_state_t *st,
104          float to_x, float to_y,
105          void *user_data)
106 {
107   /* 4 = command character space + comma + array starts with 0 index + nul character space */
108   if (draw_data->consumed + 2 * ITOA_BUF_SIZE + 4 > draw_data->size) return;
109   draw_data->str[draw_data->consumed++] = 'M';
110   draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
111   draw_data->str[draw_data->consumed++] = ',';
112   draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
113 }
114
115 static void
116 line_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
117          hb_draw_state_t *st,
118          float to_x, float to_y,
119          void *user_data)
120 {
121   if (draw_data->consumed + 2 * ITOA_BUF_SIZE + 4 > draw_data->size) return;
122   draw_data->str[draw_data->consumed++] = 'L';
123   draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
124   draw_data->str[draw_data->consumed++] = ',';
125   draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
126 }
127
128 static void
129 quadratic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
130               hb_draw_state_t *st,
131               float control_x, float control_y,
132               float to_x, float to_y,
133               void *user_data)
134 {
135
136   if (draw_data->consumed + 4 * ITOA_BUF_SIZE + 6 > draw_data->size) return;
137   draw_data->str[draw_data->consumed++] = 'Q';
138   draw_data->consumed += _hb_itoa (control_x, draw_data->str + draw_data->consumed);
139   draw_data->str[draw_data->consumed++] = ',';
140   draw_data->consumed += _hb_itoa (control_y, draw_data->str + draw_data->consumed);
141   draw_data->str[draw_data->consumed++] = ' ';
142   draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
143   draw_data->str[draw_data->consumed++] = ',';
144   draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
145 }
146
147 static void
148 cubic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
149           hb_draw_state_t *st,
150           float control1_x, float control1_y,
151           float control2_x, float control2_y,
152           float to_x, float to_y,
153           void *user_data)
154 {
155   if (draw_data->consumed + 6 * ITOA_BUF_SIZE + 8 > draw_data->size) return;
156   draw_data->str[draw_data->consumed++] = 'C';
157   draw_data->consumed += _hb_itoa (control1_x, draw_data->str + draw_data->consumed);
158   draw_data->str[draw_data->consumed++] = ',';
159   draw_data->consumed += _hb_itoa (control1_y, draw_data->str + draw_data->consumed);
160   draw_data->str[draw_data->consumed++] = ' ';
161   draw_data->consumed += _hb_itoa (control2_x, draw_data->str + draw_data->consumed);
162   draw_data->str[draw_data->consumed++] = ',';
163   draw_data->consumed += _hb_itoa (control2_y, draw_data->str + draw_data->consumed);
164   draw_data->str[draw_data->consumed++] = ' ';
165   draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
166   draw_data->str[draw_data->consumed++] = ',';
167   draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
168 }
169
170 static void
171 close_path (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
172             hb_draw_state_t *st,
173             void *user_data)
174 {
175   if (draw_data->consumed + 2 > draw_data->size) return;
176   draw_data->str[draw_data->consumed++] = 'Z';
177 }
178
179 static hb_draw_funcs_t *funcs;
180 static hb_draw_funcs_t *funcs2; /* this one translates quadratic calls to cubic ones */
181
182 static void
183 test_hb_draw_empty (void)
184 {
185   hb_font_draw_glyph (hb_font_get_empty (), 3, funcs, NULL);
186 }
187
188 static void
189 test_hb_draw_glyf (void)
190 {
191   hb_face_t *face = hb_test_open_font_file ("fonts/SourceSerifVariable-Roman-VVAR.abc.ttf");
192   hb_font_t *font = hb_font_create (face);
193   hb_face_destroy (face);
194
195   char str[1024];
196   draw_data_t draw_data = {
197     .str = str,
198     .size = sizeof (str),
199     .consumed = 0
200   };
201
202   draw_data.consumed = 0;
203   hb_font_draw_glyph (font, 4, funcs, &draw_data);
204
205   draw_data.consumed = 0;
206   hb_font_draw_glyph (font, 3, funcs, &draw_data);
207   char expected[] = "M275,442Q232,442 198,420Q164,397 145,353Q126,309 126,245"
208                     "Q126,182 147,139Q167,95 204,73Q240,50 287,50Q330,50 367,70"
209                     "Q404,90 427,128L451,116Q431,54 384,21Q336,-13 266,-13"
210                     "Q198,-13 148,18Q97,48 70,104Q43,160 43,236Q43,314 76,371"
211                     "Q108,427 160,457Q212,487 272,487Q316,487 354,470Q392,453 417,424"
212                     "Q442,395 448,358Q441,321 403,321Q378,321 367,334"
213                     "Q355,347 350,366L325,454L371,417Q346,430 321,436Q296,442 275,442Z";
214   g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
215
216   /* Test translating quadratic calls to cubic by a _draw_funcs_t that doesn't set the callback */
217   draw_data.consumed = 0;
218   hb_font_draw_glyph (font, 3, funcs2, &draw_data);
219   char expected2[] = "M275,442C246,442 221,435 198,420C175,405 158,382 145,353"
220                      "C132,324 126,288 126,245C126,203 133,168 147,139C160,110 179,88 204,73"
221                      "C228,58 256,50 287,50C316,50 342,57 367,70C392,83 412,103 427,128"
222                      "L451,116C438,75 415,43 384,21C352,-2 313,-13 266,-13C221,-13 181,-3 148,18"
223                      "C114,38 88,67 70,104C52,141 43,185 43,236C43,288 54,333 76,371"
224                      "C97,408 125,437 160,457C195,477 232,487 272,487C301,487 329,481 354,470"
225                      "C379,459 400,443 417,424C434,405 444,383 448,358C443,333 428,321 403,321"
226                      "C386,321 374,325 367,334C359,343 353,353 350,366L325,454L371,417"
227                      "C354,426 338,432 321,436C304,440 289,442 275,442Z";
228   g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
229
230   hb_variation_t var;
231   var.tag = HB_TAG ('w','g','h','t');
232   var.value = 800;
233   hb_font_set_variations (font, &var, 1);
234
235   draw_data.consumed = 0;
236   hb_font_draw_glyph (font, 3, funcs, &draw_data);
237   char expected3[] = "M323,448Q297,448 271,430Q244,412 226,371Q209,330 209,261"
238                      "Q209,204 225,166Q242,127 272,107Q303,86 344,86Q378,86 404,101"
239                      "Q430,115 451,137L488,103Q458,42 404,13Q350,-16 279,-16"
240                      "Q211,-16 153,13Q95,41 60,98Q25,156 25,241Q25,323 62,382"
241                      "Q99,440 163,470Q226,501 303,501Q357,501 399,480Q440,460 464,426"
242                      "Q488,392 492,352Q475,297 420,297Q390,297 366,319Q342,342 339,401"
243                      "L333,469L411,427Q387,438 367,443Q348,448 323,448Z";
244   g_assert_cmpmem (str, draw_data.consumed, expected3, sizeof (expected3) - 1);
245
246   hb_font_destroy (font);
247 }
248
249 static void
250 test_hb_draw_cff1 (void)
251 {
252   hb_face_t *face = hb_test_open_font_file ("fonts/cff1_seac.otf");
253   hb_font_t *font = hb_font_create (face);
254   hb_face_destroy (face);
255
256   char str[1024];
257   draw_data_t draw_data = {
258     .str = str,
259     .size = sizeof (str),
260     .consumed = 0
261   };
262   hb_font_draw_glyph (font, 3, funcs, &draw_data);
263   char expected[] = "M203,367C227,440 248,512 268,588L272,588C293,512 314,440 338,367L369,267L172,267L203,367Z"
264                     "M3,0L88,0L151,200L390,200L452,0L541,0L319,656L225,656L3,0Z"
265                     "M300,653L342,694L201,861L143,806L300,653Z";
266   g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
267
268   hb_font_destroy (font);
269 }
270
271 static void
272 test_hb_draw_cff1_rline (void)
273 {
274   /* https://github.com/harfbuzz/harfbuzz/pull/2053 */
275   hb_face_t *face = hb_test_open_font_file ("fonts/RanaKufi-Regular.subset.otf");
276   hb_font_t *font = hb_font_create (face);
277   hb_face_destroy (face);
278
279   char str[1024];
280   draw_data_t draw_data = {
281     .str = str,
282     .size = sizeof (str),
283     .consumed = 0
284   };
285   hb_font_draw_glyph (font, 1, funcs, &draw_data);
286   char expected[] = "M775,400C705,400 650,343 650,274L650,250L391,250L713,572L392,893"
287                     "L287,1000C311,942 296,869 250,823C250,823 286,858 321,823L571,572"
288                     "L150,150L750,150L750,276C750,289 761,300 775,300C789,300 800,289 800,276"
289                     "L800,100L150,100C100,100 100,150 100,150C100,85 58,23 0,0L900,0L900,274"
290                     "C900,343 844,400 775,400Z";
291   g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
292
293   hb_font_destroy (font);
294 }
295
296 static void
297 test_hb_draw_cff2 (void)
298 {
299   hb_face_t *face = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
300   hb_font_t *font = hb_font_create (face);
301   hb_face_destroy (face);
302
303   char str[1024];
304   draw_data_t draw_data = {
305     .str = str,
306     .size = sizeof (str)
307   };
308
309   draw_data.consumed = 0;
310   hb_font_draw_glyph (font, 3, funcs, &draw_data);
311   char expected[] = "M275,442C303,442 337,435 371,417L325,454L350,366"
312                     "C357,341 370,321 403,321C428,321 443,333 448,358"
313                     "C435,432 361,487 272,487C153,487 43,393 43,236"
314                     "C43,83 129,-13 266,-13C360,-13 424,33 451,116L427,128"
315                     "C396,78 345,50 287,50C193,50 126,119 126,245C126,373 188,442 275,442Z";
316   g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
317
318   hb_variation_t var;
319   var.tag = HB_TAG ('w','g','h','t');
320   var.value = 800;
321   hb_font_set_variations (font, &var, 1);
322
323   draw_data.consumed = 0;
324   hb_font_draw_glyph (font, 3, funcs, &draw_data);
325   char expected2[] = "M323,448C356,448 380,441 411,427L333,469L339,401"
326                      "C343,322 379,297 420,297C458,297 480,314 492,352"
327                      "C486,433 412,501 303,501C148,501 25,406 25,241"
328                      "C25,70 143,-16 279,-16C374,-16 447,22 488,103L451,137"
329                      "C423,107 390,86 344,86C262,86 209,148 209,261C209,398 271,448 323,448Z";
330   g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
331
332   hb_font_destroy (font);
333 }
334
335 static void
336 test_hb_draw_ttf_parser_tests (void)
337 {
338   /* https://github.com/RazrFalcon/ttf-parser/blob/337e7d1c/tests/tests.rs#L50-L133 */
339   char str[1024];
340   draw_data_t draw_data = {
341     .str = str,
342     .size = sizeof (str)
343   };
344   {
345     hb_face_t *face = hb_test_open_font_file ("fonts/glyphs.ttf");
346     hb_font_t *font = hb_font_create (face);
347     hb_face_destroy (face);
348     {
349       draw_data.consumed = 0;
350       hb_font_draw_glyph (font, 0, funcs, &draw_data);
351       char expected[] = "M50,0L50,750L450,750L450,0L50,0Z";
352       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
353     }
354     {
355       draw_data.consumed = 0;
356       hb_font_draw_glyph (font, 1, funcs, &draw_data);
357       char expected[] = "M56,416L56,487L514,487L514,416L56,416ZM56,217L56,288L514,288L514,217L56,217Z";
358       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
359     }
360     {
361       draw_data.consumed = 0;
362       hb_font_draw_glyph (font, 4, funcs, &draw_data);
363       char expected[] = "M332,468L197,468L197,0L109,0L109,468L15,468L15,509L109,539"
364                         "L109,570Q109,674 155,720Q201,765 283,765Q315,765 342,760"
365                         "Q368,754 387,747L364,678Q348,683 327,688Q306,693 284,693"
366                         "Q240,693 219,664Q197,634 197,571L197,536L332,536L332,468Z"
367                         "M474,737Q494,737 510,724Q525,710 525,681Q525,653 510,639"
368                         "Q494,625 474,625Q452,625 437,639Q422,653 422,681"
369                         "Q422,710 437,724Q452,737 474,737ZM517,536L517,0L429,0L429,536L517,536Z";
370       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
371     }
372     {
373       draw_data.consumed = 0;
374       hb_font_draw_glyph (font, 5, funcs, &draw_data);
375       char expected[] = "M15,0Q15,0 15,0Z";
376       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
377     }
378     {
379       draw_data.consumed = 0;
380       hb_font_draw_glyph (font, 6, funcs, &draw_data);
381       char expected[] = "M346,468L211,468L211,0L123,0L123,468L29,468L29,509L123,539"
382                         "L123,570Q123,674 169,720Q215,765 297,765Q329,765 356,760"
383                         "Q382,754 401,747L378,678Q362,683 341,688Q320,693 298,693"
384                         "Q254,693 233,664Q211,634 211,571L211,536L346,536L346,468Z"
385                         "M15,0Q15,0 15,0Z";
386       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
387     }
388
389     hb_font_destroy (font);
390   }
391   {
392     hb_face_t *face = hb_test_open_font_file ("fonts/cff1_flex.otf");
393     hb_font_t *font = hb_font_create (face);
394     hb_face_destroy (face);
395
396     draw_data.consumed = 0;
397     hb_font_draw_glyph (font, 1, funcs, &draw_data);
398     char expected[] = "M0,0C100,0 150,-20 250,-20C350,-20 400,0 500,0C500,100 520,150 520,250"
399                       "C520,350 500,400 500,500C400,500 350,520 250,520C150,520 100,500 0,500"
400                       "C0,400 -20,350 -20,250C-20,150 0,100 0,0ZM50,50C50,130 34,170 34,250"
401                       "C34,330 50,370 50,450C130,450 170,466 250,466C330,466 370,450 450,450"
402                       "C450,370 466,330 466,250C466,170 450,130 450,50C370,50 330,34 250,34"
403                       "C170,34 130,50 50,50Z";
404     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
405
406     hb_font_destroy (font);
407   }
408   {
409     hb_face_t *face = hb_test_open_font_file ("fonts/cff1_dotsect.nohints.otf");
410     hb_font_t *font = hb_font_create (face);
411     hb_face_destroy (face);
412
413     draw_data.consumed = 0;
414     hb_font_draw_glyph (font, 1, funcs, &draw_data);
415     char expected[] = "M82,0L164,0L164,486L82,486L82,0Z"
416                       "M124,586C156,586 181,608 181,639C181,671 156,692 124,692"
417                       "C92,692 67,671 67,639C67,608 92,586 124,586Z";
418     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
419
420     hb_font_destroy (font);
421   }
422 }
423
424 static void
425 test_hb_draw_font_kit_glyphs_tests (void)
426 {
427   /* https://github.com/foliojs/fontkit/blob/master/test/glyphs.js */
428   char str[2048];
429   draw_data_t draw_data = {
430     .str = str,
431     .size = sizeof (str)
432   };
433   /* truetype glyphs */
434   {
435     hb_face_t *face = hb_test_open_font_file ("fonts/OpenSans-Regular.ttf");
436     hb_font_t *font = hb_font_create (face);
437     hb_face_destroy (face);
438
439     /* should get a path for the glyph */
440     draw_data.consumed = 0;
441     hb_font_draw_glyph (font, 37, funcs, &draw_data);
442     char expected[] = "M201,1462L614,1462Q905,1462 1035,1375Q1165,1288 1165,1100"
443                       "Q1165,970 1093,886Q1020,801 881,776L881,766Q1214,709 1214,416"
444                       "Q1214,220 1082,110Q949,0 711,0L201,0L201,1462ZM371,836L651,836"
445                       "Q831,836 910,893Q989,949 989,1083Q989,1206 901,1261"
446                       "Q813,1315 621,1315L371,1315L371,836ZM371,692L371,145L676,145"
447                       "Q853,145 943,214Q1032,282 1032,428Q1032,564 941,628Q849,692 662,692L371,692Z";
448     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
449
450     /* should get a path for the glyph */
451     draw_data.consumed = 0;
452     hb_font_draw_glyph (font, 171, funcs, &draw_data);
453     char expected2[] = "M639,-20Q396,-20 256,128Q115,276 115,539Q115,804 246,960Q376,1116 596,1116"
454                        "Q802,1116 922,981Q1042,845 1042,623L1042,518L287,518Q292,325 385,225"
455                        "Q477,125 645,125Q822,125 995,199L995,51Q907,13 829,-3Q750,-20 639,-20Z"
456                        "M594,977Q462,977 384,891Q305,805 291,653L864,653Q864,810 794,894"
457                        "Q724,977 594,977ZM471,1266Q519,1328 575,1416Q630,1504 662,1569"
458                        "L864,1569L864,1548Q820,1483 733,1388Q646,1293 582,1241L471,1241L471,1266Z";
459     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
460
461     hb_font_destroy (font);
462   }
463   {
464     hb_face_t *face = hb_test_open_font_file ("fonts/Mada-VF.ttf");
465     hb_font_t *font = hb_font_create (face);
466     hb_face_destroy (face);
467
468     hb_buffer_t *buffer = hb_buffer_create ();
469     hb_codepoint_t codepoint = 1610; /* ي */
470     hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
471     hb_buffer_set_direction (buffer, HB_DIRECTION_RTL);
472     hb_shape (font, buffer, NULL, 0);
473     codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
474     hb_buffer_destroy (buffer);
475
476     /* should resolve composite glyphs recursively */
477     draw_data.consumed = 0;
478     hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
479     char expected[] = "M581,274L443,274Q409,274 384,259Q359,243 348,219Q336,194 340,166"
480                       "Q343,138 365,111L468,-13Q470,-10 473,-6Q475,-3 477,0L253,0Q225,0 203,8"
481                       "Q180,15 168,32Q155,48 155,73L155,269L50,269L50,73Q50,24 69,-10"
482                       "Q88,-44 118,-64Q147,-85 181,-94Q214,-104 243,-104L473,-104"
483                       "Q501,-104 525,-91Q549,-78 564,-56Q578,-34 578,-8Q578,18 557,43"
484                       "L442,182Q439,179 437,176Q435,173 432,170L581,170L581,274ZM184,-194"
485                       "Q184,-216 199,-231Q214,-246 236,-246Q258,-246 273,-231Q288,-216 288,-194"
486                       "Q288,-172 273,-157Q258,-142 236,-142Q214,-142 199,-157Q184,-172 184,-194Z"
487                       "M360,-194Q360,-216 375,-231Q390,-246 412,-246Q434,-246 449,-231"
488                       "Q464,-216 464,-194Q464,-172 449,-157Q434,-142 412,-142"
489                       "Q390,-142 375,-157Q360,-172 360,-194Z";
490     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
491
492     /* should transform points of a composite glyph */
493     draw_data.consumed = 0;
494     hb_font_draw_glyph (font, 2, funcs, &draw_data); /* 2 == arAlef.fina */
495     char expected2[] = "M155,624L155,84Q150,90 146,95Q141,99 136,105"
496                        "L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51"
497                        "Q50,74 50,104L50,624L155,624ZM282,105L312,105"
498                        "L312,0L282,0L282,105Z";
499     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
500
501     hb_font_destroy (font);
502   }
503   /* CFF glyphs, should get a path for the glyph */
504   {
505     hb_face_t *face = hb_test_open_font_file ("fonts/SourceSansPro-Regular.otf");
506     hb_font_t *font = hb_font_create (face);
507     hb_face_destroy (face);
508
509     draw_data.consumed = 0;
510     hb_font_draw_glyph (font, 5, funcs, &draw_data);
511     char expected[] = "M90,0L258,0C456,0 564,122 564,331C564,539 456,656 254,656L90,656L90,0Z"
512                       "M173,68L173,588L248,588C401,588 478,496 478,331C478,165 401,68 248,68L173,68Z";
513     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
514
515     hb_font_destroy (font);
516   }
517   /* CFF glyphs (CID font) */
518   {
519     /* replaced with a subset as the original one was 15MB */
520     hb_face_t *face = hb_test_open_font_file ("fonts/NotoSansCJKkr-Regular-subset-colon.ttf");
521     hb_font_t *font = hb_font_create (face);
522     hb_face_destroy (face);
523
524     draw_data.consumed = 0;
525     hb_font_draw_glyph (font, 1, funcs, &draw_data);
526     char expected[] = "M139,390C175,390 205,419 205,459C205,501 175,530 139,530C103,530 73,501 73,459"
527                       "C73,419 103,390 139,390ZM139,-13C175,-13 205,15 205,56C205,97 175,127 139,127"
528                       "C103,127 73,97 73,56C73,15 103,-13 139,-13Z";
529     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
530
531     hb_font_destroy (font);
532   }
533   /* Skip SBIX glyphs (empty path), COLR glyphs (empty path), WOFF ttf glyphs, WOFF2 ttf glyph */
534 }
535
536 static void
537 test_hb_draw_font_kit_variations_tests (void)
538 {
539   /* https://github.com/foliojs/fontkit/blob/b310db5/test/variations.js */
540   char str[2048];
541   draw_data_t draw_data = {
542     .str = str,
543     .size = sizeof (str)
544   };
545   /* Skia */
546   {
547     /* Skipping Skia tests for now even the fact we can actually do platform specific tests using our CIs */
548   }
549   /* truetype variations */
550   /* should support sharing all points */
551   {
552     hb_face_t *face = hb_test_open_font_file ("fonts/TestGVAROne.ttf");
553     hb_font_t *font = hb_font_create (face);
554     hb_face_destroy (face);
555
556     hb_variation_t var;
557     var.tag = HB_TAG ('w','g','h','t');
558     var.value = 300;
559     hb_font_set_variations (font, &var, 1);
560
561     hb_buffer_t *buffer = hb_buffer_create ();
562     hb_codepoint_t codepoint = 24396; /* 彌 */
563     hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
564     hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
565     hb_shape (font, buffer, NULL, 0);
566     codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
567     hb_buffer_destroy (buffer);
568
569     draw_data.consumed = 0;
570     hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
571     char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102"
572                       "Q796,-102 755,-98L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504"
573                       "L414,504L414,-102L371,-102ZM203,-94Q138,-94 86,-90L74,-52"
574                       "Q137,-59 188,-59Q211,-59 222,-46Q233,-34 236,12Q238,58 240,135"
575                       "Q242,211 242,262L74,262L94,527L242,527L242,719L63,719L63,754"
576                       "L285,754L285,492L133,492L117,297L285,297Q285,241 284,185"
577                       "Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94Z"
578                       "M461,12L434,43Q473,73 503,115Q478,150 441,188L469,211Q501,179 525,147"
579                       "Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43L566,20"
580                       "Q544,64 528,86Q500,44 461,12ZM465,258L438,285Q474,316 501,351"
581                       "Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453L598,434"
582                       "Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322Q491,280 465,258Z"
583                       "M707,12L680,43Q717,68 753,115Q731,147 691,188L719,211Q739,190 754,172"
584                       "Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117Q828,82 852,43"
585                       "L820,20Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730L664,-94"
586                       "L621,-94ZM348,570L324,605Q425,629 527,688L555,656Q491,621 439,601"
587                       "Q386,581 348,570ZM715,258L688,285Q727,318 753,351Q733,378 695,418L723,441"
588                       "Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281"
589                       "L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719"
590                       "L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
591     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
592
593     hb_font_destroy (font);
594   }
595   /* should support sharing enumerated points */
596   {
597     hb_face_t *face = hb_test_open_font_file ("fonts/TestGVARTwo.ttf");
598     hb_font_t *font = hb_font_create (face);
599     hb_face_destroy (face);
600
601     hb_variation_t var;
602     var.tag = HB_TAG ('w','g','h','t');
603     var.value = 300;
604     hb_font_set_variations (font, &var, 1);
605
606     hb_buffer_t *buffer = hb_buffer_create ();
607     hb_codepoint_t codepoint = 24396; /* 彌 */
608     hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
609     hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
610     hb_shape (font, buffer, NULL, 0);
611     codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
612     hb_buffer_destroy (buffer);
613
614     draw_data.consumed = 0;
615     hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
616     char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
617                       "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
618                       "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46"
619                       "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527"
620                       "L242,719L63,719L63,754L285,754L285,492L133,492L117,297L285,297"
621                       "Q285,241 284,185Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94Z"
622                       "M461,12L434,43Q473,73 503,115Q478,150 441,188L469,211Q501,179 525,147"
623                       "Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43L566,20"
624                       "Q544,64 528,86Q500,44 461,12ZM465,258L438,285Q474,316 501,351"
625                       "Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453L598,434"
626                       "Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322Q491,280 465,258Z"
627                       "M707,12L680,43Q717,68 753,115Q731,147 691,188L719,211Q739,190 754,172"
628                       "Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117Q828,82 852,43L820,20"
629                       "Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730L664,-94L621,-94ZM348,570"
630                       "L324,605Q425,629 527,688L555,656Q491,621 439,601Q386,581 348,570ZM715,258L688,285"
631                       "Q727,318 753,351Q733,378 695,418L723,441Q754,410 775,381Q794,407 813,453"
632                       "L848,434Q826,387 801,352Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258Z"
633                       "M348,719L348,754L941,754L941,719L348,719ZM936,570Q870,602 817,622"
634                       "Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
635     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
636
637     hb_font_destroy (font);
638   }
639   /* should support sharing no points */
640   {
641     hb_face_t *face = hb_test_open_font_file ("fonts/TestGVARThree.ttf");
642     hb_font_t *font = hb_font_create (face);
643     hb_face_destroy (face);
644
645     hb_variation_t var;
646     var.tag = HB_TAG ('w','g','h','t');
647     var.value = 300;
648     hb_font_set_variations (font, &var, 1);
649
650     hb_buffer_t *buffer = hb_buffer_create ();
651     hb_codepoint_t codepoint = 24396; /* 彌 */
652     hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
653     hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
654     hb_shape (font, buffer, NULL, 0);
655     codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
656     hb_buffer_destroy (buffer);
657
658     draw_data.consumed = 0;
659     hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
660     char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
661                       "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
662                       "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46"
663                       "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527L242,719"
664                       "L63,719L63,754L285,754L285,492L133,492L117,297L285,297Q285,241 284,185"
665                       "Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94ZM461,12"
666                       "L434,43Q473,73 503,115Q478,150 441,188L469,211Q501,179 525,147"
667                       "Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43L566,20Q544,64 528,86"
668                       "Q500,44 461,12ZM465,258L438,285Q474,316 501,351Q474,388 445,418L473,441"
669                       "Q500,414 523,381Q546,413 563,453L598,434Q571,382 549,352Q576,320 598,285"
670                       "L563,262Q546,294 525,322Q491,280 465,258ZM707,12L680,43Q717,68 753,115"
671                       "Q731,147 691,188L719,211Q739,190 754,172Q769,154 774,147Q793,185 809,230"
672                       "L844,211Q822,155 801,117Q828,82 852,43L820,20Q798,58 778,87Q747,43 707,12Z"
673                       "M621,-94L621,730L664,730L664,-94L621,-94ZM348,570L324,605Q425,629 527,688"
674                       "L555,656Q491,621 439,601Q386,581 348,570ZM715,258L688,285Q727,318 753,351"
675                       "Q733,378 695,418L723,441Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352"
676                       "Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754"
677                       "L941,754L941,719L348,719ZM936,570Q870,602 817,622"
678                       "Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
679     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
680
681     hb_font_destroy (font);
682   }
683
684   /* CFF2 variations */
685   {
686     hb_face_t *face = hb_test_open_font_file ("fonts/AdobeVFPrototype-Subset.otf");
687     hb_font_t *font = hb_font_create (face);
688     hb_face_destroy (face);
689
690     hb_variation_t var;
691     var.tag = HB_TAG ('w','g','h','t');
692     /* applies variations to CFF2 glyphs */
693     {
694       var.value = 100;
695       hb_font_set_variations (font, &var, 1);
696
697       hb_buffer_t *buffer = hb_buffer_create ();
698       hb_codepoint_t codepoint = '$';
699       hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
700       hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
701       hb_shape (font, buffer, NULL, 0);
702       codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
703       hb_buffer_destroy (buffer);
704
705       draw_data.consumed = 0;
706       hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
707       char expected[] = "M246,15C188,15 147,27 101,68L142,23L117,117C111,143 96,149 81,149"
708                         "C65,149 56,141 52,126C71,40 137,-13 244,-13C348,-13 436,46 436,156"
709                         "C436,229 405,295 271,349L247,359C160,393 119,439 119,506"
710                         "C119,592 178,637 262,637C311,637 346,626 390,585L348,629L373,535"
711                         "C380,510 394,503 408,503C424,503 434,510 437,526C418,614 348,665 259,665"
712                         "C161,665 78,606 78,500C78,414 128,361 224,321L261,305C367,259 395,217 395,152"
713                         "C395,65 334,15 246,15ZM267,331L267,759L240,759L240,331L267,331ZM240,-115"
714                         "L267,-115L267,331L240,331L240,-115Z";
715       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
716     }
717     {
718       var.value = 500;
719       hb_font_set_variations (font, &var, 1);
720
721       hb_buffer_t *buffer = hb_buffer_create ();
722       hb_codepoint_t codepoint = '$';
723       hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
724       hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
725       hb_shape (font, buffer, NULL, 0);
726       codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
727       hb_buffer_destroy (buffer);
728
729       draw_data.consumed = 0;
730       hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
731       char expected[] = "M251,36C206,36 165,42 118,61L176,21L161,99C151,152 129,167 101,167"
732                         "C78,167 61,155 51,131C54,43 133,-14 247,-14C388,-14 474,64 474,171"
733                         "C474,258 430,321 294,370L257,383C188,406 150,438 150,499"
734                         "C150,571 204,606 276,606C308,606 342,601 386,582L327,621"
735                         "L343,546C355,490 382,476 408,476C428,476 448,487 455,512"
736                         "C450,597 370,656 264,656C140,656 57,576 57,474C57,373 119,318 227,279"
737                         "L263,266C345,236 379,208 379,145C379,76 329,36 251,36ZM289,320"
738                         "L289,746L242,746L242,320L289,320ZM240,-115L286,-115L286,320L240,320L240,-115Z";
739       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
740     }
741     /* substitutes GSUB features depending on variations */
742     {
743       var.value = 900;
744       hb_font_set_variations (font, &var, 1);
745
746       hb_buffer_t *buffer = hb_buffer_create ();
747       hb_codepoint_t codepoint = '$';
748       hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
749       hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
750       hb_shape (font, buffer, NULL, 0);
751       codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
752       hb_buffer_destroy (buffer);
753
754       draw_data.consumed = 0;
755       hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
756       char expected[] = "M258,38C197,38 167,48 118,71L192,19L183,103C177,155 155,174 115,174"
757                         "C89,174 64,161 51,125C52,36 124,-16 258,-16C417,-16 513,67 513,175"
758                         "C513,278 457,328 322,388L289,403C232,429 203,452 203,500C203,562 244,589 301,589"
759                         "C342,589 370,585 420,562L341,607L352,539C363,468 398,454 434,454C459,454 486,468 492,506"
760                         "C491,590 408,643 290,643C141,643 57,563 57,460C57,357 122,307 233,256L265,241"
761                         "C334,209 363,186 363,130C363,77 320,38 258,38ZM318,616L318,734L252,734L252,616"
762                         "L318,616ZM253,-115L319,-115L319,14L253,14L253,-115Z";
763       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
764     }
765
766     hb_font_destroy (font);
767   }
768 }
769
770 static void
771 test_hb_draw_estedad_vf (void)
772 {
773   /* https://github.com/harfbuzz/harfbuzz/issues/2215 */
774   char str[2048];
775   draw_data_t draw_data = {
776     .str = str,
777     .size = sizeof (str)
778   };
779   {
780     /* See https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L115-L124 */
781     hb_face_t *face = hb_test_open_font_file ("fonts/Estedad-VF.ttf");
782     hb_font_t *font = hb_font_create (face);
783     hb_face_destroy (face);
784
785     hb_variation_t var;
786     hb_variation_from_string ("wght=100", -1, &var);
787     hb_font_set_variations (font, &var, 1);
788
789     draw_data.consumed = 0;
790     hb_font_draw_glyph (font, 156, funcs, &draw_data);
791     /* Skip empty path where all the points of a path are equal */
792     char expected[] = "M150,1158L182,1158Q256,1158 317,1170Q377,1182 421,1213L421,430L521,430"
793                       "L521,1490L421,1490L421,1320Q393,1279 344,1262Q294,1244 182,1244L150,1244"
794                       "L150,1158ZM1815,-122L1669,-122L1669,642L1552,642L1055,-117L1055,-206"
795                       "L1569,-206L1569,-458L1669,-458L1669,-206L1815,-206L1815,-122ZM1569,-122"
796                       "L1166,-122L1569,494L1569,-122ZM609,-79L1639,1288L1555,1334L525,-33L609,-79Z";
797     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
798
799     draw_data.consumed = 0;
800     hb_font_draw_glyph (font, 180, funcs, &draw_data);
801     /* Skip empty path where all the points of a path are equal */
802     char expected2[] = "M120,693Q120,545 177,414Q233,282 333,182Q433,81 567,24"
803                        "Q701,-33 856,-33Q1010,-33 1144,24Q1277,81 1377,182Q1477,282 1534,414"
804                        "Q1590,545 1590,693Q1590,842 1534,973Q1477,1104 1377,1205"
805                        "Q1277,1305 1144,1362Q1010,1419 856,1419Q701,1419 567,1362"
806                        "Q433,1305 333,1205Q233,1104 177,973Q120,842 120,693Z"
807                        "M220,693Q220,828 270,945Q320,1061 409,1148Q497,1235 612,1284"
808                        "Q726,1333 855,1333Q984,1333 1099,1284Q1213,1235 1302,1148"
809                        "Q1390,1061 1440,945Q1490,828 1490,693Q1490,558 1440,442"
810                        "Q1390,325 1302,237Q1213,149 1099,100Q984,51 855,51"
811                        "Q726,51 611,100Q497,149 408,237Q320,325 270,442"
812                        "Q220,558 220,693ZM690,643L690,997L886,997Q970,997 1029,949"
813                        "Q1087,901 1087,819Q1087,737 1028,690Q969,643 886,643L690,643Z"
814                        "M1165,334L973,568Q1065,591 1126,658Q1187,725 1187,819"
815                        "Q1187,896 1147,956Q1106,1015 1037,1049Q969,1083 886,1083"
816                        "L590,1083L590,310L690,310L690,557L860,557L1083,286L1165,334Z";
817     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
818
819     draw_data.consumed = 0;
820     hb_font_draw_glyph (font, 262, funcs, &draw_data);
821     /* Skip empty path where all the points of a path are equal */
822     char expected3[] = "M422,598Q495,598 545,548Q595,498 595,426Q595,353 545,303Q494,252 422,252"
823                        "Q350,252 300,303Q250,353 250,426Q250,499 300,549Q349,598 422,598ZM422,698"
824                        "Q347,698 285,662Q223,625 187,564Q150,502 150,426Q150,351 187,289"
825                        "Q223,226 285,189Q346,152 422,152Q498,152 560,189Q622,226 658,288"
826                        "Q695,351 695,426Q695,502 658,563Q621,625 559,661Q498,698 422,698Z";
827     g_assert_cmpmem (str, draw_data.consumed, expected3, sizeof (expected3) - 1);
828
829     hb_font_destroy (font);
830   }
831 }
832
833 static void
834 test_hb_draw_stroking (void)
835 {
836   /* https://skia-review.googlesource.com/c/skia/+/266945
837      https://savannah.nongnu.org/bugs/index.php?57701 */
838   char str[2048];
839   draw_data_t draw_data = {
840     .str = str,
841     .size = sizeof (str)
842   };
843   {
844     /* See https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L115-L124 */
845     hb_face_t *face = hb_test_open_font_file ("fonts/Stroking.ttf");
846     hb_font_t *font = hb_font_create (face);
847     hb_face_destroy (face);
848
849     draw_data.consumed = 0;
850     hb_font_draw_glyph (font, 6, funcs, &draw_data);
851     /* Skip empty path where all the points of a path are equal */
852     char expected[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427Q1384,332 1626,332"
853                       "Q1868,332 2089,427Q2309,521 2468,680Q2627,839 2722,1060Q2816,1280 2816,1522"
854                       "Q2816,1764 2722,1985Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712"
855                       "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985Q436,1764 436,1522ZM256,1528"
856                       "Q256,1714 306,1892Q355,2069 443,2220Q531,2370 658,2497Q784,2623 935,2711"
857                       "Q1085,2799 1263,2849Q1440,2898 1626,2898Q1812,2898 1990,2849Q2167,2799 2318,2711"
858                       "Q2468,2623 2595,2497Q2721,2370 2809,2220Q2897,2069 2947,1892Q2996,1714 2996,1528"
859                       "Q2996,1342 2947,1165Q2897,987 2809,837Q2721,686 2595,560Q2468,433 2318,345"
860                       "Q2167,257 1990,208Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
861                       "Q784,433 658,560Q531,686 443,837Q355,987 306,1165Q256,1342 256,1528Z";
862     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
863
864     draw_data.consumed = 0;
865     hb_font_draw_glyph (font, 7, funcs, &draw_data);
866     char expected2[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427"
867                        "Q1384,332 1626,332Q1868,332 2089,427Q2309,521 2468,680"
868                        "Q2627,839 2722,1060Q2816,1280 2816,1522Q2816,1764 2722,1985"
869                        "Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712"
870                        "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985"
871                        "Q436,1764 436,1522ZM256,1528Q256,1714 306,1892Q355,2069 443,2220"
872                        "Q531,2370 658,2497Q784,2623 935,2711Q1085,2799 1263,2849"
873                        "Q1440,2898 1626,2898Q1812,2898 1990,2849Q2167,2799 2318,2711"
874                        "Q2468,2623 2595,2497Q2721,2370 2809,2220Q2897,2069 2947,1892"
875                        "Q2996,1714 2996,1528Q2996,1342 2947,1165Q2897,987 2809,837"
876                        "Q2721,686 2595,560Q2468,433 2318,345Q2167,257 1990,208"
877                        "Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
878                        "Q784,433 658,560Q531,686 443,837Q355,987 306,1165"
879                        "Q256,1342 256,1528Z";
880     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
881
882     hb_font_destroy (font);
883   }
884   {
885     /* https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L131-L138 */
886     hb_face_t *face = hb_test_open_font_file ("fonts/Stroking.otf");
887     hb_font_t *font = hb_font_create (face);
888     hb_face_destroy (face);
889
890     draw_data.consumed = 0;
891     hb_font_draw_glyph (font, 4, funcs, &draw_data);
892     /* Skip empty path in CFF */
893     char expected[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372C688,212 557,81 397,81C237,81 106,212 106,372Z"
894                       "M62,373C62,188 212,39 397,39C582,39 731,188 731,373C731,558 582,708 397,708C212,708 62,558 62,373Z";
895     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
896
897     draw_data.consumed = 0;
898     hb_font_draw_glyph (font, 5, funcs, &draw_data);
899     /* Fold consequent move-to commands */
900     char expected2[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372"
901                        "C688,212 557,81 397,81C237,81 106,212 106,372ZM62,373"
902                        "C62,188 212,39 397,39C582,39 731,188 731,373"
903                        "C731,558 582,708 397,708C212,708 62,558 62,373Z";
904     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
905
906     hb_font_destroy (font);
907   }
908 }
909
910 static void
911 test_hb_draw_drawing_funcs (void)
912 {
913   char str[2048];
914   draw_data_t draw_data = {
915     .str = str,
916     .size = sizeof (str)
917   };
918
919   {
920     hb_draw_state_t st = HB_DRAW_STATE_DEFAULT;
921     draw_data.consumed = 0;
922     hb_draw_move_to (funcs, &draw_data, &st, 90.f, 0.f);
923     hb_draw_line_to (funcs, &draw_data, &st, 258.f, 0.f);
924     hb_draw_cubic_to (funcs, &draw_data, &st, 456.f, 0.f, 564.f, 122.f, 564.f, 331.f);
925     hb_draw_cubic_to (funcs, &draw_data, &st, 564.f, 539.f, 456.f, 656.f, 254.f, 656.f);
926     hb_draw_line_to (funcs, &draw_data, &st, 90.f, 656.f);
927     hb_draw_line_to (funcs, &draw_data, &st, 90.f, 0.f);
928     hb_draw_close_path (funcs, &draw_data, &st);
929
930     char expected[] = "M90,0L258,0C456,0 564,122 564,331C564,539 456,656 254,656L90,656L90,0Z";
931     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
932   }
933
934   {
935     hb_draw_state_t st = HB_DRAW_STATE_DEFAULT;
936     draw_data.consumed = 0;
937     hb_draw_move_to (funcs, &draw_data, &st, 155.f, 624.f);
938     hb_draw_line_to (funcs, &draw_data, &st, 155.f, 84.f);
939     hb_draw_quadratic_to (funcs, &draw_data, &st, 150.f, 90.f, 146.f, 95.f);
940     hb_draw_quadratic_to (funcs, &draw_data, &st, 141.f, 99.f, 136.f, 105.f);
941     hb_draw_line_to (funcs, &draw_data, &st, 292.f, 105.f);
942     hb_draw_line_to (funcs, &draw_data, &st, 292.f, 0.f);
943     hb_draw_line_to (funcs, &draw_data, &st, 156.f, 0.f);
944     hb_draw_quadratic_to (funcs, &draw_data, &st, 128.f, 0.f, 104.f, 14.f);
945     hb_draw_quadratic_to (funcs, &draw_data, &st, 79.f, 27.f, 65.f, 51.f);
946     hb_draw_quadratic_to (funcs, &draw_data, &st, 50.f, 74.f, 50.f, 104.f);
947     hb_draw_line_to (funcs, &draw_data, &st, 50.f, 624.f);
948     hb_draw_line_to (funcs, &draw_data, &st, 155.f, 624.f);
949     hb_draw_close_path (funcs, &draw_data, &st);
950
951     char expected[] = "M155,624L155,84Q150,90 146,95Q141,99 136,105"
952                        "L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51"
953                        "Q50,74 50,104L50,624L155,624Z";
954     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
955   }
956 }
957
958 static void
959 test_hb_draw_synthetic_slant (void)
960 {
961   char str[2048];
962   draw_data_t draw_data = {
963     .str = str,
964     .size = sizeof (str)
965   };
966   {
967     hb_face_t *face = hb_test_open_font_file ("fonts/OpenSans-Regular.ttf");
968     hb_font_t *font = hb_font_create (face);
969     hb_face_destroy (face);
970     hb_font_set_synthetic_slant (font, 0.2f);
971
972     draw_data.consumed = 0;
973     hb_font_draw_glyph (font, 37, funcs, &draw_data);
974     char expected[] = "M493,1462L906,1462Q1197,1462 1310,1375Q1423,1288 1385,1100"
975                       "Q1359,970 1270,886Q1180,801 1036,776L1034,766Q1356,709 1297,416"
976                       "Q1258,220 1104,110Q949,0 711,0L201,0L493,1462ZM538,836L818,836"
977                       "Q998,836 1089,893Q1179,949 1206,1083Q1230,1206 1153,1261"
978                       "Q1076,1315 884,1315L634,1315L538,836ZM509,692L400,145L705,145"
979                       "Q882,145 985,214Q1088,282 1118,428Q1145,564 1066,628Q987,692 800,692L509,692Z";
980     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
981
982     hb_font_destroy (font);
983   }
984   {
985     hb_face_t *face = hb_test_open_font_file ("fonts/SourceSansPro-Regular.otf");
986     hb_font_t *font = hb_font_create (face);
987     hb_face_destroy (face);
988     hb_font_set_synthetic_slant (font, 0.2f);
989
990     draw_data.consumed = 0;
991     hb_font_draw_glyph (font, 5, funcs, &draw_data);
992     char expected[] = "M90,0L258,0C456,0 588,122 630,331C672,539 587,656 385,656L221,656L90,0Z"
993                       "M187,68L291,588L366,588C519,588 577,496 544,331C511,165 415,68 262,68L187,68Z";
994     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
995
996     hb_font_destroy (font);
997   }
998 }
999
1000 static void
1001 test_hb_draw_subfont_scale (void)
1002 {
1003   char str[2048];
1004   draw_data_t draw_data = {
1005     .str = str,
1006     .size = sizeof (str)
1007   };
1008   signed x, y;
1009   {
1010     hb_face_t *face = hb_test_open_font_file ("fonts/OpenSans-Regular.ttf");
1011     hb_font_t *font1 = hb_font_create (face);
1012     hb_font_t *font2 = hb_font_create_sub_font (font1);
1013
1014     hb_font_get_scale (font1, &x, &y);
1015     hb_font_set_scale (font2, x*2, y*2);
1016
1017     draw_data.consumed = 0;
1018     hb_font_draw_glyph (font1, 37, funcs, &draw_data);
1019     char expected1[] = "M201,1462L614,1462Q905,1462 1035,1375Q1165,1288 1165,1100"
1020                        "Q1165,970 1093,886Q1020,801 881,776L881,766Q1214,709 1214,416"
1021                        "Q1214,220 1082,110Q949,0 711,0L201,0L201,1462ZM371,836L651,836"
1022                        "Q831,836 910,893Q989,949 989,1083Q989,1206 901,1261"
1023                        "Q813,1315 621,1315L371,1315L371,836ZM371,692L371,145L676,145"
1024                        "Q853,145 943,214Q1032,282 1032,428Q1032,564 941,628Q849,692 662,692L371,692Z";
1025     g_assert_cmpmem (str, draw_data.consumed, expected1, sizeof (expected1) - 1);
1026
1027     draw_data.consumed = 0;
1028     hb_font_draw_glyph (font2, 37, funcs, &draw_data);
1029     char expected2[] = "M402,2924L1228,2924Q1810,2924 2070,2750Q2330,2576 2330,2200"
1030                        "Q2330,1940 2185,1771Q2040,1602 1762,1552L1762,1532Q2428,1418 2428,832"
1031                        "Q2428,440 2163,220Q1898,0 1422,0L402,0L402,2924ZM742,1672L1302,1672"
1032                        "Q1662,1672 1820,1785Q1978,1898 1978,2166Q1978,2412 1802,2521"
1033                        "Q1626,2630 1242,2630L742,2630L742,1672ZM742,1384L742,290L1352,290"
1034                        "Q1706,290 1885,427Q2064,564 2064,856Q2064,1128 1881,1256Q1698,1384 1324,1384L742,1384Z";
1035     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
1036
1037     hb_font_destroy (font1);
1038     hb_font_destroy (font2);
1039     hb_face_destroy (face);
1040   }
1041   {
1042     hb_face_t *face = hb_test_open_font_file ("fonts/SourceSansPro-Regular.otf");
1043     hb_font_t *font1 = hb_font_create (face);
1044     hb_font_t *font2 = hb_font_create_sub_font (font1);
1045
1046     hb_font_get_scale (font1, &x, &y);
1047     hb_font_set_scale (font2, x*2, y*2);
1048
1049     draw_data.consumed = 0;
1050     hb_font_draw_glyph (font1, 5, funcs, &draw_data);
1051     char expected1[] = "M90,0L258,0C456,0 564,122 564,331C564,539 456,656 254,656L90,656L90,0Z"
1052                        "M173,68L173,588L248,588C401,588 478,496 478,331C478,165 401,68 248,68L173,68Z";
1053     g_assert_cmpmem (str, draw_data.consumed, expected1, sizeof (expected1) - 1);
1054
1055     draw_data.consumed = 0;
1056     hb_font_draw_glyph (font2, 5, funcs, &draw_data);
1057     char expected2[] = "M180,0L516,0C912,0 1128,244 1128,662C1128,1078 912,1312 508,1312L180,1312L180,0Z"
1058                        "M346,136L346,1176L496,1176C802,1176 956,992 956,662C956,330 802,136 496,136L346,136Z";
1059     g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
1060
1061     hb_font_destroy (font1);
1062     hb_font_destroy (font2);
1063     hb_face_destroy (face);
1064   }
1065 }
1066
1067 static void
1068 test_hb_draw_immutable (void)
1069 {
1070   hb_draw_funcs_t *draw_funcs = hb_draw_funcs_create ();
1071   g_assert (!hb_draw_funcs_is_immutable (draw_funcs));
1072   hb_draw_funcs_make_immutable (draw_funcs);
1073   g_assert (hb_draw_funcs_is_immutable (draw_funcs));
1074   hb_draw_funcs_destroy (draw_funcs);
1075 }
1076
1077 #ifdef HAVE_FREETYPE
1078 static void test_hb_draw_ft (void)
1079 {
1080   char str[1024];
1081   draw_data_t draw_data = {
1082     .str = str,
1083     .size = sizeof (str)
1084   };
1085   {
1086     hb_face_t *face = hb_test_open_font_file ("fonts/glyphs.ttf");
1087     hb_font_t *font = hb_font_create (face);
1088     hb_ft_font_set_funcs (font);
1089     hb_face_destroy (face);
1090     {
1091       draw_data.consumed = 0;
1092       hb_font_draw_glyph (font, 0, funcs, &draw_data);
1093       char expected[] = "M50,0L50,750L450,750L450,0L50,0Z";
1094       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
1095     }
1096     {
1097       draw_data.consumed = 0;
1098       hb_font_draw_glyph (font, 5, funcs, &draw_data);
1099       char expected[] = "M15,0Q15,0 15,0Z";
1100       g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
1101     }
1102     hb_font_destroy (font);
1103   }
1104   {
1105     hb_face_t *face = hb_test_open_font_file ("fonts/cff1_flex.otf");
1106     hb_font_t *font = hb_font_create (face);
1107     hb_ft_font_set_funcs (font);
1108     hb_face_destroy (face);
1109
1110     draw_data.consumed = 0;
1111     hb_font_draw_glyph (font, 1, funcs, &draw_data);
1112     char expected[] = "M0,0C100,0 150,-20 250,-20C350,-20 400,0 500,0C500,100 520,150 520,250"
1113                       "C520,350 500,400 500,500C400,500 350,520 250,520C150,520 100,500 0,500"
1114                       "C0,400 -20,350 -20,250C-20,150 0,100 0,0ZM50,50C50,130 34,170 34,250"
1115                       "C34,330 50,370 50,450C130,450 170,466 250,466C330,466 370,450 450,450"
1116                       "C450,370 466,330 466,250C466,170 450,130 450,50C370,50 330,34 250,34"
1117                       "C170,34 130,50 50,50Z";
1118     g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
1119
1120     hb_font_destroy (font);
1121   }
1122 }
1123
1124 static void
1125 test_hb_draw_compare_ot_ft (void)
1126 {
1127   char str[1024];
1128   draw_data_t draw_data = {
1129     .str = str,
1130     .size = sizeof (str),
1131     .consumed = 0
1132   };
1133   char str2[1024];
1134   draw_data_t draw_data2 = {
1135     .str = str2,
1136     .size = sizeof (str2),
1137     .consumed = 0
1138   };
1139
1140   hb_face_t *face = hb_test_open_font_file ("fonts/cff1_flex.otf");
1141   hb_font_t *font = hb_font_create (face);
1142
1143   hb_font_set_scale (font, 100, 100);
1144
1145   hb_font_draw_glyph (font, 1, funcs, &draw_data);
1146   draw_data.str[draw_data.consumed] = '\0';
1147
1148   hb_ft_font_set_funcs (font);
1149
1150   hb_font_draw_glyph (font, 1, funcs, &draw_data2);
1151   draw_data2.str[draw_data2.consumed] = '\0';
1152
1153   g_assert_cmpstr (draw_data.str, ==, draw_data2.str);
1154
1155   hb_font_destroy (font);
1156   hb_face_destroy (face);
1157 }
1158 #endif
1159
1160 int
1161 main (int argc, char **argv)
1162 {
1163   funcs = hb_draw_funcs_create ();
1164   hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
1165   hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
1166   hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, NULL, NULL);
1167   hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
1168   hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
1169   hb_draw_funcs_make_immutable (funcs);
1170
1171   funcs2 = hb_draw_funcs_create ();
1172   hb_draw_funcs_set_move_to_func (funcs2, (hb_draw_move_to_func_t) move_to, NULL, NULL);
1173   hb_draw_funcs_set_line_to_func (funcs2, (hb_draw_line_to_func_t) line_to, NULL, NULL);
1174   hb_draw_funcs_set_cubic_to_func (funcs2, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
1175   hb_draw_funcs_set_close_path_func (funcs2, (hb_draw_close_path_func_t) close_path, NULL, NULL);
1176   hb_draw_funcs_make_immutable (funcs2);
1177
1178   hb_test_init (&argc, &argv);
1179   hb_test_add (test_itoa);
1180   hb_test_add (test_hb_draw_empty);
1181   hb_test_add (test_hb_draw_glyf);
1182   hb_test_add (test_hb_draw_cff1);
1183   hb_test_add (test_hb_draw_cff1_rline);
1184   hb_test_add (test_hb_draw_cff2);
1185   hb_test_add (test_hb_draw_ttf_parser_tests);
1186   hb_test_add (test_hb_draw_font_kit_glyphs_tests);
1187   hb_test_add (test_hb_draw_font_kit_variations_tests);
1188   hb_test_add (test_hb_draw_estedad_vf);
1189  if(0) hb_test_add (test_hb_draw_stroking);
1190   hb_test_add (test_hb_draw_drawing_funcs);
1191   hb_test_add (test_hb_draw_synthetic_slant);
1192   hb_test_add (test_hb_draw_subfont_scale);
1193   hb_test_add (test_hb_draw_immutable);
1194 #ifdef HAVE_FREETYPE
1195   hb_test_add (test_hb_draw_ft);
1196   hb_test_add (test_hb_draw_compare_ot_ft);
1197 #endif
1198   unsigned result = hb_test_run ();
1199
1200   hb_draw_funcs_destroy (funcs);
1201   hb_draw_funcs_destroy (funcs2);
1202   return result;
1203 }