Skip to content

Commit

Permalink
LibWeb: Reorder some checks in PaintableWithLines::hit_test for speed
Browse files Browse the repository at this point in the history
In particular:

- Don't compute DOM node editability if we don't need it. This was 22%
  of CPU time when scrolling on Wikipedia.

- Defer inversion of transformed coordinates until we actually need
  them, after we've performed early returns.
  • Loading branch information
awesomekling committed Dec 30, 2024
1 parent 0a6793c commit 4324439
Showing 1 changed file with 12 additions and 9 deletions.
21 changes: 12 additions & 9 deletions Libraries/LibWeb/Painting/PaintableBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -924,16 +924,12 @@ TraversalDecision PaintableWithLines::hit_test(CSSPixelPoint position, HitTestTy
auto position_adjusted_by_scroll_offset = position;
position_adjusted_by_scroll_offset.translate_by(-cumulative_offset_of_enclosing_scroll_frame());

// NOTE: This CSSPixels -> Float -> CSSPixels conversion is because we can't AffineTransform::map() a CSSPixelPoint.
Gfx::FloatPoint offset_position {
(position_adjusted_by_scroll_offset.x() - transform_origin().x()).to_float(),
(position_adjusted_by_scroll_offset.y() - transform_origin().y()).to_float()
};
auto transformed_position_adjusted_by_scroll_offset = combined_css_transform().inverse().value_or({}).map(offset_position).to_type<CSSPixels>() + transform_origin();

// TextCursor hit testing mode should be able to place cursor in contenteditable elements even if they are empty
auto is_editable = layout_node_with_style_and_box_metrics().dom_node() && layout_node_with_style_and_box_metrics().dom_node()->is_editable();
if (is_editable && m_fragments.is_empty() && !has_children() && type == HitTestType::TextCursor) {
if (m_fragments.is_empty()
&& !has_children()
&& type == HitTestType::TextCursor
&& layout_node_with_style_and_box_metrics().dom_node()
&& layout_node_with_style_and_box_metrics().dom_node()->is_editable()) {
HitTestResult const hit_test_result {
.paintable = const_cast<PaintableWithLines&>(*this),
.index_in_node = 0,
Expand All @@ -948,6 +944,13 @@ TraversalDecision PaintableWithLines::hit_test(CSSPixelPoint position, HitTestTy
return PaintableBox::hit_test(position, type, callback);
}

// NOTE: This CSSPixels -> Float -> CSSPixels conversion is because we can't AffineTransform::map() a CSSPixelPoint.
Gfx::FloatPoint offset_position {
(position_adjusted_by_scroll_offset.x() - transform_origin().x()).to_float(),
(position_adjusted_by_scroll_offset.y() - transform_origin().y()).to_float()
};
auto transformed_position_adjusted_by_scroll_offset = combined_css_transform().inverse().value_or({}).map(offset_position).to_type<CSSPixels>() + transform_origin();

if (hit_test_scrollbars(transformed_position_adjusted_by_scroll_offset, callback) == TraversalDecision::Break)
return TraversalDecision::Break;

Expand Down

0 comments on commit 4324439

Please sign in to comment.