From 96a4a55dc33a3d51dc7fe94228f39fcd013124af Mon Sep 17 00:00:00 2001 From: Neil Date: Mon, 2 Dec 2024 19:58:22 +1100 Subject: Improve performance of simple case where FillRange just inserts two entries and does not need to split, merge, or delete runs. This avoids multiple binary searches and is a significant improvement for situations such as marking large numbers of search matches in a huge document. --- src/RunStyles.cxx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/RunStyles.cxx b/src/RunStyles.cxx index b1177f3b7..848670ba9 100644 --- a/src/RunStyles.cxx +++ b/src/RunStyles.cxx @@ -134,7 +134,8 @@ FillResult RunStyles::FillRange(DISTANCE position, ST return resultNoChange; } DISTANCE runEnd = RunFromPosition(end); - if (styles.ValueAt(runEnd) == value) { + const STYLE valueCurrent = styles.ValueAt(runEnd); + if (valueCurrent == value) { // End already has value so trim range. end = starts.PositionFromPartition(runEnd); if (position >= end) { @@ -143,6 +144,22 @@ FillResult RunStyles::FillRange(DISTANCE position, ST } fillLength = end - position; } else { + const DISTANCE startRun = starts.PositionFromPartition(runEnd); + if (position > startRun) { + const DISTANCE runNext = runEnd + 1; + const DISTANCE endRun = starts.PositionFromPartition(runNext); + if (end < endRun) { + // New piece is completely inside a run with a different value so its a simple + // insertion of two points [ (position, value), (end, valueCurrent) ] + const DISTANCE range[] { position, end}; + starts.InsertPartitions(runEnd + 1, range, 2); + // Temporary runEndIndex silences non-useful arithmetic overflow warnings + const ptrdiff_t runEndIndex = runEnd; + styles.Insert(runEndIndex + 1, value); + styles.Insert(runEndIndex + 2, valueCurrent); + return { true, position, fillLength }; + } + } runEnd = SplitRun(end); } DISTANCE runStart = RunFromPosition(position); -- cgit v1.2.3