From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/gdi32/tests/font.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 76d787c1440..b7624942ead 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -4102,7 +4102,10 @@ static INT CALLBACK enum_truetype_font_proc(const LOGFONTA *lf, const TEXTMETRIC
static void test_GetTextMetrics(void) { + HFONT old_hf, hf; + TEXTMETRICA tm; LOGFONTA lf; + BOOL ret; HDC hdc; INT enumed;
@@ -4113,6 +4116,19 @@ static void test_GetTextMetrics(void) enumed = 0; EnumFontFamiliesExA(hdc, &lf, enum_truetype_font_proc, (LPARAM)&enumed, 0);
+ /* Test a bug triggered by rounding up FreeType ppem */ + hf = CreateFontA(20, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, + "Tahoma"); + ok(hf != NULL, "CreateFontA failed, error %lu\n", GetLastError()); + old_hf = SelectObject(hdc, hf); + ret = GetTextMetricsA(hdc, &tm); + ok(ret, "GetTextMetricsA failed, error %lu\n", GetLastError()); + todo_wine + ok(tm.tmHeight <= 20, "Got unexpected tmHeight %ld\n", tm.tmHeight); + SelectObject(hdc, old_hf); + DeleteObject(hf); + ReleaseDC(0, hdc); }
From: Zhiyi Zhang zzhang@codeweavers.com
When height > 0, CreateFontA/W() should not return a font face exceeding the requested height. For instance, Tahoma has 2049 units of ascent, 423 units of descent and its units per EM square is 2048. When requesting a font 20 pixels in height, ppem = units_per_EM * requested_height / (ascent + descent) = 2048 * 20 / (2049 + 423) = 16.57 ~= 17. When getting the resulting height back from the ppem, resulting_height = (ascent + descent) * ppem / units_per_EM = (2049.0 + 423) * 17 / 2048 = 20.52 ~=21. So it ends up getting a larger font than requested and violates the spec.
Fix Nancy Drew: Legend of the Crystal Skull crash at start.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/gdi32/tests/font.c | 1 - dlls/win32u/freetype.c | 12 ++++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index b7624942ead..12a5bff5969 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -4124,7 +4124,6 @@ static void test_GetTextMetrics(void) old_hf = SelectObject(hdc, hf); ret = GetTextMetricsA(hdc, &tm); ok(ret, "GetTextMetricsA failed, error %lu\n", GetLastError()); - todo_wine ok(tm.tmHeight <= 20, "Got unexpected tmHeight %ld\n", tm.tmHeight); SelectObject(hdc, old_hf); DeleteObject(hf); diff --git a/dlls/win32u/freetype.c b/dlls/win32u/freetype.c index f00df7ed86d..1d1545b3d50 100644 --- a/dlls/win32u/freetype.c +++ b/dlls/win32u/freetype.c @@ -1927,10 +1927,18 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
if(height > 0) { USHORT windescent = get_fixed_windescent(pOS2->usWinDescent); + LONG units; + if(pOS2->usWinAscent + windescent == 0) - ppem = pFT_MulDiv(ft_face->units_per_EM, height, pHori->Ascender - pHori->Descender); + units = pHori->Ascender - pHori->Descender; else - ppem = pFT_MulDiv(ft_face->units_per_EM, height, pOS2->usWinAscent + windescent); + units = pOS2->usWinAscent + windescent; + ppem = pFT_MulDiv(ft_face->units_per_EM, height, units); + + /* If rounding ends up getting a font exceeding height, choose a smaller ppem */ + if(pFT_MulDiv(units, ppem, ft_face->units_per_EM) > height) + --ppem; + if(ppem > MAX_PPEM) { WARN("Ignoring too large height %d, ppem %d\n", height, ppem); ppem = 1;
This merge request was approved by Huw Davies.
This is breaking the tests here:
``` tools/runtest -q -P wine -T . -M comctl32.dll -p dlls/comctl32/tests/comctl32_test.exe status && touch dlls/comctl32/tests/status.ok wine: Unhandled division by zero at address 7E996DC8 (thread 0024), starting debugger... Unhandled exception: divide by zero in 32-bit code (0x7e996dc8). Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:7e996dc8 ESP:00a47aa0 EBP:00a47ad8 EFLAGS:00010202( R- -- I - - - ) EAX:00000014 EBX:7ea44ff4 ECX:00000015 EDX:00000000 ESI:00a47c04 EDI:7dbc3380 Stack dump: 0x00a47aa0: 7e9b3d39 7dab3560 00a47ae8 7e94537c 0x00a47ab0: 00000000 00a47acc 7ea586a0 f7eada0e 0x00a47ac0: 7ea58b4c 00000001 00a47af0 7ea44ff4 0x00a47ad0: 00a47c04 7dab3560 00a47b48 7e9a45b6 0x00a47ae0: 00a47c04 00000001 00a47b48 7e9a45b6 0x00a47af0: 7dab4970 00a47c04 00a47b20 00a47bfc Backtrace: =>0 0x7e996dc8 scale_font_metrics+0x18(tm=<internal error>, font=<internal error>) [Z:\home\julliard\wine\wine\dlls\win32u\font.c:3919] in win32u.so (0x00a47ad8) 1 0x7e996dc8 font_GetTextMetrics+0xb9(metrics=<internal error>, dev=<internal error>) [Z:\home\julliard\wine\wine\dlls\win32u\font.c:3978] in win32u.so (0x00a47ad8) 2 0x7e996dc8 font_GetTextMetrics+0xe8(dev=<internal error>, metrics=<internal error>) [Z:\home\julliard\wine\wine\dlls\win32u\font.c:3967] in win32u.so (0x00a47ad8) 3 0x7e9a45b6 NtGdiGetTextMetricsW+0x66(hdc=<internal error>, metrics=<internal error>, flags=<internal error>) [Z:\home\julliard\wine\wine\dlls\win32u\font.c:4896] in win32u.so (0x00a47b48) 4 0x66b0dc54 NtGdiGetTextMetricsW+0x34(hdc=<internal error>, metrics=<internal error>, flags=<internal error>) [Z:\home\julliard\wine\wine\dlls\win32u\wrappers.c:374] in win32u (0x00a47b78) 5 0x6c9ea2ca GetTextMetricsW+0x2a(hdc=<internal error>, metrics=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:1414] in gdi32 (0x00a47ba8) 6 0x6cc5a23c COMCTL32_GetFontMetrics+0x3c(hFont=310A006C, ptm=00A47C04) [Z:\home\julliard\wine\wine\dlls\comctl32\commctrl.c:1548] in comctl32 (0x00a47bd8) 7 0x6ccc35a5 STATUSBAR_ComputeHeight+0x25(infoPtr=<register EBX not accessible in this frame>) [Z:\home\julliard\wine\wine\dlls\comctl32\status.c:110] in comctl32 (0x00a47c58) 8 0x6ccc575e STATUSBAR_WMSetFont+0x1a(redraw=<internal error>, font=<internal error>, infoPtr=<internal error>) [Z:\home\julliard\wine\wine\dlls\comctl32\status.c:1012] in comctl32 (0x00a47cf8) 9 0x6ccc575e StatusWindowProc+0xa8e(hwnd=<internal error>, msg=<internal error>, wParam=<internal error>, lParam=<internal error>) [Z:\home\julliard\wine\wine\dlls\comctl32\status.c:1264] in comctl32 (0x00a47cf8) 10 0x6ed6313c in user32 (+0x6313c) (0x00a47d38) 11 0x6ed63659 call_window_proc+0x39(hwnd=00030058, msg=0x30, wp=0x310a006c, lp=0x1, result=00A482C8, arg=6CCC4CD0) [Z:\home\julliard\wine\wine\dlls\user32\winproc.c:131] in user32 (0x00a47d98) 12 0x6ed649ae WINPROC_CallProcAtoW+0xae(callback=6ED63620, hwnd=00030058, msg=0x30, wParam=<is not available>, lParam=0x1, result=00A482C8, arg=6CCC4CD0, mapping=WMCHAR_MAP_CALLWINDOWPROC) [Z:\home\julliard\wine\wine\dlls\user32\winproc.c:251] in user32 (0x00a48248) 13 0x6ed65983 dispatch_win_proc_params+0xe3(params=00A482CC) [Z:\home\julliard\wine\wine\dlls\user32\winproc.c:733] in user32 (0x00a48298) 14 0x6ed66c94 CallWindowProcA+0x64(func=<internal error>, hwnd=<internal error>, msg=<internal error>, wParam=<internal error>, lParam=<internal error>) [Z:\home\julliard\wine\wine\dlls\user32\winproc.c:1259] in user32 (0x00a48318) 15 0x004abb97 create_test_wndproc+0x47(hwnd=<internal error>, msg=<internal error>, wParam=<internal error>, lParam=<internal error>) [Z:\home\julliard\wine\wine\dlls\comctl32\tests\status.c:85] in comctl32_test (0x00a48368) 16 0x6ed6313c in user32 (+0x6313c) (0x00a483a8) 17 0x6ed63659 call_window_proc+0x39(hwnd=00030058, msg=0x30, wp=0x310a006c, lp=0x1, result=00A4849C, arg=004ABB50) [Z:\home\julliard\wine\wine\dlls\user32\winproc.c:131] in user32 (0x00a48408) 18 0x6ed659d2 dispatch_win_proc_params+0x132(params=00A484FC) [Z:\home\julliard\wine\wine\dlls\user32\winproc.c:736] in user32 (0x00a48458) 19 0x6ed479f4 dispatch_send_message+0x84(params=<register EBX not accessible in this frame>, wparam=<internal error>, lparam=<internal error>) [Z:\home\julliard\wine\wine\dlls\user32\message.c:611] in user32 (0x00a484b8) 20 0x6ed49361 SendMessageA+0x71(hwnd=<internal error>, msg=<internal error>, wparam=<internal error>, lparam=<internal error>) [Z:\home\julliard\wine\wine\dlls\user32\message.c:652] in user32 (0x00a48548) 21 0x004abe01 check_height_font_enumproc+0xa1(enumlf=<internal error>, ntm=<internal error>, type=<internal error>, lParam=<internal error>) [Z:\home\julliard\wine\wine\dlls\comctl32\tests\status.c:146] in comctl32_test (0x00a48608) 22 0x6c9e621b enum_proc_WtoA+0x22b(lf=<internal error>, tm=<internal error>, type=<internal error>, lparam=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:749] in gdi32 (0x00a48788) 23 0x6c9ebadd EnumFontFamiliesExW+0x25d(hdc=<internal error>, lf=<internal error>, efproc=<internal error>, lparam=<internal error>, flags=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:2097] in gdi32 (0x00a4c088) 24 0x6c9ebcf2 EnumFontFamiliesExA+0xc2(hdc=<internal error>, lf=<internal error>, efproc=<internal error>, lparam=<internal error>, flags=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:2144] in gdi32 (0x00a4c158) 25 0x004abd30 check_height_family_enumproc+0x50(enumlf=<internal error>, ntm=<internal error>, type=<internal error>, lParam=<internal error>) [Z:\home\julliard\wine\wine\dlls\comctl32\tests\status.c:168] in comctl32_test (0x00a4c1a8) 26 0x6c9e621b enum_proc_WtoA+0x22b(lf=<internal error>, tm=<internal error>, type=<internal error>, lparam=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:749] in gdi32 (0x00a4c328) 27 0x6c9ebadd EnumFontFamiliesExW+0x25d(hdc=<internal error>, lf=<internal error>, efproc=<internal error>, lparam=<internal error>, flags=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:2097] in gdi32 (0x00a4fc28) 28 0x6c9ebcf2 EnumFontFamiliesExA+0xc2(hdc=<internal error>, lf=<internal error>, efproc=<internal error>, lparam=<internal error>, flags=<internal error>) [Z:\home\julliard\wine\wine\dlls\gdi32\text.c:2144] in gdi32 (0x00a4fcf8) 29 0x004aed90 test_height+0xc26() [Z:\home\julliard\wine\wine\dlls\comctl32\tests\status.c:248] in comctl32_test (0x00a4fe08) 30 0x004aed90 func_status+0x1060() [Z:\home\julliard\wine\wine\dlls\comctl32\tests\status.c:761] in comctl32_test (0x00a4fe08) 31 0x004f7c73 run_test+0xe7(name=<internal error>) [Z:\home\julliard\wine\wine\include\wine\test.h:612] in comctl32_test (0x00a4fee8) 32 0x004f7c73 main+0x293(argc=<internal error>, argv=<internal error>) [Z:\home\julliard\wine\wine\include\wine\test.h:697] in comctl32_test (0x00a4fee8) 33 0x004f798f mainCRTStartup+0x7f() [Z:\home\julliard\wine\wine\dlls\msvcrt\crt_main.c:60] in comctl32_test (0x00a4ff30) 34 0x7b62a170 in kernel32 (+0x2a170) (0x00a4ff48) 35 0x7bc5c4e7 in ntdll (+0x5c4e7) (0x00a4ff5c) 36 0x7bc5cba0 RtlCreateUserThread(entry=004F7910, arg=7FFD1000) [Z:\home\julliard\wine\wine\dlls\ntdll\thread.c:261] in ntdll (0x00a4ffec) 0x7e996dc8 font_GetTextMetrics+0xe8 [Z:\home\julliard\wine\wine\dlls\win32u\font.c:3967] in win32u.so: idivl 0xffffffd8(%ebp),%eax 3967 if (!physdev->font) Modules: Module Address Debug info Name (53 modules) PE 00400000-00845000 Dwarf-4 comctl32_test PE 00b90000-00ff9000 Deferred ole32 PE 01980000-019f7000 Deferred winex11 PE 61740000-61836000 Deferred advapi32 PE 62fc0000-631e3000 Deferred rpcrt4 PE 63480000-6349b000 Deferred version PE 66b00000-66b58000 Dwarf-4 win32u PE 68500000-68640000 Deferred combase PE 68700000-68798000 Deferred uxtheme PE 6a280000-6a4f5000 Deferred msvcrt PE 6bc00000-6bc99000 Deferred sechost PE 6c9c0000-6cbe4000 Dwarf-4 gdi32 PE 6cc40000-6d0be000 Dwarf-4 comctl32 PE 6ed00000-6f20b000 Dwarf-4 user32 PE 70b40000-70e13000 Deferred ucrtbase PE 71200000-71253000 Deferred imm32 PE 7b000000-7b519000 Deferred kernelbase PE 7b600000-7b757000 Dwarf-4 kernel32 PE 7bc00000-7beb8000 Dwarf-4 ntdll ELF 7d000000-7d005000 Deferred <wine-loader> ELF 7e0af000-7e200000 Deferred libx11.so.6 ELF 7e4d8000-7e4e0000 Deferred libxfixes.so.3 ELF 7e4e0000-7e4ed000 Deferred libxcursor.so.1 ELF 7e4ed000-7e502000 Deferred libxi.so.6 ELF 7e502000-7e507000 Deferred libxcomposite.so.1 ELF 7e507000-7e516000 Deferred libxrandr.so.2 ELF 7e516000-7e524000 Deferred libxrender.so.1 ELF 7e524000-7e52b000 Deferred libxxf86vm.so.1 ELF 7e52b000-7e530000 Deferred libxinerama.so.1 ELF 7e530000-7e53f000 Deferred libmd.so.0 ELF 7e53f000-7e556000 Deferred libbsd.so.0 ELF 7e556000-7e55d000 Deferred libxdmcp.so.6 ELF 7e55d000-7e562000 Deferred libxau.so.6 ELF 7e562000-7e590000 Deferred libxcb.so.1 ELF 7e590000-7e5a6000 Deferred libxext.so.6 ELF 7e5da000-7e656000 Deferred winex11.so ELF 7e73c000-7e746000 Deferred libuuid.so.1 ELF 7e746000-7e776000 Deferred libexpat.so.1 ELF 7e776000-7e7c5000 Deferred libfontconfig.so.1 ELF 7e7c5000-7e7e8000 Deferred libbrotlicommon.so.1 ELF 7e7e8000-7e825000 Deferred libpng16.so.16 ELF 7e825000-7e929000 Deferred libm.so.6 ELF 7e929000-7ea79000 Dwarf-4 win32u.so ELF 7ea79000-7ec00000 Dwarf-4 libwine.so.1 ELF 7ee7d000-7ee8b000 Deferred libbrotlidec.so.1 ELF 7ee8b000-7eea8000 Deferred libz.so.1 ELF 7eea8000-7ef77000 Deferred libfreetype.so.6 ELF f7c05000-f7ca7000 Deferred ntdll.so ELF f7ca9000-f7e9d000 Deferred libc.so.6 ELF f7e9d000-f7ea3000 Deferred libdl.so.2 ELF f7ea3000-f7ec4000 Deferred libpthread.so.0 ELF f7efa000-f7f2d000 Deferred ld-linux.so.2 ELF f7f31000-f7f33000 Deferred [vdso].so ```