From d0566318ee5035ca3a4d2d65d46a80a4e3d8244c Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Wed, 4 Nov 2015 15:25:47 +0200 Subject: fontselect: replace is_postscript flag with check_postscript function DirectWrite does not provide fast access to the is_postscript flag, requiring each font to be loaded before its format can be determined. Eagerly doing this for every installed font can be quite slow, on the order of seconds. To improve performance, ask the font provider for this information only when it is actually needed, i.e. when one of the font's full names or its PostScript name matches a requested font name and we need to know whether to accept this match. The return value of check_postscript is not cached in this commit. This makes repeated calls slower than accessing is_postscript was. This should not be a problem, but if it is, the value can be cached (or precomputed) by font providers in their font private data. This commit also potentially increases the memory usage of some font providers by retaining data structures needed to implement check_postscript in their font private data. This should not be a problem either, but if it is, the value of check_postscript can be precomputed by all providers other than DirectWrite. --- libass/ass_fontselect.c | 58 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 20 deletions(-) (limited to 'libass/ass_fontselect.c') diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index e4be338..7f73529 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -70,7 +70,6 @@ struct font_info { char *postscript_name; // can be used as an alternative to index to // identify a font inside a collection - bool is_postscript; // font source ASS_FontProvider *provider; @@ -110,6 +109,13 @@ struct font_data_ft { int idx; }; +static bool check_postscript_ft(void *data) +{ + FontDataFT *fd = (FontDataFT *)data; + PS_FontInfoRec postscript_info; + return !FT_Get_PS_Font_Info(fd->face, &postscript_info); +} + static bool check_glyph_ft(void *data, uint32_t codepoint) { FontDataFT *fd = (FontDataFT *)data; @@ -149,13 +155,10 @@ get_data_embedded(void *data, unsigned char *buf, size_t offset, size_t len) } static ASS_FontProviderFuncs ft_funcs = { - get_data_embedded, - check_glyph_ft, - destroy_font_ft, - NULL, - NULL, - NULL, - NULL + .get_data = get_data_embedded, + .check_postscript = check_postscript_ft, + .check_glyph = check_glyph_ft, + .destroy_font = destroy_font_ft, }; static void load_fonts_from_dir(ASS_Library *library, const char *dir) @@ -302,7 +305,6 @@ ass_font_provider_add_font(ASS_FontProvider *provider, info->width = width; info->n_fullname = meta->n_fullname; info->n_family = meta->n_family; - info->is_postscript = meta->is_postscript; info->families = calloc(meta->n_family, sizeof(char *)); if (info->families == NULL) @@ -406,6 +408,14 @@ void ass_font_provider_free(ASS_FontProvider *provider) free(provider); } +static bool check_postscript(ASS_FontInfo *fi) +{ + ASS_FontProvider *provider = fi->provider; + assert(provider && provider->funcs.check_postscript); + + return provider->funcs.check_postscript(fi->priv); +} + /** * \brief Return whether the given font is in the given family. */ @@ -425,17 +435,27 @@ static bool matches_family_name(ASS_FontInfo *f, const char *family) static bool matches_full_or_postscript_name(ASS_FontInfo *f, const char *fullname) { - if (f->is_postscript) { - if (f->postscript_name != NULL && - ass_strcasecmp(f->postscript_name, fullname) == 0) - return true; - } else { - for (int i = 0; i < f->n_fullname; i++) { - if (ass_strcasecmp(f->fullnames[i], fullname) == 0) - return true; + bool matches_fullname = false; + bool matches_postscript_name = false; + + for (int i = 0; i < f->n_fullname; i++) { + if (ass_strcasecmp(f->fullnames[i], fullname) == 0) { + matches_fullname = true; + break; } } - return false; + + if (f->postscript_name != NULL && + ass_strcasecmp(f->postscript_name, fullname) == 0) + matches_postscript_name = true; + + if (matches_fullname == matches_postscript_name) + return matches_fullname; + + if (check_postscript(f)) + return matches_postscript_name; + else + return matches_fullname; } /** @@ -730,7 +750,6 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) int slant, weight; char *fullnames[MAX_FULLNAME]; char *families[MAX_FULLNAME]; - PS_FontInfoRec postscript_info; // we're only interested in outlines if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) @@ -788,7 +807,6 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) info->width = 100; // FIXME, should probably query the OS/2 table info->postscript_name = (char *)FT_Get_Postscript_Name(face); - info->is_postscript = !FT_Get_PS_Font_Info(face, &postscript_info); info->families = calloc(sizeof(char *), num_family); if (info->families == NULL) -- cgit v1.2.3