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