diff options
| author | Maxime Coste <mawww@kakoune.org> | 2022-12-06 17:51:28 +1100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2022-12-06 17:51:28 +1100 |
| commit | 93c50b3cd97ef78c678aa84010a5481ce0f11245 (patch) | |
| tree | 22c616dafb1070f6c1e029818f6d0e58f20d2804 /src/display_buffer.cc | |
| parent | 933e4a599cfd3fc09edd67a024b8af08bbec7c01 (diff) | |
Avoid calculating atom length in DisplayLine::trim_from
Calculating the length of an atom means we need to decode every
codepoint and compute its column width. This can prove quite expensive
in trim_from as we can have full buffer lines, so on buffer with long
lines we might have to go through megabytes of undisplayed data.
Diffstat (limited to 'src/display_buffer.cc')
| -rw-r--r-- | src/display_buffer.cc | 73 |
1 files changed, 47 insertions, 26 deletions
diff --git a/src/display_buffer.cc b/src/display_buffer.cc index c9b74d04..02007d8f 100644 --- a/src/display_buffer.cc +++ b/src/display_buffer.cc @@ -55,24 +55,56 @@ ColumnCount DisplayAtom::length() const return 0; } -void DisplayAtom::trim_begin(ColumnCount count) +bool DisplayAtom::empty() const { if (m_type == Range) - m_range.begin = utf8::advance(get_iterator(*m_buffer, m_range.begin), - get_iterator(*m_buffer, m_range.end), - count).coord(); + return m_range.begin == m_range.end; else - m_text = m_text.substr(count).str(); + return m_text.empty(); } -void DisplayAtom::trim_end(ColumnCount count) +ColumnCount DisplayAtom::trim_begin(ColumnCount count) { + ColumnCount res = 0; if (m_type == Range) - m_range.end = utf8::advance(get_iterator(*m_buffer, m_range.end), - get_iterator(*m_buffer, m_range.begin), - -count).coord(); + { + auto it = get_iterator(*m_buffer, m_range.begin); + auto end = get_iterator(*m_buffer, m_range.end); + while (it != end and res < count) + res += codepoint_width(utf8::read_codepoint(it, end)); + m_range.begin = std::min(it.coord(), m_range.end); + } + else + { + auto it = m_text.begin(); + while (it != m_text.end() and res < count) + res += codepoint_width(utf8::read_codepoint(it, m_text.end())); + m_text = String{it, m_text.end()}; + } + + return res; +} + +ColumnCount DisplayAtom::trim_end_to_length(ColumnCount count) +{ + ColumnCount res = 0; + if (m_type == Range) + { + auto it = get_iterator(*m_buffer, m_range.begin); + auto end = get_iterator(*m_buffer, m_range.end); + while (it != end and res < count) + res += codepoint_width(utf8::read_codepoint(it, end)); + m_range.end = std::min(it.coord(), m_range.end); + } else - m_text = m_text.substr(0, m_text.column_length() - count).str(); + { + auto it = m_text.begin(); + while (it != m_text.end() and res < count) + res += codepoint_width(utf8::read_codepoint(it, m_text.end())); + m_text = String{m_text.begin(), it}; + } + + return res; } DisplayLine::DisplayLine(AtomList atoms) @@ -222,26 +254,15 @@ bool DisplayLine::trim_from(ColumnCount first_col, ColumnCount front, ColumnCoun while (front > 0 and it != end()) { - auto len = it->length(); - if (len <= front) - { - m_atoms.erase(it); - front -= len; - } - else - { - it->trim_begin(front); - front = 0; - } + front -= it->trim_begin(front); + if (it->empty()) + it = m_atoms.erase(it); } it = begin(); for (; it != end() and col_count > 0; ++it) - col_count -= it->length(); - - bool did_trim = it != end() || col_count < 0; - if (col_count < 0) - (it-1)->trim_end(-col_count); + col_count -= it->trim_end_to_length(col_count); + bool did_trim = it != end() && col_count == 0; m_atoms.erase(it, end()); compute_range(); |
