diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 9c343e798..89cbbcd75 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -135,6 +135,7 @@ hb_script_get_horizontal_direction hb_language_from_string hb_language_to_string hb_language_get_default +hb_language_matches hb_feature_from_string hb_feature_to_string hb_variation_from_string diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index ad4a831ec..aa4ad4cf3 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -983,7 +983,7 @@ struct Chain #ifndef HB_NO_AAT else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting && /* TODO: Rudimentary language matching. */ - map->face->table.ltag->get_language (setting - 1) == map->props.language) + hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language)) { flags &= feature.disableFlags; flags |= feature.enableFlags; diff --git a/src/hb-common.cc b/src/hb-common.cc index 80f36feea..e6ef98b94 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -441,6 +441,38 @@ hb_language_get_default () return language; } +/** + * hb_language_matches: + * @language: The #hb_language_t to work on + * @specific: Another #hb_language_t + * + * Check whether a second language tag is the same or a more + * specific version of the provided language tag. For example, + * "fa_IR.utf8" is a more specific tag for "fa" or for "fa_IR". + * + * Return value: `true` if languages match, `false` otherwise. + * + * Since: REPLACEME + **/ +hb_bool_t +hb_language_matches (hb_language_t language, + hb_language_t specific) +{ + if (language == specific) return true; + if (!language || !specific) return false; + + const char *l = language->s; + const char *s = specific->s; + unsigned ll = strlen (l); + unsigned sl = strlen (s); + + if (ll > sl) + return false; + + return strncmp (l, s, ll) == 0 && + (s[ll] == '\0' || s[ll] == '-'); +} + /* hb_script_t */ diff --git a/src/hb-common.h b/src/hb-common.h index 7b897a6c5..7c7ad87c7 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -326,6 +326,9 @@ hb_language_to_string (hb_language_t language); HB_EXTERN hb_language_t hb_language_get_default (void); +HB_EXTERN hb_bool_t +hb_language_matches (hb_language_t language, + hb_language_t specific); /** * hb_script_t: diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index 01107aad6..1f2131ffc 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -175,15 +175,11 @@ _hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact) signed c = strcmp (astr, bstr); - if (!exact && c) - { - unsigned la = strlen (astr); - unsigned lb = strlen (bstr); - // 'a' is the user request, and 'b' is string in the font. - // If eg. user asks for "en-us" and font has "en", approve. - if (la > lb && astr[lb] == '-' && !strncmp (astr, bstr, lb)) - return 0; - } + // 'a' is the user request, and 'b' is string in the font. + // If eg. user asks for "en-us" and font has "en", approve. + if (!exact && c && + hb_language_matches (b->language, a->language)) + return 0; return c; } diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index ce5cdce98..ceb3bf6df 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -214,6 +214,8 @@ lang_matches (const char *lang_str, const char *spec, unsigned spec_len) { + /* Same as hb_language_matches(); duplicated. */ + if (likely ((unsigned) (limit - lang_str) < spec_len)) return false;