Add hb_ot_tags_to_script_and_language

This commit is contained in:
David Corbett 2018-07-23 21:19:23 -04:00 committed by Behdad Esfahbod
parent 3f8877473f
commit 7f1fbfe2e3
5 changed files with 112 additions and 19 deletions

View File

@ -560,7 +560,8 @@ HB_OT_TAG_DEFAULT_LANGUAGE
HB_OT_TAG_DEFAULT_SCRIPT
hb_ot_tag_to_language
hb_ot_tag_to_script
hb_ot_tags
hb_ot_tags_from_script_and_language
hb_ot_tags_to_script_and_language
</SECTION>
<SECTION>

View File

@ -59,7 +59,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
hb_ot_tags (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
for (unsigned int table_index = 0; table_index < 2; table_index++) {
hb_tag_t table_tag = table_tags[table_index];

View File

@ -121,7 +121,7 @@ hb_ot_tags_from_script (hb_script_t script,
{
unsigned int count = 2;
hb_tag_t tags[2];
hb_ot_tags (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
*script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
*script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
}
@ -231,7 +231,7 @@ hb_ot_tag_from_language (hb_language_t language)
{
unsigned int count = 1;
hb_tag_t tags[1];
hb_ot_tags (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
}
@ -307,6 +307,8 @@ parse_private_use_subtag (const char *private_use_subtag,
for (; i < 4; i++)
tag[i] = ' ';
tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
tags[0] ^= ~0xDFDFDFDF;
*count = 1;
return false;
}
@ -316,7 +318,7 @@ parse_private_use_subtag (const char *private_use_subtag,
}
/**
* hb_ot_tags:
* hb_ot_tags_from_script_and_language:
* @script: an #hb_script_t to convert.
* @language: an #hb_language_t to convert.
* @script_count: (allow-none): maximum number of script tags to retrieve (IN)
@ -332,12 +334,12 @@ parse_private_use_subtag (const char *private_use_subtag,
*
**/
void
hb_ot_tags (hb_script_t script,
hb_language_t language,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */,
unsigned int *language_count /* IN/OUT */,
hb_tag_t *language_tags /* OUT */)
hb_ot_tags_from_script_and_language (hb_script_t script,
hb_language_t language,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */,
unsigned int *language_count /* IN/OUT */,
hb_tag_t *language_tags /* OUT */)
{
bool needs_script = true;
@ -428,6 +430,61 @@ hb_ot_tag_to_language (hb_tag_t tag)
}
}
/**
* hb_ot_tags_to_script_and_language:
* @script_tag: a script tag
* @language_tag: a language tag
* @script (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
* @language (allow-none): the #hb_language_t corresponding to @script_tag and
* @language_tag (OUT).
*
* Converts a script tag and a language tag to an #hb_script_t and an
* #hb_language_t.
*
**/
void
hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
hb_tag_t language_tag,
hb_script_t *script /* OUT */,
hb_language_t *language /* OUT */)
{
hb_script_t script_out = hb_ot_tag_to_script (script_tag);
if (script)
*script = script_out;
if (language) {
unsigned int script_count = 1;
hb_tag_t primary_script_tag[1];
hb_ot_tags_from_script_and_language (script_out, HB_LANGUAGE_INVALID, &script_count, primary_script_tag, nullptr, nullptr);
*language = hb_ot_tag_to_language (language_tag);
if (script_count == 0 || primary_script_tag[0] != script_tag) {
unsigned char *buf;
const char *lang_str = hb_language_to_string (*language);
size_t len = strlen (lang_str);
buf = (unsigned char *) malloc (len + 11);
if (unlikely (!buf)) {
*language = nullptr;
} else {
memcpy (buf, lang_str, len);
if (lang_str[0] != 'x' || lang_str[1] != '-') {
buf[len++] = '-';
buf[len++] = 'x';
}
buf[len++] = '-';
buf[len++] = 'h';
buf[len++] = 'b';
buf[len++] = 's';
buf[len++] = 'c';
buf[len++] = script_tag >> 24;
buf[len++] = (script_tag >> 16) & 0xFF;
buf[len++] = (script_tag >> 8) & 0xFF;
buf[len++] = script_tag & 0xFF;
*language = hb_language_from_string ((char *) buf, len);
free (buf);
}
}
}
}
#ifdef MAIN
static inline void
test_langs_sorted (void)

View File

@ -43,12 +43,12 @@ HB_BEGIN_DECLS
#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u
HB_EXTERN void
hb_ot_tags (hb_script_t script,
hb_language_t language,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */,
unsigned int *language_count /* IN/OUT */,
hb_tag_t *language_tags /* OUT */);
hb_ot_tags_from_script_and_language (hb_script_t script,
hb_language_t language,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */,
unsigned int *language_count /* IN/OUT */,
hb_tag_t *language_tags /* OUT */);
HB_EXTERN hb_script_t
hb_ot_tag_to_script (hb_tag_t tag);
@ -56,6 +56,12 @@ hb_ot_tag_to_script (hb_tag_t tag);
HB_EXTERN hb_language_t
hb_ot_tag_to_language (hb_tag_t tag);
HB_EXTERN void
hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
hb_tag_t language_tag,
hb_script_t *script /* OUT */,
hb_language_t *language /* OUT */);
HB_END_DECLS

View File

@ -60,7 +60,7 @@ test_script_tags_from_language (const char *s, const char *lang_s, hb_script_t s
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);
tag = hb_tag_from_string (s, -1);
hb_ot_tags (script, hb_language_from_string (lang_s, -1), &count, &t, NULL, NULL);
hb_ot_tags_from_script_and_language (script, hb_language_from_string (lang_s, -1), &count, &t, NULL, NULL);
if (count != 0)
{
@ -212,6 +212,31 @@ test_tag_to_language (const char *tag_s, const char *lang_s)
g_assert (lang == hb_ot_tag_to_language (tag));
}
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)
{
hb_script_t actual_script[1];
hb_language_t actual_lang[1];
hb_tag_t script_tag = hb_tag_from_string (script_tag_s, -1);
hb_tag_t lang_tag = hb_tag_from_string (lang_tag_s, -1);
hb_ot_tags_to_script_and_language (script_tag, lang_tag, actual_script, actual_lang);
g_assert_cmphex (*actual_script, ==, hb_tag_from_string (script_s, -1));
g_assert_cmpstr (hb_language_to_string (*actual_lang), ==, lang_s);
}
static void
test_ot_tags_to_script_and_language (void)
{
test_tags_to_script_and_language ("DFLT", "ENG", "", "en-x-hbscdflt");
test_tags_to_script_and_language ("latn", "ENG", "Latn", "en");
test_tags_to_script_and_language ("deva", "MAR", "Deva", "mr-x-hbscdeva");
test_tags_to_script_and_language ("dev2", "MAR", "Deva", "mr");
test_tags_to_script_and_language ("qaa", "QTZ0", "Qaaa", "x-hbotqtz0-hbscqaa");
}
static void
test_ot_tag_language (void)
{
@ -406,7 +431,7 @@ test_tags (hb_script_t script,
hb_language_t lang = hb_language_from_string (lang_s, -1);
va_start (expected_tags, expected_language_count);
hb_ot_tags (script, lang, &script_count, script_tags, &language_count, language_tags);
hb_ot_tags_from_script_and_language (script, lang, &script_count, script_tags, &language_count, language_tags);
g_assert_cmpuint (script_count, ==, expected_script_count);
g_assert_cmpuint (language_count, ==, expected_language_count);
@ -427,11 +452,13 @@ static void
test_ot_tag_full (void)
{
test_tags (HB_SCRIPT_INVALID, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "ENG");
test_tags (HB_SCRIPT_INVALID, "en-x-hbscdflt", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "DFLT", "ENG");
test_tags (HB_SCRIPT_LATIN, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "latn", "ENG");
test_tags (HB_SCRIPT_LATIN, "en", 0, 0, 0, 0);
test_tags (HB_SCRIPT_INVALID, "und-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
test_tags (HB_SCRIPT_INVALID, "en-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
test_tags (HB_SCRIPT_INVALID, "x-hbot1234-hbsc5678", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
test_tags (HB_SCRIPT_INVALID, "x-hbsc5678-hbot1234", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
test_tags (HB_SCRIPT_MALAYALAM, "ml", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 2, 2, "mlm2", "mlym", "MAL", "MLR");
test_tags (HB_SCRIPT_MALAYALAM, "ml", 1, 1, 1, 1, "mlm2", "MAL");
test_tags (HB_SCRIPT_INVALID, "xyz", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "XYZ");
@ -448,6 +475,8 @@ main (int argc, char **argv)
hb_test_add (test_ot_tag_script_from_language);
hb_test_add (test_ot_tag_script_indic);
hb_test_add (test_ot_tags_to_script_and_language);
hb_test_add (test_ot_tag_language);
hb_test_add (test_ot_tag_full);