mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:37:43 +00:00
LibWeb: Remove Utf8View usage and try avoiding StringBuilder in TextNode
This patch completely reworks TextNode::compute_text_for_rendering(). It removes the unnecessary usage of Utf8View to find spaces in a String. Furthermore, it adds a couple fast return paths for common but trivial cases such as empty, single-character and whitespace-less strings. For the HTML spec bookmarks, around two thirds of all function calls (which amounts to around 10'000) use the fast paths and thus avoid allocating a StringBuilder just to build a copy of the already present String.
This commit is contained in:
parent
9c0cfede59
commit
054c742d17
1 changed files with 49 additions and 21 deletions
|
@ -103,35 +103,63 @@ void TextNode::paint_cursor_if_needed(PaintContext& context, const LineBoxFragme
|
||||||
context.painter().draw_rect(cursor_rect, computed_values().color());
|
context.painter().draw_rect(cursor_rect, computed_values().color());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: This collapes whitespace into a single ASCII space if collapse is true. If previous_is_empty_or_ends_in_whitespace, it also strips leading whitespace.
|
||||||
void TextNode::compute_text_for_rendering(bool collapse, bool previous_is_empty_or_ends_in_whitespace)
|
void TextNode::compute_text_for_rendering(bool collapse, bool previous_is_empty_or_ends_in_whitespace)
|
||||||
{
|
{
|
||||||
if (!collapse) {
|
auto& data = dom_node().data();
|
||||||
m_text_for_rendering = dom_node().data();
|
if (!collapse || data.is_empty()) {
|
||||||
|
m_text_for_rendering = data;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collapse whitespace into single spaces
|
// NOTE: A couple fast returns to avoid unnecessarily allocating a StringBuilder.
|
||||||
auto utf8_view = Utf8View(dom_node().data());
|
if (data.length() == 1) {
|
||||||
StringBuilder builder(dom_node().data().length());
|
if (is_ascii_space(data[0])) {
|
||||||
auto it = utf8_view.begin();
|
if (previous_is_empty_or_ends_in_whitespace)
|
||||||
auto skip_over_whitespace = [&] {
|
m_text_for_rendering = String::empty();
|
||||||
auto prev = it;
|
else {
|
||||||
while (it != utf8_view.end() && is_ascii_space(*it)) {
|
static String s_single_space_string = " ";
|
||||||
prev = it;
|
m_text_for_rendering = s_single_space_string;
|
||||||
++it;
|
}
|
||||||
}
|
|
||||||
it = prev;
|
|
||||||
};
|
|
||||||
if (previous_is_empty_or_ends_in_whitespace)
|
|
||||||
skip_over_whitespace();
|
|
||||||
for (; it != utf8_view.end(); ++it) {
|
|
||||||
if (!is_ascii_space(*it)) {
|
|
||||||
builder.append(StringView { it.underlying_code_point_bytes() });
|
|
||||||
} else {
|
} else {
|
||||||
builder.append(' ');
|
m_text_for_rendering = data;
|
||||||
skip_over_whitespace();
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains_space = false;
|
||||||
|
for (auto& c : data) {
|
||||||
|
if (is_ascii_space(c)) {
|
||||||
|
contains_space = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!contains_space) {
|
||||||
|
m_text_for_rendering = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder(data.length());
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
auto skip_over_whitespace = [&index, &data] {
|
||||||
|
while (index < data.length() && is_ascii_space(data[index]))
|
||||||
|
++index;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (previous_is_empty_or_ends_in_whitespace)
|
||||||
|
skip_over_whitespace();
|
||||||
|
while (index < data.length()) {
|
||||||
|
if (is_ascii_space(data[index])) {
|
||||||
|
builder.append(' ');
|
||||||
|
++index;
|
||||||
|
skip_over_whitespace();
|
||||||
|
} else {
|
||||||
|
builder.append(data[index]);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_text_for_rendering = builder.to_string();
|
m_text_for_rendering = builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue