gdi32: Move the font link support out of freetype.c.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-10-31 10:19:08 +01:00
parent c438a62ddf
commit bc19adf474
3 changed files with 336 additions and 391 deletions

View File

@ -214,6 +214,11 @@ static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i'
static const WCHAR Lucida_Sans_Unicode[] = {'L','u','c','i','d','a',' ','S','a','n','s',' ','U','n','i','c','o','d','e',0};
static const WCHAR Microsoft_Sans_Serif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0 };
static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
static const WCHAR MS_UI_Gothic[] = {'M','S',' ','U','I',' ','G','o','t','h','i','c',0};
static const WCHAR SimSun[] = {'S','i','m','S','u','n',0};
static const WCHAR Gulim[] = {'G','u','l','i','m',0};
static const WCHAR PMingLiU[] = {'P','M','i','n','g','L','i','U',0};
static const WCHAR Batang[] = {'B','a','t','a','n','g',0};
static const struct nls_update_font_list
{
@ -461,7 +466,7 @@ static BOOL add_gdi_font_subst( const WCHAR *from_name, int from_charset, const
return TRUE;
}
void load_gdi_font_subst(void)
static void load_gdi_font_subst(void)
{
HKEY hkey;
DWORD i = 0, type, dlen, vlen;
@ -552,6 +557,36 @@ struct gdi_font_family *find_family_from_any_name( const WCHAR *name )
return NULL;
}
static const struct list *get_family_face_list( const struct gdi_font_family *family )
{
return family->replacement ? &family->replacement->faces : &family->faces;
}
static struct gdi_font_face *find_face_from_filename( const WCHAR *file_name, const WCHAR *family_name )
{
struct gdi_font_family *family;
struct gdi_font_face *face;
const WCHAR *file;
TRACE( "looking for file %s name %s\n", debugstr_w(file_name), debugstr_w(family_name) );
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
{
if (family_name && strncmpiW( family_name, family->family_name, LF_FACESIZE - 1 )) continue;
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
{
if (!face->file) continue;
file = strrchrW(face->file, '\\');
if (!file) file = face->file;
else file++;
if (strcmpiW( file, file_name )) continue;
face->refcount++;
return face;
}
}
return NULL;
}
static BOOL add_family_replacement( const WCHAR *new_name, const WCHAR *replace )
{
struct gdi_font_family *new_family, *family;
@ -596,7 +631,7 @@ static BOOL add_family_replacement( const WCHAR *new_name, const WCHAR *replace
* Wingdings. However if a real Wingdings font is present the
* replacement does not take place.
*/
void load_gdi_font_replacements(void)
static void load_gdi_font_replacements(void)
{
HKEY hkey;
DWORD i = 0, type, dlen, vlen;
@ -652,6 +687,250 @@ struct gdi_font_face *create_face( const WCHAR *style, const WCHAR *fullname, co
return face;
}
/* font links */
static struct list font_links = LIST_INIT(font_links);
struct gdi_font_link *find_gdi_font_link( const WCHAR *name )
{
struct gdi_font_link *link;
LIST_FOR_EACH_ENTRY( link, &font_links, struct gdi_font_link, entry )
if (!strncmpiW( link->name, name, LF_FACESIZE - 1 )) return link;
return NULL;
}
struct gdi_font_family *find_family_from_font_links( const WCHAR *name, const WCHAR *subst,
FONTSIGNATURE fs )
{
struct gdi_font_link *link;
struct gdi_font_link_entry *entry;
struct gdi_font_family *family;
LIST_FOR_EACH_ENTRY( link, &font_links, struct gdi_font_link, entry )
{
if (!strncmpiW( link->name, name, LF_FACESIZE - 1) ||
(subst && !strncmpiW( link->name, subst, LF_FACESIZE - 1 )))
{
TRACE("found entry in system list\n");
LIST_FOR_EACH_ENTRY( entry, &link->links, struct gdi_font_link_entry, entry )
{
const struct gdi_font_link *links;
family = find_family_from_name( entry->family_name );
if (!fs.fsCsb[0]) return family;
if (fs.fsCsb[0] & entry->fs.fsCsb[0]) return family;
if ((links = find_gdi_font_link( family->family_name )) && fs.fsCsb[0] & links->fs.fsCsb[0])
return family;
}
}
}
return NULL;
}
static struct gdi_font_link *add_gdi_font_link( const WCHAR *name )
{
struct gdi_font_link *link = find_gdi_font_link( name );
if (link) return link;
if ((link = HeapAlloc( GetProcessHeap(), 0, sizeof(*link) )))
{
lstrcpynW( link->name, name, LF_FACESIZE );
memset( &link->fs, 0, sizeof(link->fs) );
list_init( &link->links );
list_add_tail( &font_links, &link->entry );
}
return link;
}
static void add_gdi_font_link_entry( struct gdi_font_link *link, const WCHAR *family_name, FONTSIGNATURE fs )
{
struct gdi_font_link_entry *entry;
entry = HeapAlloc( GetProcessHeap(), 0, sizeof(*entry) );
lstrcpynW( entry->family_name, family_name, LF_FACESIZE );
entry->fs = fs;
link->fs.fsCsb[0] |= fs.fsCsb[0];
link->fs.fsCsb[1] |= fs.fsCsb[1];
list_add_tail( &link->links, &entry->entry );
}
static const WCHAR * const font_links_list[] =
{
Lucida_Sans_Unicode,
Microsoft_Sans_Serif,
Tahoma
};
static const struct font_links_defaults_list
{
/* Keyed off substitution for "MS Shell Dlg" */
const WCHAR *shelldlg;
/* Maximum of four substitutes, plus terminating NULL pointer */
const WCHAR *substitutes[5];
} font_links_defaults_list[] =
{
/* Non East-Asian */
{ Tahoma, /* FIXME unverified ordering */
{ MS_UI_Gothic, SimSun, Gulim, PMingLiU, NULL }
},
/* Below lists are courtesy of
* http://blogs.msdn.com/michkap/archive/2005/06/18/430507.aspx
*/
/* Japanese */
{ MS_UI_Gothic,
{ MS_UI_Gothic, PMingLiU, SimSun, Gulim, NULL }
},
/* Chinese Simplified */
{ SimSun,
{ SimSun, PMingLiU, MS_UI_Gothic, Batang, NULL }
},
/* Korean */
{ Gulim,
{ Gulim, PMingLiU, MS_UI_Gothic, SimSun, NULL }
},
/* Chinese Traditional */
{ PMingLiU,
{ PMingLiU, SimSun, MS_UI_Gothic, Batang, NULL }
}
};
static void populate_system_links( const WCHAR *name, const WCHAR * const *values )
{
struct gdi_font_family *family;
struct gdi_font_face *face;
struct gdi_font_link *font_link;
const WCHAR *file, *value;
/* Don't store fonts that are only substitutes for other fonts */
if (get_gdi_font_subst( name, -1, NULL ))
{
TRACE( "%s: Internal SystemLink entry for substituted font, ignoring\n", debugstr_w(name) );
return;
}
font_link = add_gdi_font_link( name );
for ( ; *values; values++)
{
if (!strcmpiW( name, *values )) continue;
if (!(value = get_gdi_font_subst( *values, -1, NULL ))) value = *values;
if (!(family = find_family_from_name( value ))) continue;
/* use first extant filename for this Family */
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
{
if (!face->file) continue;
file = strrchrW(face->file, '\\');
if (!file) file = face->file;
else file++;
if ((face = find_face_from_filename( file, value )))
{
add_gdi_font_link_entry( font_link, face->family->family_name, face->fs );
TRACE( "added internal SystemLink for %s to %s in %s\n",
debugstr_w(name), debugstr_w(value), debugstr_w(file) );
}
else TRACE( "Unable to find file %s face name %s\n", debugstr_w(file), debugstr_w(value) );
break;
}
}
}
static void load_system_links(void)
{
static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s',' ','N','T','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','L','i','n','k','\\',
'S','y','s','t','e','m','L','i','n','k',0};
static const WCHAR tahoma_ttf[] = {'t','a','h','o','m','a','.','t','t','f',0};
static const WCHAR System[] = {'S','y','s','t','e','m',0};
static const WCHAR MS_Shell_Dlg[] = {'M','S',' ','S','h','e','l','l',' ','D','l','g',0};
HKEY hkey;
DWORD i, j;
const WCHAR *shelldlg_name;
struct gdi_font_link *font_link, *system_font_link;
struct gdi_font_face *face;
if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, system_link, &hkey ))
{
WCHAR value[MAX_PATH], data[1024];
DWORD type, val_len, data_len;
WCHAR *entry, *next;
val_len = ARRAY_SIZE(value);
data_len = sizeof(data);
i = 0;
while (!RegEnumValueW( hkey, i++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len))
{
/* Don't store fonts that are only substitutes for other fonts */
if (!get_gdi_font_subst( value, -1, NULL ))
{
font_link = add_gdi_font_link( value );
for (entry = data; (char *)entry < (char *)data + data_len && *entry; entry = next)
{
const WCHAR *family_name = NULL;
WCHAR *p;
TRACE("%s: %s\n", debugstr_w(value), debugstr_w(entry));
next = entry + strlenW(entry) + 1;
if ((p = strchrW( entry, ',' )))
{
*p++ = 0;
while (isspaceW(*p)) p++;
if (!(family_name = get_gdi_font_subst( p, -1, NULL ))) family_name = p;
}
if ((face = find_face_from_filename( entry, family_name )))
{
add_gdi_font_link_entry( font_link, face->family->family_name, face->fs );
TRACE("Adding file %s index %u\n", debugstr_w(face->file), face->face_index);
}
else TRACE( "Unable to find file %s family %s\n",
debugstr_w(entry), debugstr_w(family_name) );
}
}
else TRACE("%s: SystemLink entry for substituted font, ignoring\n", debugstr_w(value));
val_len = ARRAY_SIZE(value);
data_len = sizeof(data);
}
RegCloseKey( hkey );
}
if ((shelldlg_name = get_gdi_font_subst( MS_Shell_Dlg, -1, NULL )))
{
for (i = 0; i < ARRAY_SIZE(font_links_defaults_list); i++)
{
const WCHAR *subst = get_gdi_font_subst( font_links_defaults_list[i].shelldlg, -1, NULL );
if ((!strcmpiW( font_links_defaults_list[i].shelldlg, shelldlg_name ) ||
(subst && !strcmpiW( subst, shelldlg_name ))))
{
for (j = 0; j < ARRAY_SIZE(font_links_list); j++)
populate_system_links( font_links_list[j], font_links_defaults_list[i].substitutes );
if (!strcmpiW(shelldlg_name, font_links_defaults_list[i].substitutes[0]))
populate_system_links( shelldlg_name, font_links_defaults_list[i].substitutes );
}
}
}
else WARN( "could not find FontSubstitute for MS Shell Dlg\n" );
/* Explicitly add an entry for the system font, this links to Tahoma and any links
that Tahoma has */
system_font_link = add_gdi_font_link( System );
if ((face = find_face_from_filename( tahoma_ttf, Tahoma )))
{
add_gdi_font_link_entry( system_font_link, face->family->family_name, face->fs );
TRACE("Found Tahoma in %s index %u\n", debugstr_w(face->file), face->face_index);
}
if ((font_link = find_gdi_font_link( Tahoma )))
{
struct gdi_font_link_entry *entry;
LIST_FOR_EACH_ENTRY( entry, &font_link->links, struct gdi_font_link_entry, entry )
add_gdi_font_link_entry( system_font_link, entry->family_name, entry->fs );
}
}
/* realized font objects */
#define FIRST_FONT_HANDLE 1
@ -2418,6 +2697,9 @@ void font_init(void)
update_codepage();
WineEngInit( &font_funcs );
load_gdi_font_subst();
load_gdi_font_replacements();
load_system_links();
dump_gdi_font_subst();
}

View File

@ -237,11 +237,6 @@ typedef struct gdi_font_face Face;
typedef struct gdi_font_family Family;
typedef struct {
struct list entry;
Face *face;
} CHILD_FONT;
struct font_private_data
{
FT_Face ft_face;
@ -253,13 +248,6 @@ static inline FT_Face get_ft_face( struct gdi_font *font )
return ((struct font_private_data *)font->private)->ft_face;
}
typedef struct {
struct list entry;
const WCHAR *font_name;
FONTSIGNATURE fs;
struct list links;
} SYSTEM_LINKS;
struct enum_charset_element {
DWORD mask;
DWORD charset;
@ -271,8 +259,6 @@ struct enum_charset_list {
struct enum_charset_element element[32];
};
static struct list system_links = LIST_INIT(system_links);
static const struct font_backend_funcs font_funcs;
static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
@ -289,15 +275,6 @@ static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','
'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
/* Interesting and well-known (frequently-assumed!) font names */
static const WCHAR Lucida_Sans_Unicode[] = {'L','u','c','i','d','a',' ','S','a','n','s',' ','U','n','i','c','o','d','e',0};
static const WCHAR Microsoft_Sans_Serif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0 };
static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
static const WCHAR MS_UI_Gothic[] = {'M','S',' ','U','I',' ','G','o','t','h','i','c',0};
static const WCHAR SimSun[] = {'S','i','m','S','u','n',0};
static const WCHAR Gulim[] = {'G','u','l','i','m',0};
static const WCHAR PMingLiU[] = {'P','M','i','n','g','L','i','U',0};
static const WCHAR Batang[] = {'B','a','t','a','n','g',0};
static const WCHAR arial[] = {'A','r','i','a','l',0};
static const WCHAR bitstream_vera_sans[] = {'B','i','t','s','t','r','e','a','m',' ','V','e','r','a',' ','S','a','n','s',0};
static const WCHAR bitstream_vera_sans_mono[] = {'B','i','t','s','t','r','e','a','m',' ','V','e','r','a',' ','S','a','n','s',' ','M','o','n','o',0};
@ -367,11 +344,6 @@ static BOOL CDECL freetype_set_outline_text_metrics( struct gdi_font *font );
static BOOL CDECL freetype_set_bitmap_text_metrics( struct gdi_font *font );
static void remove_face_from_cache( Face *face );
static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s',' ','N','T','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','F','o','n','t','L','i','n','k','\\',
'S','y','s','t','e','m','L','i','n','k',0};
/****************************************
* Notes on .fon files
*
@ -666,36 +638,6 @@ static const struct list *get_face_list_from_family(const Family *family)
return &family->faces;
}
static Face *find_face_from_filename(const WCHAR *file_name, const WCHAR *face_name)
{
Family *family;
Face *face;
const WCHAR *file;
TRACE("looking for file %s name %s\n", debugstr_w(file_name), debugstr_w(face_name));
LIST_FOR_EACH_ENTRY(family, &font_list, Family, entry)
{
const struct list *face_list;
if (face_name && strncmpiW( face_name, family->family_name, LF_FACESIZE - 1 )) continue;
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
{
if (!face->file)
continue;
file = strrchrW(face->file, '\\');
if(!file)
file = face->file;
else
file++;
if(strcmpiW(file, file_name)) continue;
face->refcount++;
return face;
}
}
return NULL;
}
static LPWSTR strdupW(LPCWSTR p)
{
LPWSTR ret;
@ -1730,279 +1672,6 @@ static void DumpFontList(void)
}
}
static const WCHAR *font_links_list[] =
{
Lucida_Sans_Unicode,
Microsoft_Sans_Serif,
Tahoma
};
static const struct font_links_defaults_list
{
/* Keyed off substitution for "MS Shell Dlg" */
const WCHAR *shelldlg;
/* Maximum of four substitutes, plus terminating NULL pointer */
const WCHAR *substitutes[5];
} font_links_defaults_list[] =
{
/* Non East-Asian */
{ Tahoma, /* FIXME unverified ordering */
{ MS_UI_Gothic, SimSun, Gulim, PMingLiU, NULL }
},
/* Below lists are courtesy of
* http://blogs.msdn.com/michkap/archive/2005/06/18/430507.aspx
*/
/* Japanese */
{ MS_UI_Gothic,
{ MS_UI_Gothic, PMingLiU, SimSun, Gulim, NULL }
},
/* Chinese Simplified */
{ SimSun,
{ SimSun, PMingLiU, MS_UI_Gothic, Batang, NULL }
},
/* Korean */
{ Gulim,
{ Gulim, PMingLiU, MS_UI_Gothic, SimSun, NULL }
},
/* Chinese Traditional */
{ PMingLiU,
{ PMingLiU, SimSun, MS_UI_Gothic, Batang, NULL }
}
};
static SYSTEM_LINKS *find_font_link(const WCHAR *name)
{
SYSTEM_LINKS *font_link;
LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
{
if(!strncmpiW(font_link->font_name, name, LF_FACESIZE - 1))
return font_link;
}
return NULL;
}
static void populate_system_links(const WCHAR *name, const WCHAR *const *values)
{
const WCHAR *value;
int i;
Family *family;
Face *face;
const WCHAR *file;
if (values)
{
SYSTEM_LINKS *font_link;
/* Don't store fonts that are only substitutes for other fonts */
if (get_gdi_font_subst( name, -1, NULL ))
{
TRACE("%s: Internal SystemLink entry for substituted font, ignoring\n", debugstr_w(name));
return;
}
font_link = find_font_link(name);
if (font_link == NULL)
{
font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
font_link->font_name = strdupW(name);
list_init(&font_link->links);
list_add_tail(&system_links, &font_link->entry);
}
memset(&font_link->fs, 0, sizeof font_link->fs);
for (i = 0; values[i] != NULL; i++)
{
const struct list *face_list;
CHILD_FONT *child_font;
if (!strcmpiW( name, values[i] )) continue;
if (!(value = get_gdi_font_subst( values[i], -1, NULL ))) value = values[i];
family = find_family_from_name(value);
if (!family)
continue;
file = NULL;
/* Use first extant filename for this Family */
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
{
if (!face->file)
continue;
file = strrchrW(face->file, '\\');
if (!file)
file = face->file;
else
file++;
break;
}
if (!file)
continue;
face = find_face_from_filename(file, value);
if(!face)
{
TRACE("Unable to find file %s face name %s\n", debugstr_w(file), debugstr_w(value));
continue;
}
child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
child_font->face = face;
font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
TRACE("Adding file %s index %u\n", debugstr_w(child_font->face->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(file));
}
}
}
/*************************************************************
* init_system_links
*/
static void init_system_links(void)
{
HKEY hkey;
DWORD type, max_val, max_data, val_len, data_len, index;
WCHAR *value, *data;
WCHAR *entry, *next;
const WCHAR *shelldlg_name;
SYSTEM_LINKS *font_link, *system_font_link;
CHILD_FONT *child_font;
static const WCHAR tahoma_ttf[] = {'t','a','h','o','m','a','.','t','t','f',0};
static const WCHAR System[] = {'S','y','s','t','e','m',0};
static const WCHAR MS_Shell_Dlg[] = {'M','S',' ','S','h','e','l','l',' ','D','l','g',0};
Face *face;
UINT i, j;
if(RegOpenKeyW(HKEY_LOCAL_MACHINE, system_link, &hkey) == ERROR_SUCCESS)
{
RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val, &max_data, NULL, NULL);
value = HeapAlloc(GetProcessHeap(), 0, (max_val + 1) * sizeof(WCHAR));
data = HeapAlloc(GetProcessHeap(), 0, max_data);
val_len = max_val + 1;
data_len = max_data;
index = 0;
while(RegEnumValueW(hkey, index++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len) == ERROR_SUCCESS)
{
/* Don't store fonts that are only substitutes for other fonts */
if (get_gdi_font_subst( value, -1, NULL ))
{
TRACE("%s: SystemLink entry for substituted font, ignoring\n", debugstr_w(value));
goto next;
}
font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
font_link->font_name = strdupW(value);
memset(&font_link->fs, 0, sizeof font_link->fs);
list_init(&font_link->links);
for(entry = data; (char*)entry < (char*)data + data_len && *entry != 0; entry = next)
{
const WCHAR *face_name = NULL;
WCHAR *p;
CHILD_FONT *child_font;
TRACE("%s: %s\n", debugstr_w(value), debugstr_w(entry));
next = entry + strlenW(entry) + 1;
if ((p = strchrW(entry, ',')))
{
*p++ = 0;
while (isspaceW(*p)) p++;
if (!(face_name = get_gdi_font_subst( p, -1, NULL ))) face_name = p;
}
face = find_face_from_filename(entry, face_name);
if(!face)
{
TRACE("Unable to find file %s face name %s\n", debugstr_w(entry), debugstr_w(face_name));
continue;
}
child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
child_font->face = face;
font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
TRACE("Adding file %s index %u\n",
debugstr_w(child_font->face->file), child_font->face->face_index);
list_add_tail(&font_link->links, &child_font->entry);
}
list_add_tail(&system_links, &font_link->entry);
next:
val_len = max_val + 1;
data_len = max_data;
}
HeapFree(GetProcessHeap(), 0, value);
HeapFree(GetProcessHeap(), 0, data);
RegCloseKey(hkey);
}
if (!(shelldlg_name = get_gdi_font_subst( MS_Shell_Dlg, -1, NULL ))) {
WARN("could not find FontSubstitute for MS Shell Dlg\n");
goto skip_internal;
}
for (i = 0; i < ARRAY_SIZE(font_links_defaults_list); i++)
{
const WCHAR *subst = get_gdi_font_subst( font_links_defaults_list[i].shelldlg, -1, NULL );
if ((!strcmpiW(font_links_defaults_list[i].shelldlg, shelldlg_name) ||
(subst && !strcmpiW( subst, shelldlg_name ))))
{
for (j = 0; j < ARRAY_SIZE(font_links_list); j++)
populate_system_links(font_links_list[j], font_links_defaults_list[i].substitutes);
if (!strcmpiW( shelldlg_name, font_links_defaults_list[i].substitutes[0] ))
populate_system_links( shelldlg_name, font_links_defaults_list[i].substitutes );
}
else if (strcmpiW( shelldlg_name, font_links_defaults_list[i].substitutes[0] ))
{
populate_system_links(font_links_defaults_list[i].substitutes[0], NULL);
}
}
skip_internal:
/* Explicitly add an entry for the system font, this links to Tahoma and any links
that Tahoma has */
system_font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*system_font_link));
system_font_link->font_name = strdupW(System);
memset(&system_font_link->fs, 0, sizeof system_font_link->fs);
list_init(&system_font_link->links);
face = find_face_from_filename(tahoma_ttf, Tahoma);
if(face)
{
child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
child_font->face = face;
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 %u\n",
debugstr_w(child_font->face->file), child_font->face->face_index);
list_add_tail(&system_font_link->links, &child_font->entry);
}
font_link = find_font_link(Tahoma);
if (font_link != NULL)
{
CHILD_FONT *font_link_entry;
LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
{
CHILD_FONT *new_child;
new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
new_child->face = font_link_entry->face;
new_child->face->refcount++;
system_font_link->fs.fsCsb[0] |= font_link_entry->face->fs.fsCsb[0];
system_font_link->fs.fsCsb[1] |= font_link_entry->face->fs.fsCsb[1];
list_add_tail(&system_font_link->links, &new_child->entry);
}
}
list_add_tail(&system_links, &system_font_link->entry);
}
#ifdef __ANDROID__
static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
{
@ -2663,14 +2332,10 @@ BOOL WineEngInit( const struct font_backend_funcs **funcs )
reorder_font_list();
DumpFontList();
load_gdi_font_subst();
load_gdi_font_replacements();
if(disposition == REG_CREATED_NEW_KEY)
update_reg_entries();
init_system_links();
ReleaseMutex(font_mutex);
return TRUE;
}
@ -2800,12 +2465,12 @@ static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp)
*cp = acp;
if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
{
const SYSTEM_LINKS *font_link;
const struct gdi_font_link *font_link;
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
return csi.ciCharset;
font_link = find_font_link(family_name);
font_link = find_gdi_font_link(family_name);
if (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
return csi.ciCharset;
}
@ -3050,9 +2715,10 @@ static LONG load_VDMX(struct gdi_font *font, LONG height)
/*************************************************************
* add_child_font
*/
static void add_child_font( struct gdi_font *font, Face *face )
static void add_child_font( struct gdi_font *font, const WCHAR *family_name )
{
struct gdi_font *child;
Family *family;
Face *child_face, *best_face = NULL;
UINT penalty = 0, new_penalty = 0;
BOOL bold, italic, bd, it;
@ -3060,7 +2726,9 @@ static void add_child_font( struct gdi_font *font, Face *face )
italic = !!font->lf.lfItalic;
bold = font->lf.lfWeight > FW_MEDIUM;
LIST_FOR_EACH_ENTRY( child_face, get_face_list_from_family( face->family ), Face, entry )
if (!(family = find_family_from_name( family_name ))) return;
LIST_FOR_EACH_ENTRY( child_face, get_face_list_from_family( family ), Face, entry )
{
it = !!(child_face->ntmFlags & NTM_ITALIC);
bd = !!(child_face->ntmFlags & NTM_BOLD);
@ -3071,20 +2739,20 @@ static void add_child_font( struct gdi_font *font, Face *face )
best_face = child_face;
}
}
if (best_face) face = best_face;
if (!best_face) return;
child = alloc_gdi_font( face->file, face->data_ptr, face->data_size );
child->fake_italic = italic && !(face->ntmFlags & NTM_ITALIC);
child->fake_bold = bold && !(face->ntmFlags & NTM_BOLD);
child = alloc_gdi_font( best_face->file, best_face->data_ptr, best_face->data_size );
child->fake_italic = italic && !(best_face->ntmFlags & NTM_ITALIC);
child->fake_bold = bold && !(best_face->ntmFlags & NTM_BOLD);
child->lf = font->lf;
child->matrix = font->matrix;
child->can_use_bitmap = font->can_use_bitmap;
child->face_index = face->face_index;
child->ntmFlags = face->ntmFlags;
child->aa_flags = HIWORD( face->flags );
child->face_index = best_face->face_index;
child->ntmFlags = best_face->ntmFlags;
child->aa_flags = HIWORD( best_face->flags );
child->scale_y = font->scale_y;
child->base_font = font;
set_gdi_font_names( child, face->family->family_name, face->style_name, face->full_name );
set_gdi_font_names( child, family_name, best_face->style_name, best_face->full_name );
list_add_tail( &font->child_fonts, &child->entry );
TRACE( "created child font %p for base %p\n", child, font );
@ -3095,18 +2763,18 @@ static void add_child_font( struct gdi_font *font, Face *face )
*/
static void create_child_font_list( struct gdi_font *font )
{
SYSTEM_LINKS *font_link;
CHILD_FONT *font_link_entry;
const WCHAR *font_name;
struct gdi_font_link *font_link;
struct gdi_font_link_entry *entry;
const WCHAR* font_name;
if (!(font_name = get_gdi_font_subst( get_gdi_font_name(font), -1, NULL )))
font_name = get_gdi_font_name( font );
font_link = find_font_link(font_name);
font_link = find_gdi_font_link(font_name);
if (font_link != NULL)
{
TRACE("found entry in system list\n");
LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
add_child_font( font, font_link_entry->face );
LIST_FOR_EACH_ENTRY( entry, &font_link->links, struct gdi_font_link_entry, entry )
add_child_font( font, entry->family_name );
}
/*
* if not SYMBOL or OEM then we also get all the fonts for Microsoft
@ -3115,12 +2783,12 @@ static void create_child_font_list( struct gdi_font *font )
if (is_dbcs_ansi_cp(GetACP()) && font->charset != SYMBOL_CHARSET && font->charset != OEM_CHARSET &&
strcmpiW(font_name,szDefaultFallbackLink) != 0)
{
font_link = find_font_link(szDefaultFallbackLink);
font_link = find_gdi_font_link(szDefaultFallbackLink);
if (font_link != NULL)
{
TRACE("found entry in default fallback list\n");
LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
add_child_font( font, font_link_entry->face );
LIST_FOR_EACH_ENTRY( entry, &font_link->links, struct gdi_font_link_entry, entry )
add_child_font( font, entry->family_name );
}
}
}
@ -3285,7 +2953,7 @@ static Family* get_fontconfig_family(DWORD pitch_and_family, const CHARSETINFO *
i++)
{
Face *face;
const SYSTEM_LINKS *font_link;
const struct gdi_font_link *font_link;
const struct list *face_list;
if (!want_vertical)
@ -3303,7 +2971,7 @@ static Family* get_fontconfig_family(DWORD pitch_and_family, const CHARSETINFO *
family = find_family_from_any_name(nameW);
if (!family) continue;
font_link = find_font_link( family->family_name );
font_link = find_gdi_font_link( family->family_name );
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY( face, face_list, Face, entry ) {
if (!face->scalable)
@ -3440,7 +3108,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
CHARSETINFO csi;
FMAT2 dcmat;
const WCHAR *orig_name = NULL;
const SYSTEM_LINKS *font_link;
const struct gdi_font_link *font_link;
GetObjectW( hfont, sizeof(lf), &lf );
lf.lfWidth = abs(lf.lfWidth);
@ -3513,7 +3181,6 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
family = NULL;
if(lf.lfFaceName[0] != '\0') {
CHILD_FONT *font_link_entry;
LPWSTR FaceName = lf.lfFaceName;
int subst_charset;
const WCHAR *subst = get_gdi_font_subst( FaceName, lf.lfCharSet, &subst_charset );
@ -3535,7 +3202,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
if (!strncmpiW( family->family_name, FaceName, LF_FACESIZE - 1 ) ||
(subst && !strncmpiW( family->family_name, subst, LF_FACESIZE - 1 )))
{
font_link = find_font_link( family->family_name );
font_link = find_gdi_font_link( family->family_name );
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY( face, face_list, Face, entry ) {
if (!(face->scalable || can_use_bitmap))
@ -3559,7 +3226,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
{
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0] || !csi.fs.fsCsb[0])
goto found_face;
font_link = find_font_link( family->family_name );
font_link = find_gdi_font_link( family->family_name );
if (font_link != NULL &&
csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
goto found_face;
@ -3571,28 +3238,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
* Try check the SystemLink list first for a replacement font.
* We may find good replacements there.
*/
LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
{
if(!strncmpiW(font_link->font_name, FaceName, LF_FACESIZE - 1) ||
(subst && !strncmpiW( font_link->font_name, subst, LF_FACESIZE - 1 )))
{
TRACE("found entry in system list\n");
LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
{
const SYSTEM_LINKS *links;
face = font_link_entry->face;
if (!(face->scalable || can_use_bitmap))
continue;
family = face->family;
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0] || !csi.fs.fsCsb[0])
goto found;
links = find_font_link( family->family_name );
if (links != NULL && csi.fs.fsCsb[0] & links->fs.fsCsb[0])
goto found;
}
}
}
if ((family = find_family_from_font_links( FaceName, subst, csi.fs ))) goto found;
}
orig_name = NULL; /* substitution is no longer relevant */
@ -3626,7 +3272,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
if (!strncmpiW( family->family_name, lf.lfFaceName, LF_FACESIZE - 1 ))
{
font_link = find_font_link( family->family_name );
font_link = find_gdi_font_link( family->family_name );
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY( face, face_list, Face, entry ) {
if (!(face->scalable || can_use_bitmap))
@ -3647,7 +3293,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
last_resort_family = NULL;
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
font_link = find_font_link( family->family_name );
font_link = find_gdi_font_link( family->family_name );
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY( face, face_list, Face, entry ) {
if(!(face->flags & ADDFONT_VERTICAL_FONT) == !want_vertical &&
@ -3693,7 +3339,7 @@ found:
height = lf.lfHeight;
face = best = best_bitmap = NULL;
font_link = find_font_link( family->family_name );
font_link = find_gdi_font_link( family->family_name );
face_list = get_face_list_from_family(family);
LIST_FOR_EACH_ENTRY(face, face_list, Face, entry)
{

View File

@ -351,6 +351,21 @@ struct gdi_font_face
struct gdi_font_enum_data *cached_enum_data;
};
struct gdi_font_link
{
struct list entry;
struct list links;
WCHAR name[LF_FACESIZE];
FONTSIGNATURE fs;
};
struct gdi_font_link_entry
{
struct list entry;
FONTSIGNATURE fs;
WCHAR family_name[LF_FACESIZE];
};
struct gdi_font
{
struct list entry;
@ -444,18 +459,20 @@ extern void load_file_system_fonts(void) DECLSPEC_HIDDEN;
extern void load_registry_fonts(void) DECLSPEC_HIDDEN;
extern const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset ) DECLSPEC_HIDDEN;
extern void load_gdi_font_subst(void) DECLSPEC_HIDDEN;
extern struct list font_list DECLSPEC_HIDDEN;
extern struct gdi_font_family *create_family( const WCHAR *name, const WCHAR *second_name ) DECLSPEC_HIDDEN;
extern void release_family( struct gdi_font_family *family ) DECLSPEC_HIDDEN;
extern struct gdi_font_family *find_family_from_name( const WCHAR *name ) DECLSPEC_HIDDEN;
extern struct gdi_font_family *find_family_from_any_name( const WCHAR *name ) DECLSPEC_HIDDEN;
extern void load_gdi_font_replacements(void) DECLSPEC_HIDDEN;
extern struct gdi_font_face *create_face( const WCHAR *style, const WCHAR *fullname, const WCHAR *file,
UINT index, FONTSIGNATURE fs, DWORD ntmflags,
DWORD version, DWORD flags, const struct bitmap_font_size *size ) DECLSPEC_HIDDEN;
extern struct gdi_font_link *find_gdi_font_link( const WCHAR *name ) DECLSPEC_HIDDEN;
extern struct gdi_font_family *find_family_from_font_links( const WCHAR *name, const WCHAR *subst,
FONTSIGNATURE fs ) DECLSPEC_HIDDEN;
extern struct gdi_font *alloc_gdi_font( const WCHAR *file, void *data_ptr, SIZE_T data_size ) DECLSPEC_HIDDEN;
extern void free_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern void cache_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;