1 /*
2 * Copyright © 2011 Google, Inc.
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 * Google Author(s): Behdad Esfahbod
25 */
26
27 #include "hb-test.h"
28
29 #include <hb-ot.h>
30
31 /* Unit tests for hb-ot-tag.h */
32
33
34 /* https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags */
35
36 static void
test_simple_tags(const char * s,hb_script_t script)37 test_simple_tags (const char *s, hb_script_t script)
38 {
39 hb_script_t tag;
40 unsigned int count = 2;
41 hb_tag_t t[2];
42
43 g_test_message ("Testing script %c%c%c%c: tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s);
44 tag = hb_tag_from_string (s, -1);
45
46 hb_ot_tags_from_script_and_language (script,
47 HB_LANGUAGE_INVALID,
48 &count, t, NULL, NULL);
49
50 if (count)
51 g_assert_cmphex (t[0], ==, tag);
52 else
53 g_assert_cmphex (HB_TAG_CHAR4 ("DFLT"), ==, tag);
54
55 g_assert_cmphex (hb_ot_tag_to_script (tag), ==, script);
56 }
57
58 static void
test_script_tags_from_language(const char * s,const char * lang_s,hb_script_t script)59 test_script_tags_from_language (const char *s, const char *lang_s, hb_script_t script)
60 {
61 hb_script_t tag;
62 unsigned int count = 1;
63 hb_tag_t t;
64
65 g_test_message ("Testing script %c%c%c%c: script tag %s, language tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s, lang_s);
66 tag = hb_tag_from_string (s, -1);
67
68 hb_ot_tags_from_script_and_language (script, hb_language_from_string (lang_s, -1), &count, &t, NULL, NULL);
69
70 if (count != 0)
71 {
72 g_assert_cmpuint (count, ==, 1);
73 g_assert_cmphex (t, ==, tag);
74 }
75 }
76
77 static void
test_indic_tags(const char * s1,const char * s2,const char * s3,hb_script_t script)78 test_indic_tags (const char *s1, const char *s2, const char *s3, hb_script_t script)
79 {
80 hb_script_t tag1, tag2, tag3;
81 hb_tag_t t[3];
82 unsigned int count = 3;
83
84 g_test_message ("Testing script %c%c%c%c: USE tag %s, new tag %s, old tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s1, s2, s3);
85 tag1 = hb_tag_from_string (s1, -1);
86 tag2 = hb_tag_from_string (s2, -1);
87 tag3 = hb_tag_from_string (s3, -1);
88
89 hb_ot_tags_from_script_and_language (script,
90 HB_LANGUAGE_INVALID,
91 &count, t, NULL, NULL);
92
93 g_assert_cmpuint (count, ==, 3);
94 g_assert_cmphex (t[0], ==, tag1);
95 g_assert_cmphex (t[1], ==, tag2);
96 g_assert_cmphex (t[2], ==, tag3);
97
98 g_assert_cmphex (hb_ot_tag_to_script (tag1), ==, script);
99 g_assert_cmphex (hb_ot_tag_to_script (tag2), ==, script);
100 g_assert_cmphex (hb_ot_tag_to_script (tag3), ==, script);
101 }
102
103 static void
test_ot_tag_script_degenerate(void)104 test_ot_tag_script_degenerate (void)
105 {
106 hb_tag_t t[2];
107 unsigned int count = 2;
108
109 g_assert_cmphex (HB_TAG_CHAR4 ("DFLT"), ==, HB_OT_TAG_DEFAULT_SCRIPT);
110
111 /* HIRAGANA and KATAKANA both map to 'kana' */
112 test_simple_tags ("kana", HB_SCRIPT_KATAKANA);
113
114 hb_ot_tags_from_script_and_language (HB_SCRIPT_HIRAGANA,
115 HB_LANGUAGE_INVALID,
116 &count, t, NULL, NULL);
117
118 g_assert_cmpuint (count, ==, 1);
119 g_assert_cmphex (t[0], ==, HB_TAG_CHAR4 ("kana"));
120
121 test_simple_tags ("DFLT", HB_SCRIPT_INVALID);
122
123 /* Spaces are replaced */
124 g_assert_cmphex (hb_ot_tag_to_script (HB_TAG_CHAR4 ("be ")), ==, hb_script_from_string ("Beee", -1));
125 }
126
127 static void
test_ot_tag_script_simple(void)128 test_ot_tag_script_simple (void)
129 {
130 /* Arbitrary non-existent script */
131 test_simple_tags ("wwyz", hb_script_from_string ("wWyZ", -1));
132
133 /* These we don't really care about */
134 test_simple_tags ("zyyy", HB_SCRIPT_COMMON);
135 test_simple_tags ("zinh", HB_SCRIPT_INHERITED);
136 test_simple_tags ("zzzz", HB_SCRIPT_UNKNOWN);
137
138 test_simple_tags ("arab", HB_SCRIPT_ARABIC);
139 test_simple_tags ("copt", HB_SCRIPT_COPTIC);
140 test_simple_tags ("kana", HB_SCRIPT_KATAKANA);
141 test_simple_tags ("latn", HB_SCRIPT_LATIN);
142
143 /* These are trickier since their OT script tags have space. */
144 test_simple_tags ("lao ", HB_SCRIPT_LAO);
145 test_simple_tags ("yi ", HB_SCRIPT_YI);
146 /* Unicode-5.0 additions */
147 test_simple_tags ("nko ", HB_SCRIPT_NKO);
148 /* Unicode-5.1 additions */
149 test_simple_tags ("vai ", HB_SCRIPT_VAI);
150
151 /* https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags */
152
153 /* Unicode-5.2 additions */
154 test_simple_tags ("mtei", HB_SCRIPT_MEETEI_MAYEK);
155 /* Unicode-6.0 additions */
156 test_simple_tags ("mand", HB_SCRIPT_MANDAIC);
157 }
158
159 static void
test_ot_tag_script_from_language(void)160 test_ot_tag_script_from_language (void)
161 {
162 test_script_tags_from_language (NULL, NULL, HB_SCRIPT_INVALID);
163 test_script_tags_from_language (NULL, "en", HB_SCRIPT_INVALID);
164 test_script_tags_from_language ("copt", "en", HB_SCRIPT_COPTIC);
165 test_script_tags_from_language (NULL, "x-hbsc", HB_SCRIPT_INVALID);
166 test_script_tags_from_language ("copt", "x-hbsc", HB_SCRIPT_COPTIC);
167 test_script_tags_from_language ("abc ", "x-hbscabc", HB_SCRIPT_INVALID);
168 test_script_tags_from_language ("deva", "x-hbscdeva", HB_SCRIPT_INVALID);
169 test_script_tags_from_language ("dev2", "x-hbscdev2", HB_SCRIPT_INVALID);
170 test_script_tags_from_language ("dev3", "x-hbscdev3", HB_SCRIPT_INVALID);
171 test_script_tags_from_language ("copt", "x-hbotpap0-hbsccopt", HB_SCRIPT_INVALID);
172 test_script_tags_from_language (NULL, "en-x-hbsc", HB_SCRIPT_INVALID);
173 test_script_tags_from_language ("copt", "en-x-hbsc", HB_SCRIPT_COPTIC);
174 test_script_tags_from_language ("abc ", "en-x-hbscabc", HB_SCRIPT_INVALID);
175 test_script_tags_from_language ("deva", "en-x-hbscdeva", HB_SCRIPT_INVALID);
176 test_script_tags_from_language ("dev2", "en-x-hbscdev2", HB_SCRIPT_INVALID);
177 test_script_tags_from_language ("dev3", "en-x-hbscdev3", HB_SCRIPT_INVALID);
178 test_script_tags_from_language ("copt", "en-x-hbotpap0-hbsccopt", HB_SCRIPT_INVALID);
179 }
180
181 static void
test_ot_tag_script_indic(void)182 test_ot_tag_script_indic (void)
183 {
184 test_indic_tags ("bng3", "bng2", "beng", HB_SCRIPT_BENGALI);
185 test_indic_tags ("dev3", "dev2", "deva", HB_SCRIPT_DEVANAGARI);
186 test_indic_tags ("gjr3", "gjr2", "gujr", HB_SCRIPT_GUJARATI);
187 test_indic_tags ("gur3", "gur2", "guru", HB_SCRIPT_GURMUKHI);
188 test_indic_tags ("knd3", "knd2", "knda", HB_SCRIPT_KANNADA);
189 test_indic_tags ("mlm3", "mlm2", "mlym", HB_SCRIPT_MALAYALAM);
190 test_indic_tags ("ory3", "ory2", "orya", HB_SCRIPT_ORIYA);
191 test_indic_tags ("tml3", "tml2", "taml", HB_SCRIPT_TAMIL);
192 test_indic_tags ("tel3", "tel2", "telu", HB_SCRIPT_TELUGU);
193 test_indic_tags ("mym3", "mym2", "mymr", HB_SCRIPT_MYANMAR);
194 }
195
196
197
198 /* https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags */
199
200 static void
test_language_two_way(const char * tag_s,const char * lang_s)201 test_language_two_way (const char *tag_s, const char *lang_s)
202 {
203 hb_language_t lang = hb_language_from_string (lang_s, -1);
204 hb_tag_t tag = hb_tag_from_string (tag_s, -1);
205 hb_tag_t tag2;
206 unsigned int count = 1;
207
208 g_test_message ("Testing language %s <-> tag %s", lang_s, tag_s);
209
210 hb_ot_tags_from_script_and_language (HB_SCRIPT_INVALID,
211 lang,
212 NULL, NULL, &count, &tag2);
213
214 if (count)
215 g_assert_cmphex (tag, ==, tag2);
216 else
217 g_assert_cmphex (tag, ==, HB_TAG_CHAR4 ("dflt"));
218 g_assert (lang == hb_ot_tag_to_language (tag));
219 }
220
221 static void
test_tag_from_language(const char * tag_s,const char * lang_s)222 test_tag_from_language (const char *tag_s, const char *lang_s)
223 {
224 hb_language_t lang = hb_language_from_string (lang_s, -1);
225 hb_tag_t tag = hb_tag_from_string (tag_s, -1);
226 hb_tag_t tag2;
227 unsigned int count = 1;
228
229 g_test_message ("Testing language %s -> tag %s", lang_s, tag_s);
230
231 hb_ot_tags_from_script_and_language (HB_SCRIPT_INVALID,
232 lang,
233 NULL, NULL, &count, &tag2);
234
235 if (count)
236 g_assert_cmphex (tag, ==, tag2);
237 else
238 g_assert_cmphex (tag, ==, HB_TAG_CHAR4 ("dflt"));
239 }
240
241 static void
test_tag_to_language(const char * tag_s,const char * lang_s)242 test_tag_to_language (const char *tag_s, const char *lang_s)
243 {
244 hb_language_t lang = hb_language_from_string (lang_s, -1);
245 hb_tag_t tag = hb_tag_from_string (tag_s, -1);
246
247 g_test_message ("Testing tag %s -> language %s", tag_s, lang_s);
248
249 g_assert (lang == hb_ot_tag_to_language (tag));
250 }
251
252 static void
test_tags_to_script_and_language(const char * script_tag_s,const char * lang_tag_s,const char * script_s,const char * lang_s)253 test_tags_to_script_and_language (const char *script_tag_s,
254 const char *lang_tag_s,
255 const char *script_s,
256 const char *lang_s)
257 {
258 hb_script_t actual_script[1];
259 hb_language_t actual_lang[1];
260 hb_tag_t script_tag = hb_tag_from_string (script_tag_s, -1);
261 hb_tag_t lang_tag = hb_tag_from_string (lang_tag_s, -1);
262 hb_ot_tags_to_script_and_language (script_tag, lang_tag, actual_script, actual_lang);
263 g_assert_cmphex (*actual_script, ==, hb_tag_from_string (script_s, -1));
264 g_assert_cmpstr (hb_language_to_string (*actual_lang), ==, lang_s);
265 }
266
267 static void
test_ot_tags_to_script_and_language(void)268 test_ot_tags_to_script_and_language (void)
269 {
270 test_tags_to_script_and_language ("DFLT", "ENG", "", "en-x-hbscdflt");
271 test_tags_to_script_and_language ("latn", "ENG", "Latn", "en");
272 test_tags_to_script_and_language ("deva", "MAR", "Deva", "mr-x-hbscdeva");
273 test_tags_to_script_and_language ("dev2", "MAR", "Deva", "mr-x-hbscdev2");
274 test_tags_to_script_and_language ("dev3", "MAR", "Deva", "mr");
275 test_tags_to_script_and_language ("qaa", "QTZ0", "Qaaa", "x-hbotqtz0-hbscqaa");
276 }
277
278 static void
test_ot_tag_language(void)279 test_ot_tag_language (void)
280 {
281 g_assert_cmphex (HB_TAG_CHAR4 ("dflt"), ==, HB_OT_TAG_DEFAULT_LANGUAGE);
282 test_language_two_way ("dflt", NULL);
283
284 test_language_two_way ("ARA", "ar");
285
286 test_language_two_way ("AZE", "az");
287 test_tag_from_language ("AZE", "az-ir");
288 test_tag_from_language ("AZE", "az-az");
289
290 test_language_two_way ("ENG", "en");
291 test_tag_from_language ("ENG", "en_US");
292
293 test_language_two_way ("CJA", "cja"); /* Western Cham */
294 test_language_two_way ("CJM", "cjm"); /* Eastern Cham */
295 test_language_two_way ("EVN", "eve");
296
297 test_language_two_way ("HAL", "cfm"); /* BCP47 and current ISO639-3 code for Halam/Falam Chin */
298 test_tag_from_language ("HAL", "flm"); /* Retired ISO639-3 code for Halam/Falam Chin */
299
300 test_tag_from_language ("QIN", "bgr"); /* Bawm Chin */
301 test_tag_from_language ("QIN", "cbl"); /* Bualkhaw Chin */
302 test_tag_from_language ("QIN", "cka"); /* Khumi Awa Chin */
303 test_tag_from_language ("QIN", "cmr"); /* Mro-Khimi Chin */
304 test_tag_from_language ("QIN", "cnb"); /* Chinbon Chin */
305 test_tag_from_language ("QIN", "cnh"); /* Hakha Chin */
306 test_tag_from_language ("QIN", "cnk"); /* Khumi Chin */
307 test_tag_from_language ("QIN", "cnw"); /* Ngawn Chin */
308 test_tag_from_language ("QIN", "csh"); /* Asho Chin */
309 test_tag_from_language ("QIN", "csy"); /* Siyin Chin */
310 test_tag_from_language ("QIN", "ctd"); /* Tedim Chin */
311 test_tag_from_language ("QIN", "czt"); /* Zotung Chin */
312 test_tag_from_language ("QIN", "dao"); /* Daai Chin */
313 test_tag_from_language ("QIN", "hlt"); /* Matu Chin */
314 test_tag_from_language ("QIN", "mrh"); /* Mara Chin */
315 test_tag_from_language ("QIN", "pck"); /* Paite Chin */
316 test_tag_from_language ("QIN", "sez"); /* Senthang Chin */
317 test_tag_from_language ("QIN", "tcp"); /* Tawr Chin */
318 test_tag_from_language ("QIN", "tcz"); /* Thado Chin */
319 test_tag_from_language ("QIN", "yos"); /* Yos, deprecated by IANA in favor of Zou [zom] */
320 test_tag_from_language ("QIN", "zom"); /* Zou */
321 test_tag_to_language ("QIN", "bgr"); /* no single BCP47 tag for Chin; picking Bawm Chin */
322
323 test_language_two_way ("FAR", "fa");
324 test_tag_from_language ("FAR", "fa_IR");
325
326 test_language_two_way ("SWA", "aii"); /* Swadaya Aramaic */
327
328 test_language_two_way ("SYR", "syr"); /* Syriac [macrolanguage] */
329 test_tag_from_language ("SYR", "amw"); /* Western Neo-Aramaic */
330 test_tag_from_language ("SYR", "cld"); /* Chaldean Neo-Aramaic */
331 test_tag_from_language ("SYR", "syc"); /* Classical Syriac */
332
333 test_language_two_way ("TUA", "tru"); /* Turoyo Aramaic */
334
335 test_tag_from_language ("ZHS", "zh"); /* Chinese */
336 test_tag_from_language ("ZHS", "zh-cn"); /* Chinese (China) */
337 test_tag_from_language ("ZHS", "zh-sg"); /* Chinese (Singapore) */
338 test_tag_from_language ("ZHH", "zh-mo"); /* Chinese (Macao) */
339 test_tag_from_language ("ZHH", "zh-hant-mo"); /* Chinese (Macao) */
340 test_language_two_way ("ZHH", "zh-HK"); /* Chinese (Hong Kong) */
341 test_tag_from_language ("ZHH", "zH-HanT-hK"); /* Chinese (Hong Kong) */
342 test_tag_from_language ("ZHT", "zh-tw"); /* Chinese (Taiwan) */
343 test_language_two_way ("ZHS", "zh-Hans"); /* Chinese (Simplified) */
344 test_language_two_way ("ZHT", "zh-Hant"); /* Chinese (Traditional) */
345 test_tag_from_language ("ZHS", "zh-xx"); /* Chinese (Other) */
346
347 test_tag_from_language ("ZHS", "zh-Hans-TW");
348
349 test_tag_from_language ("ZHH", "yue");
350 test_tag_from_language ("ZHH", "yue-Hant");
351 test_tag_from_language ("ZHS", "yue-Hans");
352
353 test_tag_from_language ("ZHS", "zh"); /* Chinese */
354 test_tag_from_language ("ZHS", "zh-xx");
355
356 test_language_two_way ("ABC", "x-hbotabc");
357 test_tag_from_language ("ABC", "asdf-asdf-wer-x-hbotabc-zxc");
358 test_tag_from_language ("ABC", "asdf-asdf-wer-x-hbotabc");
359 test_tag_from_language ("ABCD", "asdf-asdf-wer-x-hbotabcd");
360
361 test_tag_from_language ("dflt", "asdf-asdf-wer-x-hbot-zxc");
362
363 test_tag_from_language ("dflt", "xy");
364 test_tag_from_language ("XYZ", "xyz"); /* Unknown ISO 639-3 */
365 test_tag_from_language ("XYZ", "xyz-qw"); /* Unknown ISO 639-3 */
366
367 /*
368 * Invalid input. The precise answer does not matter, as long as it
369 * does not crash or get into an infinite loop.
370 */
371 test_tag_from_language ("IPPH", "-fonipa");
372
373 /*
374 * Tags that contain "-fonipa" as a substring but which do not contain
375 * the subtag "fonipa".
376 */
377 test_tag_from_language ("ENG", "en-fonipax");
378 test_tag_from_language ("ENG", "en-x-fonipa");
379 test_tag_from_language ("ENG", "en-a-fonipa");
380 test_tag_from_language ("ENG", "en-a-qwe-b-fonipa");
381
382 /* International Phonetic Alphabet */
383 test_tag_from_language ("IPPH", "en-fonipa");
384 test_tag_from_language ("IPPH", "en-fonipax-fonipa");
385 test_tag_from_language ("IPPH", "rm-CH-fonipa-sursilv-x-foobar");
386 test_language_two_way ("IPPH", "und-fonipa");
387 test_tag_from_language ("IPPH", "zh-fonipa");
388
389 /* North American Phonetic Alphabet (Americanist Phonetic Notation) */
390 test_tag_from_language ("APPH", "en-fonnapa");
391 test_tag_from_language ("APPH", "chr-fonnapa");
392 test_language_two_way ("APPH", "und-fonnapa");
393
394 /* Khutsuri Georgian */
395 test_tag_from_language ("KGE", "ka-Geok");
396 test_language_two_way ("KGE", "und-Geok");
397
398 /* Irish Traditional */
399 test_language_two_way ("IRT", "ga-Latg");
400
401 /* Moldavian */
402 test_language_two_way ("MOL", "ro-MD");
403
404 /* Polytonic Greek */
405 test_language_two_way ("PGR", "el-polyton");
406 test_tag_from_language ("PGR", "el-CY-polyton");
407
408 /* Estrangela Syriac */
409 test_tag_from_language ("SYRE", "aii-Syre");
410 test_tag_from_language ("SYRE", "de-Syre");
411 test_tag_from_language ("SYRE", "syr-Syre");
412 test_language_two_way ("SYRE", "und-Syre");
413
414 /* Western Syriac */
415 test_tag_from_language ("SYRJ", "aii-Syrj");
416 test_tag_from_language ("SYRJ", "de-Syrj");
417 test_tag_from_language ("SYRJ", "syr-Syrj");
418 test_language_two_way ("SYRJ", "und-Syrj");
419
420 /* Eastern Syriac */
421 test_tag_from_language ("SYRN", "aii-Syrn");
422 test_tag_from_language ("SYRN", "de-Syrn");
423 test_tag_from_language ("SYRN", "syr-Syrn");
424 test_language_two_way ("SYRN", "und-Syrn");
425
426 /* Test that x-hbot overrides the base language */
427 test_tag_from_language ("ABC", "fa-x-hbotabc-zxc");
428 test_tag_from_language ("ABC", "fa-ir-x-hbotabc-zxc");
429 test_tag_from_language ("ABC", "zh-x-hbotabc-zxc");
430 test_tag_from_language ("ABC", "zh-cn-x-hbotabc-zxc");
431 test_tag_from_language ("ABC", "zh-xy-x-hbotabc-zxc");
432 test_tag_from_language ("ABC", "xyz-xy-x-hbotabc-zxc");
433
434 /* Unnormalized BCP 47 tags */
435 test_tag_from_language ("ARA", "ar-aao");
436 test_tag_from_language ("JBO", "art-lojban");
437 test_tag_from_language ("KOK", "kok-gom");
438 test_tag_from_language ("LTZ", "i-lux");
439 test_tag_from_language ("MNG", "drh");
440 test_tag_from_language ("MOR", "ar-ary");
441 test_tag_from_language ("MOR", "ar-ary-DZ");
442 test_tag_from_language ("NOR", "no-bok");
443 test_tag_from_language ("NYN", "no-nyn");
444 test_tag_from_language ("ZHS", "i-hak");
445 test_tag_from_language ("ZHS", "zh-guoyu");
446 test_tag_from_language ("ZHS", "zh-min");
447 test_tag_from_language ("ZHS", "zh-min-nan");
448 test_tag_from_language ("ZHS", "zh-xiang");
449
450 /* A UN M.49 region code, not an extended language subtag */
451 test_tag_from_language ("ARA", "ar-001");
452
453 /* An invalid tag */
454 test_tag_from_language ("TRK", "tr@foo=bar");
455 }
456
457 static void
test_tags(hb_script_t script,const char * lang_s,unsigned int script_count,unsigned int language_count,unsigned int expected_script_count,unsigned int expected_language_count,...)458 test_tags (hb_script_t script,
459 const char *lang_s,
460 unsigned int script_count,
461 unsigned int language_count,
462 unsigned int expected_script_count,
463 unsigned int expected_language_count,
464 ...)
465 {
466 va_list expected_tags;
467 unsigned int i;
468 hb_tag_t *script_tags = malloc (script_count * sizeof (hb_tag_t));
469 hb_tag_t *language_tags = malloc (language_count * sizeof (hb_tag_t));
470 hb_language_t lang;
471 g_assert (script_tags);
472 g_assert (language_tags);
473 lang = hb_language_from_string (lang_s, -1);
474 va_start (expected_tags, expected_language_count);
475
476 hb_ot_tags_from_script_and_language (script, lang, &script_count, script_tags, &language_count, language_tags);
477
478 g_assert_cmpuint (script_count, ==, expected_script_count);
479 g_assert_cmpuint (language_count, ==, expected_language_count);
480
481 for (i = 0; i < script_count + language_count; i++)
482 {
483 hb_tag_t expected_tag = hb_tag_from_string (va_arg (expected_tags, const char *), -1);
484 hb_tag_t actual_tag = i < script_count ? script_tags[i] : language_tags[i - script_count];
485 g_assert_cmphex (actual_tag, ==, expected_tag);
486 }
487
488 free (script_tags);
489 free (language_tags);
490 va_end (expected_tags);
491 }
492
493 static void
test_ot_tag_full(void)494 test_ot_tag_full (void)
495 {
496 test_tags (HB_SCRIPT_INVALID, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "ENG");
497 test_tags (HB_SCRIPT_INVALID, "en-x-hbscdflt", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "DFLT", "ENG");
498 test_tags (HB_SCRIPT_LATIN, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "latn", "ENG");
499 test_tags (HB_SCRIPT_LATIN, "en", 0, 0, 0, 0);
500 test_tags (HB_SCRIPT_INVALID, "und-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
501 test_tags (HB_SCRIPT_INVALID, "en-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
502 test_tags (HB_SCRIPT_INVALID, "x-hbot1234-hbsc5678", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
503 test_tags (HB_SCRIPT_INVALID, "x-hbsc5678-hbot1234", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
504 test_tags (HB_SCRIPT_MALAYALAM, "ml", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 3, 2, "mlm3", "mlm2", "mlym", "MAL", "MLR");
505 test_tags (HB_SCRIPT_MALAYALAM, "ml", 1, 1, 1, 1, "mlm3", "MAL");
506 test_tags (HB_SCRIPT_INVALID, "xyz", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "XYZ");
507 test_tags (HB_SCRIPT_INVALID, "xy", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 0);
508 }
509
510 int
main(int argc,char ** argv)511 main (int argc, char **argv)
512 {
513 hb_test_init (&argc, &argv);
514
515 hb_test_add (test_ot_tag_script_degenerate);
516 hb_test_add (test_ot_tag_script_simple);
517 hb_test_add (test_ot_tag_script_from_language);
518 hb_test_add (test_ot_tag_script_indic);
519
520 hb_test_add (test_ot_tags_to_script_and_language);
521
522 hb_test_add (test_ot_tag_language);
523
524 hb_test_add (test_ot_tag_full);
525
526 return hb_test_run();
527 }
528