1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:58:11 +00:00

LibWeb: Make Paintable::containing_block() return a PaintableBox*

Every single client of this function was immediately calling paintable()
on the result anyway, so there was no need to return a layout node!

This automatically leverages the cached containing block pointer we
already have in Paintable, which melts away a bunch of unnecessary
traversal in hit testing and painting. :^)
This commit is contained in:
Andreas Kling 2024-03-01 15:30:44 +01:00
parent c3980eda9e
commit d1b5f55f91
9 changed files with 32 additions and 36 deletions

View file

@ -923,13 +923,8 @@ JS::NonnullGCPtr<Geometry::DOMRectList> Element::get_client_rects() const
} }
Gfx::AffineTransform transform; Gfx::AffineTransform transform;
for (auto const* containing_block = this->layout_node(); containing_block; containing_block = containing_block->containing_block()) { for (auto const* containing_block = this->paintable_box(); containing_block; containing_block = containing_block->containing_block()) {
Gfx::AffineTransform containing_block_transform; transform = transform.multiply(Gfx::extract_2d_affine_transform(containing_block->transform()));
if (containing_block->paintable() && containing_block->paintable()->is_paintable_box()) {
auto const& containing_block_paintable_box = static_cast<Painting::PaintableBox const&>(*containing_block->paintable());
containing_block_transform = Gfx::extract_2d_affine_transform(containing_block_paintable_box.transform());
}
transform = transform.multiply(containing_block_transform);
} }
auto const* paintable = this->paintable(); auto const* paintable = this->paintable();

View file

@ -174,7 +174,7 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint position, CSSPixelPoint scree
if (paintable) { if (paintable) {
auto* containing_block = paintable->containing_block(); auto* containing_block = paintable->containing_block();
while (containing_block) { while (containing_block) {
auto handled_scroll_event = const_cast<Painting::PaintableBox*>(containing_block->paintable_box())->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y); auto handled_scroll_event = containing_block->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y);
if (handled_scroll_event) if (handled_scroll_event)
return true; return true;
containing_block = containing_block->containing_block(); containing_block = containing_block->containing_block();

View file

@ -73,7 +73,7 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const
auto& painter = context.recording_painter(); auto& painter = context.recording_painter();
if (phase == PaintPhase::Background) { if (phase == PaintPhase::Background) {
auto containing_block_position_in_absolute_coordinates = containing_block()->paintable_box()->absolute_position(); auto containing_block_position_in_absolute_coordinates = containing_block()->absolute_position();
for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) { for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) {
CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() };
@ -118,7 +118,7 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const
.left = computed_values().border_left(), .left = computed_values().border_left(),
}; };
auto containing_block_position_in_absolute_coordinates = containing_block()->paintable_box()->absolute_position(); auto containing_block_position_in_absolute_coordinates = containing_block()->absolute_position();
for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) { for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) {
CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() };
@ -247,7 +247,7 @@ CSSPixelRect InlinePaintable::bounding_rect() const
if (bounding_rect.is_empty()) { if (bounding_rect.is_empty()) {
// FIXME: This is adhoc, and we should return rect of empty fragment instead. // FIXME: This is adhoc, and we should return rect of empty fragment instead.
auto containing_block_position_in_absolute_coordinates = containing_block()->paintable_box()->absolute_position(); auto containing_block_position_in_absolute_coordinates = containing_block()->absolute_position();
return { containing_block_position_in_absolute_coordinates, { 0, 0 } }; return { containing_block_position_in_absolute_coordinates, { 0, 0 } };
} }
return bounding_rect; return bounding_rect;

View file

@ -128,8 +128,6 @@ void Paintable::set_needs_display() const
auto* containing_block = this->containing_block(); auto* containing_block = this->containing_block();
if (!containing_block) if (!containing_block)
return; return;
if (!containing_block->paintable_box())
return;
auto navigable = this->navigable(); auto navigable = this->navigable();
if (!navigable) if (!navigable)
return; return;
@ -140,9 +138,9 @@ void Paintable::set_needs_display() const
navigable->set_needs_display(fragment.absolute_rect()); navigable->set_needs_display(fragment.absolute_rect());
} }
if (!is<Painting::PaintableWithLines>(*containing_block->paintable_box())) if (!is<Painting::PaintableWithLines>(*containing_block))
return; return;
static_cast<Painting::PaintableWithLines const&>(*containing_block->paintable_box()).for_each_fragment([&](auto& fragment) { static_cast<Painting::PaintableWithLines const&>(*containing_block).for_each_fragment([&](auto& fragment) {
navigable->set_needs_display(fragment.absolute_rect()); navigable->set_needs_display(fragment.absolute_rect());
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
@ -162,8 +160,8 @@ CSSPixelPoint Paintable::box_type_agnostic_position() const
} }
CSSPixelPoint position; CSSPixelPoint position;
if (auto const* block = containing_block(); block && block->paintable() && is<Painting::PaintableWithLines>(*block->paintable())) { if (auto const* block = containing_block(); block && is<Painting::PaintableWithLines>(*block)) {
static_cast<Painting::PaintableWithLines const&>(*block->paintable_box()).for_each_fragment([&](auto& fragment) { static_cast<Painting::PaintableWithLines const&>(*block).for_each_fragment([&](auto& fragment) {
position = fragment.absolute_rect().location(); position = fragment.absolute_rect().location();
return IterationDecision::Break; return IterationDecision::Break;
}); });

View file

@ -181,10 +181,15 @@ public:
virtual void set_needs_display() const; virtual void set_needs_display() const;
Layout::Box const* containing_block() const PaintableBox* containing_block() const
{ {
if (!m_containing_block.has_value()) if (!m_containing_block.has_value()) {
m_containing_block = m_layout_node->containing_block(); auto containing_layout_box = m_layout_node->containing_block();
if (containing_layout_box)
m_containing_block = const_cast<PaintableBox*>(containing_layout_box->paintable_box());
else
m_containing_block = nullptr;
}
return *m_containing_block; return *m_containing_block;
} }
@ -209,7 +214,7 @@ private:
JS::GCPtr<DOM::Node> m_dom_node; JS::GCPtr<DOM::Node> m_dom_node;
JS::NonnullGCPtr<Layout::Node const> m_layout_node; JS::NonnullGCPtr<Layout::Node const> m_layout_node;
JS::NonnullGCPtr<HTML::BrowsingContext> m_browsing_context; JS::NonnullGCPtr<HTML::BrowsingContext> m_browsing_context;
Optional<JS::GCPtr<Layout::Box const>> mutable m_containing_block; Optional<JS::GCPtr<PaintableBox>> mutable m_containing_block;
OwnPtr<StackingContext> m_stacking_context; OwnPtr<StackingContext> m_stacking_context;
}; };

View file

@ -117,8 +117,8 @@ CSSPixelPoint PaintableBox::offset() const
CSSPixelRect PaintableBox::compute_absolute_rect() const CSSPixelRect PaintableBox::compute_absolute_rect() const
{ {
CSSPixelRect rect { offset(), content_size() }; CSSPixelRect rect { offset(), content_size() };
for (auto const* block = containing_block(); block && block->paintable(); block = block->paintable()->containing_block()) for (auto const* block = containing_block(); block; block = block->containing_block())
rect.translate_by(block->paintable_box()->offset()); rect.translate_by(block->offset());
return rect; return rect;
} }
@ -126,10 +126,10 @@ CSSPixelRect PaintableBox::compute_absolute_padding_rect_with_css_transform_appl
{ {
CSSPixelRect rect { offset(), content_size() }; CSSPixelRect rect { offset(), content_size() };
for (auto const* block = containing_block(); block; block = block->containing_block()) { for (auto const* block = containing_block(); block; block = block->containing_block()) {
auto offset = block->paintable_box()->offset(); auto offset = block->offset();
auto affine_transform = Gfx::extract_2d_affine_transform(block->paintable_box()->transform()); auto affine_transform = Gfx::extract_2d_affine_transform(block->transform());
offset.translate_by(affine_transform.translation().to_type<CSSPixels>()); offset.translate_by(affine_transform.translation().to_type<CSSPixels>());
offset.translate_by(-block->paintable_box()->scroll_offset()); offset.translate_by(-block->scroll_offset());
rect.translate_by(offset); rect.translate_by(offset);
} }
auto affine_transform = Gfx::extract_2d_affine_transform(transform()); auto affine_transform = Gfx::extract_2d_affine_transform(transform());
@ -146,8 +146,8 @@ CSSPixelRect PaintableBox::compute_absolute_padding_rect_with_css_transform_appl
Gfx::AffineTransform PaintableBox::compute_combined_css_transform() const Gfx::AffineTransform PaintableBox::compute_combined_css_transform() const
{ {
Gfx::AffineTransform combined_transform; Gfx::AffineTransform combined_transform;
for (auto const* ancestor = &this->layout_box(); ancestor; ancestor = ancestor->containing_block()) { for (auto const* ancestor = this; ancestor; ancestor = ancestor->containing_block()) {
auto affine_transform = Gfx::extract_2d_affine_transform(ancestor->paintable_box()->transform()); auto affine_transform = Gfx::extract_2d_affine_transform(ancestor->transform());
combined_transform = combined_transform.multiply(affine_transform); combined_transform = combined_transform.multiply(affine_transform);
} }
return combined_transform; return combined_transform;

View file

@ -25,8 +25,8 @@ CSSPixelRect const PaintableFragment::absolute_rect() const
{ {
CSSPixelRect rect { {}, size() }; CSSPixelRect rect { {}, size() };
auto const* containing_block = paintable().containing_block(); auto const* containing_block = paintable().containing_block();
if (containing_block && containing_block->paintable_box()) if (containing_block)
rect.set_location(containing_block->paintable_box()->absolute_position()); rect.set_location(containing_block->absolute_position());
rect.translate_by(offset()); rect.translate_by(offset());
return rect; return rect;
} }

View file

@ -25,7 +25,7 @@ CSSPixelRect SVGPaintable::compute_absolute_rect() const
{ {
if (auto* svg_svg_box = layout_box().first_ancestor_of_type<Layout::SVGSVGBox>()) { if (auto* svg_svg_box = layout_box().first_ancestor_of_type<Layout::SVGSVGBox>()) {
CSSPixelRect rect { offset(), content_size() }; CSSPixelRect rect { offset(), content_size() };
for (Layout::Box const* ancestor = svg_svg_box; ancestor && ancestor->paintable(); ancestor = ancestor->paintable()->containing_block()) for (Layout::Box const* ancestor = svg_svg_box; ancestor; ancestor = ancestor->containing_block())
rect.translate_by(ancestor->paintable_box()->offset()); rect.translate_by(ancestor->paintable_box()->offset());
return rect; return rect;
} }

View file

@ -77,8 +77,7 @@ void ViewportPaintable::assign_scroll_frames()
for_each_in_subtree([&](auto const& paintable) { for_each_in_subtree([&](auto const& paintable) {
for (auto block = paintable.containing_block(); block; block = block->containing_block()) { for (auto block = paintable.containing_block(); block; block = block->containing_block()) {
auto const& block_paintable_box = *block->paintable_box(); if (auto scroll_frame = scroll_state.get(block); scroll_frame.has_value()) {
if (auto scroll_frame = scroll_state.get(&block_paintable_box); scroll_frame.has_value()) {
if (paintable.is_paintable_box()) { if (paintable.is_paintable_box()) {
auto const& paintable_box = static_cast<PaintableBox const&>(paintable); auto const& paintable_box = static_cast<PaintableBox const&>(paintable);
const_cast<PaintableBox&>(paintable_box).set_enclosing_scroll_frame(scroll_frame.value()); const_cast<PaintableBox&>(paintable_box).set_enclosing_scroll_frame(scroll_frame.value());
@ -108,8 +107,7 @@ void ViewportPaintable::assign_clip_frames()
for_each_in_subtree([&](auto const& paintable) { for_each_in_subtree([&](auto const& paintable) {
for (auto block = paintable.containing_block(); block; block = block->containing_block()) { for (auto block = paintable.containing_block(); block; block = block->containing_block()) {
auto const& block_paintable_box = *block->paintable_box(); if (auto clip_frame = clip_state.get(block); clip_frame.has_value()) {
if (auto clip_frame = clip_state.get(&block_paintable_box); clip_frame.has_value()) {
if (paintable.is_paintable_box()) { if (paintable.is_paintable_box()) {
auto const& paintable_box = static_cast<PaintableBox const&>(paintable); auto const& paintable_box = static_cast<PaintableBox const&>(paintable);
const_cast<PaintableBox&>(paintable_box).set_enclosing_clip_frame(clip_frame.value()); const_cast<PaintableBox&>(paintable_box).set_enclosing_clip_frame(clip_frame.value());
@ -251,7 +249,7 @@ void ViewportPaintable::resolve_paint_only_properties()
auto const& bottom_right_border_radius = inline_paintable.computed_values().border_bottom_right_radius(); auto const& bottom_right_border_radius = inline_paintable.computed_values().border_bottom_right_radius();
auto const& bottom_left_border_radius = inline_paintable.computed_values().border_bottom_left_radius(); auto const& bottom_left_border_radius = inline_paintable.computed_values().border_bottom_left_radius();
auto containing_block_position_in_absolute_coordinates = inline_paintable.containing_block()->paintable_box()->absolute_position(); auto containing_block_position_in_absolute_coordinates = inline_paintable.containing_block()->absolute_position();
for (size_t i = 0; i < fragments.size(); ++i) { for (size_t i = 0; i < fragments.size(); ++i) {
auto is_first_fragment = i == 0; auto is_first_fragment = i == 0;
auto is_last_fragment = i == fragments.size() - 1; auto is_last_fragment = i == fragments.size() - 1;