Nikolay Sivov : dwrite: Add a zero width line after last mandatory breakpoint.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Feb 3 10:23:53 CST 2016


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Feb  2 23:14:37 2016 +0300

dwrite: Add a zero width line after last mandatory breakpoint.

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

---

 dlls/dwrite/layout.c       | 59 +++++++++++++++++++++++++++-------------------
 dlls/dwrite/tests/layout.c | 46 ++++++++++++++++++++++++++++++++----
 2 files changed, 77 insertions(+), 28 deletions(-)

diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 93d096d..9cbbb38 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -1572,6 +1572,31 @@ static HRESULT layout_add_underline(struct dwrite_textlayout *layout, struct lay
     return S_OK;
 }
 
+/* Adds zero width line, metrics are derived from font at specified text position. */
+static HRESULT layout_set_dummy_line_metrics(struct dwrite_textlayout *layout, UINT32 pos, UINT32 *line)
+{
+    DWRITE_FONT_METRICS fontmetrics;
+    DWRITE_LINE_METRICS metrics;
+    struct layout_range *range;
+    IDWriteFontFace *fontface;
+    HRESULT hr;
+
+    range = get_layout_range_by_pos(layout, pos);
+    hr = create_fontface_by_pos(layout, range, &fontface);
+    if (FAILED(hr))
+        return hr;
+
+    layout_get_font_metrics(layout, fontface, range->fontsize, &fontmetrics);
+    layout_get_font_height(range->fontsize, &fontmetrics, &metrics.baseline, &metrics.height);
+    IDWriteFontFace_Release(fontface);
+
+    metrics.length = 0;
+    metrics.trailingWhitespaceLength = 0;
+    metrics.newlineLength = 0;
+    metrics.isTrimmed = FALSE;
+    return layout_set_line_metrics(layout, &metrics, line);
+}
+
 static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
 {
     BOOL is_rtl = layout->format.readingdir == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
@@ -1720,30 +1745,16 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
         textpos += layout->clustermetrics[i].length;
     }
 
-    /* Add dummy line when there's no text. Metrics come from first range. */
-    if (layout->len == 0) {
-        DWRITE_FONT_METRICS fontmetrics;
-        struct layout_range *range;
-        IDWriteFontFace *fontface;
-
-        range = get_layout_range_by_pos(layout, 0);
-        hr = create_fontface_by_pos(layout, range, &fontface);
-        if (FAILED(hr))
-            return hr;
-
-        layout_get_font_metrics(layout, fontface, range->fontsize, &fontmetrics);
-        layout_get_font_height(range->fontsize, &fontmetrics, &metrics.baseline, &metrics.height);
-        IDWriteFontFace_Release(fontface);
-
-        line = 0;
-        metrics.length = 0;
-        metrics.trailingWhitespaceLength = 0;
-        metrics.newlineLength = 0;
-        metrics.isTrimmed = FALSE;
-        hr = layout_set_line_metrics(layout, &metrics, &line);
-        if (FAILED(hr))
-            return hr;
-    }
+    /* Add dummy line if:
+       - there's no text, metrics come from first range in this case;
+       - last ended with a mandatory break, metrics come from last text position.
+    */
+    if (layout->len == 0)
+        hr = layout_set_dummy_line_metrics(layout, 0, &line);
+    else if (layout->clustermetrics[layout->cluster_count-1].isNewline)
+        hr = layout_set_dummy_line_metrics(layout, layout->len-1, &line);
+    if (FAILED(hr))
+        return hr;
 
     layout->metrics.left = is_rtl ? layout->metrics.layoutWidth - layout->metrics.width : 0.0f;
     layout->metrics.top = 0.0f;
diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c
index bf46df8..e1903db 100644
--- a/dlls/dwrite/tests/layout.c
+++ b/dlls/dwrite/tests/layout.c
@@ -3226,6 +3226,7 @@ static void test_GetLineMetrics(void)
     static const WCHAR str3W[] = {'a','\r','b','\n','c','\n','\r','d','\r','\n',0};
     static const WCHAR strW[] = {'a','b','c','d',' ',0};
     static const WCHAR str2W[] = {'a','b','\r','c','d',0};
+    static const WCHAR str4W[] = {'a','\r',0};
     IDWriteFontCollection *syscollection;
     DWRITE_FONT_METRICS fontmetrics;
     DWRITE_LINE_METRICS metrics[6];
@@ -3367,7 +3368,6 @@ static void test_GetLineMetrics(void)
     count = 0;
     hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, sizeof(metrics)/sizeof(*metrics), &count);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-todo_wine
     ok(count == 6, "got %u\n", count);
 
     ok(metrics[0].length == 2, "got %u\n", metrics[0].length);
@@ -3375,7 +3375,6 @@ todo_wine
     ok(metrics[2].length == 2, "got %u\n", metrics[2].length);
     ok(metrics[3].length == 1, "got %u\n", metrics[3].length);
     ok(metrics[4].length == 3, "got %u\n", metrics[4].length);
-todo_wine
     ok(metrics[5].length == 0, "got %u\n", metrics[5].length);
 
     ok(metrics[0].newlineLength == 1, "got %u\n", metrics[0].newlineLength);
@@ -3383,7 +3382,6 @@ todo_wine
     ok(metrics[2].newlineLength == 1, "got %u\n", metrics[2].newlineLength);
     ok(metrics[3].newlineLength == 1, "got %u\n", metrics[3].newlineLength);
     ok(metrics[4].newlineLength == 2, "got %u\n", metrics[4].newlineLength);
-todo_wine
     ok(metrics[5].newlineLength == 0, "got %u\n", metrics[5].newlineLength);
 
     ok(metrics[0].trailingWhitespaceLength == 1, "got %u\n", metrics[0].newlineLength);
@@ -3391,7 +3389,6 @@ todo_wine
     ok(metrics[2].trailingWhitespaceLength == 1, "got %u\n", metrics[2].newlineLength);
     ok(metrics[3].trailingWhitespaceLength == 1, "got %u\n", metrics[3].newlineLength);
     ok(metrics[4].trailingWhitespaceLength == 2, "got %u\n", metrics[4].newlineLength);
-todo_wine
     ok(metrics[5].trailingWhitespaceLength == 0, "got %u\n", metrics[5].newlineLength);
 
     IDWriteTextLayout_Release(layout);
@@ -3444,6 +3441,47 @@ todo_wine
 
     IDWriteTextLayout_Release(layout);
 
+    /* text is "a\r" */
+    hr = IDWriteFactory_CreateTextLayout(factory, str4W, 2, format, 100.0f, 300.0f, &layout);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    count = 0;
+    memset(metrics, 0, sizeof(metrics));
+    hr = IDWriteTextLayout_GetLineMetrics(layout, metrics, sizeof(metrics)/sizeof(*metrics), &count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(count == 2, "got %u\n", count);
+    ok(metrics[0].length == 2, "got %u\n", metrics[0].length);
+    ok(metrics[0].newlineLength == 1, "got %u\n", metrics[0].newlineLength);
+    ok(metrics[0].height > 0.0f, "got %f\n", metrics[0].height);
+    ok(metrics[0].baseline > 0.0f, "got %f\n", metrics[0].baseline);
+    ok(metrics[1].length == 0, "got %u\n", metrics[1].length);
+    ok(metrics[1].newlineLength == 0, "got %u\n", metrics[1].newlineLength);
+    ok(metrics[1].height > 0.0f, "got %f\n", metrics[1].height);
+    ok(metrics[1].baseline > 0.0f, "got %f\n", metrics[1].baseline);
+
+    range.startPosition = 1;
+    range.length = 1;
+    hr = IDWriteTextLayout_SetFontSize(layout, 80.0f, range);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 2, 2, &count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(count == 2, "got %u\n", count);
+todo_wine {
+    ok(metrics[3].height > metrics[1].height, "got %f, old %f\n", metrics[3].height, metrics[1].height);
+    ok(metrics[3].baseline > metrics[1].baseline, "got %f, old %f\n", metrics[3].baseline, metrics[1].baseline);
+}
+    /* revert to original format */
+    hr = IDWriteTextLayout_SetFontSize(layout, 12.0f, range);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = IDWriteTextLayout_GetLineMetrics(layout, metrics + 2, 2, &count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(count == 2, "got %u\n", count);
+    ok(metrics[3].height == metrics[1].height, "got %f, old %f\n", metrics[3].height, metrics[1].height);
+    ok(metrics[3].baseline == metrics[1].baseline, "got %f, old %f\n", metrics[3].baseline, metrics[1].baseline);
+
+    IDWriteTextLayout_Release(layout);
+
     IDWriteTextFormat_Release(format);
     IDWriteFontFace_Release(fontface);
     IDWriteFactory_Release(factory);




More information about the wine-cvs mailing list