gdi32: Move the handling of font family fallbacks out of freetype.c.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
caf0b9c082
commit
4cddf0d47d
|
@ -240,32 +240,25 @@ static const WCHAR liberation_sans[] = {'L','i','b','e','r','a','t','i','o','n',
|
||||||
static const WCHAR liberation_serif[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','e','r','i','f',0};
|
static const WCHAR liberation_serif[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','e','r','i','f',0};
|
||||||
static const WCHAR times_new_roman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n',0};
|
static const WCHAR times_new_roman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n',0};
|
||||||
|
|
||||||
static const WCHAR * const default_serif_list[] =
|
static const WCHAR * const default_serif_list[3] =
|
||||||
{
|
{
|
||||||
times_new_roman,
|
times_new_roman,
|
||||||
liberation_serif,
|
liberation_serif,
|
||||||
bitstream_vera_serif,
|
bitstream_vera_serif
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
static const WCHAR * const default_fixed_list[] =
|
static const WCHAR * const default_fixed_list[3] =
|
||||||
{
|
{
|
||||||
courier_new,
|
courier_new,
|
||||||
liberation_mono,
|
liberation_mono,
|
||||||
bitstream_vera_sans_mono,
|
bitstream_vera_sans_mono
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
static const WCHAR * const default_sans_list[] =
|
static const WCHAR * const default_sans_list[3] =
|
||||||
{
|
{
|
||||||
arial,
|
arial,
|
||||||
liberation_sans,
|
liberation_sans,
|
||||||
bitstream_vera_sans,
|
bitstream_vera_sans
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const WCHAR *default_serif = times_new_roman;
|
|
||||||
const WCHAR *default_fixed = courier_new;
|
|
||||||
const WCHAR *default_sans = arial;
|
|
||||||
|
|
||||||
static const struct nls_update_font_list
|
static const struct nls_update_font_list
|
||||||
{
|
{
|
||||||
UINT ansi_cp, oem_cp;
|
UINT ansi_cp, oem_cp;
|
||||||
|
@ -732,26 +725,44 @@ static void dump_gdi_font_list(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const WCHAR *set_default_family( const WCHAR * const *name_list )
|
static BOOL enum_fallbacks( DWORD pitch_and_family, int index, WCHAR buffer[LF_FACESIZE] )
|
||||||
|
{
|
||||||
|
if (index < 3)
|
||||||
|
{
|
||||||
|
const WCHAR * const *defaults;
|
||||||
|
|
||||||
|
if ((pitch_and_family & FIXED_PITCH) || (pitch_and_family & 0xf0) == FF_MODERN)
|
||||||
|
defaults = default_fixed_list;
|
||||||
|
else if ((pitch_and_family & 0xf0) == FF_ROMAN)
|
||||||
|
defaults = default_serif_list;
|
||||||
|
else
|
||||||
|
defaults = default_sans_list;
|
||||||
|
lstrcpynW( buffer, defaults[index], LF_FACESIZE );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return font_funcs->enum_family_fallbacks( pitch_and_family, index - 3, buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_default_family( DWORD pitch_and_family )
|
||||||
{
|
{
|
||||||
struct gdi_font_family *family;
|
struct gdi_font_family *family;
|
||||||
const WCHAR * const *entry;
|
WCHAR name[LF_FACESIZE];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
for (entry = name_list; *entry; entry++)
|
while (enum_fallbacks( pitch_and_family, i++, name ))
|
||||||
{
|
{
|
||||||
if (!(family = find_family_from_name( *entry ))) continue;
|
if (!(family = find_family_from_name( name ))) continue;
|
||||||
list_remove( &family->entry );
|
list_remove( &family->entry );
|
||||||
list_add_head( &font_list, &family->entry );
|
list_add_head( &font_list, &family->entry );
|
||||||
return *entry;
|
return;
|
||||||
}
|
}
|
||||||
return *name_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reorder_font_list(void)
|
static void reorder_font_list(void)
|
||||||
{
|
{
|
||||||
default_serif = set_default_family( default_serif_list );
|
set_default_family( FF_ROMAN );
|
||||||
default_fixed = set_default_family( default_fixed_list );
|
set_default_family( FF_MODERN );
|
||||||
default_sans = set_default_family( default_sans_list );
|
set_default_family( FF_SWISS );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_face( struct gdi_font_face *face )
|
static void release_face( struct gdi_font_face *face )
|
||||||
|
@ -1483,14 +1494,28 @@ struct gdi_font_face *find_any_face( const LOGFONTW *lf, FONTSIGNATURE fs,
|
||||||
{
|
{
|
||||||
struct gdi_font_family *family;
|
struct gdi_font_family *family;
|
||||||
struct gdi_font_face *face;
|
struct gdi_font_face *face;
|
||||||
|
WCHAR name[LF_FACESIZE];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
/* first try only scalable */
|
/* first try the family fallbacks */
|
||||||
|
while (enum_fallbacks( lf->lfPitchAndFamily, i++, name ))
|
||||||
|
{
|
||||||
|
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
||||||
|
{
|
||||||
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
||||||
|
if (strcmpiW( family->family_name + want_vertical, name ) &&
|
||||||
|
strcmpiW( family->second_name + want_vertical, name )) continue;
|
||||||
|
if ((face = find_best_matching_face( family, lf, fs, FALSE ))) return face;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* otherwise try only scalable */
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
||||||
{
|
{
|
||||||
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
||||||
if ((face = find_best_matching_face( family, lf, fs, FALSE ))) return face;
|
if ((face = find_best_matching_face( family, lf, fs, FALSE ))) return face;
|
||||||
}
|
}
|
||||||
if (!can_use_bitmap) return NULL;
|
if (!can_use_bitmap) return NULL;
|
||||||
|
/* then also bitmap fonts */
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
||||||
{
|
{
|
||||||
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
||||||
|
|
|
@ -1218,6 +1218,9 @@ static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
|
||||||
#ifdef SONAME_LIBFONTCONFIG
|
#ifdef SONAME_LIBFONTCONFIG
|
||||||
|
|
||||||
static BOOL fontconfig_enabled;
|
static BOOL fontconfig_enabled;
|
||||||
|
static FcPattern *pattern_serif;
|
||||||
|
static FcPattern *pattern_fixed;
|
||||||
|
static FcPattern *pattern_sans;
|
||||||
|
|
||||||
static UINT parse_aa_pattern( FcPattern *pattern )
|
static UINT parse_aa_pattern( FcPattern *pattern )
|
||||||
{
|
{
|
||||||
|
@ -1242,6 +1245,23 @@ static UINT parse_aa_pattern( FcPattern *pattern )
|
||||||
return aa_flags;
|
return aa_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FcPattern *create_family_pattern( const char *name )
|
||||||
|
{
|
||||||
|
FcPattern *ret, *pattern = pFcPatternCreate();
|
||||||
|
FcResult result;
|
||||||
|
|
||||||
|
pFcPatternAddString( pattern, FC_FAMILY, (const FcChar8 *)name );
|
||||||
|
pFcPatternAddString( pattern, FC_NAMELANG, (const FcChar8 *)"en-us" );
|
||||||
|
pFcPatternAddString( pattern, FC_PRGNAME, (const FcChar8 *)"wine" );
|
||||||
|
pFcConfigSubstitute( NULL, pattern, FcMatchPattern );
|
||||||
|
pFcDefaultSubstitute( pattern );
|
||||||
|
ret = pFcFontMatch( NULL, pattern, &result );
|
||||||
|
pFcPatternDestroy( pattern );
|
||||||
|
if (ret && result == FcResultMatch) return ret;
|
||||||
|
pFcPatternDestroy( ret );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void init_fontconfig(void)
|
static void init_fontconfig(void)
|
||||||
{
|
{
|
||||||
void *fc_handle = dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW);
|
void *fc_handle = dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW);
|
||||||
|
@ -1281,6 +1301,9 @@ static void init_fontconfig(void)
|
||||||
default_aa_flags = parse_aa_pattern( pattern );
|
default_aa_flags = parse_aa_pattern( pattern );
|
||||||
pFcPatternDestroy( pattern );
|
pFcPatternDestroy( pattern );
|
||||||
}
|
}
|
||||||
|
pattern_serif = create_family_pattern( "serif" );
|
||||||
|
pattern_fixed = create_family_pattern( "monospace" );
|
||||||
|
pattern_sans = create_family_pattern( "sans" );
|
||||||
|
|
||||||
TRACE( "enabled, default flags = %x\n", default_aa_flags );
|
TRACE( "enabled, default flags = %x\n", default_aa_flags );
|
||||||
fontconfig_enabled = TRUE;
|
fontconfig_enabled = TRUE;
|
||||||
|
@ -2070,67 +2093,28 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* fontconfig_enum_family_fallbacks
|
||||||
|
*/
|
||||||
|
static BOOL CDECL fontconfig_enum_family_fallbacks( DWORD pitch_and_family, int index,
|
||||||
|
WCHAR buffer[LF_FACESIZE] )
|
||||||
|
{
|
||||||
#ifdef SONAME_LIBFONTCONFIG
|
#ifdef SONAME_LIBFONTCONFIG
|
||||||
static struct gdi_font_face *get_fontconfig_face( const LOGFONTW *lf, FONTSIGNATURE fs, BOOL want_vertical )
|
FcPattern *pat;
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
WCHAR nameW[LF_FACESIZE];
|
|
||||||
FcChar8 *str;
|
FcChar8 *str;
|
||||||
FcPattern *pat = NULL, *best = NULL;
|
|
||||||
FcResult result;
|
|
||||||
FcBool r;
|
|
||||||
int ret, i;
|
|
||||||
struct gdi_font_face *face = NULL;
|
|
||||||
|
|
||||||
if (!fs.fsCsb[0]) return NULL;
|
if ((pitch_and_family & FIXED_PITCH) || (pitch_and_family & 0xf0) == FF_MODERN) pat = pattern_fixed;
|
||||||
|
else if ((pitch_and_family & 0xf0) == FF_ROMAN) pat = pattern_serif;
|
||||||
|
else pat = pattern_sans;
|
||||||
|
|
||||||
if((lf->lfPitchAndFamily & FIXED_PITCH) ||
|
if (!pat) return FALSE;
|
||||||
(lf->lfPitchAndFamily & 0xF0) == FF_MODERN)
|
if (pFcPatternGetString( pat, FC_FAMILY, index, &str ) != FcResultMatch) return FALSE;
|
||||||
name = "monospace";
|
if (!MultiByteToWideChar( CP_UTF8, 0, (char *)str, -1, buffer, LF_FACESIZE ))
|
||||||
else if((lf->lfPitchAndFamily & 0xF0) == FF_ROMAN)
|
buffer[LF_FACESIZE - 1] = 0;
|
||||||
name = "serif";
|
return TRUE;
|
||||||
else
|
|
||||||
name = "sans-serif";
|
|
||||||
|
|
||||||
pat = pFcPatternCreate();
|
|
||||||
if (!pat) return NULL;
|
|
||||||
r = pFcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name);
|
|
||||||
if (!r) goto end;
|
|
||||||
r = pFcPatternAddString(pat, FC_NAMELANG, (const FcChar8 *)"en-us");
|
|
||||||
if (!r) goto end;
|
|
||||||
r = pFcPatternAddString(pat, FC_PRGNAME, (const FcChar8 *)"wine");
|
|
||||||
if (!r) goto end;
|
|
||||||
r = pFcConfigSubstitute(NULL, pat, FcMatchPattern);
|
|
||||||
if (!r) goto end;
|
|
||||||
pFcDefaultSubstitute(pat);
|
|
||||||
|
|
||||||
best = pFcFontMatch(NULL, pat, &result);
|
|
||||||
if (!best || result != FcResultMatch) goto end;
|
|
||||||
|
|
||||||
for (i = 0; pFcPatternGetString(best, FC_FAMILY, i, &str) == FcResultMatch; i++)
|
|
||||||
{
|
|
||||||
if (!want_vertical)
|
|
||||||
{
|
|
||||||
ret = MultiByteToWideChar(CP_UTF8, 0, (const char*)str, -1,
|
|
||||||
nameW, ARRAY_SIZE(nameW));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nameW[0] = '@';
|
|
||||||
ret = MultiByteToWideChar(CP_UTF8, 0, (const char*)str, -1,
|
|
||||||
nameW + 1, ARRAY_SIZE(nameW) - 1);
|
|
||||||
}
|
|
||||||
if (!ret) continue;
|
|
||||||
if ((face = find_matching_face_by_name( nameW, NULL, lf, fs, FALSE ))) break;
|
|
||||||
}
|
|
||||||
if (face) TRACE("got %s\n", wine_dbgstr_w(nameW));
|
|
||||||
|
|
||||||
end:
|
|
||||||
pFcPatternDestroy(pat);
|
|
||||||
pFcPatternDestroy(best);
|
|
||||||
return face;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static DWORD get_ttc_offset( FT_Face ft_face, UINT face_index )
|
static DWORD get_ttc_offset( FT_Face ft_face, UINT face_index )
|
||||||
{
|
{
|
||||||
|
@ -2340,27 +2324,6 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
|
||||||
|
|
||||||
want_vertical = (lf.lfFaceName[0] == '@');
|
want_vertical = (lf.lfFaceName[0] == '@');
|
||||||
|
|
||||||
/* Face families are in the top 4 bits of lfPitchAndFamily,
|
|
||||||
so mask with 0xF0 before testing */
|
|
||||||
|
|
||||||
if((lf.lfPitchAndFamily & FIXED_PITCH) ||
|
|
||||||
(lf.lfPitchAndFamily & 0xF0) == FF_MODERN)
|
|
||||||
strcpyW(lf.lfFaceName, default_fixed);
|
|
||||||
else if((lf.lfPitchAndFamily & 0xF0) == FF_ROMAN)
|
|
||||||
strcpyW(lf.lfFaceName, default_serif);
|
|
||||||
else if((lf.lfPitchAndFamily & 0xF0) == FF_SWISS)
|
|
||||||
strcpyW(lf.lfFaceName, default_sans);
|
|
||||||
else
|
|
||||||
strcpyW(lf.lfFaceName, default_sans);
|
|
||||||
|
|
||||||
if ((face = find_matching_face_by_name( lf.lfFaceName, NULL, &lf, csi.fs, can_use_bitmap )))
|
|
||||||
goto found_face;
|
|
||||||
|
|
||||||
#ifdef SONAME_LIBFONTCONFIG
|
|
||||||
/* Try FontConfig substitutions if the face isn't found */
|
|
||||||
if ((face = get_fontconfig_face( &lf, csi.fs, want_vertical ))) goto found_face;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((face = find_any_face( &lf, csi.fs, can_use_bitmap, want_vertical ))) goto found_face;
|
if ((face = find_any_face( &lf, csi.fs, can_use_bitmap, want_vertical ))) goto found_face;
|
||||||
csi.fs.fsCsb[0] = 0;
|
csi.fs.fsCsb[0] = 0;
|
||||||
if ((face = find_any_face( &lf, csi.fs, can_use_bitmap, want_vertical ))) goto found_face;
|
if ((face = find_any_face( &lf, csi.fs, can_use_bitmap, want_vertical ))) goto found_face;
|
||||||
|
@ -4231,6 +4194,7 @@ static const struct font_backend_funcs font_funcs =
|
||||||
{
|
{
|
||||||
freetype_SelectFont,
|
freetype_SelectFont,
|
||||||
freetype_load_fonts,
|
freetype_load_fonts,
|
||||||
|
fontconfig_enum_family_fallbacks,
|
||||||
freetype_add_font,
|
freetype_add_font,
|
||||||
freetype_add_mem_font,
|
freetype_add_mem_font,
|
||||||
freetype_load_font,
|
freetype_load_font,
|
||||||
|
|
|
@ -428,6 +428,7 @@ struct font_backend_funcs
|
||||||
struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont );
|
struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont );
|
||||||
|
|
||||||
void (CDECL *load_fonts)(void);
|
void (CDECL *load_fonts)(void);
|
||||||
|
BOOL (CDECL *enum_family_fallbacks)( DWORD pitch_and_family, int index, WCHAR buffer[LF_FACESIZE] );
|
||||||
INT (CDECL *add_font)( const WCHAR *file, DWORD flags );
|
INT (CDECL *add_font)( const WCHAR *file, DWORD flags );
|
||||||
INT (CDECL *add_mem_font)( void *ptr, SIZE_T size, DWORD flags );
|
INT (CDECL *add_mem_font)( void *ptr, SIZE_T size, DWORD flags );
|
||||||
|
|
||||||
|
@ -474,9 +475,6 @@ extern struct gdi_font *create_gdi_font( const struct gdi_font_face *face, const
|
||||||
const LOGFONTW *lf ) DECLSPEC_HIDDEN;
|
const LOGFONTW *lf ) DECLSPEC_HIDDEN;
|
||||||
extern void *get_GSUB_vert_feature( struct gdi_font *font ) DECLSPEC_HIDDEN;
|
extern void *get_GSUB_vert_feature( struct gdi_font *font ) DECLSPEC_HIDDEN;
|
||||||
extern void font_init(void) DECLSPEC_HIDDEN;
|
extern void font_init(void) DECLSPEC_HIDDEN;
|
||||||
extern const WCHAR *default_serif DECLSPEC_HIDDEN;
|
|
||||||
extern const WCHAR *default_fixed DECLSPEC_HIDDEN;
|
|
||||||
extern const WCHAR *default_sans DECLSPEC_HIDDEN;
|
|
||||||
|
|
||||||
/* freetype.c */
|
/* freetype.c */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue