summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2021-06-18 03:31:43 +0300
committerOleg Oshmyan <chortos@inbox.lv>2021-07-10 02:36:31 +0300
commit4fb7394f7b9b4f4e4f3e2825c5ec5344a69619f2 (patch)
tree7cdd00717f83c9bd40afa507a9c5288975151822
parentd7e0e17ce571a8eca8fdf978a7c00c096782d037 (diff)
downloadlibass-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.am2
-rw-r--r--libass/ass_directwrite.c122
-rw-r--r--libass/ass_directwrite_info_template.h87
-rw-r--r--libass/dwrite_c.h103
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);