From: Nikolay Sivov Subject: dwrite: Fix splitting by bidi levels Message-Id: <555EEEA5.9030302@codeweavers.com> Date: Fri, 22 May 2015 11:53:57 +0300 --- From 4038479e891aca541a8d64e7c75b359bba9f6862 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 22 May 2015 11:27:51 +0300 Subject: [PATCH] dwrite: Fix splitting by bidi levels --- dlls/dwrite/layout.c | 38 ++++++++++++++------------------------ dlls/dwrite/tests/analyzer.c | 7 +++++++ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 40ef1bb..1f72b91 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -2811,15 +2811,17 @@ static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface); struct layout_run *cur_run; + TRACE("%u %u %u %u\n", position, length, explicitLevel, resolvedLevel); + LIST_FOR_EACH_ENTRY(cur_run, &layout->runs, struct layout_run, entry) { struct regular_layout_run *cur = &cur_run->u.regular; - struct layout_run *run, *run2; + struct layout_run *run; if (cur_run->kind == LAYOUT_RUN_INLINE) continue; /* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */ - if (position < cur->descr.textPosition || position > cur->descr.textPosition + cur->descr.stringLength) + if (position < cur->descr.textPosition || position >= cur->descr.textPosition + cur->descr.stringLength) continue; /* full hit - just set run level */ @@ -2836,35 +2838,23 @@ static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink continue; } - /* now starting point is in a run, so it splits it */ + /* all fully covered runs are processed at this point, reuse existing run for remaining + reported bidi range and add another run for the rest of original one */ + run = alloc_layout_run(LAYOUT_RUN_REGULAR); if (!run) return E_OUTOFMEMORY; *run = *cur_run; - run->u.regular.descr.textPosition = position; - run->u.regular.descr.stringLength = cur->descr.stringLength - position + cur->descr.textPosition; - run->u.regular.descr.string = &layout->str[position]; - run->u.regular.run.bidiLevel = resolvedLevel; - cur->descr.stringLength -= position - cur->descr.textPosition; + run->u.regular.descr.textPosition = position + length; + run->u.regular.descr.stringLength = cur->descr.stringLength - length; + run->u.regular.descr.string = &layout->str[position + length]; - list_add_after(&cur_run->entry, &run->entry); - - if (position + length == run->u.regular.descr.textPosition + run->u.regular.descr.stringLength) - break; + /* reduce existing run */ + cur->run.bidiLevel = resolvedLevel; + cur->descr.stringLength -= length; - /* split second time */ - run2 = alloc_layout_run(LAYOUT_RUN_REGULAR); - if (!run2) - return E_OUTOFMEMORY; - - *run2 = *cur_run; - run2->u.regular.descr.textPosition = run->u.regular.descr.textPosition + run->u.regular.descr.stringLength; - run2->u.regular.descr.stringLength = cur->descr.textPosition + cur->descr.stringLength - position - length; - run2->u.regular.descr.string = &layout->str[run2->u.regular.descr.textPosition]; - run->u.regular.descr.stringLength -= run2->u.regular.descr.stringLength; - - list_add_after(&run->entry, &run2->entry); + list_add_after(&cur_run->entry, &run->entry); break; } diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c index 0043526..43c2a66 100644 --- a/dlls/dwrite/tests/analyzer.c +++ b/dlls/dwrite/tests/analyzer.c @@ -878,6 +878,13 @@ static struct sa_test sa_tests[] = { {0x2d30,0x2d4a,0}, 1, { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }} }, + { + /* LRE/PDF */ + {0x202a,0x202c,'a','b','c','\r',0}, 3, + { { 0, 2, DWRITE_SCRIPT_SHAPES_NO_VISUAL }, + { 2, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }, + { 5, 1, DWRITE_SCRIPT_SHAPES_NO_VISUAL } } + }, /* keep this as end marker */ { {0} } }; -- 2.1.4