external/freetype/StaticLibrary_freetype.mk    |    1 +
 vcl/unx/generic/glyphs/freetype_glyphcache.cxx |   17 +++++++++++++++++
 2 files changed, 18 insertions(+)

New commits:
commit 1c7e2d295ab58480332442f3a26734a1482a8d82
Author:     Tor Lillqvist <[email protected]>
AuthorDate: Sat Nov 22 00:50:11 2025 +0100
Commit:     Thorsten Behrens <[email protected]>
CommitDate: Tue Dec 2 16:52:09 2025 +0100

    Make the weird FT_Done_MM_Var() trick in vcl work also on Windows
    
    For Windows we build freetype as a static library. But we must build
    freetype with DLL_EXPORT defined so that symbols like FT_Done_MM_Var
    get exported by the DLL into which the static freetype library is
    linked. That is mergedlo.dll or vcllo.dll.
    
    Then in vcl's dlFT_Done_MM_Var() we can't just call
    osl_getAsciiFunctionSymbol() with a nullptr for the first "module"
    parameter and expect it to look through all modules, like dlsym() does
    on Unixes. On Windows, osl_getAsciiFunctionSymbol() calls
    GetProcAddress(), and passing a NULL first parameter to tht is simply
    invalid. We must look for FT_Done_MM_Var in mergedlo.dll, or if that
    isn't loaded, vcllo.dll.
    
    Possibly it would be simpler to just pretend we don't HAVE_DLAPI in
    this case and call FT_Done_MM_Var() directly.
    
    Without this commit, FT_Done_MM_Var will not be found, so the code
    will just call free() instead of FT_Done_MM_Var(), and if built using
    the debugging C library that will lead to a strange assertion failure
    in the C library. With the non-debugging C library it might perhaps
    lead to some odd bug, or just not do whatever proper deallocation of
    resources or something it is that FT_Done_MM_Var() does.
    
    Change-Id: Ia7b726cc7167ba22ea8f3263ad85f8cd4ac5c483
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194608
    Reviewed-by: Thorsten Behrens <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/external/freetype/StaticLibrary_freetype.mk 
b/external/freetype/StaticLibrary_freetype.mk
index 978a904d62ba..4dc6a3ad634d 100644
--- a/external/freetype/StaticLibrary_freetype.mk
+++ b/external/freetype/StaticLibrary_freetype.mk
@@ -24,6 +24,7 @@ $(eval $(call gb_StaticLibrary_add_defs,freetype,\
        -DDLG_STATIC \
        -DZ_PREFIX \
        -DFT2_BUILD_LIBRARY \
+       -DDLL_EXPORT \
        -DFT_DEBUG_LOGGING \
 ))
 
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx 
b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
index aa6da15885ff..8ebff2ada0a5 100644
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
@@ -183,9 +183,26 @@ namespace
     {
 #if !HAVE_DLAPI
         FT_Done_MM_Var(library, amaster);
+#else
+#ifdef _WIN32
+        // Unlike on Unixes, we can't pass a NULL module parameter to
+        // osl_getAsciiFunctionSymbol(), i.e. GetProcAddress(), and
+        // have it look through all modules loaded, like dlsym() does.
+        // Instead, we "know" that FT_Done_MM_Var will wither be in
+        // mergedlo.dll or vcllo.dll.
+        void(*func)(FT_Library, FT_MM_Var*) = nullptr;
+        oslModule module;
+        if (osl_getModuleHandle((u"mergedlo.dll"_ustr).pData, &module) ||
+            osl_getModuleHandle((u"vcllo.dll"_ustr).pData, &module))
+            func = reinterpret_cast<void(*)(FT_Library, FT_MM_Var*)>(
+                osl_getAsciiFunctionSymbol(module, "FT_Done_MM_Var"));
+        // If FT_Done_MM_Var is not found, we will crash or something,
+        // at least in a build with the debugging C runtime, as
+        // calling free() below is very wrong, I think.
 #else
         static auto func = reinterpret_cast<void(*)(FT_Library, FT_MM_Var*)>(
             osl_getAsciiFunctionSymbol(nullptr, "FT_Done_MM_Var"));
+#endif
         if (func)
             func(library, amaster);
         else

Reply via email to