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

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 20 11:27:54 CDT 2016


Module: wine
Branch: master
Commit: a940ab325a543e24d1bde7a5e336400bbd1f75bf
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a940ab325a543e24d1bde7a5e336400bbd1f75bf

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri May 20 12:50:22 2016 +0300

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

Mirrors commit 71cabaa4b93f040e16519c6f8253673480995ac7.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/bidi.c           |   4 ++
 dlls/dwrite/tests/analyzer.c | 157 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 142 insertions(+), 19 deletions(-)

diff --git a/dlls/dwrite/bidi.c b/dlls/dwrite/bidi.c
index 3deabfc..32c4075 100644
--- a/dlls/dwrite/bidi.c
+++ b/dlls/dwrite/bidi.c
@@ -946,6 +946,10 @@ static void bidi_resolve_resolved(UINT8 baselevel, const UINT8 *classes, UINT8 *
                 levels[j--] = 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])) {
             int j = i;
             while (j >= sos && is_rule_L1_reset_class(classes[j]))
diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c
index 90d7f6f..d008178 100644
--- a/dlls/dwrite/tests/analyzer.c
+++ b/dlls/dwrite/tests/analyzer.c
@@ -284,14 +284,22 @@ static HRESULT WINAPI analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink *i
     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,
         UINT32 position,
         UINT32 length,
         UINT8 explicitLevel,
         UINT8 resolvedLevel)
 {
-    ok(0, "unexpected\n");
-    return E_NOTIMPL;
+    if (position + length > BIDI_LEVELS_COUNT) {
+        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,
@@ -345,20 +353,32 @@ static ULONG WINAPI analysissource_Release(IDWriteTextAnalysisSource *iface)
     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,
     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_len = 0;
     }
     else
     {
-        *text = &g_source[position];
-        *text_len = lstrlenW(g_source) - position;
+        *text = source->text + position;
+        *text_len = lstrlenW(source->text) - position;
     }
 
     return S_OK;
@@ -374,8 +394,8 @@ static HRESULT WINAPI analysissource_GetTextBeforePosition(IDWriteTextAnalysisSo
 static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection(
     IDWriteTextAnalysisSource *iface)
 {
-    ok(0, "unexpected\n");
-    return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
+    struct testanalysissource *source = impl_from_IDWriteTextAnalysisSource(iface);
+    return source->direction;
 }
 
 static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface,
@@ -404,7 +424,7 @@ static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
     analysissource_GetNumberSubstitution
 };
 
-static IDWriteTextAnalysisSource analysissource = { &analysissourcevtbl };
+static struct testanalysissource analysissource = { { &analysissourcevtbl } };
 
 static IDWriteFontFace *create_fontface(void)
 {
@@ -918,12 +938,12 @@ static void get_script_analysis(const WCHAR *str, DWRITE_SCRIPT_ANALYSIS *sa)
     IDWriteTextAnalyzer *analyzer;
     HRESULT hr;
 
-    g_source = str;
-
+    analysissource.text = str;
     hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
     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);
 
     *sa = g_sa;
@@ -940,10 +960,11 @@ static void test_AnalyzeScript(void)
 
     while (*ptr->string)
     {
-        g_source = ptr->string;
+        analysissource.text = ptr->string;
 
         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_sequence(sequences, ANALYZER_ID, expected_seq[0]->sequence, wine_dbgstr_w(ptr->string), FALSE);
         ptr++;
@@ -1041,16 +1062,17 @@ static void test_AnalyzeLineBreakpoints(void)
     hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    g_source = emptyW;
-    hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &analysissource, 0, 0, &analysissink);
+    analysissource.text = emptyW;
+    hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &analysissource.IDWriteTextAnalysisSource_iface, 0, 0,
+        &analysissink);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     while (*ptr->text)
     {
         UINT32 len;
 
-        g_source = ptr->text;
-        len = lstrlenW(g_source);
+        analysissource.text = ptr->text;
+        len = lstrlenW(ptr->text);
 
         if (len > BREAKPOINT_COUNT) {
             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));
-        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);
         compare_breakpoints(ptr, g_actual_bp);
 
@@ -2130,6 +2153,101 @@ static void test_GetGdiCompatibleGlyphPlacements(void)
     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)
 {
     HRESULT hr;
@@ -2147,6 +2265,7 @@ START_TEST(analyzer)
 
     test_AnalyzeScript();
     test_AnalyzeLineBreakpoints();
+    test_AnalyzeBidi();
     test_GetScriptProperties();
     test_GetTextComplexity();
     test_GetGlyphs();




More information about the wine-cvs mailing list