Nikolay Sivov : dwrite: Clip range length to text length when updating breakpoints.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Jun 29 08:12:10 CDT 2015
Module: wine
Branch: master
Commit: 1002119a6082a8bce118bec4190d0b54c99778de
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1002119a6082a8bce118bec4190d0b54c99778de
Author: Nikolay Sivov <nsivov at 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);
More information about the wine-cvs
mailing list