LibGUI: Validate TextDocument spans when merging them, not when painting

TextDocument::merge_span_collections() automatically makes sure that the
spans are valid, move forwards, are in order, and do not overlap. This
means we don't have to check these things every time TextEditor paints
the document.

merge_span_collections() now does these checks instead. I am not certain
they are still useful, but someone in the past certainly did. I have
modified them to take advantage of the operator overloads and Formatter
that we now have.
This commit is contained in:
Sam Atkins 2023-02-20 16:00:31 +00:00 committed by Andreas Kling
parent 54d45d4ac6
commit 04deb81f71
Notes: sideshowbarker 2024-07-17 04:34:25 +09:00
2 changed files with 22 additions and 25 deletions

View File

@ -1,12 +1,14 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Badge.h>
#include <AK/CharacterTypes.h>
#include <AK/Debug.h>
#include <AK/QuickSort.h>
#include <AK/ScopeGuard.h>
#include <AK/StdLibExtras.h>
@ -1409,7 +1411,27 @@ void TextDocument::merge_span_collections()
}
m_spans.clear();
TextDocumentSpan previous_span { .range = { TextPosition(0, 0), TextPosition(0, 0) }, .attributes = {} };
for (auto span : merged_spans) {
// Validate spans
if (!span.span.range.is_valid()) {
dbgln_if(TEXTEDITOR_DEBUG, "Invalid span {} => ignoring", span.span.range);
continue;
}
if (span.span.range.end() < span.span.range.start()) {
dbgln_if(TEXTEDITOR_DEBUG, "Span {} has negative length => ignoring", span.span.range);
continue;
}
if (span.span.range.end() < previous_span.range.start()) {
dbgln_if(TEXTEDITOR_DEBUG, "Spans not sorted (Span {} ends before previous span {}) => ignoring", span.span.range, previous_span.range);
continue;
}
if (span.span.range.start() < previous_span.range.end()) {
dbgln_if(TEXTEDITOR_DEBUG, "Span {} overlaps previous span {} => ignoring", span.span.range, previous_span.range);
continue;
}
previous_span = span.span;
m_spans.append(move(span.span));
}
}

View File

@ -584,42 +584,17 @@ void TextEditor::paint_event(PaintEvent& event)
break;
}
auto& span = document().spans()[span_index];
if (!span.range.is_valid()) {
++span_index;
continue;
}
if (span.range.end().line() < line_index) {
dbgln_if(TEXTEDITOR_DEBUG, "spans not sorted (span end {}:{} is before current line {}) => ignoring", span.range.end().line(), span.range.end().column(), line_index);
++span_index;
continue;
}
if (span.range.start().line() > line_index
|| (span.range.start().line() == line_index && span.range.start().column() >= start_of_visual_line + visual_line_text.length())) {
// no more spans in this line, moving on
break;
}
if (span.range.start().line() == span.range.end().line() && span.range.end().column() < span.range.start().column()) {
dbgln_if(TEXTEDITOR_DEBUG, "span from {}:{} to {}:{} has negative length => ignoring", span.range.start().line(), span.range.start().column(), span.range.end().line(), span.range.end().column());
++span_index;
continue;
}
if (span.range.end().line() == line_index && span.range.end().column() < start_of_visual_line + next_column) {
dbgln_if(TEXTEDITOR_DEBUG, "spans not sorted (span end {}:{} is before current position {}:{}) => ignoring",
span.range.end().line(), span.range.end().column(), line_index, start_of_visual_line + next_column);
++span_index;
continue;
}
size_t span_start;
if (span.range.start().line() < line_index || span.range.start().column() < start_of_visual_line) {
span_start = 0;
} else {
span_start = span.range.start().column() - start_of_visual_line;
}
if (span_start < next_column) {
dbgln_if(TEXTEDITOR_DEBUG, "span started before the current position, maybe two spans overlap? (span start {} is before current position {}) => ignoring", span_start, next_column);
++span_index;
continue;
}
size_t span_end;
bool span_consumed;
if (span.range.end().line() > line_index || span.range.end().column() > start_of_visual_line + visual_line_text.length()) {