[1/5] gdi32: Separate font loading from adding a font to global font list. Take 3.

Dmitry Timoshkov dmitry at codeweavers.com
Wed Nov 17 09:44:31 CST 2010


---
 dlls/gdi32/freetype.c |  304 +++++++++++++++++++++++++++++++++----------------
 1 files changed, 205 insertions(+), 99 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index e2db1aa..78387be 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -280,7 +280,7 @@ typedef struct tagFace {
 
 typedef struct tagFamily {
     struct list entry;
-    const WCHAR *FamilyName;
+    WCHAR *FamilyName;
     struct list faces;
 } Family;
 
@@ -1166,6 +1166,14 @@ static FT_Error load_sfnt_table(FT_Face ft_face, FT_ULong table, FT_Long offset,
     return err;
 }
 
+static void free_face(Face *face)
+{
+    HeapFree(GetProcessHeap(), 0, face->file);
+    HeapFree(GetProcessHeap(), 0, face->StyleName);
+    HeapFree(GetProcessHeap(), 0, face->cached_enum_data);
+    HeapFree(GetProcessHeap(), 0, face);
+}
+
 static inline int TestStyles(DWORD flags, DWORD styles)
 {
     return (flags & styles) == styles;
@@ -1205,9 +1213,121 @@ static void AddFaceToFamily(Face *face, Family *family)
     list_add_before( entry, &face->entry );
 }
 
+static int add_face_to_family(Family *family, Face *face, const WCHAR *fake_family)
+{
+    struct list *face_ptr;
+    Face *global_face;
+
+    face_ptr = list_head(&family->faces);
+    while (face_ptr)
+    {
+        global_face = LIST_ENTRY(face_ptr, Face, entry);
+        face_ptr = list_next(&family->faces, face_ptr);
+
+        if (!strcmpiW(global_face->StyleName, face->StyleName) &&
+            (face->scalable || (face->size.y_ppem == global_face->size.y_ppem && !memcmp(&face->fs, &global_face->fs, sizeof(face->fs)))))
+        {
+            TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
+                  debugstr_w(family->FamilyName), debugstr_w(face->StyleName),
+                  global_face->font_version, face->font_version);
+
+            if (fake_family)
+            {
+                TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
+                return 0;
+            }
+            if (face->font_version <= global_face->font_version)
+            {
+                TRACE("Original font is newer so skipping this one\n");
+                return 0;
+            }
+
+            TRACE("Replacing original with this one\n");
+            list_remove(&global_face->entry);
+            free_face(global_face);
+            break;
+        }
+    }
+
+    TRACE("Adding face %s to family %s\n", debugstr_w(face->StyleName),
+           debugstr_w(family->FamilyName));
+
+    list_remove(&face->entry);
+    AddFaceToFamily(face, family);
+    return 1;
+}
+
+static int add_family_to_global_list(Family *family, const WCHAR *fake_family)
+{
+    struct list *family_ptr, *face_ptr, *face_ptr_safe;
+    Family *global_family = NULL;
+    int num_faces_added = 0;
+
+    LIST_FOR_EACH(family_ptr, &font_list)
+    {
+        global_family = LIST_ENTRY(family_ptr, Family, entry);
+        if(!strcmpiW(global_family->FamilyName, family->FamilyName))
+            break;
+        global_family = NULL;
+    }
+
+    if (!global_family)
+    {
+        TRACE("Adding new family %s\n", debugstr_w(family->FamilyName));
+        list_remove(&family->entry);
+        list_add_tail(&font_list, &family->entry);
+        global_family = family;
+    }
+
+    LIST_FOR_EACH_SAFE(face_ptr, face_ptr_safe, &family->faces)
+    {
+        Face *face = LIST_ENTRY(face_ptr, Face, entry);
+
+        if (add_face_to_family(global_family, face, fake_family))
+        {
+            num_faces_added++;
+
+            if (!(face->fs.fsCsb[0] & FS_SYMBOL))
+                have_installed_roman_font = TRUE;
+        }
+    }
+
+    return num_faces_added;
+}
+
+static int add_font_to_global_list(const struct list *flist,
+                        const WCHAR *fake_family, const WCHAR *target_family)
+{
+    struct list *family_ptr, *family_ptr_safe;
+    int num_faces_added = 0;
+
+    LIST_FOR_EACH_SAFE(family_ptr, family_ptr_safe, flist)
+    {
+        Family *family = LIST_ENTRY(family_ptr, Family, entry);
+
+        if (target_family && strcmpiW(family->FamilyName, target_family) != 0)
+        {
+            TRACE("Incorrect family name for replacement\n");
+            continue;
+        }
+
+        if (fake_family)
+        {
+            HeapFree(GetProcessHeap(), 0, family->FamilyName);
+            family->FamilyName = strdupW(fake_family);
+        }
+
+        num_faces_added += add_family_to_global_list(family, fake_family);
+    }
+
+    return num_faces_added;
+}
+
 #define ADDFONT_EXTERNAL_FONT 0x01
 #define ADDFONT_FORCE_BITMAP  0x02
-static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_size, char *fake_family, const WCHAR *target_family, DWORD flags)
+
+static int load_font(const char *file, void *font_data_ptr, DWORD font_data_size,
+                     struct list *flist, DWORD flags)
 {
     FT_Face ft_face;
     TT_OS2 *pOS2;
@@ -1216,7 +1336,6 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
     DWORD len;
     Family *family;
     Face *face;
-    struct list *family_elem_ptr, *face_elem_ptr;
     FT_Error err;
     FT_Long face_index = 0, num_faces;
 #ifdef HAVE_FREETYPE_FTWINFNT_H
@@ -1239,7 +1358,7 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
             for(cursor = mac_list; *cursor; cursor++)
             {
                 had_one = TRUE;
-                AddFontToList(*cursor, NULL, 0, NULL, NULL, flags);
+                load_font(*cursor, NULL, 0, flist, flags);
                 HeapFree(GetProcessHeap(), 0, *cursor);
             }
             HeapFree(GetProcessHeap(), 0, mac_list);
@@ -1250,8 +1369,6 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
 #endif /* HAVE_CARBON_CARBON_H */
 
     do {
-        char *family_name = fake_family;
-
         if (file)
         {
             TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
@@ -1320,23 +1437,6 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
             return 0;
         }
 
-        if (target_family)
-        {
-            localised_family = get_familyname(ft_face);
-            if (localised_family && strcmpiW(localised_family,target_family)!=0)
-            {
-                TRACE("Skipping Index %i: Incorrect Family name for replacement\n",(INT)face_index);
-                HeapFree(GetProcessHeap(), 0, localised_family);
-                num_faces = ft_face->num_faces;
-                pFT_Done_Face(ft_face);
-                continue;
-            }
-            HeapFree(GetProcessHeap(), 0, localised_family);
-        }
-
-        if(!family_name)
-            family_name = ft_face->family_name;
-
         bitmap_num = 0;
         do {
             My_FT_Bitmap_Size *size = NULL;
@@ -1345,41 +1445,32 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
             if(!FT_IS_SCALABLE(ft_face))
                 size = (My_FT_Bitmap_Size *)ft_face->available_sizes + bitmap_num;
 
-            len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
+            len = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0);
             english_family = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-            MultiByteToWideChar(CP_ACP, 0, family_name, -1, english_family, len);
-
-            localised_family = NULL;
-            if(!fake_family) {
-                localised_family = get_familyname(ft_face);
-                if(localised_family && !strcmpiW(localised_family, english_family)) {
-                    HeapFree(GetProcessHeap(), 0, localised_family);
-                    localised_family = NULL;
-                }
-            }
+            MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, english_family, len);
 
-            family = NULL;
-            LIST_FOR_EACH(family_elem_ptr, &font_list) {
-                family = LIST_ENTRY(family_elem_ptr, Family, entry);
-                if(!strcmpiW(family->FamilyName, localised_family ? localised_family : english_family))
-                    break;
-                family = NULL;
+            localised_family = get_familyname(ft_face);
+            if (localised_family && !strcmpiW(localised_family, english_family))
+            {
+                HeapFree(GetProcessHeap(), 0, localised_family);
+                localised_family = NULL;
             }
-            if(!family) {
-                family = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
-                family->FamilyName = strdupW(localised_family ? localised_family : english_family);
-                list_init(&family->faces);
-                list_add_tail(&font_list, &family->entry);
-
-                if(localised_family) {
-                    FontSubst *subst = HeapAlloc(GetProcessHeap(), 0, sizeof(*subst));
-                    subst->from.name = strdupW(english_family);
-                    subst->from.charset = -1;
-                    subst->to.name = strdupW(localised_family);
-                    subst->to.charset = -1;
-                    add_font_subst(&font_subst_list, subst, 0);
-                }
+
+            family = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
+            family->FamilyName = strdupW(localised_family ? localised_family : english_family);
+            list_init(&family->faces);
+            list_add_tail(flist, &family->entry);
+
+            if (localised_family)
+            {
+                FontSubst *subst = HeapAlloc(GetProcessHeap(), 0, sizeof(*subst));
+                subst->from.name = strdupW(english_family);
+                subst->from.charset = -1;
+                subst->to.name = strdupW(localised_family);
+                subst->to.charset = -1;
+                add_font_subst(&font_subst_list, subst, 0);
             }
+
             HeapFree(GetProcessHeap(), 0, localised_family);
             HeapFree(GetProcessHeap(), 0, english_family);
 
@@ -1417,38 +1508,6 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
                 internal_leading = winfnt_header.internal_leading;
             }
 #endif
-
-            face_elem_ptr = list_head(&family->faces);
-            while(face_elem_ptr) {
-                face = LIST_ENTRY(face_elem_ptr, Face, entry);
-                face_elem_ptr = list_next(&family->faces, face_elem_ptr);
-                if(!strcmpiW(face->StyleName, StyleW) &&
-                   (FT_IS_SCALABLE(ft_face) || ((size->y_ppem == face->size.y_ppem) && !memcmp(&fs, &face->fs, sizeof(fs)) ))) {
-                    TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
-                          debugstr_w(family->FamilyName), debugstr_w(StyleW),
-                          face->font_version,  pHeader ? pHeader->Font_Revision : 0);
-
-                    if(fake_family) {
-                        TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
-                        HeapFree(GetProcessHeap(), 0, StyleW);
-                        pFT_Done_Face(ft_face);
-                        return 1;
-                    }
-                    if(!pHeader || pHeader->Font_Revision <= face->font_version) {
-                        TRACE("Original font is newer so skipping this one\n");
-                        HeapFree(GetProcessHeap(), 0, StyleW);
-                        pFT_Done_Face(ft_face);
-                        return 1;
-                    } else {
-                        TRACE("Replacing original with this one\n");
-                        list_remove(&face->entry);
-                        HeapFree(GetProcessHeap(), 0, face->file);
-                        HeapFree(GetProcessHeap(), 0, face->StyleName);
-                        HeapFree(GetProcessHeap(), 0, face);
-                        break;
-                    }
-                }
-            }
             face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
             face->cached_enum_data = NULL;
             face->StyleName = StyleW;
@@ -1523,33 +1582,47 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
                 }
             }
 
-            if (!(face->fs.fsCsb[0] & FS_SYMBOL))
-                have_installed_roman_font = TRUE;
-
             AddFaceToFamily(face, family);
 
         } while(!FT_IS_SCALABLE(ft_face) && ++bitmap_num < ft_face->num_fixed_sizes);
 
 	num_faces = ft_face->num_faces;
 	pFT_Done_Face(ft_face);
-	TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
-	      debugstr_w(StyleW));
+	TRACE("Loaded font %s %s (%ld of %ld)\n", debugstr_w(family->FamilyName),
+	      debugstr_w(StyleW), face_index + 1, num_faces);
     } while(num_faces > ++face_index);
     return num_faces;
 }
 
-static INT AddFontFileToList(const char *file, char *fake_family, const WCHAR *target_family, DWORD flags)
+static void free_font_list(const struct list *flist)
 {
-    return AddFontToList(file, NULL, 0, fake_family, target_family, flags);
+    struct list *family_ptr, *family_ptr_safe;
+
+    LIST_FOR_EACH_SAFE(family_ptr, family_ptr_safe, flist)
+    {
+        struct list *face_ptr, *face_ptr_safe;
+        Family *family = LIST_ENTRY(family_ptr, Family, entry);
+
+        LIST_FOR_EACH_SAFE(face_ptr, face_ptr_safe, &family->faces)
+        {
+            Face *face = LIST_ENTRY(face_ptr, Face, entry);
+            list_remove(&face->entry);
+            free_face(face);
+        }
+
+        list_remove(&family->entry);
+        HeapFree(GetProcessHeap(), 0, family->FamilyName);
+        HeapFree(GetProcessHeap(), 0, family);
+    }
 }
 
-static void DumpFontList(void)
+static void dump_font_list(const struct list *flist)
 {
     Family *family;
     Face *face;
     struct list *family_elem_ptr, *face_elem_ptr;
 
-    LIST_FOR_EACH(family_elem_ptr, &font_list) {
+    LIST_FOR_EACH(family_elem_ptr, flist) {
         family = LIST_ENTRY(family_elem_ptr, Family, entry); 
         TRACE("Family: %s\n", debugstr_w(family->FamilyName));
         LIST_FOR_EACH(face_elem_ptr, &family->faces) {
@@ -1563,6 +1636,41 @@ static void DumpFontList(void)
     return;
 }
 
+static void DumpFontList(void)
+{
+    dump_font_list(&font_list);
+}
+
+static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_size, const WCHAR *fake_family, const WCHAR *target_family, DWORD flags)
+{
+    struct list flist;
+    INT ret;
+
+    list_init(&flist);
+
+    if (!load_font(file, font_data_ptr, font_data_size, &flist, flags))
+    {
+        free_font_list(&flist);
+        return 0;
+    }
+
+    dump_font_list(&flist);
+
+    ret = add_font_to_global_list(&flist, fake_family, target_family);
+    if (!ret)
+    {
+        free_font_list(&flist);
+        /* no added fonts means that the font is already loaded */
+        ret = 1;
+    }
+    return ret;
+}
+
+static INT AddFontFileToList(const char *file, const WCHAR *fake_family, const WCHAR *target_family, DWORD flags)
+{
+    return AddFontToList(file, NULL, 0, fake_family, target_family, flags);
+}
+
 /***********************************************************
  * The replacement list is a way to map an entire font
  * family onto another family.  For example adding
@@ -1584,7 +1692,6 @@ static void LoadReplaceList(void)
     Family *family;
     Face *face;
     struct list *family_elem_ptr, *face_elem_ptr;
-    CHAR familyA[400];
 
     /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */
     if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts\\Replacements", &hkey) == ERROR_SUCCESS)
@@ -1602,7 +1709,6 @@ static void LoadReplaceList(void)
 			    &dlen) == ERROR_SUCCESS) {
 	    TRACE("Got %s=%s\n", debugstr_w(value), debugstr_w(data));
             /* "NewName"="Oldname" */
-            WideCharToMultiByte(CP_ACP, 0, value, -1, familyA, sizeof(familyA), NULL, NULL);
 
             /* Find the old family and hence all of the font files
                in that family */
@@ -1612,9 +1718,9 @@ static void LoadReplaceList(void)
                     LIST_FOR_EACH(face_elem_ptr, &family->faces) {
                         face = LIST_ENTRY(face_elem_ptr, Face, entry);
                         TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
-                              debugstr_w(face->StyleName), familyA);
+                              debugstr_w(face->StyleName), debugstr_w(value));
                         /* Now add a new entry with the new family name */
-                        AddFontToList(face->file, face->font_data_ptr, face->font_data_size, familyA, family->FamilyName, ADDFONT_FORCE_BITMAP | (face->external ? ADDFONT_EXTERNAL_FONT : 0));
+                        AddFontToList(face->file, face->font_data_ptr, face->font_data_size, value, family->FamilyName, ADDFONT_FORCE_BITMAP | (face->external ? ADDFONT_EXTERNAL_FONT : 0));
                     }
                     break;
                 }
-- 
1.7.0.6




More information about the wine-patches mailing list