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.
This commit is contained in:
parent
933e4a599c
commit
93c50b3cd9
|
@ -55,24 +55,56 @@ ColumnCount DisplayAtom::length() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayAtom::trim_begin(ColumnCount count)
|
bool DisplayAtom::empty() const
|
||||||
{
|
{
|
||||||
if (m_type == Range)
|
if (m_type == Range)
|
||||||
m_range.begin = utf8::advance(get_iterator(*m_buffer, m_range.begin),
|
return m_range.begin == m_range.end;
|
||||||
get_iterator(*m_buffer, m_range.end),
|
|
||||||
count).coord();
|
|
||||||
else
|
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)
|
if (m_type == Range)
|
||||||
m_range.end = utf8::advance(get_iterator(*m_buffer, m_range.end),
|
{
|
||||||
get_iterator(*m_buffer, m_range.begin),
|
auto it = get_iterator(*m_buffer, m_range.begin);
|
||||||
-count).coord();
|
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
|
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{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
|
||||||
|
{
|
||||||
|
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)
|
DisplayLine::DisplayLine(AtomList atoms)
|
||||||
|
@ -222,26 +254,15 @@ bool DisplayLine::trim_from(ColumnCount first_col, ColumnCount front, ColumnCoun
|
||||||
|
|
||||||
while (front > 0 and it != end())
|
while (front > 0 and it != end())
|
||||||
{
|
{
|
||||||
auto len = it->length();
|
front -= it->trim_begin(front);
|
||||||
if (len <= front)
|
if (it->empty())
|
||||||
{
|
it = m_atoms.erase(it);
|
||||||
m_atoms.erase(it);
|
|
||||||
front -= len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it->trim_begin(front);
|
|
||||||
front = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it = begin();
|
it = begin();
|
||||||
for (; it != end() and col_count > 0; ++it)
|
for (; it != end() and col_count > 0; ++it)
|
||||||
col_count -= it->length();
|
col_count -= it->trim_end_to_length(col_count);
|
||||||
|
bool did_trim = it != end() && col_count == 0;
|
||||||
bool did_trim = it != end() || col_count < 0;
|
|
||||||
if (col_count < 0)
|
|
||||||
(it-1)->trim_end(-col_count);
|
|
||||||
m_atoms.erase(it, end());
|
m_atoms.erase(it, end());
|
||||||
|
|
||||||
compute_range();
|
compute_range();
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
|
|
||||||
StringView content() const;
|
StringView content() const;
|
||||||
ColumnCount length() const;
|
ColumnCount length() const;
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
const BufferCoord& begin() const
|
const BufferCoord& begin() const
|
||||||
{
|
{
|
||||||
|
@ -74,8 +75,8 @@ public:
|
||||||
|
|
||||||
Type type() const { return m_type; }
|
Type type() const { return m_type; }
|
||||||
|
|
||||||
void trim_begin(ColumnCount count);
|
ColumnCount trim_begin(ColumnCount count);
|
||||||
void trim_end(ColumnCount count);
|
ColumnCount trim_end_to_length(ColumnCount count);
|
||||||
|
|
||||||
bool operator==(const DisplayAtom& other) const
|
bool operator==(const DisplayAtom& other) const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user