[PATCH v2 0/3] MR10871: Respect runtime font smoothing settings.
-- v2: winex11.drv: Preserve disabled font smoothing. win32u: Respect runtime font smoothing settings. https://gitlab.winehq.org/wine/wine/-/merge_requests/10871
From: Ziqing Hui <zhui@codeweavers.com> --- dlls/gdi32/tests/dib.c | 114 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/dlls/gdi32/tests/dib.c b/dlls/gdi32/tests/dib.c index 14e8a9b384f..62f62afa9d8 100644 --- a/dlls/gdi32/tests/dib.c +++ b/dlls/gdi32/tests/dib.c @@ -3007,6 +3007,119 @@ static inline COLORREF aa_colorref( COLORREF dst, COLORREF text, BYTE glyph ) static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; +static unsigned int draw_runtime_smoothing_text( HDC hdc, const BITMAPINFO *bmi, BYTE *bits, + HFONT font, BOOL smoothing ) +{ + unsigned int mixed = 0, size = bmi->bmiHeader.biWidth * abs( bmi->bmiHeader.biHeight ); + static const DWORD background = 0x00ff00ff; + static const DWORD foreground = 0x00000000; + BOOL text_pixels = FALSE; + BOOL ret; + int i; + + ret = SystemParametersInfoA( SPI_SETFONTSMOOTHING, smoothing, NULL, 0 ); + ok( ret, "SPI_SETFONTSMOOTHING failed, error %lu\n", GetLastError() ); + ret = SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, 0, UlongToPtr(FE_FONTSMOOTHINGSTANDARD), 0 ); + ok( ret, "SPI_SETFONTSMOOTHINGTYPE failed, error %lu\n", GetLastError() ); + + SelectObject( hdc, GetStockObject( SYSTEM_FONT ) ); + SelectObject( hdc, font ); + + for (i = 0; i < size; i++) + ((DWORD *)bits)[i] = background; + + SetTextColor( hdc, RGB(0, 0, 0) ); + SetBkMode( hdc, TRANSPARENT ); + ret = ExtTextOutA( hdc, 8, 48, 0, NULL, "Hello Wine", 10, NULL ); + ok( ret, "ExtTextOutA failed\n" ); + + for (i = 0; i < size; i++) + { + DWORD pixel = ((DWORD *)bits)[i] & 0x00ffffff; + + if (pixel != background) + { + text_pixels = TRUE; + if (pixel != foreground) mixed++; + } + } + + ok( text_pixels, "expected some text pixels\n" ); + + return mixed; +} + +static void test_runtime_font_smoothing(void) +{ + BITMAPINFO bmi = {{ sizeof(BITMAPINFOHEADER), 256, -96, 1, 32, BI_RGB }}; + HFONT font, cleartype_font, old_font; + BOOL old_smoothing, ret; + HBITMAP dib, old_dib; + unsigned int mixed; + LOGFONTA lf = {0}; + TEXTMETRICA tm; + UINT old_type; + BYTE *bits; + HDC hdc; + + ret = SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_smoothing, 0 ); + if (!ret) + { + win_skip( "SPI_GETFONTSMOOTHING failed, error %lu\n", GetLastError() ); + return; + } + ret = SystemParametersInfoA( SPI_GETFONTSMOOTHINGTYPE, 0, &old_type, 0 ); + ok( ret, "SPI_GETFONTSMOOTHINGTYPE failed, error %lu\n", GetLastError() ); + + hdc = CreateCompatibleDC( NULL ); + ok( hdc != NULL, "CreateCompatibleDC failed\n" ); + + dib = CreateDIBSection( hdc, &bmi, DIB_RGB_COLORS, (void **)&bits, NULL, 0 ); + ok( dib != NULL, "CreateDIBSection failed\n" ); + old_dib = SelectObject( hdc, dib ); + + strcpy( lf.lfFaceName, "Tahoma" ); + lf.lfHeight = 32; + lf.lfQuality = DEFAULT_QUALITY; + + font = CreateFontIndirectA( &lf ); + ok( font != NULL, "CreateFontIndirectA failed\n" ); + lf.lfQuality = CLEARTYPE_QUALITY; + cleartype_font = CreateFontIndirectA( &lf ); + ok( cleartype_font != NULL, "CreateFontIndirectA failed\n" ); + + old_font = SelectObject( hdc, font ); + GetTextMetricsA( hdc, &tm ); + if (!(tm.tmPitchAndFamily & TMPF_VECTOR)) + { + skip( "skipping as a bitmap font has been selected for Tahoma.\n" ); + goto done; + } + + mixed = draw_runtime_smoothing_text( hdc, &bmi, bits, font, TRUE ); + ok( mixed, "expected some antialiased pixels\n" ); + + mixed = draw_runtime_smoothing_text( hdc, &bmi, bits, font, FALSE ); + todo_wine + ok( !mixed, "expected no antialiased pixels, got %u\n", mixed ); + + mixed = draw_runtime_smoothing_text( hdc, &bmi, bits, cleartype_font, FALSE ); + ok( mixed, "expected some antialiased pixels\n" ); + +done: + SelectObject( hdc, old_font ); + DeleteObject( font ); + DeleteObject( cleartype_font ); + SelectObject( hdc, old_dib ); + DeleteObject( dib ); + DeleteDC( hdc ); + + ret = SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_smoothing, NULL, 0 ); + ok( ret, "failed to restore SPI_SETFONTSMOOTHING, error %lu\n", GetLastError() ); + ret = SystemParametersInfoA( SPI_SETFONTSMOOTHINGTYPE, 0, UlongToPtr(old_type), 0 ); + ok( ret, "failed to restore SPI_SETFONTSMOOTHINGTYPE, error %lu\n", GetLastError() ); +} + static void draw_text_2( HDC hdc, const BITMAPINFO *bmi, BYTE *bits, BOOL aa ) { DWORD dib_size = get_dib_size(bmi), ret; @@ -3533,6 +3646,7 @@ START_TEST(dib) { CryptAcquireContextW(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + test_runtime_font_smoothing(); test_simple_graphics(); CryptReleaseContext(crypt_prov, 0); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10871
From: Ziqing Hui <zhui@codeweavers.com> --- dlls/win32u/font.c | 15 ++++++++++++++- dlls/win32u/sysparams.c | 33 +++++++++++++++++++++++++++++++++ dlls/win32u/win32u_private.h | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index dcc75e8096b..44950476808 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -4531,6 +4531,8 @@ static HFONT font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) LOGFONTW lf; FMAT2 dcmat; BOOL can_use_bitmap = !!(NtGdiGetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_RA_ABLE); + UINT new_font_smoothing, new_subpixel_orientation; + BOOL update_font_smoothing; NtGdiExtGetObjectW( hfont, sizeof(lf), &lf ); switch (lf.lfQuality) @@ -4580,17 +4582,28 @@ static HFONT font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) } TRACE( "DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12, dcmat.eM21, dcmat.eM22 ); + update_font_smoothing = get_font_smoothing_aa( &new_font_smoothing, + &new_subpixel_orientation ); + pthread_mutex_lock( &font_lock ); + if (update_font_smoothing) + { + font_smoothing = new_font_smoothing; + subpixel_orientation = new_subpixel_orientation; + } font = select_font( &lf, dcmat, can_use_bitmap ); if (font) { - if (!*aa_flags) *aa_flags = font->aa_flags; if (!*aa_flags) { if (lf.lfQuality == CLEARTYPE_QUALITY || lf.lfQuality == CLEARTYPE_NATURAL_QUALITY) *aa_flags = subpixel_orientation; + else if (font_smoothing == GGO_BITMAP) + *aa_flags = GGO_BITMAP; + else if (font->aa_flags) + *aa_flags = font->aa_flags; else *aa_flags = font_smoothing; } diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 00fe10f30ca..47902f80196 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -8090,3 +8090,36 @@ BOOL get_gpu_info_from_uuid( const GUID *uuid, LUID *luid, UINT32 *node_mask, ch unlock_display_devices(); return found; } + +BOOL get_font_smoothing_aa( UINT *font_aa, UINT *subpixel_orientation_aa ) +{ + DWORD type, orientation; + UINT smoothing; + + if (!volatile_base_key + || !get_entry( &entry_FONTSMOOTHING, 0, &smoothing ) + || !get_entry( &entry_FONTSMOOTHINGTYPE, 0, &type ) + || !get_entry( &entry_FONTSMOOTHINGORIENTATION, 0, &orientation )) + return FALSE; + + switch (orientation) + { + case FE_FONTSMOOTHINGORIENTATIONBGR: + *subpixel_orientation_aa = WINE_GGO_HBGR_BITMAP; + break; + case FE_FONTSMOOTHINGORIENTATIONRGB: + *subpixel_orientation_aa = WINE_GGO_HRGB_BITMAP; + break; + default: + return FALSE; + } + + if (!smoothing) + *font_aa = GGO_BITMAP; + else if (type == FE_FONTSMOOTHINGCLEARTYPE) + *font_aa = *subpixel_orientation_aa; + else + *font_aa = GGO_GRAY4_BITMAP; + + return TRUE; +} diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 031e1afec70..eec6b755f8b 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -169,6 +169,7 @@ extern COLORREF get_sys_color( int index ); extern HBRUSH get_sys_color_brush( unsigned int index ); extern HPEN get_sys_color_pen( unsigned int index ); extern UINT get_system_dpi(void); +extern BOOL get_font_smoothing_aa( UINT *font_aa, UINT *subpixel_orientation_aa ); extern int get_system_metrics( int index ); extern UINT get_thread_dpi(void); extern UINT set_thread_dpi_awareness_context( UINT context ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10871
From: Ziqing Hui <zhui@codeweavers.com> --- dlls/gdi32/tests/dib.c | 1 - dlls/winex11.drv/xrender.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dlls/gdi32/tests/dib.c b/dlls/gdi32/tests/dib.c index 62f62afa9d8..60ed7ffabc4 100644 --- a/dlls/gdi32/tests/dib.c +++ b/dlls/gdi32/tests/dib.c @@ -3100,7 +3100,6 @@ static void test_runtime_font_smoothing(void) ok( mixed, "expected some antialiased pixels\n" ); mixed = draw_runtime_smoothing_text( hdc, &bmi, bits, font, FALSE ); - todo_wine ok( !mixed, "expected no antialiased pixels, got %u\n", mixed ); mixed = draw_runtime_smoothing_text( hdc, &bmi, bits, cleartype_font, FALSE ); diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c index dd3f596cac3..b11c04a7f3a 100644 --- a/dlls/winex11.drv/xrender.c +++ b/dlls/winex11.drv/xrender.c @@ -820,14 +820,16 @@ static HFONT xrenderdrv_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) LFANDSIZE lfsz; struct xrender_physdev *physdev = get_xrender_dev( dev ); PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont ); + UINT xft_aa_flags; DWORD mode; HFONT ret; NtGdiExtGetObjectW( hfont, sizeof(lfsz.lf), &lfsz.lf ); - if (!*aa_flags) *aa_flags = get_xft_aa_flags( &lfsz.lf ); ret = next->funcs->pSelectFont( next, hfont, aa_flags ); if (!ret) return 0; + xft_aa_flags = get_xft_aa_flags( &lfsz.lf ); + if (xft_aa_flags && *aa_flags != GGO_BITMAP) *aa_flags = xft_aa_flags; switch (*aa_flags) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10871
On Wed May 13 07:23:58 2026 +0000, Ziqing Hui wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/10871/diffs?diff_id=267158&start_sha=6ca06ab73c1cc6a1ec2a6b658e246d288142c5db) OK, changed in V2.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10871#note_139652
On Wed May 13 07:23:58 2026 +0000, Ziqing Hui wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/10871/diffs?diff_id=267158&start_sha=6ca06ab73c1cc6a1ec2a6b658e246d288142c5db#1b75e47305033a70be75785c3e20296b16647756_823_824) Same, changed in V2.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10871#note_139653
participants (2)
-
Ziqing Hui -
Ziqing Hui (@zhui)