From 6452bfb612a2e04db36fd2ad25da957366f495b6 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Fri, 11 Oct 2024 20:31:19 +0200 Subject: [PATCH] LibWeb: Store scroll and sticky frames state in single vector This way we don't have to allocate separate vector with both scroll and sticky frame that is used for display list player (scroll and sticky frames share id pool), so player could access offset by frame id. No behavior change. --- Userland/Libraries/LibWeb/DOM/Document.cpp | 12 +----- .../Libraries/LibWeb/Painting/DisplayList.cpp | 5 ++- .../Libraries/LibWeb/Painting/DisplayList.h | 8 ++-- .../Libraries/LibWeb/Painting/ScrollFrame.cpp | 3 +- .../Libraries/LibWeb/Painting/ScrollFrame.h | 5 ++- .../Libraries/LibWeb/Painting/ScrollState.h | 42 ++++++++++++++----- .../LibWeb/Painting/ViewportPaintable.cpp | 10 ++--- 7 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 529a18f8f89..85df968491c 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -5582,17 +5582,7 @@ RefPtr Document::record_display_list(PaintConfig config) viewport_paintable.paint_all_phases(context); display_list->set_device_pixels_per_css_pixel(page().client().device_pixels_per_css_pixel()); - - Vector> scroll_state; - scroll_state.resize(viewport_paintable.scroll_state().scroll_frames().size() + viewport_paintable.scroll_state().sticky_frames().size()); - for (auto const& scroll_frame : viewport_paintable.scroll_state().scroll_frames()) { - scroll_state[scroll_frame->id()] = scroll_frame; - } - for (auto const& scroll_frame : viewport_paintable.scroll_state().sticky_frames()) { - scroll_state[scroll_frame->id()] = scroll_frame; - } - - display_list->set_scroll_state(move(scroll_state)); + display_list->set_scroll_state(viewport_paintable.scroll_state()); m_needs_repaint = false; diff --git a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp index 28d980cb557..e67a66c5962 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp @@ -37,7 +37,7 @@ void DisplayListPlayer::execute(DisplayList& display_list) if (command.has()) { auto& paint_scroll_bar = command.get(); - auto const& scroll_offset = scroll_state[paint_scroll_bar.scroll_frame_id]->own_offset(); + auto scroll_offset = scroll_state.own_offset_for_frame_with_id(paint_scroll_bar.scroll_frame_id); if (paint_scroll_bar.vertical) { auto offset = scroll_offset.y() * paint_scroll_bar.scroll_size; paint_scroll_bar.rect.translate_by(0, -offset.to_int() * device_pixels_per_css_pixel); @@ -48,7 +48,8 @@ void DisplayListPlayer::execute(DisplayList& display_list) } if (scroll_frame_id.has_value()) { - auto const& scroll_offset = scroll_state[scroll_frame_id.value()]->cumulative_offset().to_type().scaled(device_pixels_per_css_pixel).to_type(); + auto cumulative_offset = scroll_state.cumulative_offset_for_frame_with_id(scroll_frame_id.value()); + auto scroll_offset = cumulative_offset.to_type().scaled(device_pixels_per_css_pixel).to_type(); command.visit( [&](auto& command) { if constexpr (requires { command.translate_by(scroll_offset); }) { diff --git a/Userland/Libraries/LibWeb/Painting/DisplayList.h b/Userland/Libraries/LibWeb/Painting/DisplayList.h index 7bbad1f485a..ceffadbb7dd 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Web::Painting { @@ -96,9 +97,8 @@ public: AK::SegmentedVector const& commands() const { return m_commands; } - void set_scroll_state(Vector> scroll_state) { m_scroll_state = move(scroll_state); } - - Vector> const& scroll_state() const { return m_scroll_state; } + void set_scroll_state(ScrollState scroll_state) { m_scroll_state = move(scroll_state); } + ScrollState const& scroll_state() const { return m_scroll_state; } void set_device_pixels_per_css_pixel(double device_pixels_per_css_pixel) { m_device_pixels_per_css_pixel = device_pixels_per_css_pixel; } double device_pixels_per_css_pixel() const { return m_device_pixels_per_css_pixel; } @@ -107,7 +107,7 @@ private: DisplayList() = default; AK::SegmentedVector m_commands; - Vector> m_scroll_state; + ScrollState m_scroll_state; double m_device_pixels_per_css_pixel; }; diff --git a/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp b/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp index cbb91258689..06f2fd58ccb 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp +++ b/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp @@ -9,9 +9,10 @@ namespace Web::Painting { -ScrollFrame::ScrollFrame(PaintableBox const& paintable_box, size_t id, RefPtr parent) +ScrollFrame::ScrollFrame(PaintableBox const& paintable_box, size_t id, bool sticky, RefPtr parent) : m_paintable_box(paintable_box) , m_id(id) + , m_sticky(sticky) , m_parent(move(parent)) { } diff --git a/Userland/Libraries/LibWeb/Painting/ScrollFrame.h b/Userland/Libraries/LibWeb/Painting/ScrollFrame.h index 3ab7a02196e..f5c0c9ac408 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollFrame.h +++ b/Userland/Libraries/LibWeb/Painting/ScrollFrame.h @@ -13,12 +13,14 @@ namespace Web::Painting { class ScrollFrame : public RefCounted { public: - ScrollFrame(PaintableBox const& paintable_box, size_t id, RefPtr parent); + ScrollFrame(PaintableBox const& paintable_box, size_t id, bool sticky, RefPtr parent); PaintableBox const& paintable_box() const { return *m_paintable_box; } size_t id() const { return m_id; } + bool is_sticky() const { return m_sticky; } + CSSPixelPoint cumulative_offset() const { if (!m_cached_cumulative_offset.has_value()) { @@ -40,6 +42,7 @@ public: private: WeakPtr m_paintable_box; size_t m_id { 0 }; + bool m_sticky { false }; RefPtr m_parent; CSSPixelPoint m_own_offset; diff --git a/Userland/Libraries/LibWeb/Painting/ScrollState.h b/Userland/Libraries/LibWeb/Painting/ScrollState.h index a124ab2a82e..ddadbc550a0 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollState.h +++ b/Userland/Libraries/LibWeb/Painting/ScrollState.h @@ -12,32 +12,52 @@ namespace Web::Painting { class ScrollState { public: - NonnullRefPtr create_scroll_frame_for(PaintableBox const& paintable, RefPtr parent) + NonnullRefPtr create_scroll_frame_for(PaintableBox const& paintable_box, RefPtr parent) { - auto scroll_frame = adopt_ref(*new ScrollFrame(paintable, m_next_id++, parent)); + auto scroll_frame = adopt_ref(*new ScrollFrame(paintable_box, m_scroll_frames.size(), false, move(parent))); m_scroll_frames.append(scroll_frame); return scroll_frame; } - NonnullRefPtr create_sticky_frame_for(PaintableBox const& paintable, RefPtr parent) + NonnullRefPtr create_sticky_frame_for(PaintableBox const& paintable_box, RefPtr parent) { - auto scroll_frame = adopt_ref(*new ScrollFrame(paintable, m_next_id++, parent)); - m_sticky_frames.append(scroll_frame); + auto scroll_frame = adopt_ref(*new ScrollFrame(paintable_box, m_scroll_frames.size(), true, move(parent))); + m_scroll_frames.append(scroll_frame); return scroll_frame; } - void clear() + CSSPixelPoint cumulative_offset_for_frame_with_id(size_t id) const { - m_scroll_frames.clear(); + return m_scroll_frames[id]->cumulative_offset(); } - Vector> const& scroll_frames() const { return m_scroll_frames; } - Vector> const& sticky_frames() const { return m_sticky_frames; } + CSSPixelPoint own_offset_for_frame_with_id(size_t id) const + { + return m_scroll_frames[id]->own_offset(); + } + + template + void for_each_scroll_frame(Callback callback) const + { + for (auto const& scroll_frame : m_scroll_frames) { + if (scroll_frame->is_sticky()) + continue; + callback(scroll_frame); + } + } + + template + void for_each_sticky_frame(Callback callback) const + { + for (auto const& scroll_frame : m_scroll_frames) { + if (!scroll_frame->is_sticky()) + continue; + callback(scroll_frame); + } + } private: - size_t m_next_id { 0 }; Vector> m_scroll_frames; - Vector> m_sticky_frames; }; } diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp index 8fe4fe91a06..26d658ed1ab 100644 --- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -179,13 +179,13 @@ void ViewportPaintable::refresh_scroll_state() return; m_needs_to_refresh_scroll_state = false; - for (auto const& scroll_frame : m_scroll_state.sticky_frames()) { + m_scroll_state.for_each_sticky_frame([&](auto& scroll_frame) { auto const& sticky_box = scroll_frame->paintable_box(); auto const& sticky_insets = sticky_box.sticky_insets(); auto const* nearest_scrollable_ancestor = sticky_box.nearest_scrollable_ancestor(); if (!nearest_scrollable_ancestor) { - continue; + return; } // Min and max offsets are needed to clamp the sticky box's position to stay within bounds of containing block. @@ -250,11 +250,11 @@ void ViewportPaintable::refresh_scroll_state() } scroll_frame->set_own_offset(sticky_offset); - } + }); - for (auto const& scroll_frame : m_scroll_state.scroll_frames()) { + m_scroll_state.for_each_scroll_frame([&](auto& scroll_frame) { scroll_frame->set_own_offset(-scroll_frame->paintable_box().scroll_offset()); - } + }); } void ViewportPaintable::resolve_paint_only_properties()