[PATCH 1/6] gdi32: Introduce struct unix_face as a ft_face wrapper.

Rémi Bernon rbernon at codeweavers.com
Tue Dec 1 08:54:46 CST 2020


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

So I'm sending this last series now as it seems everybody rushes for
their patches to go in before the freeze, and as it should not have any
conflict with 196676-196680, or with the other series on the ML as it's
mostly only touching freetype.c, it'll leave more time for review.

With 196676-196680 applied, this brings some ~250ms improvement to
prefix startup (from 1.25s to 1s runtime on average for "cmd /c exit"),
and 50ms improvement to process startup (from 0.15s to 0.1s on average).

(I probably changed my test setup a bit and upgraded some font packages
since the other series so it's not exactly comparable with the previous
numbers, but the improvement indicated was measured in a consistent way
with / without this series applied)

 dlls/gdi32/freetype.c | 124 +++++++++++++++++++++++++++++++-----------
 1 file changed, 91 insertions(+), 33 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 1ee02795bed..00334b470c8 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -1092,65 +1092,123 @@ fail:
     return NULL;
 }
 
+struct unix_face
+{
+    FT_Face ft_face;
+    BOOL scalable;
+    UINT num_faces;
+    WCHAR *family_name;
+    WCHAR *second_name;
+};
+
+static struct unix_face *unix_face_create( const char *unix_name, void *data_ptr, DWORD data_size,
+                                           UINT face_index, DWORD flags )
+{
+    struct unix_face *This;
+    struct stat st;
+    int fd;
+
+    TRACE( "unix_name %s, face_index %u, data_ptr %p, data_size %u, flags %#x\n",
+           unix_name, face_index, data_ptr, data_size, flags );
+
+    if (unix_name)
+    {
+        if ((fd = open( unix_name, O_RDONLY )) == -1) return NULL;
+        if (fstat( fd, &st ) == -1)
+        {
+            close( fd );
+            return NULL;
+        }
+        data_size = st.st_size;
+        data_ptr = mmap( NULL, data_size, PROT_READ, MAP_PRIVATE, fd, 0 );
+        close( fd );
+        if (data_ptr == MAP_FAILED) return NULL;
+    }
+
+    if (!(This = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This) ))) goto done;
+
+    if (!(This->ft_face = new_ft_face( unix_name, data_ptr, data_size, face_index, flags & ADDFONT_ALLOW_BITMAP )))
+    {
+        RtlFreeHeap( GetProcessHeap(), 0, This );
+        This = NULL;
+    }
+    else
+    {
+        This->scalable = FT_IS_SCALABLE( This->ft_face );
+        This->num_faces = This->ft_face->num_faces;
+
+        This->family_name = ft_face_get_family_name( This->ft_face, system_lcid );
+        This->second_name = ft_face_get_family_name( This->ft_face, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) );
+
+        /* try to find another secondary name, preferring the lowest langids */
+        if (!RtlCompareUnicodeStrings( This->family_name, lstrlenW( This->family_name ),
+                                       This->second_name, lstrlenW( This->second_name ), TRUE ))
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, This->second_name );
+            This->second_name = ft_face_get_family_name( This->ft_face, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) );
+            if (!RtlCompareUnicodeStrings( This->family_name, lstrlenW( This->family_name ),
+                                           This->second_name, lstrlenW( This->second_name ), TRUE ))
+            {
+                RtlFreeHeap( GetProcessHeap(), 0, This->second_name );
+                This->second_name = NULL;
+            }
+        }
+    }
+
+done:
+    if (unix_name) munmap( data_ptr, data_size );
+    return This;
+}
+
+static void unix_face_destroy( struct unix_face *This )
+{
+    pFT_Done_Face( This->ft_face );
+    RtlFreeHeap( GetProcessHeap(), 0, This->second_name );
+    RtlFreeHeap( GetProcessHeap(), 0, This->family_name );
+    RtlFreeHeap( GetProcessHeap(), 0, This );
+}
+
 static int add_unix_face( const char *unix_name, const WCHAR *file, void *data_ptr, SIZE_T data_size,
                           DWORD face_index, DWORD flags, DWORD *num_faces )
 {
+    struct unix_face *unix_face;
     struct bitmap_font_size size;
     FONTSIGNATURE fs;
-    FT_Face ft_face;
-    WCHAR *family_name, *second_name, *style_name, *full_name;
+    WCHAR *style_name, *full_name;
     int ret;
 
     if (num_faces) *num_faces = 0;
 
-    if (!(ft_face = new_ft_face( unix_name, data_ptr, data_size, face_index, flags & ADDFONT_ALLOW_BITMAP )))
+    if (!(unix_face = unix_face_create( unix_name, data_ptr, data_size, face_index, flags )))
         return 0;
 
-    if (ft_face->family_name[0] == '.') /* Ignore fonts with names beginning with a dot */
+    if (unix_face->family_name[0] == '.') /* Ignore fonts with names beginning with a dot */
     {
         TRACE("Ignoring %s since its family name begins with a dot\n", debugstr_a(unix_name));
-        pFT_Done_Face( ft_face );
+        unix_face_destroy( unix_face );
         return 0;
     }
 
-    family_name = ft_face_get_family_name( ft_face, system_lcid );
-    second_name = ft_face_get_family_name( ft_face, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) );
-    style_name = ft_face_get_style_name( ft_face, system_lcid );
-    full_name = ft_face_get_full_name( ft_face, system_lcid );
-
-    /* try to find another secondary name, preferring the lowest langids */
-    if (!RtlCompareUnicodeStrings( family_name, lstrlenW(family_name),
-                                   second_name, lstrlenW(second_name), TRUE ))
-    {
-        RtlFreeHeap( GetProcessHeap(), 0, second_name );
-        second_name = ft_face_get_family_name( ft_face, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) );
-        if (!RtlCompareUnicodeStrings( family_name, lstrlenW(family_name),
-                                       second_name, lstrlenW(second_name), TRUE ))
-        {
-            RtlFreeHeap( GetProcessHeap(), 0, second_name );
-            second_name = NULL;
-        }
-    }
+    style_name = ft_face_get_style_name( unix_face->ft_face, system_lcid );
+    full_name = ft_face_get_full_name( unix_face->ft_face, system_lcid );
 
-    get_fontsig( ft_face, &fs );
-    if (!FT_IS_SCALABLE( ft_face )) get_bitmap_size( ft_face, &size );
+    get_fontsig( unix_face->ft_face, &fs );
+    if (!unix_face->scalable) get_bitmap_size( unix_face->ft_face, &size );
     if (!HIWORD( flags )) flags |= ADDFONT_AA_FLAGS( default_aa_flags );
 
-    ret = callback_funcs->add_gdi_face( family_name, second_name, style_name, full_name, file,
-                                        data_ptr, data_size, face_index, fs, get_ntm_flags( ft_face ),
-                                        get_font_version( ft_face ), flags,
-                                        FT_IS_SCALABLE(ft_face) ? NULL : &size );
+    ret = callback_funcs->add_gdi_face( unix_face->family_name, unix_face->second_name, style_name, full_name,
+                                        file, data_ptr, data_size, face_index, fs, get_ntm_flags( unix_face->ft_face ),
+                                        get_font_version( unix_face->ft_face ), flags,
+                                        unix_face->scalable ? NULL : &size );
 
     TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
           fs.fsCsb[0], fs.fsCsb[1], fs.fsUsb[0], fs.fsUsb[1], fs.fsUsb[2], fs.fsUsb[3]);
 
-    RtlFreeHeap( GetProcessHeap(), 0, family_name );
-    RtlFreeHeap( GetProcessHeap(), 0, second_name );
     RtlFreeHeap( GetProcessHeap(), 0, style_name );
     RtlFreeHeap( GetProcessHeap(), 0, full_name );
 
-    if (num_faces) *num_faces = ft_face->num_faces;
-    pFT_Done_Face( ft_face );
+    if (num_faces) *num_faces = unix_face->num_faces;
+    unix_face_destroy( unix_face );
     return ret;
 }
 
-- 
2.29.2




More information about the wine-devel mailing list