gdi32: Move the SelectFont() implementation out of freetype.c.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-11-04 09:20:26 +01:00
parent 3b87839ec9
commit 53acdd5a8a
3 changed files with 178 additions and 221 deletions

View File

@ -472,7 +472,7 @@ static void dump_gdi_font_subst(void)
}
}
const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset )
static const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset )
{
struct gdi_font_subst *subst;
@ -1162,7 +1162,7 @@ static void remove_face_from_cache( struct gdi_font_face *face )
static struct list font_links = LIST_INIT(font_links);
struct gdi_font_link *find_gdi_font_link( const WCHAR *name )
static struct gdi_font_link *find_gdi_font_link( const WCHAR *name )
{
struct gdi_font_link *link;
@ -1525,8 +1525,8 @@ static struct gdi_font_face *find_any_face( const LOGFONTW *lf, FONTSIGNATURE fs
return NULL;
}
struct gdi_font_face *find_matching_face( LOGFONTW *lf, CHARSETINFO *csi, BOOL can_use_bitmap,
const WCHAR **orig_name )
static struct gdi_font_face *find_matching_face( const LOGFONTW *lf, CHARSETINFO *csi, BOOL can_use_bitmap,
const WCHAR **orig_name )
{
BOOL want_vertical = (lf->lfFaceName[0] == '@');
struct gdi_font_face *face;
@ -1546,7 +1546,8 @@ struct gdi_font_face *find_matching_face( LOGFONTW *lf, CHARSETINFO *csi, BOOL c
{
TRACE( "substituting %s,%d -> %s,%d\n", debugstr_w(lf->lfFaceName), lf->lfCharSet,
debugstr_w(subst), (subst_charset != -1) ? subst_charset : lf->lfCharSet );
if (subst_charset != -1) lf->lfCharSet = subst_charset;
if (subst_charset != -1)
TranslateCharsetInfo( (DWORD *)(INT_PTR)subst_charset, csi, TCI_SRCCHARSET );
*orig_name = lf->lfFaceName;
}
@ -1565,7 +1566,6 @@ struct gdi_font_face *find_matching_face( LOGFONTW *lf, CHARSETINFO *csi, BOOL c
FIXME( "TCI failed on codepage %d\n", acp );
csi->fs.fsCsb[0] = 0;
}
else lf->lfCharSet = csi->ciCharset;
}
if ((face = find_any_face( lf, csi->fs, can_use_bitmap, want_vertical ))) return face;
@ -1681,7 +1681,7 @@ static struct gdi_font *alloc_gdi_font( const WCHAR *file, void *data_ptr, SIZE_
return font;
}
void free_gdi_font( struct gdi_font *font )
static void free_gdi_font( struct gdi_font *font )
{
DWORD i;
struct gdi_font *child, *child_next;
@ -1712,8 +1712,8 @@ void set_gdi_font_names( struct gdi_font *font, const WCHAR *family_name, const
font->otm.otmpFaceName = (char *)strdupW( full_name );
}
struct gdi_font *create_gdi_font( const struct gdi_font_face *face, const WCHAR *family_name,
const LOGFONTW *lf )
static struct gdi_font *create_gdi_font( const struct gdi_font_face *face, const WCHAR *family_name,
const LOGFONTW *lf )
{
struct gdi_font *font;
@ -1979,7 +1979,7 @@ static const char *get_opentype_script( const struct gdi_font *font )
}
}
void *get_GSUB_vert_feature( struct gdi_font *font )
static void *get_GSUB_vert_feature( struct gdi_font *font )
{
GSUB_Header *header;
GSUB_Script *script;
@ -2132,7 +2132,7 @@ static void add_child_font( struct gdi_font *font, const WCHAR *family_name )
TRACE( "created child font %p for base %p\n", child, font );
}
void create_child_font_list( struct gdi_font *font )
static void create_child_font_list( struct gdi_font *font )
{
static const WCHAR szDefaultFallbackLink[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0};
struct gdi_font_link *font_link;
@ -2206,7 +2206,7 @@ static DWORD hash_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bi
return hash;
}
void cache_gdi_font( struct gdi_font *font )
static void cache_gdi_font( struct gdi_font *font )
{
static DWORD cache_num = 1;
@ -2216,7 +2216,7 @@ void cache_gdi_font( struct gdi_font *font )
TRACE( "font %p\n", font );
}
struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bitmap )
static struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bitmap )
{
struct gdi_font *font;
DWORD hash = hash_font( lf, matrix, can_use_bitmap );
@ -3534,6 +3534,133 @@ static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
}
static void get_nearest_charset( const WCHAR *family_name, struct gdi_font_face *face, CHARSETINFO *csi )
{
/* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
a single face with the requested charset. The idea is to check if
the selected font supports the current ANSI codepage, if it does
return the corresponding charset, else return the first charset */
int i;
if (TranslateCharsetInfo( (DWORD*)(INT_PTR)GetACP(), csi, TCI_SRCCODEPAGE ))
{
const struct gdi_font_link *font_link;
if (csi->fs.fsCsb[0] & face->fs.fsCsb[0]) return;
font_link = find_gdi_font_link(family_name);
if (font_link && (csi->fs.fsCsb[0] & font_link->fs.fsCsb[0])) return;
}
for (i = 0; i < 32; i++)
{
DWORD fs0 = 1u << i;
if (face->fs.fsCsb[0] & fs0)
{
if (TranslateCharsetInfo(&fs0, csi, TCI_SRCFONTSIG)) return;
FIXME("TCI failing on %x\n", fs0);
}
}
FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
face->fs.fsCsb[0], debugstr_w(face->file));
csi->ciACP = GetACP();
csi->ciCharset = DEFAULT_CHARSET;
}
static struct gdi_font *select_font( LOGFONTW *lf, FMAT2 dcmat, BOOL can_use_bitmap )
{
static const WCHAR SymbolW[] = {'S','y','m','b','o','l',0};
struct gdi_font *font;
struct gdi_font_face *face;
INT height;
CHARSETINFO csi;
const WCHAR *orig_name = NULL;
/* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
SYMBOL_CHARSET so that Symbol gets picked irrespective of the
original value lfCharSet. Note this is a special case for
Symbol and doesn't happen at least for "Wingdings*" */
if (!strcmpiW( lf->lfFaceName, SymbolW )) lf->lfCharSet = SYMBOL_CHARSET;
/* check the cache first */
if ((font = find_cached_gdi_font( lf, &dcmat, can_use_bitmap )))
{
TRACE( "returning cached gdiFont(%p)\n", font );
return font;
}
if (!(face = find_matching_face( lf, &csi, can_use_bitmap, &orig_name )))
{
FIXME( "can't find a single appropriate font - bailing\n" );
return NULL;
}
height = lf->lfHeight;
font = create_gdi_font( face, orig_name, lf );
font->matrix = dcmat;
font->can_use_bitmap = can_use_bitmap;
if (!csi.fs.fsCsb[0]) get_nearest_charset( face->family->family_name, face, &csi );
font->charset = csi.ciCharset;
font->codepage = csi.ciACP;
TRACE( "Chosen: %s (%s/%p:%u)\n", debugstr_w(face->full_name), debugstr_w(face->file),
face->data_ptr, face->face_index );
font->aveWidth = height ? lf->lfWidth : 0;
if (!face->scalable)
{
/* Windows uses integer scaling factors for bitmap fonts */
INT scale, scaled_height, diff;
struct gdi_font *cachedfont;
if (height > 0)
diff = height - (signed int)face->size.height;
else
diff = -height - ((signed int)face->size.height - face->size.internal_leading);
/* FIXME: rotation of bitmap fonts is ignored */
height = abs(GDI_ROUND( (double)height * font->matrix.eM22 ));
if (font->aveWidth)
font->aveWidth = (double)font->aveWidth * font->matrix.eM11;
font->matrix.eM11 = font->matrix.eM22 = 1.0;
dcmat.eM11 = dcmat.eM22 = 1.0;
/* As we changed the matrix, we need to search the cache for the font again,
* otherwise we might explode the cache. */
if ((cachedfont = find_cached_gdi_font( lf, &dcmat, can_use_bitmap )))
{
TRACE("Found cached font after non-scalable matrix rescale!\n");
free_gdi_font( font );
return cachedfont;
}
if (height != 0) height = diff;
height += face->size.height;
scale = (height + face->size.height - 1) / face->size.height;
scaled_height = scale * face->size.height;
/* Only jump to the next height if the difference <= 25% original height */
if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
/* The jump between unscaled and doubled is delayed by 1 */
else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
font->scale_y = scale;
}
TRACE("font scale y: %f\n", font->scale_y);
if (!font_funcs->load_font( font ))
{
free_gdi_font( font );
return NULL;
}
if (face->flags & ADDFONT_VERTICAL_FONT) /* We need to try to load the GSUB table */
font->vert_feature = get_GSUB_vert_feature( font );
create_child_font_list( font );
TRACE( "caching: gdiFont=%p\n", font );
cache_gdi_font( font );
return font;
}
/*************************************************************
* font_SelectFont
*/
@ -3546,6 +3673,8 @@ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
if (hfont)
{
LOGFONTW lf;
FMAT2 dcmat;
BOOL can_use_bitmap = !!(GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_RA_ABLE);
GetObjectW( hfont, sizeof(lf), &lf );
switch (lf.lfQuality)
@ -3558,9 +3687,44 @@ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
break;
}
lf.lfWidth = abs(lf.lfWidth);
TRACE( "%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
lf.lfEscapement );
if (dc->GraphicsMode == GM_ADVANCED)
{
memcpy( &dcmat, &dc->xformWorld2Vport, sizeof(FMAT2) );
/* try to avoid not necessary glyph transformations */
if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
{
lf.lfHeight *= fabs(dcmat.eM11);
lf.lfWidth *= fabs(dcmat.eM11);
dcmat.eM11 = dcmat.eM22 = dcmat.eM11 < 0 ? -1 : 1;
}
}
else
{
/* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited font scaling abilities */
dcmat.eM11 = dcmat.eM22 = 1.0;
dcmat.eM21 = dcmat.eM12 = 0;
lf.lfOrientation = lf.lfEscapement;
if (dc->vport2WorldValid)
{
if (dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0)
lf.lfOrientation = -lf.lfOrientation;
lf.lfHeight *= fabs(dc->xformWorld2Vport.eM22);
lf.lfWidth *= fabs(dc->xformWorld2Vport.eM22);
}
}
TRACE( "DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12, dcmat.eM21, dcmat.eM22 );
EnterCriticalSection( &font_cs );
font = font_funcs->pSelectFont( dc, hfont );
font = select_font( &lf, dcmat, can_use_bitmap );
if (font && !*aa_flags)
{
*aa_flags = font->aa_flags;

View File

@ -250,8 +250,6 @@ static inline FT_Face get_ft_face( struct gdi_font *font )
static const struct font_backend_funcs font_funcs;
static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
struct font_mapping
{
struct list entry;
@ -1714,48 +1712,6 @@ static void unmap_font_file( struct font_mapping *mapping )
static LONG load_VDMX(struct gdi_font *font, LONG height);
static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp)
{
/* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
a single face with the requested charset. The idea is to check if
the selected font supports the current ANSI codepage, if it does
return the corresponding charset, else return the first charset */
CHARSETINFO csi;
int acp = GetACP(), i;
DWORD fs0;
*cp = acp;
if(TranslateCharsetInfo((DWORD*)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE))
{
const struct gdi_font_link *font_link;
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
return csi.ciCharset;
font_link = find_gdi_font_link(family_name);
if (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
return csi.ciCharset;
}
for(i = 0; i < 32; i++) {
fs0 = 1L << i;
if(face->fs.fsCsb[0] & fs0) {
if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG)) {
*cp = csi.ciACP;
return csi.ciCharset;
}
else
FIXME("TCI failing on %x\n", fs0);
}
}
FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
face->fs.fsCsb[0], debugstr_w(face->file));
*cp = acp;
return DEFAULT_CHARSET;
}
/*************************************************************
* freetype_destroy_font
*/
@ -2210,152 +2166,6 @@ static BOOL CDECL freetype_load_font( struct gdi_font *font )
}
/*************************************************************
* freetype_SelectFont
*/
static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
{
struct gdi_font *font;
Face *face;
INT height;
BOOL can_use_bitmap;
LOGFONTW lf;
CHARSETINFO csi;
FMAT2 dcmat;
const WCHAR *orig_name = NULL;
GetObjectW( hfont, sizeof(lf), &lf );
lf.lfWidth = abs(lf.lfWidth);
can_use_bitmap = !!(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE);
TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
lf.lfEscapement);
if(dc->GraphicsMode == GM_ADVANCED)
{
memcpy(&dcmat, &dc->xformWorld2Vport, sizeof(FMAT2));
/* Try to avoid not necessary glyph transformations */
if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
{
lf.lfHeight *= fabs(dcmat.eM11);
lf.lfWidth *= fabs(dcmat.eM11);
dcmat.eM11 = dcmat.eM22 = dcmat.eM11 < 0 ? -1 : 1;
}
}
else
{
/* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited
font scaling abilities. */
dcmat.eM11 = dcmat.eM22 = 1.0;
dcmat.eM21 = dcmat.eM12 = 0;
lf.lfOrientation = lf.lfEscapement;
if (dc->vport2WorldValid)
{
if (dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0)
lf.lfOrientation = -lf.lfOrientation;
lf.lfHeight *= fabs(dc->xformWorld2Vport.eM22);
lf.lfWidth *= fabs(dc->xformWorld2Vport.eM22);
}
}
TRACE("DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12,
dcmat.eM21, dcmat.eM22);
/* check the cache first */
if ((font = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) {
TRACE("returning cached gdiFont(%p) for hFont %p\n", font, hfont);
return font;
}
/* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
SYMBOL_CHARSET so that Symbol gets picked irrespective of the
original value lfCharSet. Note this is a special case for
Symbol and doesn't happen at least for "Wingdings*" */
if(!strcmpiW(lf.lfFaceName, SymbolW))
lf.lfCharSet = SYMBOL_CHARSET;
if (!(face = find_matching_face( &lf, &csi, can_use_bitmap, &orig_name )))
{
FIXME("can't find a single appropriate font - bailing\n");
return NULL;
}
height = lf.lfHeight;
TRACE("not in cache\n");
font = create_gdi_font( face, orig_name, &lf );
font->matrix = dcmat;
font->can_use_bitmap = can_use_bitmap;
if(csi.fs.fsCsb[0]) {
font->charset = lf.lfCharSet;
font->codepage = csi.ciACP;
}
else
font->charset = get_nearest_charset( face->family->family_name, face, &font->codepage );
TRACE( "Chosen: %s (%s/%p:%u)\n", debugstr_w(face->full_name), debugstr_w(face->file),
face->data_ptr, face->face_index );
font->aveWidth = height ? lf.lfWidth : 0;
if(!face->scalable) {
/* Windows uses integer scaling factors for bitmap fonts */
INT scale, scaled_height, diff;
struct gdi_font *cachedfont;
if (height > 0)
diff = height - (signed int)face->size.height;
else
diff = -height - ((signed int)face->size.height - face->size.internal_leading);
/* FIXME: rotation of bitmap fonts is ignored */
height = abs(GDI_ROUND( (double)height * font->matrix.eM22 ));
if (font->aveWidth)
font->aveWidth = (double)font->aveWidth * font->matrix.eM11;
font->matrix.eM11 = font->matrix.eM22 = 1.0;
dcmat.eM11 = dcmat.eM22 = 1.0;
/* As we changed the matrix, we need to search the cache for the font again,
* otherwise we might explode the cache. */
if((cachedfont = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) {
TRACE("Found cached font after non-scalable matrix rescale!\n");
free_gdi_font( font );
return cachedfont;
}
if (height != 0) height = diff;
height += face->size.height;
scale = (height + face->size.height - 1) / face->size.height;
scaled_height = scale * face->size.height;
/* Only jump to the next height if the difference <= 25% original height */
if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
/* The jump between unscaled and doubled is delayed by 1 */
else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
font->scale_y = scale;
}
TRACE("font scale y: %f\n", font->scale_y);
if (!freetype_load_font( font ))
{
free_gdi_font( font );
return NULL;
}
if (face->flags & ADDFONT_VERTICAL_FONT) /* We need to try to load the GSUB table */
font->vert_feature = get_GSUB_vert_feature( font );
create_child_font_list( font );
TRACE("caching: gdiFont=%p hfont=%p\n", font, hfont);
cache_gdi_font( font );
return font;
}
/*************************************************************
* freetype_get_aa_flags
*/
@ -4142,7 +3952,6 @@ static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *font, KERNINGPAI
static const struct font_backend_funcs font_funcs =
{
freetype_SelectFont,
freetype_load_fonts,
fontconfig_enum_family_fallbacks,
freetype_add_font,

View File

@ -425,8 +425,6 @@ struct gdi_font
struct font_backend_funcs
{
struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont );
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 );
@ -449,29 +447,15 @@ struct font_backend_funcs
void (CDECL *destroy_font)( struct gdi_font *font );
};
extern const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset ) DECLSPEC_HIDDEN;
extern int add_gdi_face( const WCHAR *family_name, const WCHAR *second_name,
const WCHAR *style, const WCHAR *fullname, const WCHAR *file,
void *data_ptr, SIZE_T data_size, 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 void create_child_font_list( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern struct gdi_font_face *find_matching_face( LOGFONTW *lf, CHARSETINFO *csi, BOOL can_use_bitmap,
const WCHAR **orig_name ) DECLSPEC_HIDDEN;
extern void free_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern void cache_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix,
BOOL can_use_bitmap ) DECLSPEC_HIDDEN;
static inline const WCHAR *get_gdi_font_name( struct gdi_font *font ) { return (WCHAR *)font->otm.otmpFamilyName; }
extern void set_gdi_font_names( struct gdi_font *font, const WCHAR *family_name, const WCHAR *style_name,
const WCHAR *full_name ) DECLSPEC_HIDDEN;
extern struct gdi_font *create_gdi_font( const struct gdi_font_face *face, const WCHAR *family_name,
const LOGFONTW *lf ) DECLSPEC_HIDDEN;
extern void *get_GSUB_vert_feature( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern void font_init(void) DECLSPEC_HIDDEN;
/* freetype.c */