diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index 0ac55593d3a..b394269bf14 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -38,7 +38,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c auto top_right_border_radius = computed_values().border_top_right_radius(); auto bottom_right_border_radius = computed_values().border_bottom_right_radius(); auto bottom_left_border_radius = computed_values().border_bottom_left_radius(); - auto containing_block_position_in_absolute_coordinates = layout_node().containing_block()->paint_box()->absolute_position(); + auto containing_block_position_in_absolute_coordinates = containing_block()->paint_box()->absolute_position(); for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) { Gfx::FloatRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; @@ -89,7 +89,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c .left = computed_values().border_left(), }; - auto containing_block_position_in_absolute_coordinates = layout_node().containing_block()->paint_box()->absolute_position(); + auto containing_block_position_in_absolute_coordinates = containing_block()->paint_box()->absolute_position(); for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) { Gfx::FloatRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; @@ -132,7 +132,7 @@ void InlinePaintable::for_each_fragment(Callback callback) const { // FIXME: This will be slow if the containing block has a lot of fragments! Vector fragments; - layout_node().containing_block()->paint_box()->for_each_fragment([&](auto& fragment) { + containing_block()->paint_box()->for_each_fragment([&](auto& fragment) { if (layout_node().is_inclusive_ancestor_of(fragment.layout_node())) fragments.append(fragment); return IterationDecision::Continue; diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.cpp b/Userland/Libraries/LibWeb/Painting/Paintable.cpp index 008e871defc..4ddd640e313 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/Paintable.cpp @@ -24,7 +24,7 @@ void Paintable::handle_mousemove(Badge, Gfx::IntPoint const&, unsi bool Paintable::handle_mousewheel(Badge, Gfx::IntPoint const&, unsigned, unsigned, int wheel_delta_x, int wheel_delta_y) { - if (auto* containing_block = layout_node().containing_block()) { + if (auto* containing_block = this->containing_block()) { if (!containing_block->is_scrollable()) return false; auto new_offset = containing_block->scroll_offset(); diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index ea81a8d8675..686b1a99123 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -68,6 +68,13 @@ public: void set_needs_display() const { const_cast(m_layout_node).set_needs_display(); } + Layout::BlockContainer const* containing_block() const + { + if (!m_containing_block.has_value()) + m_containing_block = const_cast(m_layout_node).containing_block(); + return *m_containing_block; + } + protected: explicit Paintable(Layout::Node const& layout_node) : m_layout_node(layout_node) @@ -76,6 +83,7 @@ protected: private: Layout::Node const& m_layout_node; + Optional mutable m_containing_block; }; } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index b0ce44c7610..c1fdbfffa85 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -58,7 +58,7 @@ void PaintableBox::set_content_size(Gfx::FloatSize const& size) Gfx::FloatPoint PaintableBox::effective_offset() const { if (m_containing_line_box_fragment.has_value()) { - auto const& fragment = layout_box().containing_block()->paint_box()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index]; + auto const& fragment = containing_block()->paint_box()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index]; return fragment.offset(); } return m_offset; @@ -66,10 +66,13 @@ Gfx::FloatPoint PaintableBox::effective_offset() const Gfx::FloatRect PaintableBox::absolute_rect() const { - Gfx::FloatRect rect { effective_offset(), content_size() }; - for (auto* block = layout_box().containing_block(); block; block = block->containing_block()) - rect.translate_by(block->paint_box()->effective_offset()); - return rect; + if (!m_absolute_rect.has_value()) { + Gfx::FloatRect rect { effective_offset(), content_size() }; + for (auto const* block = containing_block(); block && block->paintable(); block = block->paintable()->containing_block()) + rect.translate_by(block->paint_box()->effective_offset()); + m_absolute_rect = rect; + } + return *m_absolute_rect; } void PaintableBox::set_containing_line_box_fragment(Optional fragment_coordinate) diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 95545196dc4..6314a66c128 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -131,6 +131,8 @@ private: Painting::BorderRadiusData normalized_border_radius_data() const; OwnPtr m_stacking_context; + + Optional mutable m_absolute_rect; }; class PaintableWithLines : public PaintableBox {