From: Arkadiusz Hiler Subject: [PATCH] gdi32: Limit GetGlyphOutlineW(uChar) to a WORD. Message-Id: <20200921142454.267396-1-ahiler@codeweavers.com> Date: Mon, 21 Sep 2020 17:24:54 +0300 Turns out GetGlyphOutlineW() is using only two bytes for the character, which is common for GDI font API. This limits us to chars in the range 0x0000 - 0xffff. Fixes eden* PLUS+MOSAIC. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45400 Signed-off-by: Arkadiusz Hiler --- dlls/gdi32/font.c | 2 + dlls/gdi32/tests/Makefile.in | 1 + dlls/gdi32/tests/font.c | 54 ++++++++++++++++ dlls/gdi32/tests/resource.rc | 3 + dlls/gdi32/tests/wine_glyphoutlines.sfd | 79 ++++++++++++++++++++++++ dlls/gdi32/tests/wine_glyphoutlines.ttf | Bin 0 -> 1748 bytes 6 files changed, 139 insertions(+) create mode 100644 dlls/gdi32/tests/wine_glyphoutlines.sfd create mode 100644 dlls/gdi32/tests/wine_glyphoutlines.ttf diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index e099bec5e81..0fa1722d621 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -2905,6 +2905,8 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat, dc = get_dc_ptr(hdc); if(!dc) return GDI_ERROR; + uChar &= 0xFFFF; + dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline ); ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 ); release_dc_ptr( dc ); diff --git a/dlls/gdi32/tests/Makefile.in b/dlls/gdi32/tests/Makefile.in index 8b722cfe5d2..acb2051c9f9 100644 --- a/dlls/gdi32/tests/Makefile.in +++ b/dlls/gdi32/tests/Makefile.in @@ -20,6 +20,7 @@ C_SRCS = \ FONT_SRCS = \ vertical.sfd \ + wine_glyphoutlines.sfd \ wine_longname.sfd \ wine_test.sfd \ wine_ttfnames.sfd \ diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index f5c8d4dac3b..f272a10f098 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -6131,6 +6131,59 @@ static void check_vertical_metrics(const char *face) ReleaseDC(NULL, hdc); } +static void test_GetGlyphOutlineW_character_limited_to_a_word(void) +{ + char ttf_name[MAX_PATH]; + HFONT hfont, hfont_old; + LOGFONTA lf; + HDC hdc; + DWORD num, ret; + GLYPHMETRICS gm1, gm2; + + if (!write_ttf_file("wine_glyphoutlines.ttf", ttf_name)) + { + skip("Failed to create ttf file for testing\n"); + return; + } + + num = pAddFontResourceExA(ttf_name, FR_PRIVATE, 0); + ok(num == 1, "AddFontResourceExA should add 1 fonts from vertical.ttf\n"); + + hdc = CreateCompatibleDC(0); + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = 72; + lstrcpyA(lf.lfFaceName, "WineTestGlyphOutlines"); + + hfont = CreateFontIndirectA(&lf); + ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError()); + hfont_old = SelectObject(hdc, hfont); + + /* the font has two glyph with different metrics - .notdef and 0x10000 */ + + ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm1, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineW failed with %d, lest error %d\n", ret, GetLastError()); + + ret = GetGlyphOutlineW(hdc, 0x10000, GGO_METRICS, &gm2, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineW failed with %d, lest error %d\n", ret, GetLastError()); + + /* we shouldn't be able to use 0x10000 and isntead get the .notdef */ + ok(gm1.gmBlackBoxX == gm2.gmBlackBoxX, "gmBlackBoxX differs, %d should equal %d\n", gm1.gmBlackBoxX, gm2.gmBlackBoxX); + ok(gm1.gmBlackBoxY == gm2.gmBlackBoxY, "gmBlackBoxY differs, %d should equal %d\n", gm1.gmBlackBoxY, gm2.gmBlackBoxY); + ok(gm1.gmptGlyphOrigin.x == gm2.gmptGlyphOrigin.x, "gmptGlyphOrigin.x differs, %d should equal %d\n", gm1.gmptGlyphOrigin.x, gm2.gmptGlyphOrigin.x); + ok(gm1.gmptGlyphOrigin.y == gm2.gmptGlyphOrigin.y, "gmptGlyphOrigin.y difference, %d should equal %d\n", gm1.gmptGlyphOrigin.y, gm2.gmptGlyphOrigin.y); + ok(gm1.gmCellIncX == gm2.gmCellIncX, "gmCellIncX differs, %d should equal %d\n", gm1.gmCellIncX, gm2.gmCellIncX); + ok(gm1.gmCellIncY == gm2.gmCellIncY, "gmCellIncY differs, %d should equal %d\n", gm1.gmCellIncY, gm2.gmCellIncY); + + SelectObject(hdc, hfont_old); + DeleteObject(hfont); + + DeleteDC(hdc); + + ret = pRemoveFontResourceExA(ttf_name, FR_PRIVATE, 0); + ok(ret, "RemoveFontResourceEx() error %d\n", GetLastError()); + DeleteFileA(ttf_name); +} + static void test_vertical_font(void) { char ttf_name[MAX_PATH]; @@ -7396,6 +7449,7 @@ START_TEST(font) test_RealizationInfo(); test_GetTextFace(); test_GetGlyphOutline(); + test_GetGlyphOutlineW_character_limited_to_a_word(); test_GetTextMetrics2("Tahoma", -11); test_GetTextMetrics2("Tahoma", -55); test_GetTextMetrics2("Tahoma", -110); diff --git a/dlls/gdi32/tests/resource.rc b/dlls/gdi32/tests/resource.rc index b5a6107a987..c47f4bb87f9 100644 --- a/dlls/gdi32/tests/resource.rc +++ b/dlls/gdi32/tests/resource.rc @@ -37,3 +37,6 @@ wine_ttfnames.ttf RCDATA wine_ttfnames.ttf /* @makedep: wine_ttfnames_bold.ttf */ wine_ttfnames_bold.ttf RCDATA wine_ttfnames_bold.ttf + +/* @makedep: wine_glyphoutlines.ttf */ +wine_glyphoutlines.ttf RCDATA wine_glyphoutlines.ttf diff --git a/dlls/gdi32/tests/wine_glyphoutlines.sfd b/dlls/gdi32/tests/wine_glyphoutlines.sfd new file mode 100644 index 00000000000..20bd8427b84 --- /dev/null +++ b/dlls/gdi32/tests/wine_glyphoutlines.sfd @@ -0,0 +1,79 @@ +SplineFontDB: 3.2 +FontName: WineTestGlyphOutlines +FullName: WineTestGlyphOutlines +FamilyName: wine_glyphoutlines +Weight: Regular +Copyright: Copyright (c) 2020, Arkadiusz Hiler +UComments: "2020-9-21: Created with FontForge (http://fontforge.org)" +Version: 001.000 +ItalicAngle: 0 +UnderlinePosition: -100 +UnderlineWidth: 50 +Ascent: 800 +Descent: 200 +InvalidEm: 0 +LayerCount: 2 +Layer: 0 0 "Back" 1 +Layer: 1 0 "Fore" 0 +XUID: [1021 1016 2035354264 8878123] +OS2Version: 0 +OS2_WeightWidthSlopeOnly: 0 +OS2_UseTypoMetrics: 1 +CreationTime: 1600686238 +ModificationTime: 1600688343 +OS2TypoAscent: 0 +OS2TypoAOffset: 1 +OS2TypoDescent: 0 +OS2TypoDOffset: 1 +OS2TypoLinegap: 0 +OS2WinAscent: 0 +OS2WinAOffset: 1 +OS2WinDescent: 0 +OS2WinDOffset: 1 +HheadAscent: 0 +HheadAOffset: 1 +HheadDescent: 0 +HheadDOffset: 1 +OS2Vendor: 'PfEd' +DEI: 91125 +Encoding: UnicodeFull +Compacted: 1 +UnicodeInterp: none +NameList: AGL For New Fonts +DisplaySize: -48 +AntiAlias: 1 +FitToEm: 0 +WinInfo: 0 25 20 +BeginChars: 1114112 2 + +StartChar: u10000 +Encoding: 65536 65536 0 +Width: 2000 +Flags: HW +LayerCount: 2 +Fore +SplineSet +847 687 m 25 + 205 129 l 1053 +70 753 m 25 + 934 75 l 1049 +1847 687 m 25 + 1205 129 l 1053 +1070 753 m 25 + 1934 75 l 1049 +EndSplineSet +EndChar + +StartChar: .notdef +Encoding: 0 0 1 +Width: 120 +Flags: HWO +LayerCount: 2 +Fore +SplineSet +66 714 m 29 + 64 92 l 1053 +EndSplineSet +EndChar +EndChars +EndSplineFont diff --git a/dlls/gdi32/tests/wine_glyphoutlines.ttf b/dlls/gdi32/tests/wine_glyphoutlines.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2b72ddaf559bfcbbda82e2073767eb978792fa1f GIT binary patch literal 1748 zcmds1O>YxN7=C7U?R-IsfL1*~G?W}5Bw_7CL@0*@5+^F4M354QB8A0XY>SO|Yp>NL z2k5CpRh!aCRQv#XE#iR4f%c3zAta=>^uUo5C=wha^UUrTLQAFg+IKac=Y8h=nh(Da z0Jh>QSeVS^rcSPYck?!oUL(6}Y-BWt{b;9tgL>D*>4VwNC-cjII7|I}e%=kS+y0IE zeU7D~TMHWvMnd`;*ISGJ;>B|>J{bk9N$OK2&nFpBw`v677GqD*EoE-d&oH z7TT`kYw9}xHb2O_7{JH$AEDkp?=FP+3>{oQL|s+fdGE!}#|OB66Oe0RP>bB>1HUu> zEY~y8d*kT-zSJ@I!I4+!u%3~@la;})WFDTz5RSL3$aU(ikea2?hs<%zv^>;m%Ss$c z!=~6VW7EfuDeWm@ZpfI}cDJ~O6eE2j?~(g9nZ;9N1g#}fJSQWXXo{M=I9kARgJP-1 zA}=G1|`7&lm8 zJ5~*rjCjXji*Ia?!8Se=R}4;Jo49Lmn*2-sGVC^{(C;U~0^RTpmgvM!23xp*UktX< zBTgHff)dvaPLscnV+asp5ml5?LWLG zE8ZNNQCJG!pt7%p=<<+7wUEzeOkbE}NH`u55jsK7p z?~MkWVZBvWT#omrxF3g=>3!)>(ZH+L%0WdrPNv^+95VlYtN)bLbOZLUEZ^7PMRzFy sDP+2yVNPyTi(n^`@hjDR=pzoTS^ACfU-Y)e2x2_>qUY0i-qh1y19@)s4*&oF literal 0 HcmV?d00001 -- 2.28.0