summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2013-11-02 22:01:37 +0100
committerGrigori Goronzy <greg@chown.ath.cx>2015-07-10 10:42:40 +0200
commitb0776d353f8c3396165effd21e113c4f225daa0d (patch)
treedf9fb1911caa7736b4cf3a6675f3b1357ab75821
parent9014b275e9e90d796bee95249a6059e4a55f3cf9 (diff)
downloadlibass-b0776d353f8c3396165effd21e113c4f225daa0d.tar.bz2
libass-b0776d353f8c3396165effd21e113c4f225daa0d.tar.xz
fontselect: coretext: allow to match fontname using the provider
Not all APIs cache everything the same way that fontconfig does. This allows to first perform a match based on the font name and then score the matched fonts using the common code using and in memory database approach. The benefit is the application doesn't have to load all of the fonts and query for weight, slant, width, path and fullnames. I left both code paths inside ass_coretext.c. This allows to test matching problems and have a term of comparison with the slower implementation. To activate it one just has to flip the CT_FONTS_EAGER_LOAD define to 1. Here are some benchmarks with a pretty typical OS X font library of ~600 fonts and using Libass's test program to load a script with 'Helvetica Neue': CT_FONTS_EAGER_LOAD=0 0.04s user 0.02s system 79% cpu 0.081 total CT_FONTS_EAGER_LOAD=1 0.12s user 0.06s system 44% cpu 0.420 total
-rw-r--r--libass/ass_coretext.c61
-rw-r--r--libass/ass_fontselect.c10
-rw-r--r--libass/ass_types.h4
3 files changed, 70 insertions, 5 deletions
diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c
index 802b511..75a5514 100644
--- a/libass/ass_coretext.c
+++ b/libass/ass_coretext.c
@@ -25,6 +25,9 @@
#include "ass_coretext.h"
+#define CT_FONTS_EAGER_LOAD 0
+#define CT_FONTS_LAZY_LOAD !CT_FONTS_EAGER_LOAD
+
static char *cfstr2buf(CFStringRef string)
{
const char *buf_ptr = CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
@@ -149,15 +152,15 @@ static void get_font_traits(CTFontDescriptorRef fontd,
#endif
}
-static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider)
+static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd)
{
ASS_FontProviderMetaData meta;
char *families[1];
char *identifiers[1];
char *fullnames[1];
- CTFontCollectionRef coll = CTFontCollectionCreateFromAvailableFonts(NULL);
- CFArrayRef fontsd = CTFontCollectionCreateMatchingFontDescriptors(coll);
+ if (!fontsd)
+ return;
for (int i = 0; i < CFArrayGetCount(fontsd); i++) {
CTFontDescriptorRef fontd = CFArrayGetValueAtIndex(fontsd, i);
@@ -196,16 +199,66 @@ static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider)
free(path);
}
+}
+
+#if CT_FONTS_EAGER_LOAD
+static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider)
+{
+
+ CTFontCollectionRef coll = CTFontCollectionCreateFromAvailableFonts(NULL);
+ CFArrayRef fontsd = CTFontCollectionCreateMatchingFontDescriptors(coll);
+
+ process_descriptors(provider, fontsd);
CFRelease(fontsd);
CFRelease(coll);
}
+#endif
+
+#if CT_FONTS_LAZY_LOAD
+static void match_fonts(ASS_Library *lib, ASS_FontProvider *provider,
+ char *name)
+{
+ void *descr_ary[1];
+
+ CFStringRef cfname =
+ CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
+ CFMutableDictionaryRef cfattrs = CFDictionaryCreateMutable(NULL, 0, 0, 0);
+ CFDictionaryAddValue(cfattrs, kCTFontDisplayNameAttribute, cfname);
+ CTFontDescriptorRef ctdescr = CTFontDescriptorCreateWithAttributes(cfattrs);
+
+ descr_ary[0] = (void *)ctdescr;
+ CFArrayRef descriptors =
+ CFArrayCreate(NULL, (const void **)&descr_ary, 1, NULL);
+
+ CTFontCollectionRef ctcoll =
+ CTFontCollectionCreateWithFontDescriptors(descriptors, 0);
+
+ CFArrayRef fontsd =
+ CTFontCollectionCreateMatchingFontDescriptors(ctcoll);
+
+ process_descriptors(provider, fontsd);
+
+ if (fontsd)
+ CFRelease(fontsd);
+ CFRelease(ctcoll);
+ CFRelease(cfattrs);
+ CFRelease(ctdescr);
+ CFRelease(descriptors);
+ CFRelease(cfname);
+}
+#endif
static ASS_FontProviderFuncs coretext_callbacks = {
NULL,
check_glyph,
destroy_font,
+ NULL,
+#if CT_FONTS_EAGER_LOAD
NULL
+#else
+ match_fonts
+#endif
};
ASS_FontProvider *
@@ -214,7 +267,9 @@ ass_coretext_add_provider(ASS_Library *lib, ASS_FontSelector *selector)
ASS_FontProvider *provider =
ass_font_provider_new(selector, &coretext_callbacks, NULL);
+#if CT_FONTS_EAGER_LOAD
scan_fonts(lib, provider);
+#endif
return provider;
}
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c
index 799ad02..52ef192 100644
--- a/libass/ass_fontselect.c
+++ b/libass/ass_fontselect.c
@@ -465,9 +465,15 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library,
{
int num_fonts = priv->n_font;
int idx = 0;
- ASS_FontInfo *font_infos = priv->font_infos;
ASS_FontInfo req;
char *req_fullname;
+ char *tfamily = trim_space(strdup(family));
+
+ ASS_FontProvider *default_provider = priv->default_provider;
+ if (default_provider && default_provider->funcs.match_fonts)
+ default_provider->funcs.match_fonts(library, default_provider, tfamily);
+
+ ASS_FontInfo *font_infos = priv->font_infos;
// do we actually have any fonts?
if (!priv->n_font)
@@ -480,7 +486,7 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library,
req.width = 100;
req.n_fullname = 1;
req.fullnames = &req_fullname;
- req.fullnames[0] = trim_space(strdup(family));
+ req.fullnames[0] = tfamily;
// calculate similarities
font_info_req_similarity(font_infos, num_fonts, &req);
diff --git a/libass/ass_types.h b/libass/ass_types.h
index 16c970d..e7f4ec5 100644
--- a/libass/ass_types.h
+++ b/libass/ass_types.h
@@ -53,12 +53,16 @@ typedef size_t (*GetDataFunc)(void *, unsigned char*, size_t, size_t);
typedef int (*CheckGlyphFunc)(void *, uint32_t);
typedef void (*DestroyFontFunc)(void *);
typedef void (*DestroyProviderFunc)(void *);
+typedef void (*MatchFontsFunc)(ASS_Library *lib,
+ ASS_FontProvider *provider,
+ char *name);
typedef struct font_provider_funcs {
GetDataFunc get_data; // callback for memory fonts
CheckGlyphFunc check_glyph; // test codepoint for coverage
DestroyFontFunc destroy_font; // destroy a single font
DestroyProviderFunc destroy_provider; // destroy provider only
+ MatchFontsFunc match_fonts; // match fonts against some name
// XXX: add function for alias handling
} ASS_FontProviderFuncs;