[name] Implement approximate language matching

Very rudimentary.

Fixes https://github.com/harfbuzz/harfbuzz/issues/3354
This commit is contained in:
Behdad Esfahbod 2022-06-03 04:10:28 -06:00
parent 40d7d56e53
commit b39b5f2f31
2 changed files with 38 additions and 5 deletions

View File

@ -156,7 +156,7 @@ struct NameRecord
};
static int
_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
_hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact)
{
const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
@ -169,8 +169,23 @@ _hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
if (a->language == b->language) return 0;
if (!a->language) return -1;
if (!b->language) return +1;
return strcmp (hb_language_to_string (a->language),
hb_language_to_string (b->language));
const char *astr = hb_language_to_string (a->language);
const char *bstr = hb_language_to_string (b->language);
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;
}
return c;
}
static int
@ -178,7 +193,7 @@ _hb_ot_name_entry_cmp (const void *pa, const void *pb)
{
/* Compare by name_id, then language, then score, then index. */
int v = _hb_ot_name_entry_cmp_key (pa, pb);
int v = _hb_ot_name_entry_cmp_key (pa, pb, true);
if (v)
return v;
@ -330,7 +345,18 @@ struct name
const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
this->names.length,
sizeof (hb_ot_name_entry_t),
_hb_ot_name_entry_cmp_key);
_hb_ot_name_entry_cmp_key,
true);
if (!entry)
{
entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
this->names.length,
sizeof (hb_ot_name_entry_t),
_hb_ot_name_entry_cmp_key,
false);
}
if (!entry)
return -1;

View File

@ -93,10 +93,17 @@ test_ot_name (void)
name_id = entries[3].name_id;
g_assert_cmpuint (3, ==, name_id);
lang = entries[3].language;
g_assert_cmpstr (hb_language_to_string (lang), ==, "en");
g_assert_cmpuint (27, ==, hb_ot_name_get_utf8 (face, name_id, lang, &text_size, text));
g_assert_cmpuint (9, ==, text_size);
g_assert_cmpstr (text, ==, "FontForge");
g_assert_cmpuint (27, ==, hb_ot_name_get_utf8 (face, name_id, hb_language_from_string ("en_US", -1), &text_size, text));
g_assert_cmpuint (8, ==, text_size);
g_assert_cmpstr (text, ==, "FontForg");
g_assert_cmpuint (0, ==, hb_ot_name_get_utf8 (face, name_id, hb_language_from_string ("fa_IR", -1), &text_size, text));
}
int