Nikolay Sivov : dwrite: Update breakpoints in case of inline objects.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Dec 29 15:42:42 CST 2014
Module: wine
Branch: master
Commit: cb4e88196372a9361517919e912a687e23a56eaa
URL: http://source.winehq.org/git/wine.git/?a=commit;h=cb4e88196372a9361517919e912a687e23a56eaa
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Dec 26 00:01:28 2014 +0300
dwrite: Update breakpoints in case of inline objects.
---
dlls/dwrite/layout.c | 109 ++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 90 insertions(+), 19 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 1ede48c..8717f63 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -121,7 +121,8 @@ struct dwrite_textlayout {
struct list runs;
BOOL recompute;
- DWRITE_LINE_BREAKPOINT *breakpoints;
+ DWRITE_LINE_BREAKPOINT *nominal_breakpoints;
+ DWRITE_LINE_BREAKPOINT *actual_breakpoints;
};
struct dwrite_textformat {
@@ -226,6 +227,70 @@ static void free_layout_runs(struct dwrite_textlayout *layout)
}
}
+/* should only be called for ranges with inline objects */
+static inline DWRITE_BREAK_CONDITION override_break_condition(DWRITE_BREAK_CONDITION existingbreak, DWRITE_BREAK_CONDITION newbreak)
+{
+ switch (existingbreak) {
+ case DWRITE_BREAK_CONDITION_NEUTRAL:
+ return newbreak;
+ case DWRITE_BREAK_CONDITION_CAN_BREAK:
+ return newbreak == DWRITE_BREAK_CONDITION_NEUTRAL ? existingbreak : newbreak;
+ /* let's keep stronger conditions as is */
+ case DWRITE_BREAK_CONDITION_MAY_NOT_BREAK:
+ case DWRITE_BREAK_CONDITION_MUST_BREAK:
+ break;
+ default:
+ ERR("unknown break condition %d\n", existingbreak);
+ }
+
+ return existingbreak;
+}
+
+static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, const struct layout_range *cur)
+{
+ DWRITE_BREAK_CONDITION before, after;
+ HRESULT hr;
+ UINT32 i;
+
+ hr = IDWriteInlineObject_GetBreakConditions(cur->object, &before, &after);
+ if (FAILED(hr))
+ return hr;
+
+ if (!layout->actual_breakpoints) {
+ layout->actual_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
+ if (!layout->actual_breakpoints)
+ return E_OUTOFMEMORY;
+ }
+ memcpy(layout->actual_breakpoints, layout->nominal_breakpoints, sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
+
+ for (i = cur->range.startPosition; i < cur->range.length + cur->range.startPosition; i++) {
+ UINT32 j = i + cur->range.startPosition;
+ if (i == 0) {
+ if (j)
+ layout->actual_breakpoints[j].breakConditionBefore = layout->actual_breakpoints[j-1].breakConditionAfter =
+ override_break_condition(layout->actual_breakpoints[j-1].breakConditionAfter, before);
+ else
+ layout->actual_breakpoints[j].breakConditionBefore = before;
+
+ layout->actual_breakpoints[j].breakConditionAfter = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK;
+ }
+
+ layout->actual_breakpoints[j].isWhitespace = 0;
+ layout->actual_breakpoints[j].isSoftHyphen = 0;
+
+ if (i == cur->range.length - 1) {
+ layout->actual_breakpoints[j].breakConditionBefore = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK;
+ if (j < layout->len - 1)
+ layout->actual_breakpoints[j].breakConditionAfter = layout->actual_breakpoints[j+1].breakConditionAfter =
+ override_break_condition(layout->actual_breakpoints[j+1].breakConditionAfter, before);
+ else
+ layout->actual_breakpoints[j].breakConditionAfter = before;
+ }
+ }
+
+ return S_OK;
+}
+
static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
{
IDWriteTextAnalyzer *analyzer;
@@ -240,8 +305,12 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
/* inline objects override actual text in a range */
- if (cur->object)
+ if (cur->object) {
+ hr = layout_update_breakpoints_range(layout, cur);
+ if (FAILED(hr))
+ return hr;
continue;
+ }
/* initial splitting by script */
hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &layout->IDWriteTextAnalysisSource_iface,
@@ -267,24 +336,13 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout)
if (!layout->recompute)
return S_OK;
- hr = layout_compute_runs(layout);
-
- if (TRACE_ON(dwrite)) {
- struct layout_run *cur;
-
- LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
- TRACE("run [%u,%u], len %u, bidilevel %u\n", cur->descr.textPosition, cur->descr.textPosition+cur->descr.stringLength-1,
- cur->descr.stringLength, cur->run.bidiLevel);
- }
- }
-
/* nominal breakpoints are evaluated only once, because string never changes */
- if (!layout->breakpoints) {
+ if (!layout->nominal_breakpoints) {
IDWriteTextAnalyzer *analyzer;
HRESULT hr;
- layout->breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
- if (!layout->breakpoints)
+ layout->nominal_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
+ if (!layout->nominal_breakpoints)
return E_OUTOFMEMORY;
hr = get_textanalyzer(&analyzer);
@@ -296,6 +354,17 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout)
IDWriteTextAnalyzer_Release(analyzer);
}
+ hr = layout_compute_runs(layout);
+
+ if (TRACE_ON(dwrite)) {
+ struct layout_run *cur;
+
+ LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
+ TRACE("run [%u,%u], len %u, bidilevel %u\n", cur->descr.textPosition, cur->descr.textPosition+cur->descr.stringLength-1,
+ cur->descr.stringLength, cur->run.bidiLevel);
+ }
+ }
+
layout->recompute = FALSE;
return hr;
}
@@ -695,7 +764,8 @@ static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout2 *iface)
free_layout_ranges_list(This);
free_layout_runs(This);
release_format_data(&This->format);
- heap_free(This->breakpoints);
+ heap_free(This->nominal_breakpoints);
+ heap_free(This->actual_breakpoints);
heap_free(This->str);
heap_free(This);
}
@@ -1601,7 +1671,7 @@ static HRESULT WINAPI dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalys
if (position + length > layout->len)
return E_FAIL;
- memcpy(&layout->breakpoints[position], breakpoints, length*sizeof(DWRITE_LINE_BREAKPOINT));
+ memcpy(&layout->nominal_breakpoints[position], breakpoints, length*sizeof(DWRITE_LINE_BREAKPOINT));
return S_OK;
}
@@ -1833,7 +1903,8 @@ HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *forma
This->maxwidth = maxwidth;
This->maxheight = maxheight;
This->recompute = TRUE;
- This->breakpoints = NULL;
+ This->nominal_breakpoints = NULL;
+ This->actual_breakpoints = NULL;
layout_format_from_textformat(This, format);
list_init(&This->runs);
More information about the wine-cvs
mailing list