[PATCH v3] gdi32: Limit GetGlyphOutlineW(uChar) to a WORD.
Arkadiusz Hiler
ahiler at codeweavers.com
Fri Sep 25 08:25:13 CDT 2020
Turns out GetGlyphOutlineW() is using only two bytes for the character,
the rest is discarded.
Fixes eden* PLUS+MOSAIC.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45400
Signed-off-by: Arkadiusz Hiler <ahiler at codeweavers.com>
---
v3:
* ReleaseDC instead of DeleteDC
* test only with 0x10000 offset
* test GGO_GLYPH_INDEX masking
* don't print ret and GetLastError() in case of GetGlyphOutlineW failure
we get GDI_ERROR and last error is not used
* simplify comparing GLYPHMETRICS - memcmp
v2:
While investigating the failures with zh_CN locale I figured out that I did
some mistakes in my font definition and that I can just reuse wine-test.ttf:
* It has .notdef with a distinct width
* It has a few characters defined which are handy to test
The changes are:
* use wine_test font, it's even better than what I had
* make sure that our character is different than .notdef
* test multiple characters
* test multiple values in the higher bytes
* make sure that no matter what we put past the two lower bytes we get the
same character
dlls/gdi32/font.c | 2 ++
dlls/gdi32/tests/font.c | 51 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index a71b24423ac..3c5a6e9a231 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -2911,6 +2911,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/font.c b/dlls/gdi32/tests/font.c
index 0ada22d95d5..b7782417e5f 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -5823,6 +5823,56 @@ todo_wine
ReleaseDC(NULL, hdc);
}
+static void test_GetGlyphOutline_character(void)
+{
+ HFONT hfont, hfont_old;
+ LOGFONTA lf;
+ HDC hdc;
+ DWORD ret;
+ GLYPHMETRICS gm1, gm2, gmn;
+ char test_chars[] = { 'A', 'D', '!', '\0' };
+
+ memset(&lf, 0, sizeof(lf));
+ lf.lfHeight = 72;
+ lstrcpyA(lf.lfFaceName, "wine_test");
+
+ hfont = CreateFontIndirectA(&lf);
+ ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
+
+ hdc = GetDC(NULL);
+
+ hfont_old = SelectObject(hdc, hfont);
+ ok(hfont_old != NULL, "SelectObject failed\n");
+
+ ret = GetGlyphOutlineW(hdc, 'Z', GGO_METRICS, &gmn, 0, NULL, &mat);
+ ok(ret != GDI_ERROR, "GetGlyphOutlineW failed to default to .notdef for character 'Z'\n");
+
+ for (char *current_char = test_chars; *current_char != '\0'; current_char++)
+ {
+ ret = GetGlyphOutlineW(hdc, *current_char, GGO_METRICS, &gm1, 0, NULL, &mat);
+ ok(ret != GDI_ERROR, "GetGlyphOutlineW failed for '%c'\n", *current_char);
+ ok(memcmp(&gm1, &gmn, sizeof(gmn)) != 0, "the test character '%c' matches .notdef\n", *current_char);
+
+ ret = GetGlyphOutlineW(hdc, 0x10000 + *current_char, GGO_METRICS, &gm2, 0, NULL, &mat);
+ ok(ret != GDI_ERROR, "GetGlyphOutlineW failed for 0x10000 + '%c'\n", *current_char);
+ ok(memcmp(&gm1, &gm2, sizeof(gmn)) == 0, "GetGlyphOutlineW returned wrong metrics, expected character 0x10000 + '%c' to match character '%c'\n", *current_char, *current_char);
+ }
+
+ ret = GetGlyphOutlineW(hdc, 0x3, GGO_METRICS|GGO_GLYPH_INDEX, &gm1, 0, NULL, &mat);
+ ok(ret != GDI_ERROR, "GetGlyphOutlineW failed for glyph index 0x3\n");
+
+ ret = GetGlyphOutlineW(hdc, 0xFFFF, GGO_METRICS|GGO_GLYPH_INDEX, &gm2, 0, NULL, &mat);
+ ok(ret == GDI_ERROR, "GetGlyphOutlineW for nonexistent glyph index 0xFFFF has succeded\n");
+
+ ret = GetGlyphOutlineW(hdc, 0x10003, GGO_METRICS|GGO_GLYPH_INDEX, &gm1, 0, NULL, &mat);
+ ok(ret != GDI_ERROR, "GetGlyphOutlineW for index 0x10003 has failed\n");
+ ok(memcmp(&gm1, &gm2, sizeof(gmn)) == 0, "GetGlyphOutlineW returned wrong metrics, expected glyph 0x10003 to match glyph 0x3\n");
+
+ SelectObject(hdc, hfont_old);
+ DeleteObject(hfont);
+ ReleaseDC(NULL, hdc);
+}
+
static void test_fstype_fixup(void)
{
HDC hdc;
@@ -5945,6 +5995,7 @@ static void test_CreateScalableFontResource(void)
test_GetGlyphOutline_empty_contour();
test_GetGlyphOutline_metric_clipping();
+ test_GetGlyphOutline_character();
test_fstype_fixup();
ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0);
--
2.28.0
More information about the wine-devel
mailing list