summaryrefslogtreecommitdiffstats
path: root/libass/ass_directwrite.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_directwrite.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_directwrite.c')
-rw-r--r--libass/ass_directwrite.c80
1 files changed, 46 insertions, 34 deletions
diff --git a/libass/ass_directwrite.c b/libass/ass_directwrite.c
index cb21dd4..b0ee057 100644
--- a/libass/ass_directwrite.c
+++ b/libass/ass_directwrite.c
@@ -43,6 +43,7 @@ static const ASS_FontMapping font_substitutions[] = {
*/
typedef struct {
IDWriteFont *font;
+ IDWriteFontFace *face;
IDWriteFontFileStream *stream;
} FontPrivate;
@@ -224,15 +225,34 @@ static void init_FallbackLogTextRenderer(FallbackLogTextRenderer *r,
}
/*
+ * This function is called whenever a font is accessed for the
+ * first time. It will create a FontFace for metadata access and
+ * memory reading, which will be stored within the private data.
+ */
+static bool init_font_private_face(FontPrivate *priv)
+{
+ HRESULT hr;
+ IDWriteFontFace *face;
+
+ if (priv->face != NULL)
+ return true;
+
+ hr = IDWriteFont_CreateFontFace(priv->font, &face);
+ if (FAILED(hr) || !face)
+ return false;
+
+ priv->face = face;
+ return true;
+}
+
+/*
* This function is called whenever a font is used for the first
* time. It will create a FontStream for memory reading, which
* will be stored within the private data.
*/
-static bool init_font_private(FontPrivate *priv)
+static bool init_font_private_stream(FontPrivate *priv)
{
HRESULT hr = S_OK;
- IDWriteFont *font = priv->font;
- IDWriteFontFace *face = NULL;
IDWriteFontFile *file = NULL;
IDWriteFontFileStream *stream = NULL;
IDWriteFontFileLoader *loader = NULL;
@@ -243,41 +263,34 @@ static bool init_font_private(FontPrivate *priv)
if (priv->stream != NULL)
return true;
- hr = IDWriteFont_CreateFontFace(font, &face);
- if (FAILED(hr) || !face)
+ if (!init_font_private_face(priv))
return false;
/* DirectWrite only supports one file per face */
- hr = IDWriteFontFace_GetFiles(face, &n_files, &file);
- if (FAILED(hr) || !file) {
- IDWriteFontFace_Release(face);
+ hr = IDWriteFontFace_GetFiles(priv->face, &n_files, &file);
+ if (FAILED(hr) || !file)
return false;
- }
hr = IDWriteFontFile_GetReferenceKey(file, &refKey, &keySize);
if (FAILED(hr)) {
IDWriteFontFile_Release(file);
- IDWriteFontFace_Release(face);
return false;
}
hr = IDWriteFontFile_GetLoader(file, &loader);
if (FAILED(hr) || !loader) {
IDWriteFontFile_Release(file);
- IDWriteFontFace_Release(face);
return false;
}
hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, refKey, keySize, &stream);
if (FAILED(hr) || !stream) {
IDWriteFontFile_Release(file);
- IDWriteFontFace_Release(face);
return false;
}
priv->stream = stream;
IDWriteFontFile_Release(file);
- IDWriteFontFace_Release(face);
return true;
}
@@ -297,7 +310,7 @@ static size_t get_data(void *data, unsigned char *buf, size_t offset,
const void *fileBuf = NULL;
void *fragContext = NULL;
- if (!init_font_private(priv))
+ if (!init_font_private_stream(priv))
return 0;
if (buf == NULL) {
@@ -323,6 +336,22 @@ static size_t get_data(void *data, unsigned char *buf, size_t offset,
}
/*
+ * Check whether the font contains PostScript outlines.
+ */
+static bool check_postscript(void *data)
+{
+ FontPrivate *priv = (FontPrivate *) data;
+
+ if (!init_font_private_face(priv))
+ return false;
+
+ DWRITE_FONT_FACE_TYPE type = IDWriteFontFace_GetType(priv->face);
+ return type == DWRITE_FONT_FACE_TYPE_CFF ||
+ type == DWRITE_FONT_FACE_TYPE_RAW_CFF ||
+ type == DWRITE_FONT_FACE_TYPE_TYPE1;
+}
+
+/*
* Check if the passed font has a specific unicode character.
*/
static bool check_glyph(void *data, uint32_t code)
@@ -362,6 +391,8 @@ static void destroy_font(void *data)
FontPrivate *priv = (FontPrivate *) data;
IDWriteFont_Release(priv->font);
+ if (priv->face != NULL)
+ IDWriteFontFace_Release(priv->face);
if (priv->stream != NULL)
IDWriteFontFileStream_Release(priv->stream);
@@ -482,24 +513,6 @@ static int map_width(enum DWRITE_FONT_STRETCH stretch)
}
}
-static bool is_postscript(IDWriteFont *font)
-{
- HRESULT hr = S_OK;
- IDWriteFontFace *face = NULL;
- DWRITE_FONT_FACE_TYPE type;
-
- hr = IDWriteFont_CreateFontFace(font, &face);
- if (FAILED(hr) || !face)
- return false;
-
- type = IDWriteFontFace_GetType(face);
- IDWriteFontFace_Release(face);
-
- return type == DWRITE_FONT_FACE_TYPE_CFF ||
- type == DWRITE_FONT_FACE_TYPE_RAW_CFF ||
- type == DWRITE_FONT_FACE_TYPE_TYPE1;
-}
-
static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily,
ASS_FontProvider *provider)
{
@@ -613,8 +626,6 @@ static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily,
}
IDWriteLocalizedStrings_Release(familyNames);
- meta.is_postscript = is_postscript(font);
-
FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv));
if (!font_priv)
goto cleanup;
@@ -698,6 +709,7 @@ static void get_substitutions(void *priv, const char *name,
*/
static ASS_FontProviderFuncs directwrite_callbacks = {
.get_data = get_data,
+ .check_postscript = check_postscript,
.check_glyph = check_glyph,
.destroy_font = destroy_font,
.destroy_provider = destroy_provider,