Add hb_language_matches()

New API:
+ hb_language_matches()
This commit is contained in:
Behdad Esfahbod 2022-07-17 22:15:42 -06:00
parent d57ce30054
commit f7f6d278bb
6 changed files with 44 additions and 10 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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:

View File

@ -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;
}

View File

@ -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;