dwrite: Clip range length to text length when updating breakpoints.
This commit is contained in:
parent
9c54176f5c
commit
1002119a60
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue