summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2021-06-26 18:16:41 +0300
committerOleg Oshmyan <chortos@inbox.lv>2021-07-10 02:36:31 +0300
commit2a2d718e0fd6d47072566e519744634d93621353 (patch)
tree4562f6f4b7bb908061ab56d7f0dfe20da94b4fc6
parent979d7b890af66363dcdef2ae814cebe4053f2898 (diff)
downloadlibass-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.ac23
-rw-r--r--libass/ass_directwrite.c31
-rw-r--r--libass/ass_directwrite.h7
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);