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 */
_hb_reverse(char * buf,unsigned int len)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 }
_hb_itoa(int32_t num,char * buf)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
test_itoa(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
move_to(hb_position_t to_x,hb_position_t to_y,user_data_t * user_data)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
line_to(hb_position_t to_x,hb_position_t to_y,user_data_t * user_data)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
quadratic_to(hb_position_t control_x,hb_position_t control_y,hb_position_t to_x,hb_position_t to_y,user_data_t * user_data)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
cubic_to(hb_position_t control1_x,hb_position_t control1_y,hb_position_t control2_x,hb_position_t control2_y,hb_position_t to_x,hb_position_t to_y,user_data_t * user_data)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
close_path(user_data_t * user_data)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
test_hb_draw_empty(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
test_hb_draw_glyf(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 226,371Q209,330 209,261"
222 "Q209,204 225,166Q242,127 272,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,98Q25,156 25,241Q25,323 62,382"
225 "Q99,440 163,470Q226,501 303,501Q357,501 399,480Q440,460 464,426"
226 "Q488,392 492,352Q475,297 420,297Q390,297 366,319Q342,342 339,401"
227 "L333,469L411,427Q387,438 367,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
test_hb_draw_cff1(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
test_hb_draw_cff1_rline(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
test_hb_draw_cff2(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
test_hb_draw_ttf_parser_tests(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
test_hb_draw_font_kit_glyphs_tests(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,960Q376,1116 596,1116"
437 "Q802,1116 922,981Q1042,845 1042,623L1042,518L287,518Q292,325 385,225"
438 "Q477,125 645,125Q822,125 995,199L995,51Q907,13 829,-3Q750,-20 639,-20Z"
439 "M594,977Q462,977 384,891Q305,805 291,653L864,653Q864,810 794,894"
440 "Q724,977 594,977ZM471,1266Q519,1328 575,1416Q630,1504 662,1569"
441 "L864,1569L864,1548Q820,1483 733,1388Q646,1293 582,1241L471,1241L471,1266Z";
442 g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
443
444 hb_font_destroy (font);
445 }
446 {
447 hb_face_t *face = hb_test_open_font_file ("fonts/Mada-VF.ttf");
448 hb_font_t *font = hb_font_create (face);
449 hb_face_destroy (face);
450
451 hb_buffer_t *buffer = hb_buffer_create ();
452 hb_codepoint_t codepoint = 1610; /* ي */
453 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
454 hb_buffer_set_direction (buffer, HB_DIRECTION_RTL);
455 hb_shape (font, buffer, NULL, 0);
456 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
457 hb_buffer_destroy (buffer);
458
459 /* should resolve composite glyphs recursively */
460 user_data.consumed = 0;
461 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
462 char expected[] = "M581,274L443,274Q409,274 384,259Q359,243 348,219Q336,194 340,166"
463 "Q343,138 365,111L468,-13Q470,-10 473,-6Q475,-3 477,0L253,0Q225,0 203,8"
464 "Q180,15 168,32Q155,48 155,73L155,269L50,269L50,73Q50,24 69,-10"
465 "Q88,-44 118,-64Q147,-85 181,-94Q214,-104 243,-104L473,-104"
466 "Q501,-104 525,-91Q549,-78 564,-56Q578,-34 578,-8Q578,18 557,43"
467 "L442,182Q439,179 437,176Q435,173 432,170L581,170L581,274ZM184,-194"
468 "Q184,-216 199,-231Q214,-246 236,-246Q258,-246 273,-231Q288,-216 288,-194"
469 "Q288,-172 273,-157Q258,-142 236,-142Q214,-142 199,-157Q184,-172 184,-194Z"
470 "M360,-194Q360,-216 375,-231Q390,-246 412,-246Q434,-246 449,-231"
471 "Q464,-216 464,-194Q464,-172 449,-157Q434,-142 412,-142"
472 "Q390,-142 375,-157Q360,-172 360,-194Z";
473 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
474
475 /* should transform points of a composite glyph */
476 user_data.consumed = 0;
477 g_assert (hb_font_draw_glyph (font, 2, funcs, &user_data)); /* 2 == arAlef.fina */
478 char expected2[] = "M155,624L155,84Q150,90 146,95Q141,99 136,105"
479 "L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51"
480 "Q50,74 50,104L50,624L155,624ZM282,105L312,105"
481 "L312,0L282,0L282,105Z";
482 g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
483
484 hb_font_destroy (font);
485 }
486 /* CFF glyphs, should get a path for the glyph */
487 {
488 hb_face_t *face = hb_test_open_font_file ("fonts/SourceSansPro-Regular.otf");
489 hb_font_t *font = hb_font_create (face);
490 hb_face_destroy (face);
491
492 user_data.consumed = 0;
493 g_assert (hb_font_draw_glyph (font, 5, funcs, &user_data));
494 char expected[] = "M90,0L258,0C456,0 564,122 564,331C564,539 456,656 254,656L90,656L90,0Z"
495 "M173,68L173,588L248,588C401,588 478,496 478,331C478,165 401,68 248,68L173,68Z";
496 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
497
498 hb_font_destroy (font);
499 }
500 /* CFF glyphs (CID font) */
501 {
502 /* replaced with a subset as the original one was 15MB */
503 hb_face_t *face = hb_test_open_font_file ("fonts/NotoSansCJKkr-Regular-subset-colon.ttf");
504 hb_font_t *font = hb_font_create (face);
505 hb_face_destroy (face);
506
507 user_data.consumed = 0;
508 g_assert (hb_font_draw_glyph (font, 1, funcs, &user_data));
509 char expected[] = "M139,390C175,390 205,419 205,459C205,501 175,530 139,530C103,530 73,501 73,459"
510 "C73,419 103,390 139,390ZM139,-13C175,-13 205,15 205,56C205,97 175,127 139,127"
511 "C103,127 73,97 73,56C73,15 103,-13 139,-13Z";
512 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
513
514 hb_font_destroy (font);
515 }
516 /* Skip SBIX glyphs (empty path), COLR glyphs (empty path), WOFF ttf glyphs, WOFF2 ttf glyph */
517 }
518
519 static void
test_hb_draw_font_kit_variations_tests(void)520 test_hb_draw_font_kit_variations_tests (void)
521 {
522 /* https://github.com/foliojs/fontkit/blob/b310db5/test/variations.js */
523 char str[2048];
524 user_data_t user_data = {
525 .str = str,
526 .size = sizeof (str)
527 };
528 /* Skia */
529 {
530 /* Skipping Skia tests for now even the fact we can actually do platform specific tests using our CIs */
531 }
532 /* truetype variations */
533 /* should support sharing all points */
534 {
535 hb_face_t *face = hb_test_open_font_file ("fonts/TestGVAROne.ttf");
536 hb_font_t *font = hb_font_create (face);
537 hb_face_destroy (face);
538
539 hb_variation_t var;
540 var.tag = HB_TAG ('w','g','h','t');
541 var.value = 300;
542 hb_font_set_variations (font, &var, 1);
543
544 hb_buffer_t *buffer = hb_buffer_create ();
545 hb_codepoint_t codepoint = 24396; /* 彌 */
546 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
547 hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
548 hb_shape (font, buffer, NULL, 0);
549 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
550 hb_buffer_destroy (buffer);
551
552 user_data.consumed = 0;
553 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
554 char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102"
555 "Q796,-102 755,-98L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504"
556 "L414,504L414,-102L371,-102ZM203,-94Q138,-94 86,-90L74,-52"
557 "Q137,-59 188,-59Q211,-59 222,-46Q233,-34 236,12Q238,58 240,135"
558 "Q242,211 242,262L74,262L94,527L242,527L242,719L63,719L63,754"
559 "L285,754L285,492L133,492L117,297L285,297Q285,241 284,185"
560 "Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94Z"
561 "M461,12L434,43Q473,73 503,115Q478,150 441,188L469,211Q501,179 525,147"
562 "Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43L566,20"
563 "Q544,64 528,86Q500,44 461,12ZM465,258L438,285Q474,316 501,351"
564 "Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453L598,434"
565 "Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322Q491,280 465,258Z"
566 "M707,12L680,43Q717,68 753,115Q731,147 691,188L719,211Q739,190 754,172"
567 "Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117Q828,82 852,43"
568 "L820,20Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730L664,-94"
569 "L621,-94ZM348,570L324,605Q425,629 527,688L555,656Q491,621 439,601"
570 "Q386,581 348,570ZM715,258L688,285Q727,318 753,351Q733,378 695,418L723,441"
571 "Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281"
572 "L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719"
573 "L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
574 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
575
576 hb_font_destroy (font);
577 }
578 /* should support sharing enumerated points */
579 {
580 hb_face_t *face = hb_test_open_font_file ("fonts/TestGVARTwo.ttf");
581 hb_font_t *font = hb_font_create (face);
582 hb_face_destroy (face);
583
584 hb_variation_t var;
585 var.tag = HB_TAG ('w','g','h','t');
586 var.value = 300;
587 hb_font_set_variations (font, &var, 1);
588
589 hb_buffer_t *buffer = hb_buffer_create ();
590 hb_codepoint_t codepoint = 24396; /* 彌 */
591 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
592 hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
593 hb_shape (font, buffer, NULL, 0);
594 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
595 hb_buffer_destroy (buffer);
596
597 user_data.consumed = 0;
598 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
599 char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
600 "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
601 "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46"
602 "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527"
603 "L242,719L63,719L63,754L285,754L285,492L133,492L117,297L285,297"
604 "Q285,241 284,185Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94Z"
605 "M461,12L434,43Q473,73 503,115Q478,150 441,188L469,211Q501,179 525,147"
606 "Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43L566,20"
607 "Q544,64 528,86Q500,44 461,12ZM465,258L438,285Q474,316 501,351"
608 "Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453L598,434"
609 "Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322Q491,280 465,258Z"
610 "M707,12L680,43Q717,68 753,115Q731,147 691,188L719,211Q739,190 754,172"
611 "Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117Q828,82 852,43L820,20"
612 "Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730L664,-94L621,-94ZM348,570"
613 "L324,605Q425,629 527,688L555,656Q491,621 439,601Q386,581 348,570ZM715,258L688,285"
614 "Q727,318 753,351Q733,378 695,418L723,441Q754,410 775,381Q794,407 813,453"
615 "L848,434Q826,387 801,352Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258Z"
616 "M348,719L348,754L941,754L941,719L348,719ZM936,570Q870,602 817,622"
617 "Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
618 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
619
620 hb_font_destroy (font);
621 }
622 /* should support sharing no points */
623 {
624 hb_face_t *face = hb_test_open_font_file ("fonts/TestGVARThree.ttf");
625 hb_font_t *font = hb_font_create (face);
626 hb_face_destroy (face);
627
628 hb_variation_t var;
629 var.tag = HB_TAG ('w','g','h','t');
630 var.value = 300;
631 hb_font_set_variations (font, &var, 1);
632
633 hb_buffer_t *buffer = hb_buffer_create ();
634 hb_codepoint_t codepoint = 24396; /* 彌 */
635 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
636 hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
637 hb_shape (font, buffer, NULL, 0);
638 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
639 hb_buffer_destroy (buffer);
640
641 user_data.consumed = 0;
642 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
643 char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
644 "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
645 "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46"
646 "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527L242,719"
647 "L63,719L63,754L285,754L285,492L133,492L117,297L285,297Q285,241 284,185"
648 "Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94ZM461,12"
649 "L434,43Q473,73 503,115Q478,150 441,188L469,211Q501,179 525,147"
650 "Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43L566,20Q544,64 528,86"
651 "Q500,44 461,12ZM465,258L438,285Q474,316 501,351Q474,388 445,418L473,441"
652 "Q500,414 523,381Q546,413 563,453L598,434Q571,382 549,352Q576,320 598,285"
653 "L563,262Q546,294 525,322Q491,280 465,258ZM707,12L680,43Q717,68 753,115"
654 "Q731,147 691,188L719,211Q739,190 754,172Q769,154 774,147Q793,185 809,230"
655 "L844,211Q822,155 801,117Q828,82 852,43L820,20Q798,58 778,87Q747,43 707,12Z"
656 "M621,-94L621,730L664,730L664,-94L621,-94ZM348,570L324,605Q425,629 527,688"
657 "L555,656Q491,621 439,601Q386,581 348,570ZM715,258L688,285Q727,318 753,351"
658 "Q733,378 695,418L723,441Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352"
659 "Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754"
660 "L941,754L941,719L348,719ZM936,570Q870,602 817,622"
661 "Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
662 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
663
664 hb_font_destroy (font);
665 }
666
667 /* CFF2 variations */
668 {
669 hb_face_t *face = hb_test_open_font_file ("fonts/AdobeVFPrototype-Subset.otf");
670 hb_font_t *font = hb_font_create (face);
671 hb_face_destroy (face);
672
673 hb_variation_t var;
674 var.tag = HB_TAG ('w','g','h','t');
675 /* applies variations to CFF2 glyphs */
676 {
677 var.value = 100;
678 hb_font_set_variations (font, &var, 1);
679
680 hb_buffer_t *buffer = hb_buffer_create ();
681 hb_codepoint_t codepoint = '$';
682 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
683 hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
684 hb_shape (font, buffer, NULL, 0);
685 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
686 hb_buffer_destroy (buffer);
687
688 user_data.consumed = 0;
689 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
690 char expected[] = "M246,15C188,15 147,27 101,68L142,23L117,117C111,143 96,149 81,149"
691 "C65,149 56,141 52,126C71,40 137,-13 244,-13C348,-13 436,46 436,156"
692 "C436,229 405,295 271,349L247,359C160,393 119,439 119,506"
693 "C119,592 178,637 262,637C311,637 346,626 390,585L348,629L373,535"
694 "C380,510 394,503 408,503C424,503 434,510 437,526C418,614 348,665 259,665"
695 "C161,665 78,606 78,500C78,414 128,361 224,321L261,305C367,259 395,217 395,152"
696 "C395,65 334,15 246,15ZM267,331L267,759L240,759L240,331L267,331ZM240,-115"
697 "L267,-115L267,331L240,331L240,-115Z";
698 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
699 }
700 {
701 var.value = 500;
702 hb_font_set_variations (font, &var, 1);
703
704 hb_buffer_t *buffer = hb_buffer_create ();
705 hb_codepoint_t codepoint = '$';
706 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
707 hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
708 hb_shape (font, buffer, NULL, 0);
709 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
710 hb_buffer_destroy (buffer);
711
712 user_data.consumed = 0;
713 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
714 char expected[] = "M251,36C206,36 165,42 118,61L176,21L161,99C151,152 129,167 101,167"
715 "C78,167 61,155 51,131C54,43 133,-14 247,-14C388,-14 474,64 474,171"
716 "C474,258 430,321 294,370L257,383C188,406 150,438 150,499"
717 "C150,571 204,606 276,606C308,606 342,601 386,582L327,621"
718 "L343,546C355,490 382,476 408,476C428,476 448,487 455,512"
719 "C450,597 370,656 264,656C140,656 57,576 57,474C57,373 119,318 227,279"
720 "L263,266C345,236 379,208 379,145C379,76 329,36 251,36ZM289,320"
721 "L289,746L242,746L242,320L289,320ZM240,-115L286,-115L286,320L240,320L240,-115Z";
722 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
723 }
724 /* substitutes GSUB features depending on variations */
725 {
726 var.value = 900;
727 hb_font_set_variations (font, &var, 1);
728
729 hb_buffer_t *buffer = hb_buffer_create ();
730 hb_codepoint_t codepoint = '$';
731 hb_buffer_add_codepoints (buffer, &codepoint, 1, 0, -1);
732 hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
733 hb_shape (font, buffer, NULL, 0);
734 codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
735 hb_buffer_destroy (buffer);
736
737 user_data.consumed = 0;
738 g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
739 char expected[] = "M258,38C197,38 167,48 118,71L192,19L183,103C177,155 155,174 115,174"
740 "C89,174 64,161 51,125C52,36 124,-16 258,-16C417,-16 513,67 513,175"
741 "C513,278 457,328 322,388L289,403C232,429 203,452 203,500C203,562 244,589 301,589"
742 "C342,589 370,585 420,562L341,607L352,539C363,468 398,454 434,454C459,454 486,468 492,506"
743 "C491,590 408,643 290,643C141,643 57,563 57,460C57,357 122,307 233,256L265,241"
744 "C334,209 363,186 363,130C363,77 320,38 258,38ZM318,616L318,734L252,734L252,616"
745 "L318,616ZM253,-115L319,-115L319,14L253,14L253,-115Z";
746 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
747 }
748
749 hb_font_destroy (font);
750 }
751 }
752
753 static void
test_hb_draw_estedad_vf(void)754 test_hb_draw_estedad_vf (void)
755 {
756 /* https://github.com/harfbuzz/harfbuzz/issues/2215 */
757 char str[2048];
758 user_data_t user_data = {
759 .str = str,
760 .size = sizeof (str)
761 };
762 {
763 /* See https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L115-L124 */
764 hb_face_t *face = hb_test_open_font_file ("fonts/Estedad-VF.ttf");
765 hb_font_t *font = hb_font_create (face);
766 hb_face_destroy (face);
767
768 hb_variation_t var;
769 hb_variation_from_string ("wght=100", -1, &var);
770 hb_font_set_variations (font, &var, 1);
771
772 user_data.consumed = 0;
773 g_assert (hb_font_draw_glyph (font, 156, funcs, &user_data));
774 /* Skip empty path where all the points of a path are equal */
775 char expected[] = "M150,1158L182,1158Q256,1158 317,1170Q377,1182 421,1213L421,430L521,430"
776 "L521,1490L421,1490L421,1320Q393,1279 344,1262Q294,1244 182,1244L150,1244"
777 "L150,1158ZM1815,-122L1669,-122L1669,642L1552,642L1055,-117L1055,-206"
778 "L1569,-206L1569,-458L1669,-458L1669,-206L1815,-206L1815,-122ZM1569,-122"
779 "L1166,-122L1569,494L1569,-122ZM609,-79L1639,1288L1555,1334L525,-33L609,-79Z";
780 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
781
782 user_data.consumed = 0;
783 g_assert (hb_font_draw_glyph (font, 180, funcs, &user_data));
784 /* Skip empty path where all the points of a path are equal */
785 char expected2[] = "M120,693Q120,545 177,414Q233,282 333,182Q433,81 567,24"
786 "Q701,-33 856,-33Q1010,-33 1144,24Q1277,81 1377,182Q1477,282 1534,414"
787 "Q1590,545 1590,693Q1590,842 1534,973Q1477,1104 1377,1205"
788 "Q1277,1305 1144,1362Q1010,1419 856,1419Q701,1419 567,1362"
789 "Q433,1305 333,1205Q233,1104 177,973Q120,842 120,693Z"
790 "M220,693Q220,828 270,945Q320,1061 409,1148Q497,1235 612,1284"
791 "Q726,1333 855,1333Q984,1333 1099,1284Q1213,1235 1302,1148"
792 "Q1390,1061 1440,945Q1490,828 1490,693Q1490,558 1440,442"
793 "Q1390,325 1302,237Q1213,149 1099,100Q984,51 855,51"
794 "Q726,51 611,100Q497,149 408,237Q320,325 270,442"
795 "Q220,558 220,693ZM690,643L690,997L886,997Q970,997 1029,949"
796 "Q1087,901 1087,819Q1087,737 1028,690Q969,643 886,643L690,643Z"
797 "M1165,334L973,568Q1065,591 1126,658Q1187,725 1187,819"
798 "Q1187,896 1147,956Q1106,1015 1037,1049Q969,1083 886,1083"
799 "L590,1083L590,310L690,310L690,557L860,557L1083,286L1165,334Z";
800 g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
801
802 user_data.consumed = 0;
803 g_assert (hb_font_draw_glyph (font, 262, funcs, &user_data));
804 /* Skip empty path where all the points of a path are equal */
805 char expected3[] = "M422,598Q495,598 545,548Q595,498 595,426Q595,353 545,303Q494,252 422,252"
806 "Q350,252 300,303Q250,353 250,426Q250,499 300,549Q349,598 422,598ZM422,698"
807 "Q347,698 285,662Q223,625 187,564Q150,502 150,426Q150,351 187,289"
808 "Q223,226 285,189Q346,152 422,152Q498,152 560,189Q622,226 658,288"
809 "Q695,351 695,426Q695,502 658,563Q621,625 559,661Q498,698 422,698Z";
810 g_assert_cmpmem (str, user_data.consumed, expected3, sizeof (expected3) - 1);
811
812 hb_font_destroy (font);
813 }
814 }
815
816 static void
test_hb_draw_stroking(void)817 test_hb_draw_stroking (void)
818 {
819 /* https://skia-review.googlesource.com/c/skia/+/266945
820 https://savannah.nongnu.org/bugs/index.php?57701 */
821 char str[2048];
822 user_data_t user_data = {
823 .str = str,
824 .size = sizeof (str)
825 };
826 {
827 /* See https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L115-L124 */
828 hb_face_t *face = hb_test_open_font_file ("fonts/Stroking.ttf");
829 hb_font_t *font = hb_font_create (face);
830 hb_face_destroy (face);
831
832 user_data.consumed = 0;
833 g_assert (hb_font_draw_glyph (font, 6, funcs, &user_data));
834 /* Skip empty path where all the points of a path are equal */
835 char expected[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427Q1384,332 1626,332"
836 "Q1868,332 2089,427Q2309,521 2468,680Q2627,839 2722,1060Q2816,1280 2816,1522"
837 "Q2816,1764 2722,1985Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712"
838 "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985Q436,1764 436,1522ZM256,1528"
839 "Q256,1714 306,1892Q355,2069 443,2220Q531,2370 658,2497Q784,2623 935,2711"
840 "Q1085,2799 1263,2849Q1440,2898 1626,2898Q1812,2898 1990,2849Q2167,2799 2318,2711"
841 "Q2468,2623 2595,2497Q2721,2370 2809,2220Q2897,2069 2947,1892Q2996,1714 2996,1528"
842 "Q2996,1342 2947,1165Q2897,987 2809,837Q2721,686 2595,560Q2468,433 2318,345"
843 "Q2167,257 1990,208Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
844 "Q784,433 658,560Q531,686 443,837Q355,987 306,1165Q256,1342 256,1528Z";
845 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
846
847 user_data.consumed = 0;
848 g_assert (hb_font_draw_glyph (font, 7, funcs, &user_data));
849 char expected2[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427"
850 "Q1384,332 1626,332Q1868,332 2089,427Q2309,521 2468,680"
851 "Q2627,839 2722,1060Q2816,1280 2816,1522Q2816,1764 2722,1985"
852 "Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712"
853 "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985"
854 "Q436,1764 436,1522ZM256,1528Q256,1714 306,1892Q355,2069 443,2220"
855 "Q531,2370 658,2497Q784,2623 935,2711Q1085,2799 1263,2849"
856 "Q1440,2898 1626,2898Q1812,2898 1990,2849Q2167,2799 2318,2711"
857 "Q2468,2623 2595,2497Q2721,2370 2809,2220Q2897,2069 2947,1892"
858 "Q2996,1714 2996,1528Q2996,1342 2947,1165Q2897,987 2809,837"
859 "Q2721,686 2595,560Q2468,433 2318,345Q2167,257 1990,208"
860 "Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
861 "Q784,433 658,560Q531,686 443,837Q355,987 306,1165"
862 "Q256,1342 256,1528Z";
863 g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
864
865 hb_font_destroy (font);
866 }
867 {
868 /* https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L131-L138 */
869 hb_face_t *face = hb_test_open_font_file ("fonts/Stroking.otf");
870 hb_font_t *font = hb_font_create (face);
871 hb_face_destroy (face);
872
873 user_data.consumed = 0;
874 g_assert (hb_font_draw_glyph (font, 4, funcs, &user_data));
875 /* Skip empty path in CFF */
876 char expected[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372C688,212 557,81 397,81C237,81 106,212 106,372Z"
877 "M62,373C62,188 212,39 397,39C582,39 731,188 731,373C731,558 582,708 397,708C212,708 62,558 62,373Z";
878 g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
879
880 user_data.consumed = 0;
881 g_assert (hb_font_draw_glyph (font, 5, funcs, &user_data));
882 /* Fold consequent move-to commands */
883 char expected2[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372"
884 "C688,212 557,81 397,81C237,81 106,212 106,372ZM62,373"
885 "C62,188 212,39 397,39C582,39 731,188 731,373"
886 "C731,558 582,708 397,708C212,708 62,558 62,373Z";
887 g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
888
889 hb_font_destroy (font);
890 }
891 }
892
893 static void
test_hb_draw_immutable(void)894 test_hb_draw_immutable (void)
895 {
896 hb_draw_funcs_t *draw_funcs = hb_draw_funcs_create ();
897 g_assert (!hb_draw_funcs_is_immutable (draw_funcs));
898 hb_draw_funcs_make_immutable (draw_funcs);
899 g_assert (hb_draw_funcs_is_immutable (draw_funcs));
900 hb_draw_funcs_destroy (draw_funcs);
901 }
902
903 int
main(int argc,char ** argv)904 main (int argc, char **argv)
905 {
906 funcs = hb_draw_funcs_create ();
907 hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to);
908 hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to);
909 hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to);
910 hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to);
911 hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path);
912 hb_draw_funcs_make_immutable (funcs);
913
914 funcs2 = hb_draw_funcs_create ();
915 hb_draw_funcs_set_move_to_func (funcs2, (hb_draw_move_to_func_t) move_to);
916 hb_draw_funcs_set_line_to_func (funcs2, (hb_draw_line_to_func_t) line_to);
917 hb_draw_funcs_set_cubic_to_func (funcs2, (hb_draw_cubic_to_func_t) cubic_to);
918 hb_draw_funcs_set_close_path_func (funcs2, (hb_draw_close_path_func_t) close_path);
919 hb_draw_funcs_make_immutable (funcs2);
920
921 hb_test_init (&argc, &argv);
922 hb_test_add (test_itoa);
923 hb_test_add (test_hb_draw_empty);
924 hb_test_add (test_hb_draw_glyf);
925 hb_test_add (test_hb_draw_cff1);
926 hb_test_add (test_hb_draw_cff1_rline);
927 hb_test_add (test_hb_draw_cff2);
928 hb_test_add (test_hb_draw_ttf_parser_tests);
929 hb_test_add (test_hb_draw_font_kit_glyphs_tests);
930 hb_test_add (test_hb_draw_font_kit_variations_tests);
931 hb_test_add (test_hb_draw_estedad_vf);
932 hb_test_add (test_hb_draw_stroking);
933 hb_test_add (test_hb_draw_immutable);
934 unsigned result = hb_test_run ();
935
936 hb_draw_funcs_destroy (funcs);
937 hb_draw_funcs_destroy (funcs2);
938 return result;
939 }
940 #else
main(int argc HB_UNUSED,char ** argv HB_UNUSED)941 int main (int argc HB_UNUSED, char **argv HB_UNUSED)
942 {
943 return 0;
944 }
945 #endif
946