diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2021-06-26 18:16:41 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2021-07-10 02:36:31 +0300 |
commit | 2a2d718e0fd6d47072566e519744634d93621353 (patch) | |
tree | 4562f6f4b7bb908061ab56d7f0dfe20da94b4fc6 | |
parent | 979d7b890af66363dcdef2ae814cebe4053f2898 (diff) | |
download | libass-2a2d718e0fd6d47072566e519744634d93621353.tar.bz2 libass-2a2d718e0fd6d47072566e519744634d93621353.tar.xz |
directwrite: support WinRT/UWP, which forbid LoadLibrary
Normally, we delay loading Dwrite.dll until runtime to allow building
and running DirectWrite-enabled libass binaries on old Windows versions
that lack DirectWrite. However, this is forbidden in WinRT/UWP.
DirectWrite is present in all versions of Windows that support WinRT/UWP,
so we lose nothing by requiring it.
Older Windows SDKs (Microsoft and MinGW alike) lack <winapifamily.h>,
so include it only if we really need it.
Based on VLC patch for libass:
https://github.com/videolan/vlc/commit/eedb57aa96d2bc0046a6da2e081c75ae9edf8fd5
and on this autoconf code:
https://github.com/lu-zero/mfx_dispatch/commit/c51a54c15f51579804030c70592c0a26065f1242
Note: the VLC patch retained an unconditional call to FreeLibrary
in destroy_provider. However, FreeLibrary does not actually expect
NULL as argument, so this commit adds a guard to that call.
Perhaps FreeLibrary(NULL) simply fails cleanly and that's why
this has not caused VLC problems, but we should not rely on this.
-rw-r--r-- | configure.ac | 23 | ||||
-rw-r--r-- | libass/ass_directwrite.c | 31 | ||||
-rw-r--r-- | libass/ass_directwrite.h | 7 |
3 files changed, 52 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac index 5f8cf7b..8500381 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ AC_ARG_ENABLE([profile], AS_HELP_STRING([--enable-profile], AC_ARG_ENABLE([fontconfig], AS_HELP_STRING([--disable-fontconfig], [disable fontconfig support @<:@default=enabled@:>@])) AC_ARG_ENABLE([directwrite], AS_HELP_STRING([--disable-directwrite], - [disable DirectWrite support (win32 only) @<:@default=check@:>@])) + [disable DirectWrite support (Windows only) @<:@default=check@:>@])) AC_ARG_ENABLE([coretext], AS_HELP_STRING([--disable-coretext], [disable CoreText support (OSX only) @<:@default=check@:>@])) AC_ARG_ENABLE([require-system-font-provider], AS_HELP_STRING([--disable-require-system-font-provider], @@ -147,9 +147,28 @@ AS_IF([test "x$enable_directwrite" != xno], [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([[#include <windows.h>]], [[;]]) ], [ - AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite]) directwrite=true AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([for Win32 desktop APIs]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #include <winapifamily.h> + #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + #error Win32 desktop APIs are available + #endif + ]], [[;]]) + ], [ + # WinRT/UWP/app build: LoadLibrary is + # unavailable, but DirectWrite is always present + LIBS="$LIBS -ldwrite" + AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite (WinRT/UWP)]) + AC_MSG_RESULT([no]) + ], [ + # Win32/desktop build: + # DirectWrite is optional but can be loaded via LoadLibrary + AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite (Win32)]) + AC_MSG_RESULT([yes]) + ]) ], [ directwrite=false AC_MSG_RESULT([no]) diff --git a/libass/ass_directwrite.c b/libass/ass_directwrite.c index 55fce52..e6ee298 100644 --- a/libass/ass_directwrite.c +++ b/libass/ass_directwrite.c @@ -45,7 +45,9 @@ typedef struct { } FontPrivate; typedef struct { +#if ASS_WINAPI_DESKTOP HMODULE directwrite_lib; +#endif IDWriteFactory *factory; IDWriteGdiInterop *gdi_interop; } ProviderPrivate; @@ -389,7 +391,9 @@ static void destroy_provider(void *priv) ProviderPrivate *provider_priv = (ProviderPrivate *)priv; provider_priv->gdi_interop->lpVtbl->Release(provider_priv->gdi_interop); provider_priv->factory->lpVtbl->Release(provider_priv->factory); +#if ASS_WINAPI_DESKTOP FreeLibrary(provider_priv->directwrite_lib); +#endif free(provider_priv); } @@ -726,7 +730,15 @@ static ASS_FontProviderFuncs directwrite_callbacks = { .get_font_index = get_font_index, }; -typedef HRESULT (WINAPI *DWriteCreateFactoryFn)( +#if ASS_WINAPI_DESKTOP +typedef HRESULT (WINAPI *DWriteCreateFactoryFn) +#else +// LoadLibrary is forbidden in WinRT/UWP apps, so use DirectWrite directly. +// These apps cannot run on older Windows that lacks DirectWrite, +// so we lose nothing. +HRESULT WINAPI DWriteCreateFactory +#endif +( DWRITE_FACTORY_TYPE factoryType, REFIID iid, IUnknown **factory @@ -747,22 +759,23 @@ ASS_FontProvider *ass_directwrite_add_provider(ASS_Library *lib, IDWriteFactory *dwFactory = NULL; IDWriteGdiInterop *dwGdiInterop = NULL; ASS_FontProvider *provider = NULL; - DWriteCreateFactoryFn DWriteCreateFactoryPtr = NULL; ProviderPrivate *priv = NULL; +#if ASS_WINAPI_DESKTOP HMODULE directwrite_lib = LoadLibraryW(L"Dwrite.dll"); if (!directwrite_lib) goto cleanup; - DWriteCreateFactoryPtr = + DWriteCreateFactoryFn DWriteCreateFactory = (DWriteCreateFactoryFn)(void *)GetProcAddress(directwrite_lib, "DWriteCreateFactory"); - if (!DWriteCreateFactoryPtr) + if (!DWriteCreateFactory) goto cleanup; +#endif - hr = DWriteCreateFactoryPtr(DWRITE_FACTORY_TYPE_SHARED, - &IID_IDWriteFactory, - (IUnknown **) (&dwFactory)); + hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, + &IID_IDWriteFactory, + (IUnknown **) (&dwFactory)); if (FAILED(hr) || !dwFactory) { ass_msg(lib, MSGL_WARN, "Failed to initialize directwrite."); dwFactory = NULL; @@ -781,7 +794,9 @@ ASS_FontProvider *ass_directwrite_add_provider(ASS_Library *lib, if (!priv) goto cleanup; +#if ASS_WINAPI_DESKTOP priv->directwrite_lib = directwrite_lib; +#endif priv->factory = dwFactory; priv->gdi_interop = dwGdiInterop; @@ -798,8 +813,10 @@ cleanup: dwGdiInterop->lpVtbl->Release(dwGdiInterop); if (dwFactory) dwFactory->lpVtbl->Release(dwFactory); +#if ASS_WINAPI_DESKTOP if (directwrite_lib) FreeLibrary(directwrite_lib); +#endif return NULL; } diff --git a/libass/ass_directwrite.h b/libass/ass_directwrite.h index bb1159c..a14b951 100644 --- a/libass/ass_directwrite.h +++ b/libass/ass_directwrite.h @@ -22,6 +22,13 @@ #ifndef ASS_DIRECTWRITE_H #define ASS_DIRECTWRITE_H +#ifdef WINAPI_FAMILY +#include <winapifamily.h> +#define ASS_WINAPI_DESKTOP WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#else +#define ASS_WINAPI_DESKTOP 1 +#endif + ASS_FontProvider * ass_directwrite_add_provider(ASS_Library *lib, ASS_FontSelector *selector, const char *config, FT_Library ftlib); |