diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 62f9f927ccd..806ff0d1d91 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -551,6 +551,85 @@ struct gdi_font_family *find_family_from_any_name( const WCHAR *name ) return NULL; } +static BOOL add_family_replacement( const WCHAR *new_name, const WCHAR *replace ) +{ + struct gdi_font_family *new_family, *family; + struct gdi_font_face *face; + WCHAR new_name_vert[LF_FACESIZE], replace_vert[LF_FACESIZE]; + + if (!(family = find_family_from_any_name( replace ))) + { + TRACE( "%s is not available. Skip this replacement.\n", debugstr_w(replace) ); + return FALSE; + } + + if (!(new_family = create_family( new_name, NULL ))) return FALSE; + new_family->replacement = &family->faces; + TRACE( "mapping %s to %s\n", debugstr_w(replace), debugstr_w(new_name) ); + + /* also add replacement for vertical font if necessary */ + if (replace[0] == '@') return TRUE; + if (list_empty( &family->faces )) return TRUE; + face = LIST_ENTRY( list_head(&family->faces), struct gdi_font_face, entry ); + if (!(face->fs.fsCsb[0] & FS_DBCS_MASK)) return TRUE; + + new_name_vert[0] = '@'; + lstrcpynW( new_name_vert + 1, new_name, LF_FACESIZE - 1 ); + if (find_family_from_any_name( new_name_vert )) return TRUE; /* already exists */ + + replace_vert[0] = '@'; + lstrcpynW( replace_vert + 1, replace, LF_FACESIZE - 1 ); + add_family_replacement( new_name_vert, replace_vert ); + return TRUE; +} + +/* + * The replacement list is a way to map an entire font + * family onto another family. For example adding + * + * [HKCU\Software\Wine\Fonts\Replacements] + * "Wingdings"="Winedings" + * + * would enumerate the Winedings font both as Winedings and + * Wingdings. However if a real Wingdings font is present the + * replacement does not take place. + */ +void load_gdi_font_replacements(void) +{ + HKEY hkey; + DWORD i = 0, type, dlen, vlen; + WCHAR value[LF_FACESIZE], data[1024]; + + /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */ + if (RegOpenKeyA( wine_fonts_key, "Replacements", &hkey )) return; + + dlen = sizeof(data); + vlen = ARRAY_SIZE(value); + while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (BYTE *)data, &dlen )) + { + /* "NewName"="Oldname" */ + if (!find_family_from_any_name( value )) + { + if (type == REG_MULTI_SZ) + { + WCHAR *replace = data; + while (*replace) + { + if (add_family_replacement( value, replace )) break; + replace += strlenW(replace) + 1; + } + } + else if (type == REG_SZ) add_family_replacement( value, data ); + } + else TRACE("%s is available. Skip this replacement.\n", debugstr_w(value)); + + /* reset dlen and vlen */ + dlen = sizeof(data); + vlen = ARRAY_SIZE(value); + } + RegCloseKey( hkey ); +} + 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 ) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 147d65d130d..afc9add629c 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -235,8 +235,6 @@ typedef struct { typedef struct gdi_font_face Face; -#define FS_DBCS_MASK (FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB) - typedef struct gdi_font_family Family; typedef struct { @@ -365,7 +363,6 @@ static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N' static const WCHAR szDefaultFallbackLink[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}; -static BOOL map_font_family(const WCHAR *orig, const WCHAR *repl); 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 ); @@ -1735,117 +1732,6 @@ static void DumpFontList(void) } } -static BOOL map_vertical_font_family(const WCHAR *orig, const WCHAR *repl, const Family *family) -{ - Face *face; - BOOL ret = FALSE; - WCHAR *at_orig, *at_repl = NULL; - - face = LIST_ENTRY(list_head(&family->faces), Face, entry); - if (!face || !(face->fs.fsCsb[0] & FS_DBCS_MASK)) - return FALSE; - - at_orig = get_vertical_name( strdupW( orig ) ); - if (at_orig && !find_family_from_any_name(at_orig)) - { - at_repl = get_vertical_name( strdupW( repl ) ); - if (at_repl) - ret = map_font_family(at_orig, at_repl); - } - - HeapFree(GetProcessHeap(), 0, at_orig); - HeapFree(GetProcessHeap(), 0, at_repl); - - return ret; -} - -static BOOL map_font_family(const WCHAR *orig, const WCHAR *repl) -{ - Family *family = find_family_from_any_name(repl); - if (family != NULL) - { - Family *new_family = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_family)); - if (new_family != NULL) - { - TRACE("mapping %s to %s\n", debugstr_w(repl), debugstr_w(orig)); - lstrcpynW( new_family->family_name, orig, LF_FACESIZE ); - new_family->second_name[0] = 0; - list_init(&new_family->faces); - new_family->replacement = &family->faces; - list_add_tail(&font_list, &new_family->entry); - - if (repl[0] != '@') - map_vertical_font_family(orig, repl, family); - - return TRUE; - } - } - TRACE("%s is not available. Skip this replacement.\n", debugstr_w(repl)); - return FALSE; -} - -/*********************************************************** - * The replacement list is a way to map an entire font - * family onto another family. For example adding - * - * [HKCU\Software\Wine\Fonts\Replacements] - * "Wingdings"="Winedings" - * - * would enumerate the Winedings font both as Winedings and - * Wingdings. However if a real Wingdings font is present the - * replacement does not take place. - * - */ -static void LoadReplaceList(void) -{ - HKEY hkey; - DWORD valuelen, datalen, i = 0, type, dlen, vlen; - LPWSTR value; - LPVOID data; - - /* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */ - if(RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts\\Replacements", &hkey) == ERROR_SUCCESS) - { - RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &valuelen, &datalen, NULL, NULL); - - valuelen++; /* returned value doesn't include room for '\0' */ - value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR)); - data = HeapAlloc(GetProcessHeap(), 0, datalen); - - dlen = datalen; - vlen = valuelen; - while(RegEnumValueW(hkey, i++, value, &vlen, NULL, &type, data, &dlen) == ERROR_SUCCESS) - { - /* "NewName"="Oldname" */ - if(!find_family_from_any_name(value)) - { - if (type == REG_MULTI_SZ) - { - WCHAR *replace = data; - while(*replace) - { - if (map_font_family(value, replace)) - break; - replace += strlenW(replace) + 1; - } - } - else if (type == REG_SZ) - map_font_family(value, data); - } - else - TRACE("%s is available. Skip this replacement.\n", debugstr_w(value)); - - /* reset dlen and vlen */ - dlen = datalen; - vlen = valuelen; - } - HeapFree(GetProcessHeap(), 0, data); - HeapFree(GetProcessHeap(), 0, value); - RegCloseKey(hkey); - } -} - static const WCHAR *font_links_list[] = { Lucida_Sans_Unicode, @@ -2780,7 +2666,7 @@ BOOL WineEngInit( const struct font_backend_funcs **funcs ) DumpFontList(); load_gdi_font_subst(); - LoadReplaceList(); + load_gdi_font_replacements(); if(disposition == REG_CREATED_NEW_KEY) update_reg_entries(); diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 812b3f33abf..63e76e4df69 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -405,6 +405,8 @@ struct gdi_font #define MS_TTCF_TAG MS_MAKE_TAG('t', 't', 'c', 'f') #define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X') +#define FS_DBCS_MASK (FS_JISJAPAN | FS_CHINESESIMP | FS_WANSUNG | FS_CHINESETRAD | FS_JOHAB) + #define ADDFONT_EXTERNAL_FONT 0x01 #define ADDFONT_ALLOW_BITMAP 0x02 #define ADDFONT_ADD_TO_CACHE 0x04 @@ -449,6 +451,7 @@ extern struct gdi_font_family *create_family( const WCHAR *name, const WCHAR *se 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;