Alexandre Julliard : gdi32: Only mmap a given font file once.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Dec 7 07:07:54 CST 2006


Module: wine
Branch: master
Commit: 834d20024bc71462474fd793b7f1d846635b30a6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=834d20024bc71462474fd793b7f1d846635b30a6

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Dec  6 21:31:53 2006 +0100

gdi32: Only mmap a given font file once.

FT_New_Face always creates a new mapping of the font file, so do the
mapping by hand and use FT_New_Memory_Face instead.

---

 dlls/gdi32/freetype.c |   79 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index f77047e..6301a5f 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -29,6 +29,9 @@
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
 #endif
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
 #include <string.h>
 #include <dirent.h>
 #include <stdio.h>
@@ -125,6 +128,7 @@ MAKE_FUNCPTR(FT_Load_Glyph);
 MAKE_FUNCPTR(FT_Matrix_Multiply);
 MAKE_FUNCPTR(FT_MulFix);
 MAKE_FUNCPTR(FT_New_Face);
+MAKE_FUNCPTR(FT_New_Memory_Face);
 MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
 MAKE_FUNCPTR(FT_Outline_Transform);
 MAKE_FUNCPTR(FT_Outline_Translate);
@@ -253,6 +257,7 @@ typedef struct {
 struct tagGdiFont {
     struct list entry;
     FT_Face ft_face;
+    struct font_mapping *mapping;
     LPWSTR name;
     int charset;
     int codepage;
@@ -385,6 +390,18 @@ typedef struct tagFontSubst {
     NameCs to;
 } FontSubst;
 
+struct font_mapping
+{
+    struct list entry;
+    int         refcount;
+    dev_t       dev;
+    ino_t       ino;
+    void       *data;
+    size_t      size;
+};
+
+static struct list mappings_list = LIST_INIT( mappings_list );
+
 static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
 
 static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
@@ -1644,6 +1661,7 @@ BOOL WineEngInit(void)
     LOAD_FUNCPTR(FT_Matrix_Multiply)
     LOAD_FUNCPTR(FT_MulFix)
     LOAD_FUNCPTR(FT_New_Face)
+    LOAD_FUNCPTR(FT_New_Memory_Face)
     LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
     LOAD_FUNCPTR(FT_Outline_Transform)
     LOAD_FUNCPTR(FT_Outline_Translate)
@@ -1867,6 +1885,57 @@ static LONG calc_ppem_for_height(FT_Face
     return ppem;
 }
 
+static struct font_mapping *map_font( const char *name )
+{
+    struct font_mapping *mapping;
+    struct stat st;
+    int fd;
+
+    if ((fd = open( name, O_RDONLY )) == -1) return NULL;
+    if (fstat( fd, &st ) == -1) goto error;
+
+    LIST_FOR_EACH_ENTRY( mapping, &mappings_list, struct font_mapping, entry )
+    {
+        if (mapping->dev == st.st_dev && mapping->ino == st.st_ino)
+        {
+            mapping->refcount++;
+            close( fd );
+            return mapping;
+        }
+    }
+    if (!(mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(*mapping) )))
+        goto error;
+
+    mapping->data = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
+    close( fd );
+
+    if (mapping->data == MAP_FAILED)
+    {
+        HeapFree( GetProcessHeap(), 0, mapping );
+        return NULL;
+    }
+    mapping->refcount = 1;
+    mapping->dev = st.st_dev;
+    mapping->ino = st.st_ino;
+    mapping->size = st.st_size;
+    list_add_tail( &mappings_list, &mapping->entry );
+    return mapping;
+
+error:
+    close( fd );
+    return NULL;
+}
+
+static void unmap_font( struct font_mapping *mapping )
+{
+    if (!--mapping->refcount)
+    {
+        list_remove( &mapping->entry );
+        munmap( mapping->data, mapping->size );
+        HeapFree( GetProcessHeap(), 0, mapping );
+    }
+}
+
 static LONG load_VDMX(GdiFont*, LONG);
 
 static FT_Face OpenFontFile(GdiFont *font, char *file, FT_Long face_index, LONG width, LONG height)
@@ -1875,7 +1944,14 @@ static FT_Face OpenFontFile(GdiFont *fon
     FT_Face ft_face;
 
     TRACE("%s, %ld, %d x %d\n", debugstr_a(file), face_index, width, height);
-    err = pFT_New_Face(library, file, face_index, &ft_face);
+
+    if (!(font->mapping = map_font( file )))
+    {
+        WARN("failed to map %s\n", debugstr_a(file));
+        return 0;
+    }
+
+    err = pFT_New_Memory_Face(library, font->mapping->data, font->mapping->size, face_index, &ft_face);
     if(err) {
         ERR("FT_New_Face rets %d\n", err);
 	return 0;
@@ -1973,6 +2049,7 @@ static void free_font(GdiFont *font)
     }
 
     if (font->ft_face) pFT_Done_Face(font->ft_face);
+    if (font->mapping) unmap_font( font->mapping );
     HeapFree(GetProcessHeap(), 0, font->kern_pairs);
     HeapFree(GetProcessHeap(), 0, font->potm);
     HeapFree(GetProcessHeap(), 0, font->name);




More information about the wine-cvs mailing list