From 2b59029aa13d1f74a462633bae7bbeccdd79883a Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 2 Feb 2016 23:14:37 +0300 Subject: [PATCH] dwrite: Add a zero width line after last mandatory breakpoint. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- 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 93d096d5757..9cbbb3890f8 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 bf46df80528..e1903dbf571 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);