[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