[PATCH v2 6/7] gdi32/tests: Add more tests for GetCharacterPlacement.
Sven Baars
sbaars at codeweavers.com
Mon Nov 9 08:07:19 CST 2020
Similar to the tests already present for usp10.
Signed-off-by: Sven Baars <sbaars at codeweavers.com>
---
v2: Fixed test failures.
dlls/gdi32/tests/font.c | 444 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 443 insertions(+), 1 deletion(-)
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 5b5efc88743..f08b42ff66e 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -4895,12 +4895,310 @@ static void test_GetTextMetrics2(const char *fontname, int font_height)
ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
}
+struct enum_font_range_param {
+ BYTE range;
+ LOGFONTA lf;
+};
+
+static int CALLBACK enum_font_range_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM param)
+{
+ NEWTEXTMETRICEXA *ntme = (NEWTEXTMETRICEXA *)tm;
+ struct enum_font_range_param *efrp = (struct enum_font_range_param *)param;
+ int idx = 0;
+ DWORD i;
+ DWORD mask = 0;
+
+ if (type != TRUETYPE_FONTTYPE)
+ return 1;
+
+ i = efrp->range;
+ while (i >= sizeof(DWORD)*8)
+ {
+ idx++;
+ i -= (sizeof(DWORD)*8);
+ }
+ if (idx > 3)
+ return 0;
+
+ mask = 1 << i;
+
+ if (ntme->ntmFontSig.fsUsb[idx] & mask)
+ {
+ memcpy(&(efrp->lf), lf, sizeof(LOGFONTA));
+ return 0;
+ }
+ return 1;
+}
+
+static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, const WCHAR check, HFONT *hfont, HFONT *hfont_orig)
+{
+ int rc = 0;
+ struct enum_font_range_param param;
+
+ param.range = range;
+ memset(¶m.lf, 0, sizeof(LOGFONTA));
+ *hfont = NULL;
+
+ if (recommended)
+ {
+ lstrcpyA(param.lf.lfFaceName, recommended);
+ if (!EnumFontFamiliesExA(hdc, ¶m.lf, enum_font_range_proc, (LPARAM)¶m, 0))
+ {
+ *hfont = CreateFontIndirectA(¶m.lf);
+ if (*hfont)
+ {
+ winetest_trace("Using font %s.\n", param.lf.lfFaceName);
+ rc = 1;
+ }
+ }
+ if (!rc)
+ winetest_skip("Font %s is not available.\n", recommended);
+ }
+
+ if (!*hfont)
+ {
+ memset(¶m.lf, 0, sizeof(LOGFONTA));
+ param.lf.lfCharSet = DEFAULT_CHARSET;
+
+ if (!EnumFontFamiliesExA(hdc, ¶m.lf, enum_font_range_proc, (LPARAM)¶m, 0) && param.lf.lfFaceName[0])
+ {
+ *hfont = CreateFontIndirectA(¶m.lf);
+ if (*hfont)
+ winetest_trace("Trying font %s: failures will only be warnings.\n",param.lf.lfFaceName);
+ }
+ }
+
+ if (*hfont)
+ {
+ WORD glyph = 0;
+
+ *hfont_orig = SelectObject(hdc, *hfont);
+ if (GetGlyphIndicesW(hdc, &check, 1, &glyph, 0) == GDI_ERROR || glyph == 0)
+ {
+ winetest_trace("Font fails to contain required glyphs.\n");
+ SelectObject(hdc, *hfont_orig);
+ DeleteObject(*hfont);
+ *hfont = NULL;
+ rc = 0;
+ }
+ else if (!rc)
+ rc = -1;
+ }
+ else
+ winetest_trace("Failed to find usable font.\n");
+
+ return rc;
+}
+
+#define find_font_for_range(a, b, c, d, e, f) \
+ (winetest_set_location(__FILE__, __LINE__), 0) ? 0 : \
+ _find_font_for_range(a, b, c, d, e, f)
+
+struct expected_character_placement
+{
+ int order;
+ int dx;
+ int reorder;
+};
+
+static inline void _test_character_placement_ok(int valid, HDC hdc, const WCHAR *string, unsigned int str_len,
+ const struct expected_character_placement *expected, unsigned int expected_len)
+{
+ GCP_RESULTSW result;
+ unsigned int i, max_glyphs = 1.5 * str_len;
+ DWORD size;
+ int dx;
+
+ memset(&result, 0, sizeof(result));
+ result.lStructSize = sizeof(result);
+ result.lpCaretPos = heap_alloc(max_glyphs * sizeof(*result.lpCaretPos));
+ result.lpGlyphs = heap_alloc(max_glyphs * sizeof(*result.lpGlyphs));
+ result.lpOrder = heap_alloc(max_glyphs * sizeof(*result.lpOrder));
+ result.lpDx = heap_alloc(max_glyphs * sizeof(*result.lpDx));
+ result.nGlyphs = max_glyphs;
+
+ memset(result.lpOrder, -1, max_glyphs * sizeof(*result.lpOrder));
+ memset(result.lpDx, -1, max_glyphs * sizeof(*result.lpDx));
+
+ size = GetCharacterPlacementW(hdc, string, str_len, 0, &result, 0);
+ winetest_ok(size, "GetCharacterPlacementW failed.\n");
+ if (valid > 0)
+ winetest_ok(result.nGlyphs == expected_len, "Expected %d, got %d.\n", expected_len, result.nGlyphs);
+ else if (result.nGlyphs != expected_len)
+ winetest_trace("Expected %d, got %d.\n", expected_len, result.nGlyphs);
+ for (i = 0; i < result.nGlyphs; ++i)
+ {
+ if (valid > 0)
+ todo_wine_if(expected[i].order != i)
+ winetest_ok(result.lpOrder[i] == expected[i].order ||
+ broken(result.lpOrder[i] == expected[expected_len - i - 1].reorder) /* Win2008 */,
+ "Character %d, expected order %d, got %d.\n",
+ i, expected[i].order, result.lpOrder[i]);
+ else if (result.lpOrder[i] != expected[i].reorder)
+ winetest_trace("Character %d, expected order %d, got %d.\n", i, expected[i].reorder, result.lpOrder[i]);
+ if (expected[i].dx)
+ {
+ GetCharWidthI(hdc, result.lpGlyphs[result.lpOrder[i]], 1, NULL, &dx);
+ if (valid > 0)
+ winetest_ok(result.lpDx[result.lpOrder[i]] == dx, "Character %d, expected dx %d, got %d.\n",
+ i, dx, result.lpDx[result.lpOrder[i]]);
+ else if (result.lpDx[result.lpOrder[i]] != dx)
+ winetest_trace("Character %d, expected dx %d, got %d.\n",
+ i, dx, result.lpDx[result.lpOrder[i]]);
+ }
+ }
+
+ if (expected[0].reorder >= 0)
+ {
+ memset(result.lpOrder, -1, max_glyphs * sizeof(*result.lpOrder));
+ memset(result.lpDx, -1, max_glyphs * sizeof(*result.lpDx));
+
+ size = GetCharacterPlacementW(hdc, string, str_len, 0, &result, GCP_REORDER);
+ winetest_ok(size, "GetCharacterPlacementW failed with GCP_REORDER.\n");
+ if (valid > 0)
+ winetest_ok(result.nGlyphs == expected_len, "Expected %d with GCP_REORDER, got %d.\n", expected_len, result.nGlyphs);
+ else if (result.nGlyphs != expected_len)
+ winetest_trace("Expected %d with GCP_REORDER, got %d.\n", expected_len, result.nGlyphs);
+ for (i = 0; i < result.nGlyphs; ++i)
+ {
+ if (valid > 0)
+ todo_wine_if(expected[i].order != i)
+ winetest_ok(result.lpOrder[i] == expected[i].reorder, "Character %d, expected GCP_REORDER order %d, got %d.\n",
+ i, expected[i].reorder, result.lpOrder[i]);
+ else if (result.lpOrder[i] != expected[i].reorder)
+ winetest_trace("Character %d, expected GCP_REORDER order %d, got %d.\n", i, expected[i].reorder, result.lpOrder[i]);
+ if (expected[i].dx)
+ {
+ GetCharWidthI(hdc, result.lpGlyphs[result.lpOrder[i]], 1, NULL, &dx);
+ if (valid > 0)
+ winetest_ok(result.lpDx[result.lpOrder[i]] == dx, "Character %d, expected GCP_REORDER dx %d, got %d.\n",
+ i, dx, result.lpDx[result.lpOrder[i]]);
+ else if (result.lpDx[result.lpOrder[i]] != dx)
+ winetest_trace("Character %d, expected GCP_REORDER dx %d, got %d.\n",
+ i, dx, result.lpDx[result.lpOrder[i]]);
+ }
+ }
+ }
+
+ heap_free(result.lpCaretPos);
+ heap_free(result.lpGlyphs);
+ heap_free(result.lpOrder);
+ heap_free(result.lpDx);
+}
+
+#define test_character_placement_ok(a, b, c, d, e, f) \
+ (winetest_set_location(__FILE__, __LINE__), 0) ? 0 : \
+ _test_character_placement_ok(a, b, c, d, e, f)
+
static void test_GetCharacterPlacement(void)
{
+ static const WCHAR test1[] = {'w', 'i', 'n', 'e'};
+ static const struct expected_character_placement t1_expected[] =
+ {{0,1,0},{1,1,1},{2,1,2},{3,1,3}};
+
+ static const WCHAR test2[] = {0x202B, 'i', 'n', 0x202C};
+ static const struct expected_character_placement t2_expected[] =
+ {{0,0,0},{1,1,1},{2,1,2},{3,0,3}};
+
+ static const WCHAR test3[] = {'t', 't', 'f', 'f', 'f', 'i',};
+ static const struct expected_character_placement t3_expected[] =
+ {{0,1,0},{0,1,0},{0,1,0},{1,1,1},{1,1,1},{1,1,1}};
+
+ /* Hebrew */
+ static const WCHAR test_hebrew[] =
+ {0x05e9, 0x05dc, 0x05d5, 0x05dd};
+ static const struct expected_character_placement hebrew_expected[] =
+ {{0,1,3},{1,1,2},{2,1,1},{3,1,0}};
+
+ /* Arabic */
+ static const WCHAR test_arabic[] =
+ {0x0633, 0x0644, 0x0627, 0x0645};
+ static const struct expected_character_placement arabic_expected[] =
+ {{0,1,2},{1,1,1},{2,1,1},{3,1,0}};
+
+ /* Thai */
+ static const WCHAR test_thai[] =
+ {0x0e2a, 0x0e04, 0x0e23, 0x0e34, 0x0e1b, 0x0e15, 0x0e4c, 0x0e44, 0x0e17, 0x0e22};
+ static const struct expected_character_placement thai_expected[] =
+ {{0,1,0},{1,1,1},{2,1,2},{3,1,3},{4,1,4},{5,1,5},{6,1,6},{7,1,7},{8,1,8},{9,1,9}};
+
+ /* Thaana */
+ static const WCHAR test_thaana[] =
+ {0x078a, 0x07ae, 0x0792, 0x07b0, 0x0020, 0x0796, 0x07aa, 0x0789, 0x07b0, 0x0795, 0x07ac, 0x0791, 0x07b0};
+ static const struct expected_character_placement thaana_expected[] =
+ {{0,1,12},{1,1,11},{2,0,10},{3,1,9},{4,1,8},{5,1,7},{6,1,6},{7,1,5},{8,1,4},{9,1,3},{10,1,2},{11,0,1},{12,1,0}};
+
+ /* Phags-pa */
+ static const WCHAR test_phagspa[] =
+ {0xa84f, 0xa861, 0xa843, 0x0020, 0xa863, 0xa861, 0xa859, 0x0020, 0xa850, 0xa85c, 0xa85e};
+ static const struct expected_character_placement phagspa_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1},{5,1,-1},{6,1,-1},{7,1,-1},{8,1,-1},{9,1,-1},{10,1,-1}};
+
+ /* Lao */
+ static const WCHAR test_lao[] =
+ {0x0ead, 0x0eb1, 0x0e81, 0x0eaa, 0x0ead, 0x0e99, 0x0ea5, 0x0eb2, 0x0ea7};
+ static const struct expected_character_placement lao_expected[] =
+ {{0,1,0},{1,1,1},{2,1,2},{3,1,3},{4,1,4},{5,1,5},{6,1,6},{7,1,7},{8,1,8}};
+
+ /* Tibetan */
+ static const WCHAR test_tibetan[] =
+ {0x0f04, 0x0f05, 0x0f0e, 0x0020, 0x0f51, 0x0f7c, 0x0f53, 0x0f0b, 0x0f5a, 0x0f53, 0x0f0b, 0x0f51, 0x0f44, 0x0f0b, 0x0f54, 0x0f7c, 0x0f0d};
+ static const struct expected_character_placement tibetan_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1},{5,1,-1},{6,1,-1},{7,1,-1},{8,1,-1},{9,1,-1},{10,1,-1},{11,1,-1},{12,1,-1},{13,1,-1},{14,1,-1},{15,1,-1},{16,1,-1}};
+
+ /* Devanagari */
+ static const WCHAR test_devanagari[] =
+ {0x0926, 0x0947, 0x0935, 0x0928, 0x093e, 0x0917, 0x0930, 0x0940};
+ static const struct expected_character_placement devanagari_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1},{5,1,-1},{6,1,-1},{7,1,-1}};
+
+ /* Bengali */
+ static const WCHAR test_bengali[] =
+ {0x09ac, 0x09be, 0x0982, 0x09b2, 0x09be};
+ static const struct expected_character_placement bengali_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1}};
+
+ /* Gurmukhi */
+ static const WCHAR test_gurmukhi[] =
+ {0x0a17, 0x0a41, 0x0a30, 0x0a2e, 0x0a41, 0x0a16, 0x0a40};
+ static const struct expected_character_placement gurmukhi_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1},{5,1,-1},{6,1,-1}};
+
+ /* Gujarati */
+ static const WCHAR test_gujarati[] =
+ {0x0a97, 0x0ac1, 0x0a9c, 0x0ab0, 0x0abe, 0x0aa4, 0x0ac0};
+ static const struct expected_character_placement gujarati_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1},{5,1,-1},{6,1,-1}};
+
+ /* Oriya */
+ static const WCHAR test_oriya[] =
+ {0x0b13, 0x0b21, 0x0b3c, 0x0b3f, 0x0b06};
+ static const struct expected_character_placement oriya_expected[] =
+ {{0,1,0},{1,1,1},{2,1,2},{2,1,2},{3,1,3}};
+
+ /* Tamil */
+ static const WCHAR test_tamil[] =
+ {0x0ba4, 0x0bae, 0x0bbf, 0x0bb4, 0x0bcd};
+ static const struct expected_character_placement tamil_expected[] =
+ {{0,1,0},{1,1,1},{2,1,2},{3,1,3},{3,1,3}};
+
+ /* Malayalam */
+ static const WCHAR test_malayalam[] =
+ {0x0d2e, 0x0d32, 0x0d2f, 0x0d3e, 0x0d33, 0x0d02};
+ static const struct expected_character_placement malayalam_expected[] =
+ {{0,1,-1},{1,1,-1},{2,1,-1},{3,1,-1},{4,1,-1},{5,1,-1}};
+
+ /* Kannada */
+ static const WCHAR test_kannada[] =
+ {0x0c95, 0x0ca8, 0x0ccd, 0x0ca8, 0x0ca1};
+ static const struct expected_character_placement kannada_expected[] =
+ {{0,1,0},{1,1,1},{2,1,2},{2,1,2},{3,1,3}};
+
+ HFONT hfont, hfont_orig;
GCP_RESULTSA result;
DWORD size, size2;
WCHAR glyphs[20];
- int pos[20];
+ int test_valid, pos[20];
HDC hdc;
hdc = CreateCompatibleDC(0);
@@ -4947,6 +5245,150 @@ static void test_GetCharacterPlacement(void)
ok(glyphs[0] == 'W', "Unexpected first glyph %s\n", wine_dbgstr_wn(glyphs, 1));
todo_wine ok(pos[0] == 0, "Unexpected caret position %d\n", pos[0]);
+ test_valid = find_font_for_range(hdc, "Tahoma", 0, test1[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test1, 4, t1_expected, ARRAY_SIZE(t1_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Tahoma", 0, test2[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test2, 4, t2_expected, ARRAY_SIZE(t2_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Calibri", 0, test3[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test3, 6, t3_expected, ARRAY_SIZE(t3_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 11, test_hebrew[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_hebrew, 4, hebrew_expected, ARRAY_SIZE(hebrew_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 13, test_arabic[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_arabic, 4, arabic_expected, ARRAY_SIZE(arabic_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 24, test_thai[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_thai, 10, thai_expected, ARRAY_SIZE(thai_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "MV Boli", 72, test_thaana[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_thaana, 13, thaana_expected, ARRAY_SIZE(thaana_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Microsoft PhagsPa", 53, test_phagspa[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_phagspa, 11, phagspa_expected, ARRAY_SIZE(phagspa_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "DokChampa", 25, test_lao[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_lao, 9, lao_expected, ARRAY_SIZE(lao_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Microsoft Himalaya", 70, test_tibetan[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_tibetan, 17, tibetan_expected, ARRAY_SIZE(tibetan_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Mangal", 15, test_devanagari[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_devanagari, 8, devanagari_expected, ARRAY_SIZE(devanagari_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Vrinda", 16, test_bengali[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_bengali, 5, bengali_expected, ARRAY_SIZE(bengali_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Raavi", 17, test_gurmukhi[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_gurmukhi, 7, gurmukhi_expected, ARRAY_SIZE(gurmukhi_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Shruti", 18, test_gujarati[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_gujarati, 7, gujarati_expected, ARRAY_SIZE(gujarati_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Kalinga", 19, test_oriya[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_oriya, 5, oriya_expected, ARRAY_SIZE(oriya_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Latha", 20, test_tamil[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_tamil, 5, tamil_expected, ARRAY_SIZE(tamil_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Kartika", 23, test_malayalam[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_malayalam, 6, malayalam_expected, ARRAY_SIZE(malayalam_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
+ test_valid = find_font_for_range(hdc, "Tunga", 22, test_kannada[0], &hfont, &hfont_orig);
+ if (hfont != NULL)
+ {
+ test_character_placement_ok(test_valid, hdc, test_kannada, 5, kannada_expected, ARRAY_SIZE(kannada_expected));
+ SelectObject(hdc, hfont_orig);
+ DeleteObject(hfont);
+ }
+
DeleteDC(hdc);
}
--
2.25.1
More information about the wine-devel
mailing list