summaryrefslogtreecommitdiffstats
path: root/libass/ass_fontselect.c
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2015-11-04 15:25:47 +0200
committerOleg Oshmyan <chortos@inbox.lv>2015-11-04 15:38:50 +0200
commitd0566318ee5035ca3a4d2d65d46a80a4e3d8244c (patch)
treeac342a9147ddc911698235c73a36e66c485b6ce4 /libass/ass_fontselect.c
parentad5988af46f5ca698115140f9252882286539f72 (diff)
downloadlibass-d0566318ee5035ca3a4d2d65d46a80a4e3d8244c.tar.bz2
libass-d0566318ee5035ca3a4d2d65d46a80a4e3d8244c.tar.xz
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.
Diffstat (limited to 'libass/ass_fontselect.c')
-rw-r--r--libass/ass_fontselect.c58
1 files changed, 38 insertions, 20 deletions
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)