-- v2: conhost: Imrove best matching font selection in set_first_font. conhost: Merge validate_font and validate_font_metric helpers. conhost: Allow raster fonts in enum_first_font_proc.
From: Piotr Caban piotr@codeweavers.com
--- programs/conhost/window.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/programs/conhost/window.c b/programs/conhost/window.c index 9817c5fdac9..1a6cedd9cb3 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -863,8 +863,6 @@ static int CALLBACK enum_first_font_proc( const LOGFONTW *lf, const TEXTMETRICW struct font_chooser *fc = (struct font_chooser *)lparam; LOGFONTW mlf;
- if (font_type != TRUETYPE_FONTTYPE) return 1; - TRACE( "%s\n", debugstr_logfont( lf, font_type ));
if (!validate_font( fc->console, lf, fc->pass ))
From: Piotr Caban piotr@codeweavers.com
--- programs/conhost/window.c | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-)
diff --git a/programs/conhost/window.c b/programs/conhost/window.c index 1a6cedd9cb3..ae259bdb9ab 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -805,9 +805,9 @@ struct font_chooser BOOL done; };
-/* check if the font described in tm is usable as a font for the renderer */ -static BOOL validate_font_metric( struct console *console, const TEXTMETRICW *tm, - DWORD type, int pass ) +/* check if the font family described in lf and tm is usable as a font for the renderer */ +static BOOL validate_font( struct console *console, const LOGFONTW *lf, + const TEXTMETRICW *tm, DWORD type, int pass ) { switch (pass) /* we get increasingly lenient in later passes */ { @@ -815,7 +815,7 @@ static BOOL validate_font_metric( struct console *console, const TEXTMETRICW *tm if (type & RASTER_FONTTYPE) return FALSE; /* fall through */ case 1: - if (type & RASTER_FONTTYPE) + if (tm && (type & RASTER_FONTTYPE)) { if (tm->tmMaxCharWidth * (console->active->win.right - console->active->win.left + 1) >= GetSystemMetrics(SM_CXSCREEN)) @@ -825,30 +825,15 @@ static BOOL validate_font_metric( struct console *console, const TEXTMETRICW *tm return FALSE; } /* fall through */ - case 2: - if (tm->tmCharSet != DEFAULT_CHARSET && tm->tmCharSet != console->window->ui_charset) - return FALSE; - /* fall through */ - case 3: - if (tm->tmItalic || tm->tmUnderlined || tm->tmStruckOut) return FALSE; - break; - } - return TRUE; -} - -/* check if the font family described in lf is usable as a font for the renderer */ -static BOOL validate_font( struct console *console, const LOGFONTW *lf, int pass ) -{ - switch (pass) /* we get increasingly lenient in later passes */ - { - case 0: - case 1: case 2: if (lf->lfCharSet != DEFAULT_CHARSET && lf->lfCharSet != console->window->ui_charset) return FALSE; + if (tm && tm->tmCharSet != DEFAULT_CHARSET && tm->tmCharSet != console->window->ui_charset) + return FALSE; /* fall through */ case 3: if ((lf->lfPitchAndFamily & 3) != FIXED_PITCH) return FALSE; + if (tm && (tm->tmItalic || tm->tmUnderlined || tm->tmStruckOut)) return FALSE; /* fall through */ case 4: if (lf->lfFaceName[0] == '@') return FALSE; @@ -864,13 +849,9 @@ static int CALLBACK enum_first_font_proc( const LOGFONTW *lf, const TEXTMETRICW LOGFONTW mlf;
TRACE( "%s\n", debugstr_logfont( lf, font_type )); - - if (!validate_font( fc->console, lf, fc->pass )) - return 1; - TRACE( "%s\n", debugstr_textmetric( tm, font_type ));
- if (!validate_font_metric( fc->console, tm, font_type, fc->pass )) + if (!validate_font( fc->console, lf, tm, font_type, fc->pass )) return 1;
/* set default font size */ @@ -1604,7 +1585,7 @@ static int CALLBACK enum_list_font_proc( const LOGFONTW *lf, const TEXTMETRICW *
TRACE( "%s\n", debugstr_logfont( lf, font_type ));
- if (validate_font( di->console, lf, 0 )) + if (validate_font( di->console, lf, NULL, 0, 0 )) SendDlgItemMessageW( di->dialog, IDC_FNT_LIST_FONT, LB_ADDSTRING, 0, (LPARAM)lf->lfFaceName );
return 1;
From: Piotr Caban piotr@codeweavers.com
Otherwise, on systems with only Wine provided fonts, we end up selecting first non-vertical font ignoring other properties. --- programs/conhost/window.c | 98 ++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 59 deletions(-)
diff --git a/programs/conhost/window.c b/programs/conhost/window.c index ae259bdb9ab..4f404284bd5 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -799,72 +799,56 @@ static BOOL set_console_font( struct console *console, const LOGFONTW *logfont ) struct font_chooser { struct console *console; - int pass; - unsigned int font_height; - unsigned int font_width; - BOOL done; + unsigned int weight; + LOGFONTW lf; };
/* check if the font family described in lf and tm is usable as a font for the renderer */ static BOOL validate_font( struct console *console, const LOGFONTW *lf, - const TEXTMETRICW *tm, DWORD type, int pass ) + const TEXTMETRICW *tm, DWORD type, int *weight ) { - switch (pass) /* we get increasingly lenient in later passes */ + int w = 0x1; + + if (!tm) w |= 0x6; + else if (!(type & RASTER_FONTTYPE)) { - case 0: - if (type & RASTER_FONTTYPE) return FALSE; - /* fall through */ - case 1: - if (tm && (type & RASTER_FONTTYPE)) - { - if (tm->tmMaxCharWidth * (console->active->win.right - console->active->win.left + 1) - >= GetSystemMetrics(SM_CXSCREEN)) - return FALSE; - if (tm->tmHeight * (console->active->win.bottom - console->active->win.top + 1) - >= GetSystemMetrics(SM_CYSCREEN)) - return FALSE; - } - /* fall through */ - case 2: - if (lf->lfCharSet != DEFAULT_CHARSET && lf->lfCharSet != console->window->ui_charset) - return FALSE; - if (tm && tm->tmCharSet != DEFAULT_CHARSET && tm->tmCharSet != console->window->ui_charset) - return FALSE; - /* fall through */ - case 3: - if ((lf->lfPitchAndFamily & 3) != FIXED_PITCH) return FALSE; - if (tm && (tm->tmItalic || tm->tmUnderlined || tm->tmStruckOut)) return FALSE; - /* fall through */ - case 4: - if (lf->lfFaceName[0] == '@') return FALSE; - break; + w |= 0x2; + if (tm->tmMaxCharWidth * (console->active->win.right - console->active->win.left + 1) + < GetSystemMetrics(SM_CXSCREEN) + && tm->tmHeight * (console->active->win.bottom - console->active->win.top + 1) + < GetSystemMetrics(SM_CYSCREEN)) + w |= 0x4; } - return TRUE; + if ((lf->lfCharSet == DEFAULT_CHARSET || lf->lfCharSet == console->window->ui_charset) + && (!tm || tm->tmCharSet == DEFAULT_CHARSET || tm->tmCharSet == console->window->ui_charset)) + w |= 0x8; + if ((lf->lfPitchAndFamily & 3) == FIXED_PITCH + && (!tm || (!tm->tmItalic && !tm->tmUnderlined && !tm->tmStruckOut))) + w |= 0x10; + if (lf->lfFaceName[0] != '@') + w |= 0x20; + + if (weight) *weight = w; + return w == 0x3f; }
static int CALLBACK enum_first_font_proc( const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD font_type, LPARAM lparam ) { struct font_chooser *fc = (struct font_chooser *)lparam; - LOGFONTW mlf; + int weight; + BOOL ret;
TRACE( "%s\n", debugstr_logfont( lf, font_type )); TRACE( "%s\n", debugstr_textmetric( tm, font_type ));
- if (!validate_font( fc->console, lf, tm, font_type, fc->pass )) - return 1; - - /* set default font size */ - mlf = *lf; - mlf.lfHeight = fc->font_height; - mlf.lfWidth = fc->font_width; - - if (!set_console_font( fc->console, &mlf )) - return 1; - - fc->done = TRUE; - - return 0; + ret = validate_font( fc->console, lf, tm, font_type, &weight ); + if (weight > fc->weight) + { + fc->weight = weight; + fc->lf = *lf; + } + return !ret; }
static void set_first_font( struct console *console, struct console_config *config ) @@ -878,18 +862,14 @@ static void set_first_font( struct console *console, struct console_config *conf lf.lfCharSet = DEFAULT_CHARSET; lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
+ memset( &fc, 0, sizeof(fc) ); fc.console = console; - fc.font_height = config->cell_height; - fc.font_width = config->cell_width; - fc.done = FALSE;
- for (fc.pass = 0; fc.pass <= 5; fc.pass++) - { - EnumFontFamiliesExW( console->window->mem_dc, &lf, enum_first_font_proc, (LPARAM)&fc, 0); - if (fc.done) break; - } + EnumFontFamiliesExW( console->window->mem_dc, &lf, enum_first_font_proc, (LPARAM)&fc, 0);
- if (fc.pass > 5) + fc.lf.lfHeight = config->cell_height; + fc.lf.lfWidth = config->cell_width; + if (!fc.weight || !set_console_font( console, &fc.lf )) ERR("Unable to find a valid console font\n");
/* Update active configuration */ @@ -1585,7 +1565,7 @@ static int CALLBACK enum_list_font_proc( const LOGFONTW *lf, const TEXTMETRICW *
TRACE( "%s\n", debugstr_logfont( lf, font_type ));
- if (validate_font( di->console, lf, NULL, 0, 0 )) + if (validate_font( di->console, lf, NULL, 0, NULL )) SendDlgItemMessageW( di->dialog, IDC_FNT_LIST_FONT, LB_ADDSTRING, 0, (LPARAM)lf->lfFaceName );
return 1;
On Wed Apr 9 15:20:39 2025 +0000, Piotr Caban wrote:
Sure, I can enable raster fonts instead of dropping all code related to it. How is the last patch changing weights of the criteria? The code was already preferring fixed fonts over charset. Giving weight to charset (as oppossed to completely ignoring it if there's no fixed width font) is already fixing the issue. While it might make sense to improve weight calculation there's probably little benefit doing so (most systems will have a font that matches all criteria anyway).
I have pushed a version that allows raster font to be selected. Other code is not changed since I don't think there's anything wrong with weight computation (comparing to old behavior).
On Wed Apr 9 15:26:31 2025 +0000, Piotr Caban wrote:
I have pushed a version that allows raster font to be selected. Other code is not changed since I think there's nothing wrong with weight computation (comparing to old behavior).
I'd rather pick a non fixed font with correct charset over of fixed font with a non matching charset (agreeing that that case didn't exist in current code, and is potentially pedantic)