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