[2/5] gdi32: Introduce a list of font file/data. (try 2)

Kusanagi Kouichi slash at ac.auone-net.jp
Tue Apr 24 05:51:21 CDT 2012


Signed-off-by: Kusanagi Kouichi <slash at ac.auone-net.jp>
---
 dlls/gdi32/freetype.c |  181 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 122 insertions(+), 59 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index b98a843..93d4689 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -256,13 +256,21 @@ struct enum_data
     DWORD type;
 };
 
+typedef struct tagFont
+{
+    struct list entry;
+    char *file;
+    void *data_ptr;
+    DWORD data_size;
+    struct list faces;
+} Font;
+
 typedef struct tagFace {
     struct list entry;
     WCHAR *StyleName;
     WCHAR *FullName;
-    char *file;
-    void *font_data_ptr;
-    DWORD font_data_size;
+    const Font *font;
+    struct list font_entry;
     FT_Long face_index;
     FONTSIGNATURE fs;
     DWORD ntmFlags;
@@ -379,6 +387,8 @@ static struct list font_subst_list = LIST_INIT(font_subst_list);
 
 static struct list family_list = LIST_INIT(family_list);
 
+static struct list font_list = LIST_INIT(font_list);
+
 struct freetype_physdev
 {
     struct gdi_physdev dev;
@@ -916,11 +926,11 @@ 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)
+            if (!face->font->file)
                 continue;
-            file = strrchr(face->file, '/');
+            file = strrchr(face->font->file, '/');
             if(!file)
-                file = face->file;
+                file = face->font->file;
             else
                 file++;
             if(!strcasecmp(file, file_nameA))
@@ -962,6 +972,22 @@ static Family *find_family_from_any_name(const WCHAR *name)
     return NULL;
 }
 
+static Font *find_font_path(const char *file)
+{
+    if (file != NULL)
+    {
+        Font *font;
+
+        LIST_FOR_EACH_ENTRY(font, &font_list, Font, entry)
+        {
+            if (font->file != NULL && strcmp(font->file, file) == 0)
+                return font;
+        }
+    }
+
+    return NULL;
+}
+
 static void DumpSubstList(void)
 {
     FontSubst *psub;
@@ -1199,7 +1225,6 @@ static inline BOOL faces_equal( const Face *f1, const Face *f2 )
 
 static inline void free_face( Face *face )
 {
-    HeapFree( GetProcessHeap(), 0, face->file );
     HeapFree( GetProcessHeap(), 0, face->StyleName );
     HeapFree( GetProcessHeap(), 0, face->FullName );
     HeapFree( GetProcessHeap(), 0, face->cached_enum_data );
@@ -1245,6 +1270,8 @@ static BOOL insert_face_in_family_list( Face *face, Family *family )
 {
     Face *cursor;
 
+    face->family = family;
+
     LIST_FOR_EACH_ENTRY( cursor, &family->faces, Face, entry )
     {
         if (faces_equal( face, cursor ))
@@ -1256,28 +1283,25 @@ static BOOL insert_face_in_family_list( Face *face, Family *family )
             if (face->font_version <= cursor->font_version)
             {
                 TRACE("Original font %s is newer so skipping %s\n",
-                      debugstr_a(cursor->file), debugstr_a(face->file));
+                      debugstr_a(cursor->font->file), debugstr_a(face->font->file));
                 return FALSE;
             }
             else
             {
                 TRACE("Replacing original %s with %s\n",
-                      debugstr_a(cursor->file), debugstr_a(face->file));
+                      debugstr_a(cursor->font->file), debugstr_a(face->font->file));
                 list_add_before( &cursor->entry, &face->entry );
-                face->family = family;
                 list_remove( &cursor->entry);
-                free_face( cursor );
                 return TRUE;
             }
         }
         else
-            TRACE("Adding new %s\n", debugstr_a(face->file));
+            TRACE("Adding new %s\n", debugstr_a(face->font->file));
 
         if (style_order( face ) < style_order( cursor )) break;
     }
 
     list_add_before( &cursor->entry, &face->entry );
-    face->family = family;
     return TRUE;
 }
 
@@ -1319,13 +1343,28 @@ static void load_face(HKEY hkey_face, WCHAR *face_name, Family *family)
        key of a bunch of non-scalable strikes */
     if(RegQueryValueExA(hkey_face, "File Name", NULL, NULL, NULL, &needed) == ERROR_SUCCESS)
     {
-        Face *face;
-        face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
-        face->cached_enum_data = NULL;
+        Face * const face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
+        char * const file = HeapAlloc(GetProcessHeap(), 0, needed);
+        Font *font;
 
-        face->file = HeapAlloc(GetProcessHeap(), 0, needed);
-        RegQueryValueExA(hkey_face, "File Name", NULL, NULL, (BYTE*)face->file, &needed);
+        RegQueryValueExA(hkey_face, "File Name", NULL, NULL, (BYTE*)file, &needed);
+        font = find_font_path(file);
+        if (font == NULL)
+        {
+            font = HeapAlloc(GetProcessHeap(), 0, sizeof *font);
+            font->file = file;
+            font->data_ptr = NULL;
+            font->data_size = 0;
+            list_init(&font->faces);
+            list_add_tail(&font_list, &font->entry);
+        }
+        else
+        {
+            HeapFree(GetProcessHeap(), 0, file);
+        }
 
+        face->font = font;
+        face->cached_enum_data = NULL;
         face->StyleName = strdupW(face_name);
 
         if(RegQueryValueExW(hkey_face, face_full_name_value, NULL, NULL, NULL, &needed) == ERROR_SUCCESS)
@@ -1370,6 +1409,7 @@ static void load_face(HKEY hkey_face, WCHAR *face_name, Family *family)
               face->fs.fsUsb[2], face->fs.fsUsb[3]);
 
         insert_face_in_family_list(face, family);
+        list_add_tail(&font->faces, &face->font_entry);
 
         TRACE("Added font %s %s\n", debugstr_w(family->FamilyName), debugstr_w(face->StyleName));
     }
@@ -1506,7 +1546,7 @@ static void add_face_to_cache(Face *face)
     if(!face->scalable)
         HeapFree(GetProcessHeap(), 0, face_key_name);
 
-    RegSetValueExA(hkey_face, "File Name", 0, REG_BINARY, (BYTE*)face->file, strlen(face->file) + 1);
+    RegSetValueExA(hkey_face, "File Name", 0, REG_BINARY, (BYTE*)face->font->file, strlen(face->font->file) + 1);
     if (face->FullName)
         RegSetValueExW(hkey_face, face_full_name_value, 0, REG_SZ, (BYTE*)face->FullName,
                        (strlenW(face->FullName) + 1) * sizeof(WCHAR));
@@ -1707,7 +1747,7 @@ static inline void get_fontsig( FT_Face ft_face, FONTSIGNATURE *fs )
 #define ADDFONT_FORCE_BITMAP  0x02
 #define ADDFONT_ADD_TO_CACHE  0x04
 
-static Face *create_face( FT_Face ft_face, FT_Long face_index, const char *file, void *font_data_ptr, DWORD font_data_size,
+static Face *create_face( FT_Face ft_face, FT_Long face_index, const Font *font,
                           DWORD flags, BOOL vertical )
 {
     Face *face = HeapAlloc( GetProcessHeap(), 0, sizeof(*face) );
@@ -1715,19 +1755,9 @@ static Face *create_face( FT_Face ft_face, FT_Long face_index, const char *file,
 
     face->StyleName = towstr( CP_ACP, ft_face->style_name );
     face->FullName = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, TT_MS_LANGID_ENGLISH_UNITED_STATES );
-    if (file)
-    {
-        face->file = strdupA( file );
-        face->font_data_ptr = NULL;
-        face->font_data_size = 0;
-    }
-    else
-    {
-        face->file = NULL;
-        face->font_data_ptr = font_data_ptr;
-        face->font_data_size = font_data_size;
-    }
 
+    list_init(&face->entry);
+    face->font = font;
     face->face_index = face_index;
     get_fontsig( ft_face, &face->fs );
     face->ntmFlags = get_ntm_flags( ft_face );
@@ -1765,19 +1795,17 @@ static Face *create_face( FT_Face ft_face, FT_Long face_index, const char *file,
     return face;
 }
 
-static void AddFaceToList(FT_Face ft_face, const char *file, void *font_data_ptr, DWORD font_data_size,
+static void AddFaceToList(FT_Face ft_face, Font *font,
                           FT_Long face_index, DWORD flags, BOOL vertical)
 {
     Face *face;
     Family *family;
 
-    face = create_face( ft_face, face_index, file, font_data_ptr, font_data_size, flags, vertical );
+    face = create_face( ft_face, face_index, font, flags, vertical );
+    list_add_tail(&font->faces, &face->font_entry);
     family = get_family( ft_face, vertical );
     if (!insert_face_in_family_list( face, family ))
-    {
-        free_face( face );
         return;
-    }
 
     if (flags & ADDFONT_ADD_TO_CACHE)
         add_face_to_cache( face );
@@ -1864,6 +1892,7 @@ fail:
 
 static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_size, DWORD flags)
 {
+    Font *font;
     FT_Face ft_face;
     FT_Long face_index = 0, num_faces;
     INT ret = 0;
@@ -1892,6 +1921,35 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
     }
 #endif /* HAVE_CARBON_CARBON_H */
 
+    font = find_font_path(file);
+    if (font != NULL)
+    {
+        const struct list *face;
+
+        TRACE("found %s\n", debugstr_a(file));
+        LIST_FOR_EACH(face, &font->faces)
+            ++ret;
+        return ret;
+    }
+
+    font = HeapAlloc(GetProcessHeap(), 0, sizeof *font);
+    if (font == NULL)
+        return 0;
+
+    if (file)
+    {
+        font->file = strdupA( file );
+        font->data_ptr = NULL;
+        font->data_size = 0;
+    }
+    else
+    {
+        font->file = NULL;
+        font->data_ptr = font_data_ptr;
+        font->data_size = font_data_size;
+    }
+    list_init(&font->faces);
+
     do {
         ft_face = new_ft_face( file, font_data_ptr, font_data_size, face_index, flags & ADDFONT_FORCE_BITMAP );
         if (!ft_face) return 0;
@@ -1903,18 +1961,20 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
             return 0;
         }
 
-        AddFaceToList(ft_face, file, font_data_ptr, font_data_size, face_index, flags, FALSE);
+        AddFaceToList(ft_face, font, face_index, flags, FALSE);
         ++ret;
 
         if (FT_HAS_VERTICAL(ft_face))
         {
-            AddFaceToList(ft_face, file, font_data_ptr, font_data_size, face_index, flags, TRUE);
+            AddFaceToList(ft_face, font, face_index, flags, TRUE);
             ++ret;
         }
 
 	num_faces = ft_face->num_faces;
 	pFT_Done_Face(ft_face);
     } while(num_faces > ++face_index);
+
+    list_add_tail(&font_list, &font->entry);
     return ret;
 }
 
@@ -2116,11 +2176,11 @@ 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)
+                if (!face->font->file)
                     continue;
-                file = strrchr(face->file, '/');
+                file = strrchr(face->font->file, '/');
                 if (!file)
-                    file = face->file;
+                    file = face->font->file;
                 else
                     file++;
                 break;
@@ -2141,7 +2201,7 @@ static void populate_system_links(const WCHAR *name, const WCHAR *const *values)
             child_font->font = NULL;
             font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
             font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
-            TRACE("Adding file %s index %ld\n", child_font->face->file, child_font->face->face_index);
+            TRACE("Adding file %s index %ld\n", child_font->face->font->file, child_font->face->face_index);
             list_add_tail(&font_link->links, &child_font->entry);
 
             TRACE("added internal SystemLink for %s to %s in %s\n", debugstr_w(name), debugstr_w(value),debugstr_w(fileW));
@@ -2223,7 +2283,7 @@ static BOOL init_system_links(void)
                 child_font->font = NULL;
                 font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
                 font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
-                TRACE("Adding file %s index %ld\n", child_font->face->file, child_font->face->face_index);
+                TRACE("Adding file %s index %ld\n", child_font->face->font->file, child_font->face->face_index);
                 list_add_tail(&font_link->links, &child_font->entry);
             }
             list_add_tail(&system_links, &font_link->entry);
@@ -2281,7 +2341,7 @@ skip_internal:
         child_font->font = NULL;
         system_font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
         system_font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
-        TRACE("Found Tahoma in %s index %ld\n", child_font->face->file, child_font->face->face_index);
+        TRACE("Found Tahoma in %s index %ld\n", child_font->face->font->file, child_font->face->face_index);
         list_add_tail(&system_font_link->links, &child_font->entry);
     }
     font_link = find_font_link(Tahoma);
@@ -2669,13 +2729,13 @@ static void update_reg_entries(void)
             }
             strcatW(valueW, TrueType);
 
-            file = wine_get_dos_file_name(face->file);
+            file = wine_get_dos_file_name(face->font->file);
             if(file)
                 len = strlenW(file) + 1;
             else
             {
-                if((path = strrchr(face->file, '/')) == NULL)
-                    path = face->file;
+                if((path = strrchr(face->font->file, '/')) == NULL)
+                    path = face->font->file;
                 else
                     path++;
                 len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
@@ -2919,6 +2979,7 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
 static BOOL get_fontdir( const char *unix_name, struct fontdir *fd )
 {
     FT_Face ft_face = new_ft_face( unix_name, NULL, 0, 0, FALSE );
+    Font font;
     Face *face;
     Family *family;
     WCHAR *name, *english_name;
@@ -2927,13 +2988,15 @@ static BOOL get_fontdir( const char *unix_name, struct fontdir *fd )
     DWORD type;
 
     if (!ft_face) return FALSE;
-    face = create_face( ft_face, 0, unix_name, NULL, 0, 0, FALSE );
+    font.file = strdupA( unix_name );
+    face = create_face( ft_face, 0, &font, 0, FALSE );
     get_family_names( ft_face, &name, &english_name, FALSE );
     family = create_family( name, english_name );
     insert_face_in_family_list( face, family );
     pFT_Done_Face( ft_face );
 
     GetEnumStructs( face, &elf, &ntm, &type );
+    HeapFree( GetProcessHeap(), 0, font.file );
     free_family( family );
 
     if ((type & TRUETYPE_FONTTYPE) == 0) return FALSE;
@@ -3854,13 +3917,13 @@ static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
     void *data_ptr;
     DWORD data_size;
 
-    TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->file), face->font_data_ptr, face->face_index, width, height);
+    TRACE("%s/%p, %ld, %d x %d\n", debugstr_a(face->font->file), face->font->data_ptr, face->face_index, width, height);
 
-    if (face->file)
+    if (face->font->file)
     {
-        if (!(font->mapping = map_font_file( face->file )))
+        if (!(font->mapping = map_font_file( face->font->file )))
         {
-            WARN("failed to map %s\n", debugstr_a(face->file));
+            WARN("failed to map %s\n", debugstr_a(face->font->file));
             return 0;
         }
         data_ptr = font->mapping->data;
@@ -3868,8 +3931,8 @@ static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
     }
     else
     {
-        data_ptr = face->font_data_ptr;
-        data_size = face->font_data_size;
+        data_ptr = face->font->data_ptr;
+        data_size = face->font->data_size;
     }
 
     err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
@@ -3936,7 +3999,7 @@ static int get_nearest_charset(const WCHAR *family_name, Face *face, int *cp)
     }
 
     FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
-	  face->fs.fsCsb[0], face->file);
+	  face->fs.fsCsb[0], face->font->file);
     *cp = acp;
     return DEFAULT_CHARSET;
 }
@@ -4284,7 +4347,7 @@ static BOOL create_child_font_list(GdiFont *font)
             new_child->face = font_link_entry->face;
             new_child->font = NULL;
             list_add_tail(&font->child_fonts, &new_child->entry);
-            TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
+            TRACE("font %s %ld\n", debugstr_a(new_child->face->font->file), new_child->face->face_index);
         }
         ret = TRUE;
     }
@@ -4306,7 +4369,7 @@ static BOOL create_child_font_list(GdiFont *font)
                 new_child->face = font_link_entry->face;
                 new_child->font = NULL;
                 list_add_tail(&font->child_fonts, &new_child->entry);
-                TRACE("font %s %ld\n", debugstr_a(new_child->face->file), new_child->face->face_index);
+                TRACE("font %s %ld\n", debugstr_a(new_child->face->font->file), new_child->face->face_index);
             }
             ret = TRUE;
         }
@@ -4757,7 +4820,7 @@ found_face:
         ret->charset = get_nearest_charset(family->FamilyName, face, &ret->codepage);
 
     TRACE("Chosen: %s %s (%s/%p:%ld)\n", debugstr_w(family->FamilyName),
-	  debugstr_w(face->StyleName), face->file, face->font_data_ptr, face->face_index);
+	  debugstr_w(face->StyleName), face->font->file, face->font->data_ptr, face->face_index);
 
     ret->aveWidth = height ? lf.lfWidth : 0;
 
-- 
1.7.10




More information about the wine-patches mailing list