Speed up wrapping at word boundaries.
Previously, when wrapping lines at word boundaries, we would iterate forwards for "wrap-width" characters, then iterate backwards until we found a word-break, which was horribly slow. Now we record the last word-boundary we saw as we iterate forwards, getting a result in one pass. Fixes #2339.
This commit is contained in:
parent
373858f9bf
commit
82c01c5dd3
|
@ -822,6 +822,8 @@ struct WrapHighlighter : Highlighter
|
||||||
StringView content = buffer[line];
|
StringView content = buffer[line];
|
||||||
|
|
||||||
SplitPos pos = current;
|
SplitPos pos = current;
|
||||||
|
SplitPos last_boundary = {0, 0};
|
||||||
|
|
||||||
while (pos.byte < content.length() and pos.column < target_column)
|
while (pos.byte < content.length() and pos.column < target_column)
|
||||||
{
|
{
|
||||||
if (content[pos.byte] == '\t')
|
if (content[pos.byte] == '\t')
|
||||||
|
@ -831,32 +833,30 @@ struct WrapHighlighter : Highlighter
|
||||||
break;
|
break;
|
||||||
pos.column = next_column;
|
pos.column = next_column;
|
||||||
++pos.byte;
|
++pos.byte;
|
||||||
|
last_boundary = pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* it = &content[pos.byte];
|
const char* it = &content[pos.byte];
|
||||||
const ColumnCount width = codepoint_width(utf8::read_codepoint(it, content.end()));
|
const Codepoint cp = utf8::read_codepoint(it, content.end());
|
||||||
|
const ColumnCount width = codepoint_width(cp);
|
||||||
if (pos.column + width > target_column and pos.byte != current.byte) // the target column was in the char
|
if (pos.column + width > target_column and pos.byte != current.byte) // the target column was in the char
|
||||||
|
{
|
||||||
|
if (!is_word<WORD>(cp))
|
||||||
|
last_boundary = pos;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
pos.column += width;
|
pos.column += width;
|
||||||
pos.byte = (int)(it - content.begin());
|
pos.byte = (int)(it - content.begin());
|
||||||
|
if (!is_word<WORD>(cp))
|
||||||
|
last_boundary = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_word_wrap and pos.byte < content.length()) // find a word boundary before current position
|
if (m_word_wrap and pos.byte < content.length()) // find a word boundary before current position
|
||||||
{
|
if (last_boundary.byte > 0)
|
||||||
utf8::iterator<const char*> it{&content[pos.byte], content};
|
pos = last_boundary;
|
||||||
while (it != content.begin() and is_word<WORD>(*it))
|
|
||||||
--it;
|
|
||||||
|
|
||||||
if (it != content.begin() and it != &content[pos.byte] and
|
|
||||||
(it+1) > &content[current.byte])
|
|
||||||
{
|
|
||||||
const ByteCount word_split = (it+1).base() - content.begin();
|
|
||||||
pos.column -= content.substr(word_split, pos.byte - word_split).column_length();
|
|
||||||
pos.byte = word_split;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user