Module: wine Branch: master Commit: 1002119a6082a8bce118bec4190d0b54c99778de URL: http://source.winehq.org/git/wine.git/?a=commit;h=1002119a6082a8bce118bec419...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Mon Jun 29 12:52:04 2015 +0300
dwrite: Clip range length to text length when updating breakpoints.
---
dlls/dwrite/layout.c | 25 +++++++++++++------------ dlls/dwrite/tests/layout.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 9f3b9c4..3863e5c 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -423,12 +423,21 @@ static inline DWRITE_BREAK_CONDITION override_break_condition(DWRITE_BREAK_CONDI return existingbreak; }
+/* This helper should be used to get effective range length, in other words it returns number of text + positions from range starting point to the end of the range, limited by layout text length */ +static inline UINT32 get_clipped_range_length(const struct dwrite_textlayout *layout, const struct layout_range *range) +{ + if (range->h.range.startPosition + range->h.range.length <= layout->len) + return range->h.range.length; + return layout->len - range->h.range.startPosition; +} + /* Actual breakpoint data gets updated with break condition required by inline object set for range 'cur'. */ static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, const struct layout_range *cur) { DWRITE_BREAK_CONDITION before, after; + UINT32 i, length; HRESULT hr; - UINT32 i;
/* ignore returned conditions if failed */ hr = IDWriteInlineObject_GetBreakConditions(cur->object, &before, &after); @@ -442,7 +451,8 @@ static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, memcpy(layout->actual_breakpoints, layout->nominal_breakpoints, sizeof(DWRITE_LINE_BREAKPOINT)*layout->len); }
- for (i = cur->h.range.startPosition; i < cur->h.range.length + cur->h.range.startPosition; i++) { + length = get_clipped_range_length(layout, cur); + for (i = cur->h.range.startPosition; i < length + cur->h.range.startPosition; i++) { /* for first codepoint check if there's anything before it and update accordingly */ if (i == cur->h.range.startPosition) { if (i > 0) @@ -453,7 +463,7 @@ static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, layout->actual_breakpoints[i].breakConditionAfter = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK; } /* similar check for last codepoint */ - else if (i == cur->h.range.startPosition + cur->h.range.length - 1) { + else if (i == cur->h.range.startPosition + length - 1) { if (i == layout->len - 1) layout->actual_breakpoints[i].breakConditionAfter = after; else @@ -568,15 +578,6 @@ static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const s } }
-/* This helper should be used to get effective range length, in other words it returns number of text - positions from range starting point to the end of the range, limited by layout text length */ -static inline UINT32 get_clipped_range_length(const struct dwrite_textlayout *layout, const struct layout_range *range) -{ - if (range->h.range.startPosition + range->h.range.length <= layout->len) - return range->h.range.length; - return layout->len - range->h.range.startPosition; -} - static inline FLOAT get_scaled_font_metric(UINT32 metric, FLOAT emSize, const DWRITE_FONT_METRICS *metrics) { return (FLOAT)metric * emSize / (FLOAT)metrics->designUnitsPerEm; diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index ecf4183..c7ca5b7 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -591,6 +591,13 @@ static HRESULT WINAPI testinlineobj_GetBreakConditions(IDWriteInlineObject *ifac return 0x8feacafe; }
+static HRESULT WINAPI testinlineobj2_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before, + DWRITE_BREAK_CONDITION *after) +{ + *before = *after = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK; + return S_OK; +} + static IDWriteInlineObjectVtbl testinlineobjvtbl = { testinlineobj_QI, testinlineobj_AddRef, @@ -601,8 +608,19 @@ static IDWriteInlineObjectVtbl testinlineobjvtbl = { testinlineobj_GetBreakConditions };
+static IDWriteInlineObjectVtbl testinlineobjvtbl2 = { + testinlineobj_QI, + testinlineobj_AddRef, + testinlineobj_Release, + testinlineobj_Draw, + testinlineobj_GetMetrics, + testinlineobj_GetOverhangMetrics, + testinlineobj2_GetBreakConditions +}; + static IDWriteInlineObject testinlineobj = { &testinlineobjvtbl }; static IDWriteInlineObject testinlineobj2 = { &testinlineobjvtbl }; +static IDWriteInlineObject testinlineobj3 = { &testinlineobjvtbl2 };
static HRESULT WINAPI testeffect_QI(IUnknown *iface, REFIID riid, void **obj) { @@ -1728,6 +1746,26 @@ todo_wine ok(count == 2, "got %u\n", count); ok(metrics[0].isWhitespace == 0, "got %d\n", metrics[0].isWhitespace); ok(metrics[1].isWhitespace == 1, "got %d\n", metrics[1].isWhitespace); + ok(metrics[1].canWrapLineAfter == 1, "got %d\n", metrics[1].canWrapLineAfter); + IDWriteTextLayout_Release(layout); + + /* layout is fully covered by inline object with after condition DWRITE_BREAK_CONDITION_MAY_NOT_BREAK */ + hr = IDWriteFactory_CreateTextLayout(factory, str4W, 2, format, 1000.0, 1000.0, &layout); + ok(hr == S_OK, "got 0x%08x\n", hr); + + range.startPosition = 0; + range.length = ~0u; + hr = IDWriteTextLayout_SetInlineObject(layout, &testinlineobj3, range); + ok(hr == S_OK, "got 0x%08x\n", hr); + + count = 0; + memset(metrics, 0, sizeof(metrics)); + hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 2, &count); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(count == 1, "got %u\n", count); +todo_wine + ok(metrics[0].canWrapLineAfter == 1, "got %d\n", metrics[0].canWrapLineAfter); + IDWriteTextLayout_Release(layout);
IDWriteInlineObject_Release(trimm);