diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc | 157 |
1 files changed, 118 insertions, 39 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc index 1837063af8..0c63756b14 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc @@ -41,6 +41,7 @@ hb_ot_old_tag_from_script (hb_script_t script) switch ((hb_tag_t) script) { case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT; + case HB_SCRIPT_MATH: return HB_OT_TAG_MATH_SCRIPT; /* KATAKANA and HIRAGANA both map to 'kana' */ case HB_SCRIPT_HIRAGANA: return HB_TAG('k','a','n','a'); @@ -63,6 +64,8 @@ hb_ot_old_tag_to_script (hb_tag_t tag) { if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT)) return HB_SCRIPT_INVALID; + if (unlikely (tag == HB_OT_TAG_MATH_SCRIPT)) + return HB_SCRIPT_MATH; /* This side of the conversion is fully algorithmic. */ @@ -116,6 +119,17 @@ hb_ot_new_tag_to_script (hb_tag_t tag) } #ifndef HB_DISABLE_DEPRECATED +/** + * hb_ot_tags_from_script: + * @script: an #hb_script_t to convert. + * @script_tag_1: (out): output #hb_tag_t. + * @script_tag_2: (out): output #hb_tag_t. + * + * Converts an #hb_script_t to script tags. + * + * Since: 0.6.0 + * Deprecated: 2.0.0: use hb_ot_tags_from_script_and_language() instead + **/ void hb_ot_tags_from_script (hb_script_t script, hb_tag_t *script_tag_1, @@ -186,48 +200,48 @@ hb_ot_tag_to_script (hb_tag_t tag) /* hb_language_t */ -static bool +static inline bool subtag_matches (const char *lang_str, const char *limit, - const char *subtag) + const char *subtag, + unsigned subtag_len) { + if (likely ((unsigned) (limit - lang_str) < subtag_len)) + return false; + do { const char *s = strstr (lang_str, subtag); if (!s || s >= limit) return false; - if (!ISALNUM (s[strlen (subtag)])) + if (!ISALNUM (s[subtag_len])) return true; - lang_str = s + strlen (subtag); + lang_str = s + subtag_len; } while (true); } -static hb_bool_t -lang_matches (const char *lang_str, const char *spec) +static bool +lang_matches (const char *lang_str, + const char *limit, + const char *spec, + unsigned spec_len) { - unsigned int len = strlen (spec); + /* Same as hb_language_matches(); duplicated. */ + + if (likely ((unsigned) (limit - lang_str) < spec_len)) + return false; - return strncmp (lang_str, spec, len) == 0 && - (lang_str[len] == '\0' || lang_str[len] == '-'); + return strncmp (lang_str, spec, spec_len) == 0 && + (lang_str[spec_len] == '\0' || lang_str[spec_len] == '-'); } struct LangTag { - char language[4]; + hb_tag_t language; hb_tag_t tag; - int cmp (const char *a) const + int cmp (hb_tag_t a) const { - const char *b = this->language; - unsigned int da, db; - const char *p; - - p = strchr (a, '-'); - da = p ? (unsigned int) (p - a) : strlen (a); - - p = strchr (b, '-'); - db = p ? (unsigned int) (p - b) : strlen (b); - - return strncmp (a, b, hb_max (da, db)); + return a < this->language ? -1 : a > this->language ? +1 : 0; } int cmp (const LangTag *that) const { return cmp (that->language); } @@ -246,6 +260,15 @@ struct LangTag /*{"zh?", {HB_TAG('Z','H','P',' ')}},*/ /* Chinese Phonetic */ #ifndef HB_DISABLE_DEPRECATED +/** + * hb_ot_tag_from_language: + * @language: an #hb_language_t to convert. + * + * Converts an #hb_language_t to an #hb_tag_t. + * + * Since: 0.6.0 + * Deprecated: 2.0.0: use hb_ot_tags_from_script_and_language() instead + **/ hb_tag_t hb_ot_tag_from_language (hb_language_t language) { @@ -262,16 +285,19 @@ hb_ot_tags_from_language (const char *lang_str, unsigned int *count, hb_tag_t *tags) { - const char *s; - unsigned int tag_idx; +#ifndef HB_NO_LANGUAGE_LONG /* Check for matches of multiple subtags. */ if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags)) return; +#endif /* Find a language matching in the first component. */ - s = strchr (lang_str, '-'); +#ifndef HB_NO_LANGUAGE_LONG + const char *s; s = strchr (lang_str, '-'); +#endif { +#ifndef HB_NO_LANGUAGE_LONG if (s && limit - lang_str >= 6) { const char *extlang_end = strchr (s + 1, '-'); @@ -280,17 +306,42 @@ hb_ot_tags_from_language (const char *lang_str, ISALPHA (s[1])) lang_str = s + 1; } - if (hb_sorted_array (ot_languages).bfind (lang_str, &tag_idx)) +#endif + const LangTag *ot_languages = nullptr; + unsigned ot_languages_len = 0; + const char *dash = strchr (lang_str, '-'); + unsigned first_len = dash ? dash - lang_str : limit - lang_str; + if (first_len == 2) + { + ot_languages = ot_languages2; + ot_languages_len = ARRAY_LENGTH (ot_languages2); + } +#ifndef HB_NO_LANGUAGE_LONG + else if (first_len == 3) { + ot_languages = ot_languages3; + ot_languages_len = ARRAY_LENGTH (ot_languages3); + } +#endif + + hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len); + + static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */ + unsigned tag_idx = last_tag_idx; + + if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) || + hb_sorted_array (ot_languages, ot_languages_len).bfind (lang_tag, &tag_idx)) + { + last_tag_idx = tag_idx; unsigned int i; while (tag_idx != 0 && - 0 == strcmp (ot_languages[tag_idx].language, ot_languages[tag_idx - 1].language)) + ot_languages[tag_idx].language == ot_languages[tag_idx - 1].language) tag_idx--; for (i = 0; i < *count && - tag_idx + i < ARRAY_LENGTH (ot_languages) && + tag_idx + i < ot_languages_len && ot_languages[tag_idx + i].tag != HB_TAG_NONE && - 0 == strcmp (ot_languages[tag_idx + i].language, ot_languages[tag_idx].language); + ot_languages[tag_idx + i].language == ot_languages[tag_idx].language; i++) tags[i] = ot_languages[tag_idx + i].tag; *count = i; @@ -298,6 +349,7 @@ hb_ot_tags_from_language (const char *lang_str, } } +#ifndef HB_NO_LANGUAGE_LONG if (!s) s = lang_str + strlen (lang_str); if (s - lang_str == 3) { @@ -306,6 +358,7 @@ hb_ot_tags_from_language (const char *lang_str, *count = 1; return; } +#endif *count = 0; } @@ -359,7 +412,7 @@ parse_private_use_subtag (const char *private_use_subtag, /** * hb_ot_tags_from_script_and_language: * @script: an #hb_script_t to convert. - * @language: an #hb_language_t to convert. + * @language: (nullable): an #hb_language_t to convert. * @script_count: (inout) (optional): maximum number of script tags to retrieve (IN) * and actual number of script tags retrieved (OUT) * @script_tags: (out) (optional): array of size at least @script_count to store the @@ -450,15 +503,29 @@ hb_ot_tag_to_language (hb_tag_t tag) if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) return nullptr; +#ifndef HB_NO_LANGUAGE_LONG { hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag); if (disambiguated_tag != HB_LANGUAGE_INVALID) return disambiguated_tag; } +#endif - for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) - if (ot_languages[i].tag == tag) - return hb_language_from_string (ot_languages[i].language, -1); + char buf[4]; + for (i = 0; i < ARRAY_LENGTH (ot_languages2); i++) + if (ot_languages2[i].tag == tag) + { + hb_tag_to_string (ot_languages2[i].language, buf); + return hb_language_from_string (buf, 2); + } +#ifndef HB_NO_LANGUAGE_LONG + for (i = 0; i < ARRAY_LENGTH (ot_languages3); i++) + if (ot_languages3[i].tag == tag) + { + hb_tag_to_string (ot_languages3[i].language, buf); + return hb_language_from_string (buf, 3); + } +#endif /* Return a custom language in the form of "x-hbot-AABBCCDD". * If it's three letters long, also guess it's ISO 639-3 and lower-case and @@ -480,7 +547,7 @@ hb_ot_tag_to_language (hb_tag_t tag) buf[3] = '-'; str += 4; } - snprintf (str, 16, "x-hbot-%08x", tag); + snprintf (str, 16, "x-hbot-%08" PRIx32, tag); return hb_language_from_string (&*buf, -1); } } @@ -530,7 +597,7 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag, else { int shift; - memcpy (buf, lang_str, len); + hb_memcpy (buf, lang_str, len); if (lang_str[0] != 'x' || lang_str[1] != '-') { buf[len++] = '-'; buf[len++] = 'x'; @@ -554,16 +621,28 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag, static inline void test_langs_sorted () { - for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++) + for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages2); i++) + { + int c = ot_languages2[i].cmp (&ot_languages2[i - 1]); + if (c > 0) + { + fprintf (stderr, "ot_languages2 not sorted at index %u: %08x %d %08x\n", + i, ot_languages2[i-1].language, c, ot_languages2[i].language); + abort(); + } + } +#ifndef HB_NO_LANGUAGE_LONG + for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages3); i++) { - int c = ot_languages[i].cmp (&ot_languages[i - 1]); + int c = ot_languages3[i].cmp (&ot_languages3[i - 1]); if (c > 0) { - fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n", - i, ot_languages[i-1].language, c, ot_languages[i].language); + fprintf (stderr, "ot_languages3 not sorted at index %u: %08x %d %08x\n", + i, ot_languages3[i-1].language, c, ot_languages3[i].language); abort(); } } +#endif } int |