gdi32: Add some helper functions for font matching.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6c5dc58a82
commit
caf0b9c082
|
@ -554,7 +554,7 @@ static void load_gdi_font_subst(void)
|
||||||
|
|
||||||
/* font families */
|
/* font families */
|
||||||
|
|
||||||
struct list font_list = LIST_INIT(font_list);
|
static struct list font_list = LIST_INIT(font_list);
|
||||||
|
|
||||||
static struct gdi_font_family *create_family( const WCHAR *name, const WCHAR *second_name )
|
static struct gdi_font_family *create_family( const WCHAR *name, const WCHAR *second_name )
|
||||||
{
|
{
|
||||||
|
@ -592,7 +592,7 @@ static struct gdi_font_family *find_family_from_name( const WCHAR *name )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gdi_font_family *find_family_from_any_name( const WCHAR *name )
|
static struct gdi_font_family *find_family_from_any_name( const WCHAR *name )
|
||||||
{
|
{
|
||||||
struct gdi_font_family *family;
|
struct gdi_font_family *family;
|
||||||
|
|
||||||
|
@ -1160,7 +1160,7 @@ struct gdi_font_link *find_gdi_font_link( const WCHAR *name )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gdi_font_family *find_family_from_font_links( const WCHAR *name, const WCHAR *subst,
|
static struct gdi_font_family *find_family_from_font_links( const WCHAR *name, const WCHAR *subst,
|
||||||
FONTSIGNATURE fs )
|
FONTSIGNATURE fs )
|
||||||
{
|
{
|
||||||
struct gdi_font_link *link;
|
struct gdi_font_link *link;
|
||||||
|
@ -1391,6 +1391,114 @@ static void load_system_links(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* font matching */
|
||||||
|
|
||||||
|
static BOOL can_select_face( const struct gdi_font_face *face, FONTSIGNATURE fs, BOOL can_use_bitmap )
|
||||||
|
{
|
||||||
|
struct gdi_font_link *font_link;
|
||||||
|
|
||||||
|
if (!face->scalable && !can_use_bitmap) return FALSE;
|
||||||
|
if (!fs.fsCsb[0]) return TRUE;
|
||||||
|
if (fs.fsCsb[0] & face->fs.fsCsb[0]) return TRUE;
|
||||||
|
if (!(font_link = find_gdi_font_link( face->family->family_name ))) return FALSE;
|
||||||
|
if (fs.fsCsb[0] & font_link->fs.fsCsb[0]) return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gdi_font_face *find_best_matching_face( const struct gdi_font_family *family,
|
||||||
|
const LOGFONTW *lf, FONTSIGNATURE fs,
|
||||||
|
BOOL can_use_bitmap )
|
||||||
|
{
|
||||||
|
struct gdi_font_face *face = NULL, *best = NULL, *best_bitmap = NULL;
|
||||||
|
unsigned int best_score = 4;
|
||||||
|
int best_diff = 0;
|
||||||
|
int it = !!lf->lfItalic;
|
||||||
|
int bd = lf->lfWeight > 550;
|
||||||
|
int height = lf->lfHeight;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
||||||
|
{
|
||||||
|
int italic = !!(face->ntmFlags & NTM_ITALIC);
|
||||||
|
int bold = !!(face->ntmFlags & NTM_BOLD);
|
||||||
|
int score = (italic ^ it) + (bold ^ bd);
|
||||||
|
|
||||||
|
if (!can_select_face( face, fs, can_use_bitmap )) continue;
|
||||||
|
if (score > best_score) continue;
|
||||||
|
TRACE( "(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n", italic, bold, it, bd );
|
||||||
|
best_score = score;
|
||||||
|
best = face;
|
||||||
|
if (best->scalable && best_score == 0) break;
|
||||||
|
if (!best->scalable)
|
||||||
|
{
|
||||||
|
int diff;
|
||||||
|
if (height > 0)
|
||||||
|
diff = height - (signed int)best->size.height;
|
||||||
|
else
|
||||||
|
diff = -height - ((signed int)best->size.height - best->size.internal_leading);
|
||||||
|
if (!best_bitmap ||
|
||||||
|
(best_diff > 0 && diff >= 0 && diff < best_diff) ||
|
||||||
|
(best_diff < 0 && diff > best_diff))
|
||||||
|
{
|
||||||
|
TRACE( "%d is better for %d diff was %d\n", best->size.height, height, best_diff );
|
||||||
|
best_diff = diff;
|
||||||
|
best_bitmap = best;
|
||||||
|
if (best_score == 0 && best_diff == 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!best) return NULL;
|
||||||
|
return best->scalable ? best : best_bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gdi_font_face *find_matching_face_by_name( const WCHAR *name, const WCHAR *subst, const LOGFONTW *lf,
|
||||||
|
FONTSIGNATURE fs, BOOL can_use_bitmap )
|
||||||
|
{
|
||||||
|
struct gdi_font_family *family;
|
||||||
|
struct gdi_font_face *face;
|
||||||
|
|
||||||
|
family = find_family_from_any_name( name );
|
||||||
|
if (family && (face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
||||||
|
if (subst)
|
||||||
|
{
|
||||||
|
family = find_family_from_any_name( subst );
|
||||||
|
if (family && (face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search by full face name */
|
||||||
|
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
||||||
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
||||||
|
if (!strncmpiW( face->full_name, name, LF_FACESIZE - 1 ) &&
|
||||||
|
can_select_face( face, fs, can_use_bitmap ))
|
||||||
|
return face;
|
||||||
|
|
||||||
|
if ((family = find_family_from_font_links( name, subst, fs )))
|
||||||
|
{
|
||||||
|
if ((face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gdi_font_face *find_any_face( const LOGFONTW *lf, FONTSIGNATURE fs,
|
||||||
|
BOOL can_use_bitmap, BOOL want_vertical )
|
||||||
|
{
|
||||||
|
struct gdi_font_family *family;
|
||||||
|
struct gdi_font_face *face;
|
||||||
|
|
||||||
|
/* first try only scalable */
|
||||||
|
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
||||||
|
{
|
||||||
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
||||||
|
if ((face = find_best_matching_face( family, lf, fs, FALSE ))) return face;
|
||||||
|
}
|
||||||
|
if (!can_use_bitmap) return NULL;
|
||||||
|
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
|
||||||
|
{
|
||||||
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
||||||
|
if ((face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* realized font objects */
|
/* realized font objects */
|
||||||
|
|
||||||
#define FIRST_FONT_HANDLE 1
|
#define FIRST_FONT_HANDLE 1
|
||||||
|
@ -1927,31 +2035,13 @@ static UINT get_GSUB_vert_glyph( struct gdi_font *font, UINT glyph )
|
||||||
|
|
||||||
static void add_child_font( struct gdi_font *font, const WCHAR *family_name )
|
static void add_child_font( struct gdi_font *font, const WCHAR *family_name )
|
||||||
{
|
{
|
||||||
|
FONTSIGNATURE fs = {{0}};
|
||||||
struct gdi_font *child;
|
struct gdi_font *child;
|
||||||
struct gdi_font_family *family;
|
struct gdi_font_face *face;
|
||||||
struct gdi_font_face *child_face, *best_face = NULL;
|
|
||||||
UINT penalty = 0, new_penalty = 0;
|
|
||||||
BOOL bold, italic, bd, it;
|
|
||||||
|
|
||||||
italic = !!font->lf.lfItalic;
|
if (!(face = find_matching_face_by_name( family_name, NULL, &font->lf, fs, FALSE ))) return;
|
||||||
bold = font->lf.lfWeight > FW_MEDIUM;
|
|
||||||
|
|
||||||
if (!(family = find_family_from_name( family_name ))) return;
|
if (!(child = create_gdi_font( face, family_name, &font->lf ))) return;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( child_face, get_family_face_list(family), struct gdi_font_face, entry )
|
|
||||||
{
|
|
||||||
it = !!(child_face->ntmFlags & NTM_ITALIC);
|
|
||||||
bd = !!(child_face->ntmFlags & NTM_BOLD);
|
|
||||||
new_penalty = ( it ^ italic ) + ( bd ^ bold );
|
|
||||||
if (!best_face || new_penalty < penalty)
|
|
||||||
{
|
|
||||||
penalty = new_penalty;
|
|
||||||
best_face = child_face;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!best_face) return;
|
|
||||||
|
|
||||||
if (!(child = create_gdi_font( best_face, family_name, &font->lf ))) return;
|
|
||||||
child->matrix = font->matrix;
|
child->matrix = font->matrix;
|
||||||
child->can_use_bitmap = font->can_use_bitmap;
|
child->can_use_bitmap = font->can_use_bitmap;
|
||||||
child->scale_y = font->scale_y;
|
child->scale_y = font->scale_y;
|
||||||
|
|
|
@ -557,12 +557,6 @@ static BOOL is_subpixel_rendering_enabled( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct list *get_face_list_from_family(const Family *family)
|
|
||||||
{
|
|
||||||
if (family->replacement) return &family->replacement->faces;
|
|
||||||
return &family->faces;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR strdupW(LPCWSTR p)
|
static LPWSTR strdupW(LPCWSTR p)
|
||||||
{
|
{
|
||||||
LPWSTR ret;
|
LPWSTR ret;
|
||||||
|
@ -2077,7 +2071,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SONAME_LIBFONTCONFIG
|
#ifdef SONAME_LIBFONTCONFIG
|
||||||
static Family* get_fontconfig_family(DWORD pitch_and_family, const CHARSETINFO *csi, BOOL want_vertical)
|
static struct gdi_font_face *get_fontconfig_face( const LOGFONTW *lf, FONTSIGNATURE fs, BOOL want_vertical )
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
WCHAR nameW[LF_FACESIZE];
|
WCHAR nameW[LF_FACESIZE];
|
||||||
|
@ -2086,14 +2080,14 @@ static Family* get_fontconfig_family(DWORD pitch_and_family, const CHARSETINFO *
|
||||||
FcResult result;
|
FcResult result;
|
||||||
FcBool r;
|
FcBool r;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
Family *family = NULL;
|
struct gdi_font_face *face = NULL;
|
||||||
|
|
||||||
if (!csi->fs.fsCsb[0]) return NULL;
|
if (!fs.fsCsb[0]) return NULL;
|
||||||
|
|
||||||
if((pitch_and_family & FIXED_PITCH) ||
|
if((lf->lfPitchAndFamily & FIXED_PITCH) ||
|
||||||
(pitch_and_family & 0xF0) == FF_MODERN)
|
(lf->lfPitchAndFamily & 0xF0) == FF_MODERN)
|
||||||
name = "monospace";
|
name = "monospace";
|
||||||
else if((pitch_and_family & 0xF0) == FF_ROMAN)
|
else if((lf->lfPitchAndFamily & 0xF0) == FF_ROMAN)
|
||||||
name = "serif";
|
name = "serif";
|
||||||
else
|
else
|
||||||
name = "sans-serif";
|
name = "sans-serif";
|
||||||
|
@ -2113,14 +2107,8 @@ static Family* get_fontconfig_family(DWORD pitch_and_family, const CHARSETINFO *
|
||||||
best = pFcFontMatch(NULL, pat, &result);
|
best = pFcFontMatch(NULL, pat, &result);
|
||||||
if (!best || result != FcResultMatch) goto end;
|
if (!best || result != FcResultMatch) goto end;
|
||||||
|
|
||||||
for (i = 0;
|
for (i = 0; pFcPatternGetString(best, FC_FAMILY, i, &str) == FcResultMatch; i++)
|
||||||
!family && pFcPatternGetString(best, FC_FAMILY, i, &str) == FcResultMatch;
|
|
||||||
i++)
|
|
||||||
{
|
{
|
||||||
Face *face;
|
|
||||||
const struct gdi_font_link *font_link;
|
|
||||||
const struct list *face_list;
|
|
||||||
|
|
||||||
if (!want_vertical)
|
if (!want_vertical)
|
||||||
{
|
{
|
||||||
ret = MultiByteToWideChar(CP_UTF8, 0, (const char*)str, -1,
|
ret = MultiByteToWideChar(CP_UTF8, 0, (const char*)str, -1,
|
||||||
|
@ -2133,31 +2121,14 @@ static Family* get_fontconfig_family(DWORD pitch_and_family, const CHARSETINFO *
|
||||||
nameW + 1, ARRAY_SIZE(nameW) - 1);
|
nameW + 1, ARRAY_SIZE(nameW) - 1);
|
||||||
}
|
}
|
||||||
if (!ret) continue;
|
if (!ret) continue;
|
||||||
family = find_family_from_any_name(nameW);
|
if ((face = find_matching_face_by_name( nameW, NULL, lf, fs, FALSE ))) break;
|
||||||
if (!family) continue;
|
|
||||||
|
|
||||||
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)
|
|
||||||
continue;
|
|
||||||
if (csi->fs.fsCsb[0] & face->fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
if (font_link != NULL &&
|
|
||||||
csi->fs.fsCsb[0] & font_link->fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
}
|
}
|
||||||
family = NULL;
|
if (face) TRACE("got %s\n", wine_dbgstr_w(nameW));
|
||||||
}
|
|
||||||
|
|
||||||
found:
|
|
||||||
if (family)
|
|
||||||
TRACE("got %s\n", wine_dbgstr_w(nameW));
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
pFcPatternDestroy(pat);
|
pFcPatternDestroy(pat);
|
||||||
pFcPatternDestroy(best);
|
pFcPatternDestroy(best);
|
||||||
return family;
|
return face;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2261,18 +2232,14 @@ static BOOL CDECL freetype_load_font( struct gdi_font *font )
|
||||||
static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
|
static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
|
||||||
{
|
{
|
||||||
struct gdi_font *font;
|
struct gdi_font *font;
|
||||||
Face *face, *best, *best_bitmap;
|
Face *face;
|
||||||
Family *family, *last_resort_family;
|
Family *family;
|
||||||
const struct list *face_list;
|
|
||||||
INT height;
|
INT height;
|
||||||
unsigned int score = 0, new_score;
|
BOOL can_use_bitmap, want_vertical;
|
||||||
signed int diff = 0, newdiff;
|
|
||||||
BOOL bd, it, can_use_bitmap, want_vertical;
|
|
||||||
LOGFONTW lf;
|
LOGFONTW lf;
|
||||||
CHARSETINFO csi;
|
CHARSETINFO csi;
|
||||||
FMAT2 dcmat;
|
FMAT2 dcmat;
|
||||||
const WCHAR *orig_name = NULL;
|
const WCHAR *orig_name = NULL;
|
||||||
const struct gdi_font_link *font_link;
|
|
||||||
|
|
||||||
GetObjectW( hfont, sizeof(lf), &lf );
|
GetObjectW( hfont, sizeof(lf), &lf );
|
||||||
lf.lfWidth = abs(lf.lfWidth);
|
lf.lfWidth = abs(lf.lfWidth);
|
||||||
|
@ -2328,9 +2295,6 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
|
||||||
if(!strcmpiW(lf.lfFaceName, SymbolW))
|
if(!strcmpiW(lf.lfFaceName, SymbolW))
|
||||||
lf.lfCharSet = SYMBOL_CHARSET;
|
lf.lfCharSet = SYMBOL_CHARSET;
|
||||||
|
|
||||||
it = !!lf.lfItalic;
|
|
||||||
bd = lf.lfWeight > 550;
|
|
||||||
|
|
||||||
if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
|
if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
|
||||||
switch(lf.lfCharSet) {
|
switch(lf.lfCharSet) {
|
||||||
case DEFAULT_CHARSET:
|
case DEFAULT_CHARSET:
|
||||||
|
@ -2356,53 +2320,8 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
|
||||||
orig_name = FaceName;
|
orig_name = FaceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want a match on name and charset or just name if
|
if ((face = find_matching_face_by_name( FaceName, subst, &lf, csi.fs, can_use_bitmap )))
|
||||||
charset was DEFAULT_CHARSET. If the latter then
|
|
||||||
we fixup the returned charset later in get_nearest_charset
|
|
||||||
where we'll either use the charset of the current ansi codepage
|
|
||||||
or if that's unavailable the first charset that the font supports.
|
|
||||||
*/
|
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
|
|
||||||
if (!strncmpiW( family->family_name, FaceName, LF_FACESIZE - 1 ) ||
|
|
||||||
(subst && !strncmpiW( family->family_name, subst, LF_FACESIZE - 1 )))
|
|
||||||
{
|
|
||||||
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))
|
|
||||||
continue;
|
|
||||||
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
if (font_link != NULL &&
|
|
||||||
csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
if (!csi.fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search by full face name. */
|
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
|
|
||||||
face_list = get_face_list_from_family(family);
|
|
||||||
LIST_FOR_EACH_ENTRY( face, face_list, Face, entry ) {
|
|
||||||
if (!strncmpiW( face->full_name, FaceName, LF_FACESIZE - 1 ) && (face->scalable || can_use_bitmap))
|
|
||||||
{
|
|
||||||
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0] || !csi.fs.fsCsb[0])
|
|
||||||
goto found_face;
|
goto found_face;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try check the SystemLink list first for a replacement font.
|
|
||||||
* We may find good replacements there.
|
|
||||||
*/
|
|
||||||
if ((family = find_family_from_font_links( FaceName, subst, csi.fs ))) goto found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
orig_name = NULL; /* substitution is no longer relevant */
|
orig_name = NULL; /* substitution is no longer relevant */
|
||||||
|
@ -2433,119 +2352,25 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont )
|
||||||
strcpyW(lf.lfFaceName, default_sans);
|
strcpyW(lf.lfFaceName, default_sans);
|
||||||
else
|
else
|
||||||
strcpyW(lf.lfFaceName, default_sans);
|
strcpyW(lf.lfFaceName, default_sans);
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
|
|
||||||
if (!strncmpiW( family->family_name, lf.lfFaceName, LF_FACESIZE - 1 ))
|
if ((face = find_matching_face_by_name( lf.lfFaceName, NULL, &lf, csi.fs, can_use_bitmap )))
|
||||||
{
|
goto found_face;
|
||||||
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))
|
|
||||||
continue;
|
|
||||||
if (csi.fs.fsCsb[0] & face->fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
if (font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0])
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SONAME_LIBFONTCONFIG
|
#ifdef SONAME_LIBFONTCONFIG
|
||||||
/* Try FontConfig substitutions if the face isn't found */
|
/* Try FontConfig substitutions if the face isn't found */
|
||||||
family = get_fontconfig_family(lf.lfPitchAndFamily, &csi, want_vertical);
|
if ((face = get_fontconfig_face( &lf, csi.fs, want_vertical ))) goto found_face;
|
||||||
if (family) goto found;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
last_resort_family = NULL;
|
if ((face = find_any_face( &lf, csi.fs, can_use_bitmap, want_vertical ))) goto found_face;
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
|
|
||||||
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 &&
|
|
||||||
(csi.fs.fsCsb[0] & face->fs.fsCsb[0] ||
|
|
||||||
(font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0]))) {
|
|
||||||
if(face->scalable)
|
|
||||||
goto found;
|
|
||||||
if(can_use_bitmap && !last_resort_family)
|
|
||||||
last_resort_family = family;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(last_resort_family) {
|
|
||||||
family = last_resort_family;
|
|
||||||
csi.fs.fsCsb[0] = 0;
|
csi.fs.fsCsb[0] = 0;
|
||||||
goto found;
|
if ((face = find_any_face( &lf, csi.fs, can_use_bitmap, want_vertical ))) goto found_face;
|
||||||
}
|
if (want_vertical && (face = find_any_face( &lf, csi.fs, can_use_bitmap, FALSE ))) goto found_face;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
|
|
||||||
face_list = get_face_list_from_family(family);
|
|
||||||
LIST_FOR_EACH_ENTRY( face, face_list, Face, entry ) {
|
|
||||||
if(face->scalable && !(face->flags & ADDFONT_VERTICAL_FONT) == !want_vertical) {
|
|
||||||
csi.fs.fsCsb[0] = 0;
|
|
||||||
WARN("just using first face for now\n");
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
if(can_use_bitmap && !last_resort_family)
|
|
||||||
last_resort_family = family;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!last_resort_family) {
|
|
||||||
FIXME("can't find a single appropriate font - bailing\n");
|
FIXME("can't find a single appropriate font - bailing\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
WARN("could only find a bitmap font - this will probably look awful!\n");
|
|
||||||
family = last_resort_family;
|
|
||||||
csi.fs.fsCsb[0] = 0;
|
|
||||||
|
|
||||||
found:
|
|
||||||
|
|
||||||
height = lf.lfHeight;
|
|
||||||
|
|
||||||
face = best = best_bitmap = NULL;
|
|
||||||
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 (csi.fs.fsCsb[0] & face->fs.fsCsb[0] ||
|
|
||||||
(font_link != NULL && csi.fs.fsCsb[0] & font_link->fs.fsCsb[0]) ||
|
|
||||||
!csi.fs.fsCsb[0])
|
|
||||||
{
|
|
||||||
BOOL italic, bold;
|
|
||||||
|
|
||||||
italic = (face->ntmFlags & NTM_ITALIC) ? 1 : 0;
|
|
||||||
bold = (face->ntmFlags & NTM_BOLD) ? 1 : 0;
|
|
||||||
new_score = (italic ^ it) + (bold ^ bd);
|
|
||||||
if(!best || new_score <= score)
|
|
||||||
{
|
|
||||||
TRACE("(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n",
|
|
||||||
italic, bold, it, bd);
|
|
||||||
score = new_score;
|
|
||||||
best = face;
|
|
||||||
if(best->scalable && score == 0) break;
|
|
||||||
if(!best->scalable)
|
|
||||||
{
|
|
||||||
if(height > 0)
|
|
||||||
newdiff = height - (signed int)(best->size.height);
|
|
||||||
else
|
|
||||||
newdiff = -height - ((signed int)(best->size.height) - best->size.internal_leading);
|
|
||||||
if(!best_bitmap || new_score < score ||
|
|
||||||
(diff > 0 && newdiff < diff && newdiff >= 0) || (diff < 0 && newdiff > diff))
|
|
||||||
{
|
|
||||||
TRACE("%d is better for %d diff was %d\n", best->size.height, height, diff);
|
|
||||||
diff = newdiff;
|
|
||||||
best_bitmap = best;
|
|
||||||
if(score == 0 && diff == 0) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(best)
|
|
||||||
face = best->scalable ? best : best_bitmap;
|
|
||||||
|
|
||||||
found_face:
|
found_face:
|
||||||
height = lf.lfHeight;
|
height = lf.lfHeight;
|
||||||
|
family = face->family;
|
||||||
|
|
||||||
TRACE("not in cache\n");
|
TRACE("not in cache\n");
|
||||||
font = create_gdi_font( face, orig_name, &lf );
|
font = create_gdi_font( face, orig_name, &lf );
|
||||||
|
@ -2566,9 +2391,14 @@ found_face:
|
||||||
|
|
||||||
if(!face->scalable) {
|
if(!face->scalable) {
|
||||||
/* Windows uses integer scaling factors for bitmap fonts */
|
/* Windows uses integer scaling factors for bitmap fonts */
|
||||||
INT scale, scaled_height;
|
INT scale, scaled_height, diff;
|
||||||
struct gdi_font *cachedfont;
|
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 */
|
/* FIXME: rotation of bitmap fonts is ignored */
|
||||||
height = abs(GDI_ROUND( (double)height * font->matrix.eM22 ));
|
height = abs(GDI_ROUND( (double)height * font->matrix.eM22 ));
|
||||||
if (font->aveWidth)
|
if (font->aveWidth)
|
||||||
|
|
|
@ -450,8 +450,6 @@ struct font_backend_funcs
|
||||||
|
|
||||||
extern const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset ) DECLSPEC_HIDDEN;
|
extern const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern struct list font_list DECLSPEC_HIDDEN;
|
|
||||||
extern struct gdi_font_family *find_family_from_any_name( const WCHAR *name ) DECLSPEC_HIDDEN;
|
|
||||||
extern int add_gdi_face( const WCHAR *family_name, const WCHAR *second_name,
|
extern int add_gdi_face( const WCHAR *family_name, const WCHAR *second_name,
|
||||||
const WCHAR *style, const WCHAR *fullname, const WCHAR *file,
|
const WCHAR *style, const WCHAR *fullname, const WCHAR *file,
|
||||||
void *data_ptr, SIZE_T data_size, UINT index, FONTSIGNATURE fs,
|
void *data_ptr, SIZE_T data_size, UINT index, FONTSIGNATURE fs,
|
||||||
|
@ -459,9 +457,11 @@ extern int add_gdi_face( const WCHAR *family_name, const WCHAR *second_name,
|
||||||
const struct bitmap_font_size *size ) DECLSPEC_HIDDEN;
|
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_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 void create_child_font_list( struct gdi_font *font ) DECLSPEC_HIDDEN;
|
extern void create_child_font_list( struct gdi_font *font ) DECLSPEC_HIDDEN;
|
||||||
|
extern struct gdi_font_face *find_matching_face_by_name( const WCHAR *name, const WCHAR *subst, const LOGFONTW *lf,
|
||||||
|
FONTSIGNATURE fs, BOOL can_use_bitmap ) DECLSPEC_HIDDEN;
|
||||||
|
extern struct gdi_font_face *find_any_face( const LOGFONTW *lf, FONTSIGNATURE fs,
|
||||||
|
BOOL can_use_bitmap, BOOL want_vertical ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern void free_gdi_font( struct gdi_font *font ) 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 void cache_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue