Commit 1002119a authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Clip range length to text length when updating breakpoints.

parent 9c54176f
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment