diff options
author | Grigori Goronzy <greg@chown.ath.cx> | 2015-06-14 03:09:10 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@chown.ath.cx> | 2015-07-10 10:43:16 +0200 |
commit | 9f62fd8b374235b98a325b6a903d49b2f6bb4cf3 (patch) | |
tree | dbbf365c9ea4682da557543e9d24cca3301332cd | |
parent | 044b619ac125178ebc65dce79b1101afce28eecc (diff) | |
download | libass-9f62fd8b374235b98a325b6a903d49b2f6bb4cf3.tar.bz2 libass-9f62fd8b374235b98a325b6a903d49b2f6bb4cf3.tar.xz |
fontselect: improved face selection among a family
We want the best variant, but if it doesn't have the glyph coverage,
we may also use another variant from the same family.
-rw-r--r-- | libass/ass_fontselect.c | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index 26fe579..8c96e61 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -452,6 +452,14 @@ static void font_info_dump(ASS_FontInfo *font_infos, size_t len) } #endif +static int check_glyph(ASS_FontInfo *fi, uint32_t code) +{ + ASS_FontProvider *provider = fi->provider; + assert(provider && provider->funcs.check_glyph); + + return provider->funcs.check_glyph(fi->priv, code); +} + static char *select_font(ASS_FontSelector *priv, ASS_Library *library, const char *family, unsigned bold, unsigned italic, int *index, char **postscript_name, int *uid, @@ -484,22 +492,33 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, req.fullnames = &req_fullname; req.fullnames[0] = family_trim; - // match font + // Match font family name against font list unsigned score_min = UINT_MAX; for (int i = 0; i < priv->n_font; i++) { unsigned score = font_info_similarity(&priv->font_infos[i], &req); - // lowest possible score instantly matches - if (score == 0) { - idx = i; - break; - } - - // update idx if score is better + // Consider updating idx if score is better than current minimum if (score < score_min) { + // Check if the font has the requested glyph. + // We are doing this here, for every font face, because + // coverage might differ between the variants of a font + // family. In practice, it is common that the regular + // style has the best coverage while bold/italic/etc + // variants cover less (e.g. FreeSans family). + // We want to be able to match even if the closest variant + // does not have the requested glyph, but another member + // of the family has the glyph. + if (!check_glyph(&priv->font_infos[i], code)) + continue; + score_min = score; idx = i; } + + // Lowest possible score instantly matches; this is typical + // for fullname matches, but can also occur with family matches. + if (score == 0) + break; } // free font name @@ -510,15 +529,6 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, return NULL; } - // check glyph coverage - ASS_FontProvider *provider = font_infos[idx].provider; - if (!provider || !provider->funcs.check_glyph) { - return NULL; - } - if (provider->funcs.check_glyph(font_infos[idx].priv, code) == 0) { - return NULL; - } - // successfully matched, set up return values *postscript_name = font_infos[idx].postscript_name; *index = font_infos[idx].index; |