[PATCH 1/8] gdi32: Implement AddFontMemResourceEx with temp files.

Rémi Bernon rbernon at codeweavers.com
Wed Sep 9 05:21:57 CDT 2020


This makes WineEngAddFontMemResourceEx, as well as the support for
loading font face from memory in freetype.c, obsolete.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/gdi32/font.c        | 68 +++++++++++++++++++++++++----------
 dlls/gdi32/freetype.c    | 78 ++++++++--------------------------------
 dlls/gdi32/gdi_private.h |  3 +-
 3 files changed, 65 insertions(+), 84 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index e099bec5e81..e176752c2ce 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3749,7 +3749,7 @@ fail:
  */
 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
 {
-    int ret = WineEngAddFontResourceEx(str, fl, pdv);
+    int ret = WineEngAddFontResourceEx( str, fl, pdv, FALSE );
     WCHAR *filename;
     BOOL hidden;
 
@@ -3771,7 +3771,7 @@ INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
         else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
         {
             if (hidden) fl |= FR_PRIVATE | FR_NOT_ENUM;
-            ret = WineEngAddFontResourceEx( filename, fl, pdv );
+            ret = WineEngAddFontResourceEx( filename, fl, pdv, FALSE );
             HeapFree( GetProcessHeap(), 0, filename );
         }
     }
@@ -3799,8 +3799,13 @@ BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
  */
 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
 {
-    HANDLE ret;
-    DWORD num_fonts;
+    static const WCHAR tmpfmt_w[] = {'%', 's', '\\', 'w', 'i', 'n', 'e', '-', 'f',
+                                     'o', 'n', 't',  '-', '%', '#', 'x', '-', '%',
+                                     '#', 'x', '.',  't', 'm', 'p', 0};
+    HANDLE file;
+    WCHAR tmppath_w[MAX_PATH], filename_w[MAX_PATH];
+    DWORD written;
+    LUID luid;
 
     if (!pbFont || !cbFont || !pcFonts)
     {
@@ -3808,22 +3813,38 @@ HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD
         return NULL;
     }
 
-    ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
-    if (ret)
+    __TRY { *pcFonts = 0; }
+    __EXCEPT_PAGE_FAULT
     {
-        __TRY
-        {
-            *pcFonts = num_fonts;
-        }
-        __EXCEPT_PAGE_FAULT
-        {
-            WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
-            RemoveFontMemResourceEx(ret);
-            ret = 0;
-        }
-        __ENDTRY
+        WARN( "page fault while writing to *pcFonts (%p)\n", pcFonts );
+        return NULL;
     }
-    return ret;
+    __ENDTRY
+
+    GetTempPathW( MAX_PATH, tmppath_w );
+    if (!AllocateLocallyUniqueId( &luid )) return NULL;
+    sprintfW( filename_w, tmpfmt_w, tmppath_w, luid.LowPart, luid.HighPart );
+    TRACE( "writing font to temporary %s\n", debugstr_w(filename_w) );
+
+    file = CreateFileW( filename_w, GENERIC_WRITE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS,
+                        FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL );
+    if (file == INVALID_HANDLE_VALUE) return NULL;
+
+    if (WriteFile( file, pbFont, cbFont, &written, NULL ) && written == cbFont &&
+        GetFinalPathNameByHandleW( file, filename_w, MAX_PATH, FILE_NAME_NORMALIZED ))
+        *pcFonts = WineEngAddFontResourceEx( filename_w, FR_PRIVATE, NULL, TRUE );
+
+    if (*pcFonts == 0)
+    {
+        CloseHandle( file );
+        return NULL;
+    }
+
+    /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
+     * For now return something unique but quite random
+     */
+    TRACE( "Returning handle %lx\n", ((INT_PTR)file) ^ 0x87654321 );
+    return (HANDLE)(((INT_PTR)file) ^ 0x87654321);
 }
 
 /***********************************************************************
@@ -3831,7 +3852,16 @@ HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD
  */
 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
 {
-    FIXME("(%p) stub\n", fh);
+    HANDLE file = (HANDLE)(((INT_PTR)fh) ^ 0x87654321);
+    WCHAR filename_w[MAX_PATH];
+
+    TRACE( "(%p)\n", fh );
+    if (!fh) return TRUE;
+
+    if (GetFinalPathNameByHandleW( file, filename_w, MAX_PATH, FILE_NAME_NORMALIZED ))
+        WineEngRemoveFontResourceEx( filename_w, FR_PRIVATE, NULL );
+
+    CloseHandle( file );
     return TRUE;
 }
 
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index cf53f148ad1..bdd8d97b16d 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -295,6 +295,7 @@ typedef struct tagFace {
 #define ADDFONT_ADD_TO_CACHE  0x04
 #define ADDFONT_ADD_RESOURCE  0x08  /* added through AddFontResource */
 #define ADDFONT_VERTICAL_FONT 0x10
+#define ADDFONT_ADD_MEMRESOURCE 0x20 /* added through AddFontMemResource */
 #define ADDFONT_AA_FLAGS(flags) ((flags) << 16)
 
 typedef struct tagFamily {
@@ -1044,8 +1045,7 @@ static Face *find_face_from_filename(const WCHAR *file_name, const WCHAR *face_n
         face_list = get_face_list_from_family(family);
         LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
         {
-            if (!face->file)
-                continue;
+            if (face->flags & ADDFONT_ADD_MEMRESOURCE) continue;
             file = strrchrW(face->file, '/');
             if(!file)
                 file = face->file;
@@ -2592,8 +2592,7 @@ static void populate_system_links(const WCHAR *name, const WCHAR *const *values)
             face_list = get_face_list_from_family(family);
             LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
             {
-                if (!face->file)
-                    continue;
+                if (face->flags & ADDFONT_ADD_MEMRESOURCE) continue;
                 file = strrchrW(face->file, '/');
                 if (!file)
                     file = face->file;
@@ -3327,7 +3326,7 @@ static void delete_external_font_keys(void)
  *    WineEngAddFontResourceEx
  *
  */
-INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
+INT WineEngAddFontResourceEx( LPCWSTR file, DWORD flags, PVOID pdv, BOOL mem_resource )
 {
     WCHAR path[MAX_PATH];
     INT ret = 0;
@@ -3337,6 +3336,7 @@ INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
     if (ft_handle)  /* do it only if we have freetype up and running */
     {
         DWORD addfont_flags = ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE;
+        if (mem_resource) addfont_flags |= ADDFONT_ADD_MEMRESOURCE;
 
         EnterCriticalSection( &freetype_cs );
 
@@ -3346,12 +3346,12 @@ INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
         if (!ret && !strchrW(file, '\\')) {
             /* Try in %WINDIR%/fonts, needed for Fotobuch Designer */
             get_winfonts_dir_path( file, path );
-            ret = add_font_resource( path, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE );
+            ret = add_font_resource( path, addfont_flags & ~ADDFONT_ADD_TO_CACHE );
             /* Try in datadir/fonts (or builddir/fonts), needed for Magic the Gathering Online */
             if (!ret)
             {
                 get_data_dir_path( file, path );
-                ret = add_font_resource( path, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE );
+                ret = add_font_resource( path, addfont_flags & ~ADDFONT_ADD_TO_CACHE );
             }
         }
 
@@ -3360,42 +3360,6 @@ INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
     return ret;
 }
 
-/*************************************************************
- *    WineEngAddFontMemResourceEx
- *
- */
-HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
-{
-    GDI_CheckNotLock();
-
-    if (ft_handle)  /* do it only if we have freetype up and running */
-    {
-        PVOID pFontCopy = HeapAlloc(GetProcessHeap(), 0, cbFont);
-
-        TRACE("Copying %d bytes of data from %p to %p\n", cbFont, pbFont, pFontCopy);
-        memcpy(pFontCopy, pbFont, cbFont);
-
-        EnterCriticalSection( &freetype_cs );
-        *pcFonts = AddFontToList(NULL, pFontCopy, cbFont, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE);
-        LeaveCriticalSection( &freetype_cs );
-
-        if (*pcFonts == 0)
-        {
-            TRACE("AddFontToList failed\n");
-            HeapFree(GetProcessHeap(), 0, pFontCopy);
-            return 0;
-        }
-        /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
-         * For now return something unique but quite random
-         */
-        TRACE("Returning handle %lx\n", ((INT_PTR)pFontCopy)^0x87654321);
-        return (HANDLE)(((INT_PTR)pFontCopy)^0x87654321);
-    }
-
-    *pcFonts = 0;
-    return 0;
-}
-
 /*************************************************************
  *    WineEngRemoveFontResourceEx
  *
@@ -5519,25 +5483,19 @@ static const VOID * get_GSUB_vert_feature(const GdiFont *font)
 static void fill_fileinfo_from_face( GdiFont *font, Face *face )
 {
     WIN32_FILE_ATTRIBUTE_DATA info;
-    int len;
+    SIZE_T path_size;
 
-    if (!face->file)
-    {
-        font->fileinfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*font->fileinfo));
-        font->fileinfo->size.QuadPart = face->font_data_size;
-        return;
-    }
-
-    len = strlenW(face->file);
-    font->fileinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*font->fileinfo) + len * sizeof(WCHAR));
+    path_size = strlenW( face->file ) * sizeof(WCHAR);
+    font->fileinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*font->fileinfo) + path_size );
     if (GetFileAttributesExW(face->file, GetFileExInfoStandard, &info))
     {
         font->fileinfo->writetime = info.ftLastWriteTime;
         font->fileinfo->size.QuadPart = (LONGLONG)info.nFileSizeHigh << 32 | info.nFileSizeLow;
         strcpyW(font->fileinfo->path, face->file);
     }
-    else
-        memset(font->fileinfo, 0, sizeof(*font->fileinfo) + len * sizeof(WCHAR));
+
+    /* clear the path if the face was supposed to be loaded from memory */
+    if (face->flags & ADDFONT_ADD_MEMRESOURCE) memset( font->fileinfo->path, 0, path_size );
 }
 
 /*************************************************************
@@ -9292,9 +9250,9 @@ BOOL WineEngInit(void)
     return FALSE;
 }
 
-INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
+INT WineEngAddFontResourceEx( LPCWSTR file, DWORD flags, PVOID pdv, BOOL mem_resource )
 {
-    FIXME("(%s, %x, %p): stub\n", debugstr_w(file), flags, pdv);
+    FIXME( "(%s, %x, %p, %d): stub\n", debugstr_w(file), flags, pdv, mem_resource );
     return 1;
 }
 
@@ -9304,12 +9262,6 @@ INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
     return TRUE;
 }
 
-HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
-{
-    FIXME("(%p, %u, %p, %p): stub\n", pbFont, cbFont, pdv, pcFonts);
-    return NULL;
-}
-
 BOOL WineEngCreateScalableFontResource( DWORD hidden, LPCWSTR resource,
                                         LPCWSTR font_file, LPCWSTR font_path )
 {
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 6b2502c4586..51398653bd4 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -302,8 +302,7 @@ struct char_width_info
     INT unk;   /* unknown */
 };
 
-extern INT WineEngAddFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
-extern HANDLE WineEngAddFontMemResourceEx(PVOID, DWORD, PVOID, LPDWORD) DECLSPEC_HIDDEN;
+extern INT WineEngAddFontResourceEx( LPCWSTR, DWORD, PVOID, BOOL ) DECLSPEC_HIDDEN;
 extern BOOL WineEngCreateScalableFontResource(DWORD, LPCWSTR, LPCWSTR, LPCWSTR) DECLSPEC_HIDDEN;
 extern BOOL WineEngInit(void) DECLSPEC_HIDDEN;
 extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
-- 
2.28.0




More information about the wine-devel mailing list