From ab9b9cf254a7871f4f8cdee386971f0ba5c58e13 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 11 Jul 2015 19:33:44 +0200 Subject: directwrite: dynamically load dwrite.dll --- configure.ac | 5 +--- libass/ass_directwrite.cpp | 64 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index 26c2c37..61a8533 100644 --- a/configure.ac +++ b/configure.ac @@ -180,20 +180,17 @@ fi if test x$enable_directwrite != xno; then AC_LANG_PUSH([C++]) CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions" -OLDLIBS="$LIBS" # Linking to DirectWrite directly only works from Windows -LIBS="$LIBS -ldwrite" AC_MSG_CHECKING([for DIRECTWRITE]) AC_LINK_IFELSE([ AC_LANG_PROGRAM( [[#include ]], - [[DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), NULL);]],) + [[DWRITE_FACTORY_TYPE_SHARED;]],) ], [ AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite]) directwrite=true AC_MSG_RESULT([yes]) ], [ - LIBS="$OLDLIBS" directwrite=false AC_MSG_RESULT([no]) ]) diff --git a/libass/ass_directwrite.cpp b/libass/ass_directwrite.cpp index 37e1cc8..062aa31 100644 --- a/libass/ass_directwrite.cpp +++ b/libass/ass_directwrite.cpp @@ -36,6 +36,11 @@ typedef struct { IDWriteFontFileStream *stream; } FontPrivate; +typedef struct { + HMODULE directwrite_lib; + IDWriteFactory *factory; +} ProviderPrivate; + /** * Custom text renderer class for logging the fonts used. It does not * actually render anything or do anything apart from that. @@ -295,7 +300,10 @@ static int check_glyph(void *data, uint32_t code) */ static void destroy_provider(void *priv) { - ((IDWriteFactory *) priv)->Release(); + ProviderPrivate *provider_priv = (ProviderPrivate *)priv; + provider_priv->factory->Release(); + FreeLibrary(provider_priv->directwrite_lib); + free(provider_priv); } /* @@ -330,7 +338,8 @@ static char *get_fallback(void *priv, ASS_FontProviderMetaData *meta, uint32_t codepoint) { HRESULT hr; - IDWriteFactory *dw_factory = static_cast(priv); + ProviderPrivate *provider_priv = (ProviderPrivate *)priv; + IDWriteFactory *dw_factory = provider_priv->factory; IDWriteTextFormat *text_format = NULL; IDWriteTextLayout *text_layout = NULL; FallbackLogTextRenderer renderer(dw_factory); @@ -579,6 +588,11 @@ static ASS_FontProviderFuncs directwrite_callbacks = { get_fallback }; +typedef HRESULT WINAPI (*DWriteCreateFactoryFn)( + _In_ DWRITE_FACTORY_TYPE factoryType, + _In_ REFIID iid, + _Out_ IUnknown **factory +); /* * Register the directwrite provider. Upon registering @@ -593,19 +607,47 @@ ASS_FontProvider *ass_directwrite_add_provider(ASS_Library *lib, HRESULT hr = S_OK; IDWriteFactory *dwFactory = NULL; ASS_FontProvider *provider = NULL; - - hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - (IUnknown **) (&dwFactory)); - - if (FAILED(hr)) { + DWriteCreateFactoryFn DWriteCreateFactoryPtr = NULL; + ProviderPrivate *priv = NULL; + + HMODULE directwrite_lib = LoadLibraryW(L"Dwrite.dll"); + if (!directwrite_lib) + goto cleanup; + + DWriteCreateFactoryPtr = (DWriteCreateFactoryFn)GetProcAddress(directwrite_lib, + "DWriteCreateFactory"); + if (!DWriteCreateFactoryPtr) + goto cleanup; + + hr = DWriteCreateFactoryPtr(DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + (IUnknown **) (&dwFactory)); + if (FAILED(hr) || !dwFactory) { ass_msg(lib, MSGL_WARN, "Failed to initialize directwrite."); - return NULL; + dwFactory = NULL; + goto cleanup; } - provider = ass_font_provider_new(selector, &directwrite_callbacks, dwFactory); + priv = (ProviderPrivate *)calloc(sizeof(*priv), 1); + if (!priv) + goto cleanup; - scan_fonts(dwFactory, provider); + priv->directwrite_lib = directwrite_lib; + priv->factory = dwFactory; + provider = ass_font_provider_new(selector, &directwrite_callbacks, priv); + if (!provider) + goto cleanup; + scan_fonts(dwFactory, provider); return provider; + +cleanup: + + free(priv); + if (dwFactory) + dwFactory->Release(); + if (directwrite_lib) + FreeLibrary(directwrite_lib); + + return NULL; } -- cgit v1.2.3