[PATCH v5 0/2] MR10603: win32u/freetype: Fix tmExternalLeading for CFF fonts.
This fixes font scaling issues with CFF fonts this was discovered from games utilizing DxLib. https://github.com/yumetodo/DxLib/tree/master https://dxlib.xsrv.jp/index.html I've ran tests on Windows and to confirm that this change is consistent with a number of fonts. Before: {width="801" height="600"} After (this matches the windows visual from testing in a VM): {width="767" height="572"} Related Proton Issue: https://github.com/ValveSoftware/Proton/issues/7299 Full Disclosure: An LLM was used to assist in finding this bug, the original fix written by the LLM wrote a loader binary that changed the pointers for `GetTextMetricsA` and `GetTextMetricsW` to point to a custom implementation that always set `tmExternalLeading`. The LLM determined that `GDI returns 0 when (winAscent + winDescent) > (Ascender - Descender)`, after testing on WIndows I found this to be incorrect, the actual difference is that CFF fonts always set `tmExternalLeading` to 0. ~~The test case for this fix was LLM generated but reviewed and tested on both Windows and Linux by me.~~ Test case: ``` WINEPREFIX=/tmp/wine-font winetricks allfonts WINEPREFIX=/tmp/wine-font ./loader/wine ./dlls/gdi32/tests/i386-windows/gdi32_test.exe ``` Patched: ``` font.c:4266: test_CFF_external_leading: tested 51 CFF fonts (0 failures) ``` Unpatched Wine: ``` font.c:4266: test_CFF_external_leading: tested 51 CFF fonts (51 failures) ``` Windows 11: ``` font.c:4266: test_CFF_external_leading: tested 48 CFF fonts (0 failures) ``` -- v5: gdi32: Add test for tmExternalLeading for CFF fonts. win32u/freetype: Fix tmExternalLeading for CFF fonts. https://gitlab.winehq.org/wine/wine/-/merge_requests/10603
From: Arie Miller <renari@arimil.com> --- dlls/win32u/freetype.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dlls/win32u/freetype.c b/dlls/win32u/freetype.c index a660b166a0f..42f62dc191a 100644 --- a/dlls/win32u/freetype.c +++ b/dlls/win32u/freetype.c @@ -3392,12 +3392,16 @@ static BOOL freetype_set_outline_text_metrics( struct gdi_font *font ) TM.tmHeight = TM.tmAscent + TM.tmDescent; - /* MSDN says: - el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender))) - */ - TM.tmExternalLeading = max(0, SCALE_Y(pHori->Line_Gap - - ((ascent + descent) - - (pHori->Ascender - pHori->Descender)))); + /* MSDN documents the formula: + * el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender))) + * but Windows GDI does not follow this for OpenType-CFF fonts: for any font + * containing a 'CFF ' table it reports tmExternalLeading = 0. + */ + if (font->ntmFlags & NTM_PS_OPENTYPE) + TM.tmExternalLeading = 0; + else + TM.tmExternalLeading = max(0, + SCALE_Y(pHori->Line_Gap - ((ascent + descent) - (pHori->Ascender - pHori->Descender)))); TM.tmAveCharWidth = SCALE_X(pOS2->xAvgCharWidth); if (TM.tmAveCharWidth == 0) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10603
From: Arie Miller <renari@arimil.com> --- dlls/gdi32/tests/font.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index c56180b1ce6..cae7a562786 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -4132,6 +4132,33 @@ static void test_GetTextMetrics(void) ReleaseDC(0, hdc); } +static void test_CFF_external_leading(void) +{ + HDC hdc; + LOGFONTW lf; + HFONT hfont, hfont_prev; + TEXTMETRICW tm; + + if(!is_font_installed("f.k Kikai Chokoku")) + { + skip("f.k Kikai Chokoku is not installed so skipping this test\n"); + return; + } + + memset(&lf, 0, sizeof(lf)); + wcscpy(lf.lfFaceName, L"f.k Kikai Chokoku"); + hfont = CreateFontIndirectW(&lf); + hdc = CreateCompatibleDC(0); + ok(hdc != NULL, "CreateCompatibleDC failed\n"); + hfont_prev = SelectObject(hdc, hfont); + ok(GetTextMetricsW(hdc, &tm), "GetTextMetricsW failed\n"); + ok(tm.tmExternalLeading == 0, "Expected tmExternalLeading 0, got %ld\n", tm.tmExternalLeading); + + SelectObject(hdc, hfont_prev); + DeleteObject(hfont); + DeleteDC(hdc); +} + static void test_nonexistent_font(void) { static const struct @@ -8067,6 +8094,7 @@ START_TEST(font) skip("Arial Black or Symbol/Wingdings is not installed\n"); test_EnumFontFamiliesEx_default_charset(); test_GetTextMetrics(); + test_CFF_external_leading(); test_RealizationInfo(); test_GetTextFace(); test_GetGlyphOutline(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10603
On Thu Apr 16 16:57:30 2026 +0000, Arie Miller wrote:
OK, that is fine I will write a new test case myself. The test has been rewritten by me.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10603#note_136558
I've finished writing a new test, it now uses the recommended font, I tested this on my system wine where it correctly fails. ``` font.c:4267: Test failed: Expected tmExternalLeading 0, got 3 ``` With wine build from this branch there is no output, as expected. I did not retest Windows, however the fix hasn't changed so I don't think that is necessary. Let me know if there's anything I missed because this test was mostly made just from copying existing tests to get to the minimal implementation, so it's likely I overlooked something that is needed. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10603#note_136560
On Fri Apr 17 13:46:31 2026 +0000, Arie Miller wrote:
I've finished writing a new test, it now uses the recommended font, I tested this on my system wine where it correctly fails. ``` font.c:4267: Test failed: Expected tmExternalLeading 0, got 3 ``` With wine build from this branch there is no output, as expected. I did not retest Windows. Let me know if there's anything I missed because this test was mostly made just from copying existing tests to get to the minimal implementation, so it's likely I overlooked something that is needed. Could you use a font you generated with [Wine FontForge](https://gitlab.winehq.org/wine/fontforge) instead of f.k Kikai Chokoku font? For example, we test the vertical writing feature in the `test_vertical_font` function using [`vertical.ttf`](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/gdi32/tests/vertical....), which is generated from [`vertical.sfd`](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/gdi32/tests/vertical....).
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10603#note_136755
On Fri Apr 17 13:46:31 2026 +0000, Akihiro Sagawa wrote:
Could you use a font you generated with [Wine FontForge](https://gitlab.winehq.org/wine/fontforge) instead of f.k Kikai Chokoku font? For example, we test the vertical writing feature in the `test_vertical_font` function using [`vertical.ttf`](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/gdi32/tests/vertical....), which is generated from [`vertical.sfd`](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/gdi32/tests/vertical....). I'm looking into it but it seems Wine FontForge has not been updated in a long time making it incompatible with newer versions of gcc is there any notable differences from Wine FontForge and FontForge? Since FontForge is in my repos package manager.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10603#note_136817
On Fri Apr 17 18:51:59 2026 +0000, Arie Miller wrote:
I'm looking into it but it seems Wine FontForge has not been updated in a long time making it incompatible with newer versions of gcc is there any notable differences from Wine FontForge and FontForge? Since FontForge is in my repos package manager. I spent a few hours looking into this and this is actually a really big change to the build system because it currently is only setup to generate `ttf` files which will not trigger this issue.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10603#note_136868
participants (3)
-
Akihiro Sagawa (@sgwaki) -
Arie Miller -
Arie Miller (@Arimil)