From 488070876efea2c28ff3e3945c4568c3d831a254 Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Fri, 30 Oct 2015 01:13:59 +0200 Subject: directwrite: split out the inner loop of scan_fonts as a separate function This has the side effect that the ASS_FontProviderMetaData instance is now cleared for every font rather than only once at the start of the search, which fixes some use-after-free scenarios and prevents the creation of chimeric fonts using names left over from other fonts processed earlier. This lays the groundwork for further code simplification and error handling improvements within this function, which will come in a separate commit. This commit is transparent to `git blame -w` except for return statements. --- libass/ass_directwrite.c | 226 ++++++++++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 109 deletions(-) (limited to 'libass') diff --git a/libass/ass_directwrite.c b/libass/ass_directwrite.c index bf40cfb..be029e6 100644 --- a/libass/ass_directwrite.c +++ b/libass/ass_directwrite.c @@ -500,6 +500,122 @@ static bool is_postscript(IDWriteFont *font) type == DWRITE_FONT_FACE_TYPE_TYPE1; } +static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily, + ASS_FontProvider *provider) +{ + HRESULT hr = S_OK; + DWRITE_FONT_METRICS metrics; + DWRITE_FONT_STYLE style; + ASS_FontProviderMetaData meta = {0}; + wchar_t temp_name[NAME_MAX_LENGTH]; + int size_needed = 0; + IDWriteLocalizedStrings *familyNames = NULL; + IDWriteLocalizedStrings *fontNames = NULL; + IDWriteLocalizedStrings *psNames = NULL; + BOOL exists = FALSE; + + meta.weight = IDWriteFont_GetWeight(font); + meta.width = map_width(IDWriteFont_GetStretch(font)); + IDWriteFont_GetMetrics(font, &metrics); + style = IDWriteFont_GetStyle(font); + meta.slant = (style == DWRITE_FONT_STYLE_NORMAL) ? FONT_SLANT_NONE : + (style == DWRITE_FONT_STYLE_OBLIQUE)? FONT_SLANT_OBLIQUE : + (style == DWRITE_FONT_STYLE_ITALIC) ? FONT_SLANT_ITALIC : FONT_SLANT_NONE; + + hr = IDWriteFont_GetInformationalStrings(font, + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames,&exists); + if (FAILED(hr)) { + IDWriteFont_Release(font); + return; + } + + if (exists) { + hr = IDWriteLocalizedStrings_GetString(psNames, 0, temp_name, NAME_MAX_LENGTH); + if (FAILED(hr)) { + IDWriteLocalizedStrings_Release(psNames); + IDWriteFont_Release(font); + return; + } + + temp_name[NAME_MAX_LENGTH-1] = 0; + size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL); + char *mbName = (char *) malloc(size_needed); + WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); + meta.postscript_name = mbName; + + IDWriteLocalizedStrings_Release(psNames); + } + + hr = IDWriteFont_GetInformationalStrings(font, + DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames,&exists); + if (FAILED(hr)) { + IDWriteFont_Release(font); + return; + } + + if (exists) { + meta.n_fullname = IDWriteLocalizedStrings_GetCount(fontNames); + meta.fullnames = (char **) calloc(meta.n_fullname, sizeof(char *)); + for (UINT32 k = 0; k < meta.n_fullname; ++k) { + hr = IDWriteLocalizedStrings_GetString(fontNames, k, + temp_name, + NAME_MAX_LENGTH); + if (FAILED(hr)) { + continue; + } + + temp_name[NAME_MAX_LENGTH-1] = 0; + size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL); + char *mbName = (char *) malloc(size_needed); + WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); + meta.fullnames[k] = mbName; + } + IDWriteLocalizedStrings_Release(fontNames); + } + + hr = IDWriteFont_GetInformationalStrings(font, + DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists); + if (!exists) + hr = IDWriteFontFamily_GetFamilyNames(fontFamily, &familyNames); + if (FAILED(hr)) { + IDWriteFont_Release(font); + return; + } + + meta.n_family = IDWriteLocalizedStrings_GetCount(familyNames); + meta.families = (char **) calloc(meta.n_family, sizeof(char *)); + for (UINT32 k = 0; k < meta.n_family; ++k) { + hr = IDWriteLocalizedStrings_GetString(familyNames, k, + temp_name, + NAME_MAX_LENGTH); + if (FAILED(hr)) { + continue; + } + + temp_name[NAME_MAX_LENGTH-1] = 0; + size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL); + char *mbName = (char *) malloc(size_needed); + WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); + meta.families[k] = mbName; + } + IDWriteLocalizedStrings_Release(familyNames); + + meta.is_postscript = is_postscript(font); + + FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); + font_priv->font = font; + + ass_font_provider_add_font(provider, &meta, NULL, 0, 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(meta.postscript_name); +} + /* * Scan every system font on the current machine and add it * to the libass lookup. Stores the FontPrivate as private data @@ -511,12 +627,7 @@ static void scan_fonts(IDWriteFactory *factory, HRESULT hr = S_OK; IDWriteFontCollection *fontCollection = NULL; IDWriteFont *font = NULL; - DWRITE_FONT_METRICS metrics; - DWRITE_FONT_STYLE style; - ASS_FontProviderMetaData meta = {0}; hr = IDWriteFactory_GetSystemFontCollection(factory, &fontCollection, FALSE); - wchar_t temp_name[NAME_MAX_LENGTH]; - int size_needed = 0; if (FAILED(hr) || !fontCollection) return; @@ -525,10 +636,6 @@ static void scan_fonts(IDWriteFactory *factory, for (UINT32 i = 0; i < familyCount; ++i) { IDWriteFontFamily *fontFamily = NULL; - IDWriteLocalizedStrings *familyNames = NULL; - IDWriteLocalizedStrings *fontNames = NULL; - IDWriteLocalizedStrings *psNames = NULL; - BOOL exists = FALSE; hr = IDWriteFontCollection_GetFontFamily(fontCollection, i, &fontFamily); if (FAILED(hr)) @@ -547,106 +654,7 @@ static void scan_fonts(IDWriteFactory *factory, continue; } - meta.weight = IDWriteFont_GetWeight(font); - meta.width = map_width(IDWriteFont_GetStretch(font)); - IDWriteFont_GetMetrics(font, &metrics); - style = IDWriteFont_GetStyle(font); - meta.slant = (style == DWRITE_FONT_STYLE_NORMAL) ? FONT_SLANT_NONE : - (style == DWRITE_FONT_STYLE_OBLIQUE)? FONT_SLANT_OBLIQUE : - (style == DWRITE_FONT_STYLE_ITALIC) ? FONT_SLANT_ITALIC : FONT_SLANT_NONE; - - hr = IDWriteFont_GetInformationalStrings(font, - DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames,&exists); - if (FAILED(hr)) { - IDWriteFont_Release(font); - continue; - } - - if (exists) { - hr = IDWriteLocalizedStrings_GetString(psNames, 0, temp_name, NAME_MAX_LENGTH); - if (FAILED(hr)) { - IDWriteLocalizedStrings_Release(psNames); - IDWriteFont_Release(font); - continue; - } - - temp_name[NAME_MAX_LENGTH-1] = 0; - size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL); - char *mbName = (char *) malloc(size_needed); - WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); - meta.postscript_name = mbName; - - IDWriteLocalizedStrings_Release(psNames); - } - - hr = IDWriteFont_GetInformationalStrings(font, - DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames,&exists); - if (FAILED(hr)) { - IDWriteFont_Release(font); - continue; - } - - if (exists) { - meta.n_fullname = IDWriteLocalizedStrings_GetCount(fontNames); - meta.fullnames = (char **) calloc(meta.n_fullname, sizeof(char *)); - for (UINT32 k = 0; k < meta.n_fullname; ++k) { - hr = IDWriteLocalizedStrings_GetString(fontNames, k, - temp_name, - NAME_MAX_LENGTH); - if (FAILED(hr)) { - continue; - } - - temp_name[NAME_MAX_LENGTH-1] = 0; - size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL); - char *mbName = (char *) malloc(size_needed); - WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); - meta.fullnames[k] = mbName; - } - IDWriteLocalizedStrings_Release(fontNames); - } - - hr = IDWriteFont_GetInformationalStrings(font, - DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists); - if (!exists) - hr = IDWriteFontFamily_GetFamilyNames(fontFamily, &familyNames); - if (FAILED(hr)) { - IDWriteFont_Release(font); - continue; - } - - meta.n_family = IDWriteLocalizedStrings_GetCount(familyNames); - meta.families = (char **) calloc(meta.n_family, sizeof(char *)); - for (UINT32 k = 0; k < meta.n_family; ++k) { - hr = IDWriteLocalizedStrings_GetString(familyNames, k, - temp_name, - NAME_MAX_LENGTH); - if (FAILED(hr)) { - continue; - } - - temp_name[NAME_MAX_LENGTH-1] = 0; - size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL); - char *mbName = (char *) malloc(size_needed); - WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); - meta.families[k] = mbName; - } - IDWriteLocalizedStrings_Release(familyNames); - - meta.is_postscript = is_postscript(font); - - FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); - font_priv->font = font; - - ass_font_provider_add_font(provider, &meta, NULL, 0, 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(meta.postscript_name); + add_font(font, fontFamily, provider); } } } -- cgit v1.2.3