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