From c3392661e031d01b9cba19ad25f91462c5fb8116 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Sat, 23 May 2015 13:12:43 +0200 Subject: directwrite: cache FontFileStream Extract a function to set up FontFileStream and store it in a newly introduced private struct. Fix memory management as well. --- libass/ass_directwrite.cpp | 121 +++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 36 deletions(-) diff --git a/libass/ass_directwrite.cpp b/libass/ass_directwrite.cpp index abf7e67..ea495e9 100644 --- a/libass/ass_directwrite.cpp +++ b/libass/ass_directwrite.cpp @@ -28,77 +28,106 @@ extern "C" #include "ass_utils.h" } -static size_t get_data(void * priv, unsigned char* buf, size_t offset, size_t length) +typedef struct { + IDWriteFont *font; + IDWriteFontFileStream *stream; +} FontPrivate; + +static bool init_font_private(FontPrivate *priv) { HRESULT hr = S_OK; + IDWriteFont* font = priv->font; IDWriteFontFace* face = NULL; - IDWriteFont* font = (IDWriteFont*)priv; - IDWriteFontFile* files = NULL; + IDWriteFontFile* file = NULL; IDWriteFontFileStream* stream = NULL; IDWriteFontFileLoader* loader = NULL; - UINT32 n_files = 0; - UINT64 fileSize; - const void* fileBuf = NULL; - - hr = font->CreateFontFace(&face); + UINT32 n_files = 1; const void* refKey = NULL; UINT32 keySize = 0; - void* fragContext = NULL; + if (priv->stream != NULL) + return true; + + hr = font->CreateFontFace(&face); if (FAILED(hr) || !face) - return 0; + return false; - hr = face->GetFiles(&n_files, NULL); - if (FAILED(hr)) - return 0; + hr = face->GetFiles(&n_files, &file); + if (FAILED(hr) || !file) { + face->Release(); + return false; + } - hr = face->GetFiles(&n_files, &files); - if (FAILED(hr) || !files) - return 0; + hr = file->GetReferenceKey(&refKey, &keySize); + if (FAILED(hr)) { + file->Release(); + face->Release(); + return false; + } - hr = files[0].GetReferenceKey(&refKey, &keySize); - if (FAILED(hr)) - return 0; + hr = file->GetLoader(&loader); + if (FAILED(hr) || !loader) { + file->Release(); + face->Release(); + return false; + } - hr = files[0].GetLoader(&loader); - if (FAILED(hr) || !loader) - return 0; + hr = loader->CreateStreamFromKey(refKey, keySize, &stream); + if (FAILED(hr) || !stream) { + file->Release(); + face->Release(); + return false; + } - hr = loader->CreateStreamFromKey(refKey,keySize,&stream); - if (FAILED(hr) || !stream) + priv->stream = stream; + file->Release(); + face->Release(); + + return true; +} + +static size_t get_data(void *data, unsigned char* buf, size_t offset, size_t length) +{ + HRESULT hr = S_OK; + FontPrivate *priv = (FontPrivate *)data; + const void *fileBuf = NULL; + void *fragContext = NULL; + + if (!init_font_private(priv)) return 0; - if (buf == NULL) - { - hr = stream->GetFileSize(&fileSize); + if (buf == NULL) { + UINT64 fileSize; + hr = priv->stream->GetFileSize(&fileSize); if (FAILED(hr)) return 0; return fileSize; } - - hr = stream->ReadFileFragment(&fileBuf, offset, length, &fragContext); + + hr = priv->stream->ReadFileFragment(&fileBuf, offset, length, &fragContext); if (FAILED(hr) || !fileBuf) return 0; memcpy(buf, fileBuf, length); - stream->ReleaseFileFragment(fragContext); + priv->stream->ReleaseFileFragment(fragContext); return length; } -static int check_glyph(void *priv, uint32_t code) +static int check_glyph(void *data, uint32_t code) { - //TODO: use IDWriteFont::HasCharacter method - //see: https://msdn.microsoft.com/en-us/library/windows/desktop/dd371165(v=vs.85).aspx HRESULT hr = S_OK; + FontPrivate *priv = (FontPrivate *)data; BOOL exists = FALSE; - ((IDWriteFont*)priv)->HasCharacter(code, &exists); + if (code == 0) + return 1; + priv->font->HasCharacter(code, &exists); if (FAILED(hr)) - return FALSE; + return 0; return exists; } @@ -108,6 +137,17 @@ static void destroy(void* priv) ((IDWriteFactory*)priv)->Release(); } +static void destroy_font(void *data) +{ + FontPrivate *priv = (FontPrivate *)data; + + priv->font->Release(); + if (priv->stream != NULL) + priv->stream->Release(); + + free(priv); +} + static void scan_fonts(IDWriteFactory *factory, ASS_FontProvider *provider) { HRESULT hr = S_OK; @@ -204,9 +244,18 @@ static void scan_fonts(IDWriteFactory *factory, ASS_FontProvider *provider) meta.families[k] = mbName; } - ass_font_provider_add_font(provider, &meta, NULL, j, psName, font); + FontPrivate *font_priv = (FontPrivate *)calloc(1, sizeof(*font_priv)); + font_priv->font = font; + + ass_font_provider_add_font(provider, &meta, NULL, 0, psName, font_priv); + + for (UINT32 k = 0; k < meta.n_family; ++k) + free(meta.families[k]); + for (UINT32 k = 0; k < meta.n_fullname; ++k) + free(meta.fullnames[k]); free(meta.fullnames); free(meta.families); + free(psName); } } } -- cgit v1.2.3