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