diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2021-06-18 03:31:43 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2021-07-10 02:36:31 +0300 |
commit | 4fb7394f7b9b4f4e4f3e2825c5ec5344a69619f2 (patch) | |
tree | 7cdd00717f83c9bd40afa507a9c5288975151822 | |
parent | d7e0e17ce571a8eca8fdf978a7c00c096782d037 (diff) | |
download | libass-4fb7394f7b9b4f4e4f3e2825c5ec5344a69619f2.tar.bz2 libass-4fb7394f7b9b4f4e4f3e2825c5ec5344a69619f2.tar.xz |
directwrite: read metadata from IDWriteFontFace3 if possible
This avoids an extra trip to FreeType.
-rw-r--r-- | libass/Makefile.am | 2 | ||||
-rw-r--r-- | libass/ass_directwrite.c | 122 | ||||
-rw-r--r-- | libass/ass_directwrite_info_template.h | 87 | ||||
-rw-r--r-- | libass/dwrite_c.h | 103 |
4 files changed, 237 insertions, 77 deletions
diff --git a/libass/Makefile.am b/libass/Makefile.am index 80857ed..0423d2e 100644 --- a/libass/Makefile.am +++ b/libass/Makefile.am @@ -18,7 +18,7 @@ SRC_INTEL = x86/rasterizer.asm x86/blend_bitmaps.asm x86/be_blur.asm x86/blur.as x86/cpuid.h SRC_FONTCONFIG = ass_fontconfig.c ass_fontconfig.h -SRC_DIRECTWRITE = ass_directwrite.c ass_directwrite.h dwrite_c.h +SRC_DIRECTWRITE = ass_directwrite.c ass_directwrite.h ass_directwrite_info_template.h dwrite_c.h SRC_CORETEXT = ass_coretext.c ass_coretext.h lib_LTLIBRARIES = libass.la diff --git a/libass/ass_directwrite.c b/libass/ass_directwrite.c index 7b80765..ccb82c3 100644 --- a/libass/ass_directwrite.c +++ b/libass/ass_directwrite.c @@ -597,22 +597,55 @@ static int map_width(enum DWRITE_FONT_STRETCH stretch) } } +#define FONT_TYPE IDWriteFontFace3 +#include "ass_directwrite_info_template.h" +#undef FONT_TYPE + static void add_font_face(IDWriteFontFace *face, ASS_FontProvider *provider, ASS_SharedHDC *shared_hdc) { ASS_FontProviderMetaData meta = {0}; - FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); - if (!font_priv) { - IDWriteFontFace_Release(face); - return; + IDWriteFontFace3 *face3; + HRESULT hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace3, + (void **) &face3); + if (SUCCEEDED(hr) && face3) { + bool success = get_font_info_IDWriteFontFace3(face3, &meta); + IDWriteFontFace3_Release(face3); + if (!success) + goto cleanup; } + + FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); + if (!font_priv) + goto cleanup; + font_priv->face = face; + face = NULL; + #if ASS_WINAPI_DESKTOP font_priv->shared_hdc = hdc_retain(shared_hdc); #endif ass_font_provider_add_font(provider, &meta, NULL, 0, font_priv); + +cleanup: + if (meta.families) { + for (int k = 0; k < meta.n_family; k++) + free(meta.families[k]); + free(meta.families); + } + + if (meta.fullnames) { + for (int k = 0; k < meta.n_fullname; k++) + free(meta.fullnames[k]); + free(meta.fullnames); + } + + free(meta.postscript_name); + + if (face) + IDWriteFontFace_Release(face); } #if ASS_WINAPI_DESKTOP @@ -757,92 +790,31 @@ static void add_font_set(IDWriteFontSet *fontSet, ASS_FontProvider *provider) if (IDWriteFontFaceReference_GetSimulations(faceRef) != 0) goto cleanup; - IDWriteFontFace *face; + IDWriteFontFace3 *face; hr = IDWriteFontFaceReference_CreateFontFace(faceRef, &face); - if (FAILED(hr)) + if (FAILED(hr) || !face) goto cleanup; - add_font_face(face, provider, NULL); + add_font_face((IDWriteFontFace *) face, provider, NULL); cleanup: IDWriteFontFaceReference_Release(faceRef); } } +#define FONT_TYPE IDWriteFont +#define FAMILY_AS_ARG +#include "ass_directwrite_info_template.h" +#undef FONT_TYPE +#undef FAMILY_AS_ARG + static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily, ASS_FontProvider *provider) { - HRESULT hr; - BOOL exists; ASS_FontProviderMetaData meta = {0}; - - meta.weight = IDWriteFont_GetWeight(font); - meta.width = map_width(IDWriteFont_GetStretch(font)); - - DWRITE_FONT_STYLE 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; - - IDWriteLocalizedStrings *psNames; - hr = IDWriteFont_GetInformationalStrings(font, - DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames, &exists); - if (FAILED(hr)) - goto cleanup; - - if (exists) { - meta.postscript_name = get_utf8_name(psNames, 0); - IDWriteLocalizedStrings_Release(psNames); - if (!meta.postscript_name) - goto cleanup; - } - - IDWriteLocalizedStrings *fontNames; - hr = IDWriteFont_GetInformationalStrings(font, - DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames, &exists); - if (FAILED(hr)) - goto cleanup; - - if (exists) { - meta.n_fullname = IDWriteLocalizedStrings_GetCount(fontNames); - meta.fullnames = (char **) calloc(meta.n_fullname, sizeof(char *)); - if (!meta.fullnames) { - IDWriteLocalizedStrings_Release(fontNames); - goto cleanup; - } - for (int k = 0; k < meta.n_fullname; k++) { - meta.fullnames[k] = get_utf8_name(fontNames, k); - if (!meta.fullnames[k]) { - IDWriteLocalizedStrings_Release(fontNames); - goto cleanup; - } - } - IDWriteLocalizedStrings_Release(fontNames); - } - - IDWriteLocalizedStrings *familyNames; - hr = IDWriteFont_GetInformationalStrings(font, - DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists); - if (!FAILED(hr) && !exists) - hr = IDWriteFontFamily_GetFamilyNames(fontFamily, &familyNames); - if (FAILED(hr)) + if (!get_font_info_IDWriteFont(font, fontFamily, &meta)) goto cleanup; - meta.n_family = IDWriteLocalizedStrings_GetCount(familyNames); - meta.families = (char **) calloc(meta.n_family, sizeof(char *)); - if (!meta.families) { - IDWriteLocalizedStrings_Release(familyNames); - goto cleanup; - } - for (int k = 0; k < meta.n_family; k++) { - meta.families[k] = get_utf8_name(familyNames, k); - if (!meta.families[k]) { - IDWriteLocalizedStrings_Release(familyNames); - goto cleanup; - } - } - IDWriteLocalizedStrings_Release(familyNames); - FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); if (!font_priv) goto cleanup; diff --git a/libass/ass_directwrite_info_template.h b/libass/ass_directwrite_info_template.h new file mode 100644 index 0000000..7c545d1 --- /dev/null +++ b/libass/ass_directwrite_info_template.h @@ -0,0 +1,87 @@ +#define CONCAT(a, b) a ## b +#define NAME(suffix) CONCAT(get_font_info_, suffix) +static bool NAME(FONT_TYPE)(FONT_TYPE *font, +#ifdef FAMILY_AS_ARG + IDWriteFontFamily *fontFamily, +#endif + ASS_FontProviderMetaData *meta) +#undef NAME +#undef CONCAT +{ + HRESULT hr; + BOOL exists; + + meta->weight = font->lpVtbl->GetWeight(font); + meta->width = map_width(font->lpVtbl->GetStretch(font)); + + DWRITE_FONT_STYLE style = font->lpVtbl->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; + + IDWriteLocalizedStrings *psNames; + hr = font->lpVtbl->GetInformationalStrings(font, + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames, &exists); + if (FAILED(hr)) + return false; + + if (exists) { + meta->postscript_name = get_utf8_name(psNames, 0); + IDWriteLocalizedStrings_Release(psNames); + if (!meta->postscript_name) + return false; + } + + IDWriteLocalizedStrings *fontNames; + hr = font->lpVtbl->GetInformationalStrings(font, + DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames, &exists); + if (FAILED(hr)) + return false; + + if (exists) { + meta->n_fullname = IDWriteLocalizedStrings_GetCount(fontNames); + meta->fullnames = (char **) calloc(meta->n_fullname, sizeof(char *)); + if (!meta->fullnames) { + IDWriteLocalizedStrings_Release(fontNames); + return false; + } + for (int k = 0; k < meta->n_fullname; k++) { + meta->fullnames[k] = get_utf8_name(fontNames, k); + if (!meta->fullnames[k]) { + IDWriteLocalizedStrings_Release(fontNames); + return false; + } + } + IDWriteLocalizedStrings_Release(fontNames); + } + + IDWriteLocalizedStrings *familyNames; + hr = font->lpVtbl->GetInformationalStrings(font, + DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists); + if (!FAILED(hr) && !exists) { +#ifdef FAMILY_AS_ARG + hr = IDWriteFontFamily_GetFamilyNames(fontFamily, &familyNames); +#else + hr = font->lpVtbl->GetFamilyNames(font, &familyNames); +#endif + } + if (FAILED(hr)) + return false; + + meta->n_family = IDWriteLocalizedStrings_GetCount(familyNames); + meta->families = (char **) calloc(meta->n_family, sizeof(char *)); + if (!meta->families) { + IDWriteLocalizedStrings_Release(familyNames); + return false; + } + for (int k = 0; k < meta->n_family; k++) { + meta->families[k] = get_utf8_name(familyNames, k); + if (!meta->families[k]) { + IDWriteLocalizedStrings_Release(familyNames); + return false; + } + } + IDWriteLocalizedStrings_Release(familyNames); + + return true; +} diff --git a/libass/dwrite_c.h b/libass/dwrite_c.h index 5537832..686a471 100644 --- a/libass/dwrite_c.h +++ b/libass/dwrite_c.h @@ -19,6 +19,7 @@ typedef struct IDWriteFactory3 IDWriteFactory3; typedef struct IDWriteFont IDWriteFont; typedef struct IDWriteFontCollection IDWriteFontCollection; typedef struct IDWriteFontFace IDWriteFontFace; +typedef struct IDWriteFontFace3 IDWriteFontFace3; typedef struct IDWriteFontFaceReference IDWriteFontFaceReference; typedef struct IDWriteFontFamily IDWriteFontFamily; typedef struct IDWriteFontList IDWriteFontList; @@ -482,6 +483,8 @@ DECLARE_INTERFACE_(IDWriteFontFace,IUnknown) END_INTERFACE }; #ifdef COBJMACROS +#define IDWriteFontFace_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IDWriteFontFace_AddRef(This) (This)->lpVtbl->AddRef(This) #define IDWriteFontFace_Release(This) (This)->lpVtbl->Release(This) #define IDWriteFontFace_GetType(This) (This)->lpVtbl->GetType(This) #define IDWriteFontFace_GetFiles(This,numberOfFiles,fontFiles) (This)->lpVtbl->GetFiles(This,numberOfFiles,fontFiles) @@ -490,6 +493,103 @@ DECLARE_INTERFACE_(IDWriteFontFace,IUnknown) #endif /*COBJMACROS*/ #undef INTERFACE +#define INTERFACE IDWriteFontFace3 +DECLARE_INTERFACE_(IDWriteFontFace3,IDWriteFontFace) +{ + BEGIN_INTERFACE + +#ifndef __cplusplus + /* IUnknown methods */ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + /* IDWriteFontFace methods */ + STDMETHOD_(DWRITE_FONT_FACE_TYPE, GetType)(THIS) PURE; + + STDMETHOD(GetFiles)(THIS_ + UINT32 *numberOfFiles, + IDWriteFontFile **fontFiles) PURE; + + STDMETHOD_(UINT32, GetIndex)(THIS) PURE; + + STDMETHOD(dummy1)(THIS); + STDMETHOD(dummy2)(THIS); + STDMETHOD(dummy3)(THIS); + STDMETHOD(dummy4)(THIS); + STDMETHOD(dummy5)(THIS); + + STDMETHOD(GetGlyphIndices)(THIS_ + UINT32 const *codePoints, + UINT32 codePointCount, + UINT16 *glyphIndices) PURE; + + STDMETHOD(dummy6)(THIS); + STDMETHOD(dummy7)(THIS); + STDMETHOD(dummy8)(THIS); + STDMETHOD(dummy9)(THIS); + STDMETHOD(dummy10)(THIS); + STDMETHOD(dummy11)(THIS); +#endif + + /* IDWriteFontFace1 methods */ + STDMETHOD(dummy12)(THIS); + STDMETHOD(dummy13)(THIS); + STDMETHOD(dummy14)(THIS); + STDMETHOD(dummy15)(THIS); + STDMETHOD(dummy16)(THIS); + STDMETHOD(dummy17)(THIS); + STDMETHOD(dummy18)(THIS); + STDMETHOD(dummy19)(THIS); + STDMETHOD(dummy20)(THIS); + STDMETHOD(dummy21)(THIS); + STDMETHOD(dummy22)(THIS); + STDMETHOD(dummy23)(THIS); + + /* IDWriteFontFace2 methods */ + STDMETHOD(dummy24)(THIS); + STDMETHOD(dummy25)(THIS); + STDMETHOD(dummy26)(THIS); + STDMETHOD(dummy27)(THIS); + STDMETHOD(dummy28)(THIS); + + /* IDWriteFontFace3 methods */ + STDMETHOD(dummy29)(THIS); + STDMETHOD(dummy30)(THIS); + + STDMETHOD_(DWRITE_FONT_WEIGHT, GetWeight)(THIS) PURE; + STDMETHOD_(DWRITE_FONT_STRETCH, GetStretch)(THIS) PURE; + STDMETHOD_(DWRITE_FONT_STYLE, GetStyle)(THIS) PURE; + + STDMETHOD(GetFamilyNames)(THIS_ + IDWriteLocalizedStrings **names) PURE; + + STDMETHOD(dummy31)(THIS); + + STDMETHOD(GetInformationalStrings)(THIS_ + DWRITE_INFORMATIONAL_STRING_ID informationalStringID, + IDWriteLocalizedStrings **informationalStrings, + BOOL *exists) PURE; + + /* rest dropped */ + END_INTERFACE +}; +#ifdef COBJMACROS +#define IDWriteFontFace3_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IDWriteFontFace3_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IDWriteFontFace3_Release(This) (This)->lpVtbl->Release(This) +#define IDWriteFontFace3_GetType(This) (This)->lpVtbl->GetType(This) +#define IDWriteFontFace3_GetFiles(This,numberOfFiles,fontFiles) (This)->lpVtbl->GetFiles(This,numberOfFiles,fontFiles) +#define IDWriteFontFace3_GetIndex(This) (This)->lpVtbl->GetIndex(This) +#define IDWriteFontFace3_GetGlyphIndices(This,codePoints,codePointCount,glyphIndices) (This)->lpVtbl->GetGlyphIndices(This,codePoints,codePointCount,glyphIndices) +#define IDWriteFontFace3_GetWeight(This) (This)->lpVtbl->GetWeight(This) +#define IDWriteFontFace3_GetStretch(This) (This)->lpVtbl->GetStretch(This) +#define IDWriteFontFace3_GetStyle(This) (This)->lpVtbl->GetStyle(This) +#define IDWriteFontFace3_GetFamilyNames(This,names) (This)->lpVtbl->GetFamilyNames(This,names) +#define IDWriteFontFace3_GetInformationalStrings(This,informationalStringID,informationalStrings,exists) (This)->lpVtbl->GetInformationalStrings(This,informationalStringID,informationalStrings,exists) +#endif /*COBJMACROS*/ + +#undef INTERFACE #define INTERFACE IDWriteFontFaceReference DECLARE_INTERFACE_(IDWriteFontFaceReference,IUnknown) { @@ -503,7 +603,7 @@ DECLARE_INTERFACE_(IDWriteFontFaceReference,IUnknown) #endif STDMETHOD(CreateFontFace)(THIS_ - IDWriteFontFace/*3*/ **fontFace) PURE; + IDWriteFontFace3 **fontFace) PURE; STDMETHOD(dummy1)(THIS); STDMETHOD(dummy2)(THIS); @@ -947,6 +1047,7 @@ DECLARE_INTERFACE_(IDWriteGdiInterop,IUnknown) DEFINE_GUID(IID_IDWriteFactory, 0xb859ee5a,0xd838,0x4b5b,0xa2,0xe8,0x1a,0xdc,0x7d,0x93,0xdb,0x48); DEFINE_GUID(IID_IDWriteFactory3, 0x9a1b41c3,0xd3bb,0x466a,0x87,0xfc,0xfe,0x67,0x55,0x6a,0x3b,0x65); +DEFINE_GUID(IID_IDWriteFontFace3, 0xd37d7598,0x09be,0x4222,0xa2,0x36,0x20,0x81,0x34,0x1c,0xc1,0xf2); DEFINE_GUID(IID_IDWritePixelSnapping, 0xeaf3a2da,0xecf4,0x4d24,0xb6,0x44,0xb3,0x4f,0x68,0x42,0x02,0x4b); DEFINE_GUID(IID_IDWriteTextRenderer, 0xef8a8135,0x5cc6,0x45fe,0x88,0x25,0xc5,0xa0,0x72,0x4e,0xb8,0x19); |