diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index f9e3c111079..46e3769eb56 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -830,11 +830,61 @@ static HRESULT WINAPI dwritetextanalyzer1_GetScriptProperties(IDWriteTextAnalyze return S_OK; } +static inline BOOL is_char_from_simple_script(WCHAR c) +{ + if (IS_HIGH_SURROGATE(c) || IS_LOW_SURROGATE(c)) + return FALSE; + else { + UINT16 script = get_char_script(c); + return !dwritescripts_properties[script].is_complex; + } +} + static HRESULT WINAPI dwritetextanalyzer1_GetTextComplexity(IDWriteTextAnalyzer2 *iface, const WCHAR *text, UINT32 len, IDWriteFontFace *face, BOOL *is_simple, UINT32 *len_read, UINT16 *indices) { - FIXME("(%s:%u %p %p %p %p): stub\n", debugstr_wn(text, len), len, face, is_simple, len_read, indices); - return E_NOTIMPL; + HRESULT hr = S_OK; + int i; + + TRACE("(%s:%u %p %p %p %p)\n", debugstr_wn(text, len), len, face, is_simple, len_read, indices); + + *is_simple = FALSE; + *len_read = 0; + + if (!face) + return E_INVALIDARG; + + if (len == 0) { + *is_simple = TRUE; + return S_OK; + } + + *is_simple = text[0] && is_char_from_simple_script(text[0]); + for (i = 1; i < len && text[i]; i++) { + if (is_char_from_simple_script(text[i])) { + if (!*is_simple) + break; + } + else + *is_simple = FALSE; + } + + *len_read = i; + + /* fetch indices */ + if (*is_simple && indices) { + UINT32 *codepoints = heap_alloc(*len_read*sizeof(UINT32)); + if (!codepoints) + return E_OUTOFMEMORY; + + for (i = 0; i < *len_read; i++) + codepoints[i] = text[i]; + + hr = IDWriteFontFace_GetGlyphIndices(face, codepoints, *len_read, indices); + heap_free(codepoints); + } + + return hr; } static HRESULT WINAPI dwritetextanalyzer1_GetJustificationOpportunities(IDWriteTextAnalyzer2 *iface, diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c index 490165fef93..45e2e0779d2 100644 --- a/dlls/dwrite/tests/analyzer.c +++ b/dlls/dwrite/tests/analyzer.c @@ -922,7 +922,7 @@ static void test_GetScriptProperties(void) hr = IDWriteTextAnalyzer_QueryInterface(analyzer, &IID_IDWriteTextAnalyzer1, (void**)&analyzer1); IDWriteTextAnalyzer_Release(analyzer); if (hr != S_OK) { - win_skip("IDWriteTextAnalyzer1 is not supported.\n"); + win_skip("GetScriptProperties() is not supported.\n"); return; } @@ -940,6 +940,117 @@ if (0) /* crashes on native */ IDWriteTextAnalyzer1_Release(analyzer1); } +struct textcomplexity_test { + const WCHAR text[5]; + UINT32 length; + BOOL simple; + UINT32 len_read; +}; + +static const struct textcomplexity_test textcomplexity_tests[] = { + { {0}, 1, FALSE, 1 }, + { {0}, 0, TRUE, 0 }, + { {0x610,0}, 0, TRUE, 0 }, + { {'A','B','C','D',0}, 3, TRUE, 3 }, + { {'A','B','C','D',0}, 5, TRUE, 4 }, + { {'A','B','C','D',0}, 10, TRUE, 4 }, + { {'A',0x610,'C','D',0}, 1, TRUE, 1 }, + { {'A',0x610,'C','D',0}, 2, FALSE, 2 }, + { {0x610,'A','C','D',0}, 1, FALSE, 1 }, + { {0x610,'A','C','D',0}, 2, FALSE, 1 }, + { {0x610,0x610,'C','D',0}, 2, FALSE, 2 }, + { {0xd800,'A','B',0}, 1, FALSE, 1 }, + { {0xd800,'A','B',0}, 2, FALSE, 1 }, + { {0xdc00,'A','B',0}, 2, FALSE, 1 } +}; + +static void test_GetTextComplexity(void) +{ + static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0}; + static const WCHAR textW[] = {'A','B','C',0}; + IDWriteTextAnalyzer1 *analyzer1; + IDWriteTextAnalyzer *analyzer; + IDWriteGdiInterop *interop; + IDWriteFontFace *fontface; + UINT16 indices[10]; + IDWriteFont *font; + LOGFONTW logfont; + BOOL simple; + HRESULT hr; + UINT32 len; + int i; + + hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteTextAnalyzer_QueryInterface(analyzer, &IID_IDWriteTextAnalyzer1, (void**)&analyzer1); + IDWriteTextAnalyzer_Release(analyzer); + if (hr != S_OK) { + win_skip("GetTextComplexity() is not supported.\n"); + return; + } + +if (0) { /* crashes on native */ + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, NULL, 0, NULL, NULL, NULL, NULL); + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, NULL, 0, NULL, NULL, &len, NULL); + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, textW, 3, NULL, NULL, NULL, NULL); + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, textW, 3, NULL, NULL, &len, NULL); + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, textW, 3, NULL, &simple, NULL, NULL); +} + + len = 1; + simple = TRUE; + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, NULL, 0, NULL, &simple, &len, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(len == 0, "got %d\n", len); + ok(simple == FALSE, "got %d\n", simple); + + len = 1; + simple = TRUE; + indices[0] = 1; + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, textW, 3, NULL, &simple, &len, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(len == 0, "got %d\n", len); + ok(simple == FALSE, "got %d\n", simple); + ok(indices[0] == 1, "got %d\n", indices[0]); + + /* so font face is required, create one */ + hr = IDWriteFactory_GetGdiInterop(factory, &interop); + ok(hr == S_OK, "got 0x%08x\n", hr); + + memset(&logfont, 0, sizeof(logfont)); + logfont.lfHeight = 12; + logfont.lfWidth = 12; + logfont.lfWeight = FW_NORMAL; + logfont.lfItalic = 1; + lstrcpyW(logfont.lfFaceName, tahomaW); + + hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFont_CreateFontFace(font, &fontface); + ok(hr == S_OK, "got 0x%08x\n", hr); + + for (i = 0; i < sizeof(textcomplexity_tests)/sizeof(struct textcomplexity_test); i++) { + const struct textcomplexity_test *ptr = &textcomplexity_tests[i]; + len = 1; + simple = !ptr->simple; + indices[0] = 0; + hr = IDWriteTextAnalyzer1_GetTextComplexity(analyzer1, ptr->text, ptr->length, fontface, &simple, &len, indices); + ok(hr == S_OK, "%d: got 0x%08x\n", i, hr); + ok(len == ptr->len_read, "%d: read length: got %d, expected %d\n", i, len, ptr->len_read); + ok(simple == ptr->simple, "%d: simple: got %d, expected %d\n", i, simple, ptr->simple); + if (simple && ptr->length) + ok(indices[0] > 0, "%d: got %d\n", i, indices[0]); + else + ok(indices[0] == 0, "%d: got %d\n", i, indices[0]); + } + + IDWriteFontFace_Release(fontface); + IDWriteGdiInterop_Release(interop); + IDWriteTextAnalyzer1_Release(analyzer1); +} + START_TEST(analyzer) { HRESULT hr; @@ -958,6 +1069,7 @@ START_TEST(analyzer) test_AnalyzeScript(); test_AnalyzeLineBreakpoints(); test_GetScriptProperties(); + test_GetTextComplexity(); IDWriteFactory_Release(factory); }