This fixes "out of realized font handles" errors seen with Valve games like Half-Life 2 (which uses more than 1000 font handles).
The new limit of 5000 is roughly inspired by the Windows limit, although there are differences. On Windows 11 I can call `CreateFont()` (and then `SetMapMode()`, `SelectObject()`, `SetTextAlign()` to realize the font) exactly 5000 times before it hits the handle limit.
Under Wine, child fonts use handles as well, so the limit is usually hit before 5000 `CreateFont()` calls. But, there is caching so that `CreateFont()` calls with identical arguments do not count towards the limit. Ultimately the old limit of 256 was sufficient for almost all applications, and 5000 should be enough for all but the worst-behaved apps.
-- v4: win32u: Raise realized font handle limit to 5000.
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/win32u/font.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 5776c6dccc5..eedc36f8c0d 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -6249,7 +6249,8 @@ ULONG WINAPI NtGdiMakeFontDir( DWORD embed, BYTE *buffer, UINT size, const WCHAR if (path[len / sizeof(WCHAR) - 1]) return 0; if (wcslen( path ) != len / sizeof(WCHAR) - 1) return 0;
- if (!(font = alloc_gdi_font( path, NULL, 0 ))) return 0; + pthread_mutex_lock( &font_lock ); + if (!(font = alloc_gdi_font( path, NULL, 0 ))) goto done; font->lf.lfHeight = 100; if (!font_funcs->load_font( font )) goto done; if (!font_funcs->set_outline_text_metrics( font )) goto done; @@ -6282,10 +6283,12 @@ ULONG WINAPI NtGdiMakeFontDir( DWORD embed, BYTE *buffer, UINT size, const WCHAR
memcpy( buffer, &fontdir, sizeof(fontdir) ); free_gdi_font( font ); + pthread_mutex_unlock( &font_lock ); return fontdir.dfFace + pos;
done: - free_gdi_font( font ); + if (font) free_gdi_font( font ); + pthread_mutex_unlock( &font_lock ); return 0; }
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/win32u/font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index eedc36f8c0d..32403b77c1d 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -2302,7 +2302,7 @@ static struct gdi_font_face *find_matching_face( const LOGFONTW *lf, CHARSETINFO /* realized font objects */
#define FIRST_FONT_HANDLE 1 -#define MAX_FONT_HANDLES 256 +#define MAX_FONT_HANDLES 5000
struct font_handle_entry {
On Thu Apr 24 18:31:58 2025 +0000, Alexandre Julliard wrote:
If we are going to limit it to 5000 anyway, dynamic allocation doesn't seem necessary.
Makes sense, enlarging the array to 5000 elements only takes up 80 kB vs 4 kB currently