dwrite: Resolve BNs and embedding and override formatting characters to preceding level.

Mirrors commit 71cabaa4b9.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-05-20 12:50:22 +03:00 committed by Alexandre Julliard
parent 778717673e
commit a940ab325a
2 changed files with 142 additions and 19 deletions

View File

@ -946,6 +946,10 @@ static void bidi_resolve_resolved(UINT8 baselevel, const UINT8 *classes, UINT8 *
levels[j--] = baselevel; levels[j--] = baselevel;
levels[i] = baselevel; levels[i] = baselevel;
} }
else if (classes[i] == LRE || classes[i] == RLE || classes[i] == LRO || classes[i] == RLO ||
classes[i] == PDF || classes[i] == BN) {
levels[i] = i ? levels[i - 1] : baselevel;
}
if (i == eos && is_rule_L1_reset_class(classes[i])) { if (i == eos && is_rule_L1_reset_class(classes[i])) {
int j = i; int j = i;
while (j >= sos && is_rule_L1_reset_class(classes[j])) while (j >= sos && is_rule_L1_reset_class(classes[j]))

View File

@ -284,14 +284,22 @@ static HRESULT WINAPI analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink *i
return S_OK; return S_OK;
} }
#define BIDI_LEVELS_COUNT 10
static UINT8 g_explicit_levels[BIDI_LEVELS_COUNT];
static UINT8 g_resolved_levels[BIDI_LEVELS_COUNT];
static HRESULT WINAPI analysissink_SetBidiLevel(IDWriteTextAnalysisSink *iface, static HRESULT WINAPI analysissink_SetBidiLevel(IDWriteTextAnalysisSink *iface,
UINT32 position, UINT32 position,
UINT32 length, UINT32 length,
UINT8 explicitLevel, UINT8 explicitLevel,
UINT8 resolvedLevel) UINT8 resolvedLevel)
{ {
ok(0, "unexpected\n"); if (position + length > BIDI_LEVELS_COUNT) {
return E_NOTIMPL; ok(0, "SetBidiLevel: reported pos=%u, len=%u overflows expected length %d\n", position, length, BIDI_LEVELS_COUNT);
return E_FAIL;
}
memset(g_explicit_levels + position, explicitLevel, length);
memset(g_resolved_levels + position, resolvedLevel, length);
return S_OK;
} }
static HRESULT WINAPI analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface, static HRESULT WINAPI analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface,
@ -345,20 +353,32 @@ static ULONG WINAPI analysissource_Release(IDWriteTextAnalysisSource *iface)
return 1; return 1;
} }
static const WCHAR *g_source; struct testanalysissource
{
IDWriteTextAnalysisSource IDWriteTextAnalysisSource_iface;
const WCHAR *text;
DWRITE_READING_DIRECTION direction;
};
static inline struct testanalysissource *impl_from_IDWriteTextAnalysisSource(IDWriteTextAnalysisSource *iface)
{
return CONTAINING_RECORD(iface, struct testanalysissource, IDWriteTextAnalysisSource_iface);
}
static HRESULT WINAPI analysissource_GetTextAtPosition(IDWriteTextAnalysisSource *iface, static HRESULT WINAPI analysissource_GetTextAtPosition(IDWriteTextAnalysisSource *iface,
UINT32 position, WCHAR const** text, UINT32* text_len) UINT32 position, WCHAR const** text, UINT32* text_len)
{ {
if (position >= lstrlenW(g_source)) struct testanalysissource *source = impl_from_IDWriteTextAnalysisSource(iface);
if (position >= lstrlenW(source->text))
{ {
*text = NULL; *text = NULL;
*text_len = 0; *text_len = 0;
} }
else else
{ {
*text = &g_source[position]; *text = source->text + position;
*text_len = lstrlenW(g_source) - position; *text_len = lstrlenW(source->text) - position;
} }
return S_OK; return S_OK;
@ -374,8 +394,8 @@ static HRESULT WINAPI analysissource_GetTextBeforePosition(IDWriteTextAnalysisSo
static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection( static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection(
IDWriteTextAnalysisSource *iface) IDWriteTextAnalysisSource *iface)
{ {
ok(0, "unexpected\n"); struct testanalysissource *source = impl_from_IDWriteTextAnalysisSource(iface);
return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT; return source->direction;
} }
static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface, static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface,
@ -404,7 +424,7 @@ static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
analysissource_GetNumberSubstitution analysissource_GetNumberSubstitution
}; };
static IDWriteTextAnalysisSource analysissource = { &analysissourcevtbl }; static struct testanalysissource analysissource = { { &analysissourcevtbl } };
static IDWriteFontFace *create_fontface(void) static IDWriteFontFace *create_fontface(void)
{ {
@ -918,12 +938,12 @@ static void get_script_analysis(const WCHAR *str, DWRITE_SCRIPT_ANALYSIS *sa)
IDWriteTextAnalyzer *analyzer; IDWriteTextAnalyzer *analyzer;
HRESULT hr; HRESULT hr;
g_source = str; analysissource.text = str;
hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer); hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource, 0, lstrlenW(g_source), &analysissink2); hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource.IDWriteTextAnalysisSource_iface, 0,
lstrlenW(analysissource.text), &analysissink2);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
*sa = g_sa; *sa = g_sa;
@ -940,10 +960,11 @@ static void test_AnalyzeScript(void)
while (*ptr->string) while (*ptr->string)
{ {
g_source = ptr->string; analysissource.text = ptr->string;
init_expected_sa(expected_seq, ptr); init_expected_sa(expected_seq, ptr);
hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource, 0, lstrlenW(g_source), &analysissink); hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource.IDWriteTextAnalysisSource_iface, 0,
lstrlenW(ptr->string), &analysissink);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, ANALYZER_ID, expected_seq[0]->sequence, wine_dbgstr_w(ptr->string), FALSE); ok_sequence(sequences, ANALYZER_ID, expected_seq[0]->sequence, wine_dbgstr_w(ptr->string), FALSE);
ptr++; ptr++;
@ -1041,16 +1062,17 @@ static void test_AnalyzeLineBreakpoints(void)
hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer); hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
g_source = emptyW; analysissource.text = emptyW;
hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &analysissource, 0, 0, &analysissink); hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &analysissource.IDWriteTextAnalysisSource_iface, 0, 0,
&analysissink);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
while (*ptr->text) while (*ptr->text)
{ {
UINT32 len; UINT32 len;
g_source = ptr->text; analysissource.text = ptr->text;
len = lstrlenW(g_source); len = lstrlenW(ptr->text);
if (len > BREAKPOINT_COUNT) { if (len > BREAKPOINT_COUNT) {
ok(0, "test %u: increase BREAKPOINT_COUNT to at least %u\n", i, len); ok(0, "test %u: increase BREAKPOINT_COUNT to at least %u\n", i, len);
@ -1060,7 +1082,8 @@ static void test_AnalyzeLineBreakpoints(void)
} }
memset(g_actual_bp, 0, sizeof(g_actual_bp)); memset(g_actual_bp, 0, sizeof(g_actual_bp));
hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &analysissource, 0, len, &analysissink); hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &analysissource.IDWriteTextAnalysisSource_iface,
0, len, &analysissink);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
compare_breakpoints(ptr, g_actual_bp); compare_breakpoints(ptr, g_actual_bp);
@ -2130,6 +2153,101 @@ static void test_GetGdiCompatibleGlyphPlacements(void)
IDWriteTextAnalyzer_Release(analyzer); IDWriteTextAnalyzer_Release(analyzer);
} }
struct bidi_test
{
const WCHAR text[BIDI_LEVELS_COUNT];
DWRITE_READING_DIRECTION direction;
UINT8 explicit[BIDI_LEVELS_COUNT];
UINT8 resolved[BIDI_LEVELS_COUNT];
};
static const struct bidi_test bidi_tests[] = {
{
{ 0x645, 0x6cc, 0x200c, 0x6a9, 0x646, 0x645, 0 },
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT,
{ 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1 }
},
{
{ 0x645, 0x6cc, 0x200c, 0x6a9, 0x646, 0x645, 0 },
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT,
{ 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1 }
},
{
{ 0x200c, 0x645, 0x6cc, 0x6a9, 0x646, 0x645, 0 },
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT,
{ 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1 }
},
{
{ 0x200c, 0x645, 0x6cc, 0x6a9, 0x646, 0x645, 0 },
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT,
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 1 }
},
{
{ 'A', 0x200c, 'B', 0 },
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT,
{ 1, 1, 1 },
{ 2, 2, 2 }
},
{
{ 'A', 0x200c, 'B', 0 },
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT,
{ 0, 0, 0 },
{ 0, 0, 0 }
},
{
{ 0 }
}
};
static void compare_bidi_levels(const struct bidi_test *test, UINT32 len, UINT8 *explicit, UINT8 *resolved)
{
ok(!memcmp(explicit, test->explicit, len), "wrong explicit levels\n");
ok(!memcmp(resolved, test->resolved, len), "wrong resolved levels\n");
}
static void test_AnalyzeBidi(void)
{
const struct bidi_test *ptr = bidi_tests;
IDWriteTextAnalyzer *analyzer;
UINT32 i = 0;
HRESULT hr;
hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
ok(hr == S_OK, "got 0x%08x\n", hr);
while (*ptr->text)
{
UINT32 len;
analysissource.text = ptr->text;
len = lstrlenW(ptr->text);
analysissource.direction = ptr->direction;
if (len > BIDI_LEVELS_COUNT) {
ok(0, "test %u: increase BIDI_LEVELS_COUNT to at least %u\n", i, len);
i++;
ptr++;
continue;
}
memset(g_explicit_levels, 0, sizeof(g_explicit_levels));
memset(g_resolved_levels, 0, sizeof(g_resolved_levels));
hr = IDWriteTextAnalyzer_AnalyzeBidi(analyzer, &analysissource.IDWriteTextAnalysisSource_iface, 0,
len, &analysissink);
ok(hr == S_OK, "%u: got 0x%08x\n", i, hr);
compare_bidi_levels(ptr, len, g_explicit_levels, g_resolved_levels);
i++;
ptr++;
}
IDWriteTextAnalyzer_Release(analyzer);
}
START_TEST(analyzer) START_TEST(analyzer)
{ {
HRESULT hr; HRESULT hr;
@ -2147,6 +2265,7 @@ START_TEST(analyzer)
test_AnalyzeScript(); test_AnalyzeScript();
test_AnalyzeLineBreakpoints(); test_AnalyzeLineBreakpoints();
test_AnalyzeBidi();
test_GetScriptProperties(); test_GetScriptProperties();
test_GetTextComplexity(); test_GetTextComplexity();
test_GetGlyphs(); test_GetGlyphs();