From: Sven Baars Subject: [PATCH v2 4/7] gdi32/tests: Add tests for zero-width control characters. Message-Id: <20201109140720.472712-4-sbaars@codeweavers.com> Date: Mon, 9 Nov 2020 15:07:16 +0100 In-Reply-To: <20201109140720.472712-1-sbaars@codeweavers.com> References: <20201109140720.472712-1-sbaars@codeweavers.com> Signed-off-by: Sven Baars --- v2: Fixed test failures. dlls/gdi32/tests/font.c | 134 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 2592db2cc06..8985476ed82 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -7666,6 +7666,139 @@ done: ReleaseDC(0, hdc); } +static void test_zero_width_control(void) +{ + int len, dx, nfit, pos[20]; + DWORD size, charcount; + GCP_RESULTSW result; + WCHAR space_glyph; + WCHAR glyphs[20]; + unsigned int i; + LOGFONTA lf; + HFONT hfont; + BOOL ret; + SIZE sz; + HDC hdc; + ABC abc; + + static const WCHAR nul[] = {0}; + static const WCHAR space[] = {' '}; + static const WCHAR zero_width_control[] = { + 0x0009, /* \t */ + 0x000a, /* \n */ + 0x000d, /* \r */ + 0x001c, /* FS */ + 0x001d, /* GS */ + 0x001e, /* RS */ + 0x001f, /* US */ + 0x200b, /* ZWSP */ + 0x200c, /* ZWNJ */ + 0x200d, /* ZWJ */ + 0x200e, /* LRM */ + 0x200f, /* RLM */ + 0x202a, /* LRE */ + 0x202c, /* PDF */ + 0x202d, /* LRO */ + 0x202b, /* RLE */ + 0x202e, /* RLO */ + }; + + memset(&lf, 0, sizeof(lf)); + strcpy(lf.lfFaceName, "Tahoma"); + lf.lfHeight = 20; + + hfont = CreateFontIndirectA(&lf); + hdc = GetDC(NULL); + hfont = SelectObject(hdc, hfont); + + memset(&result, 0, sizeof(result)); + result.lStructSize = sizeof(result); + result.lpCaretPos = pos; + result.lpGlyphs = glyphs; + + for (i = 0; i < ARRAY_SIZE(zero_width_control); ++i) + { + WCHAR test[] = {'W', 'i', 'n', 'e', ' ', zero_width_control[i], 'T', 'e', 's', 't', 0}; + + /* Some control characters are treated as space */ + result.nGlyphs = 20; + size = GetCharacterPlacementW(hdc, test, 10, 0, &result, 0); + ok(size, "Test %d: GetCharacterPlacementA failed.\n", i); + ok(result.nGlyphs == 10, "Test %d: unexpected number of glyphs %u.\n", i, result.nGlyphs); + todo_wine ok(glyphs[5] == glyphs[4], "Test %d: unexpected glyphs %s.\n", i, wine_dbgstr_wn(glyphs, result.nGlyphs)); + if (i < 15) + todo_wine ok(pos[6] - pos[5] == 0, "Test %d: unexpected width %d.\n", i, pos[6] - pos[5]); + else + ok(pos[6] - pos[5] > 0, "Test %d: unexpected width %d.\n", i, pos[6] - pos[5]); + ok(pos[5] - pos[4] > 0, "Test %d: unexpected width %d.\n", i, pos[5] - pos[4]); + + /* They all have zero width in GetTextExtentExPoint */ + nfit = -1; + dx = -1; + sz.cx = -1; + ret = GetTextExtentExPointW(hdc, zero_width_control + i, 1, 1000, &nfit, &dx, &sz); + ok(ret, "Test %d: expected TRUE.\n", i); + ok(nfit == 1, "Test %d: got %d.\n", i, nfit); + todo_wine ok(dx == 0, "Test %d: got %d.\n", i, dx); + todo_wine ok(sz.cx == 0, "Test %d: got %d.\n", i, sz.cx); + + /* They do not all have zero width in GetCharWidth32 */ + len = -1; + ret = GetCharWidth32W(hdc, zero_width_control[i], zero_width_control[i], &len); + ok(ret, "Test %d: expected TRUE.\n", i); + + /* Because ABC does not have zero width */ + memset(&abc, 0, sizeof(abc)); + ret = GetCharABCWidthsW(hdc, zero_width_control[i], zero_width_control[i], &abc); + ok(ret, "Test %d: expected TRUE.\n", i); + + if (i < 7) + { + ok(len > 0, "Test %d: got %d.\n", i, len); + ok(abc.abcA + abc.abcB + abc.abcC <= len && abc.abcA + abc.abcB + abc.abcC > 0, + "Test %d: expected %d >= %d > 0.\n", i, len, abc.abcA + abc.abcB + abc.abcC); + ok(abc.abcB > 0, "Test %d: got %d.\n", i, abc.abcB); + } + else + { + todo_wine ok(len == 0 || broken(i > 11) /* before Win10 */, "Test %d: got %d.\n", i, len); + ok(abc.abcA + abc.abcB + abc.abcC == len, + "Test %d: expected %d == 0.\n", i, abc.abcA + abc.abcB + abc.abcC); + ok(abc.abcB > 0, "Test %d: got %d.\n", i, abc.abcB); + } + } + + /* The NUL character does not have zero width */ + nfit = -1; + dx = -1; + sz.cx = -1; + ret = GetTextExtentExPointW(hdc, nul, 1, 1000, &nfit, &dx, &sz); + ok(ret, "Expected TRUE.\n"); + ok(nfit == 1, "Got %d.\n", nfit); + ok(dx > 0, "Got %d.\n", dx); + ok(sz.cx > 0, "Got %d.\n", sz.cx); + + memset(&abc, 0, sizeof(abc)); + ret = GetCharABCWidthsW(hdc, 0, 0, &abc); + ok(ret, "Expected TRUE.\n"); + todo_wine ok(abc.abcA == 0, "Got %d.\n", abc.abcA); + ok(abc.abcB > 0, "Got %d.\n", abc.abcB); + ok(abc.abcC >= 0, "Got %d.\n", abc.abcC); + + /* Test that characters that are treated as spaces by GetCharacterPlacement */ + /* are not treated like spaces by GetGlyphIndices. */ + charcount = GetGlyphIndicesW(hdc, space, 1, &space_glyph, 0); + ok(charcount == 1, "Wrong character count %d.\n", charcount); + + charcount = GetGlyphIndicesW(hdc, zero_width_control, ARRAY_SIZE(zero_width_control), glyphs, 0); + ok(charcount == ARRAY_SIZE(zero_width_control), "Wrong character count %d.\n", charcount); + for (i = 0; i < ARRAY_SIZE(zero_width_control); ++i) + ok(glyphs[i] != space_glyph, "Test %d: glyph is a space: %04x\n", i, glyphs[i]); + + DeleteObject(hfont); + ReleaseDC(NULL, hdc); +} + START_TEST(font) { static const char *test_names[] = @@ -7752,6 +7885,7 @@ START_TEST(font) test_ttf_names(); test_lang_names(); test_char_width(); + test_zero_width_control(); /* These tests should be last test until RemoveFontResource * is properly implemented. -- 2.25.1