mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 05:39:11 +00:00
LibWeb: Do not mutate display list while scroll offset application
Copy a display list item and apply scroll offset instead of mutating display list directly. It's a preparation for upcoming changes where a display list will be cached across repaints and used multiple times with different scroll offsets.
This commit is contained in:
parent
7ddb94c4d6
commit
e2ad568095
Notes:
github-actions[bot]
2024-08-19 16:58:23 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: e2ad568095
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1106
3 changed files with 32 additions and 24 deletions
|
@ -2128,13 +2128,15 @@ RefPtr<Painting::DisplayList> Navigable::record_display_list(PaintConfig config)
|
|||
|
||||
viewport_paintable.paint_all_phases(context);
|
||||
|
||||
Vector<Gfx::IntPoint> scroll_offsets_by_frame_id;
|
||||
scroll_offsets_by_frame_id.resize(viewport_paintable.scroll_state.size());
|
||||
for (auto [_, scrollable_frame] : viewport_paintable.scroll_state) {
|
||||
auto scroll_offset = context.rounded_device_point(scrollable_frame->cumulative_offset).to_type<int>();
|
||||
scroll_offsets_by_frame_id[scrollable_frame->id] = scroll_offset;
|
||||
display_list->set_device_pixels_per_css_pixel(page.client().device_pixels_per_css_pixel());
|
||||
|
||||
Vector<RefPtr<Painting::ScrollFrame>> scroll_state;
|
||||
scroll_state.resize(viewport_paintable.scroll_state.size());
|
||||
for (auto& [_, scrollable_frame] : viewport_paintable.scroll_state) {
|
||||
scroll_state[scrollable_frame->id] = scrollable_frame;
|
||||
}
|
||||
display_list_recorder.display_list().apply_scroll_offsets(scroll_offsets_by_frame_id);
|
||||
|
||||
display_list->set_scroll_state(move(scroll_state));
|
||||
|
||||
m_needs_repaint = false;
|
||||
|
||||
|
|
|
@ -24,28 +24,26 @@ static Optional<Gfx::IntRect> command_bounding_rectangle(Command const& command)
|
|||
});
|
||||
}
|
||||
|
||||
void DisplayList::apply_scroll_offsets(Vector<Gfx::IntPoint> const& offsets_by_frame_id)
|
||||
{
|
||||
for (auto& command_with_scroll_id : m_commands) {
|
||||
if (command_with_scroll_id.scroll_frame_id.has_value()) {
|
||||
auto const& scroll_frame_id = command_with_scroll_id.scroll_frame_id.value();
|
||||
auto const& scroll_offset = offsets_by_frame_id[scroll_frame_id];
|
||||
command_with_scroll_id.command.visit(
|
||||
[&](auto& command) {
|
||||
if constexpr (requires { command.translate_by(scroll_offset); })
|
||||
command.translate_by(scroll_offset);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListPlayer::execute(DisplayList& display_list)
|
||||
{
|
||||
auto const& commands = display_list.commands();
|
||||
auto const& scroll_state = display_list.scroll_state();
|
||||
auto device_pixels_per_css_pixel = display_list.device_pixels_per_css_pixel();
|
||||
|
||||
size_t next_command_index = 0;
|
||||
while (next_command_index < commands.size()) {
|
||||
auto const& command = commands[next_command_index++].command;
|
||||
auto scroll_frame_id = commands[next_command_index].scroll_frame_id;
|
||||
auto command = commands[next_command_index++].command;
|
||||
if (scroll_frame_id.has_value()) {
|
||||
auto const& scroll_offset = scroll_state[scroll_frame_id.value()]->cumulative_offset.to_type<double>().scaled(device_pixels_per_css_pixel).to_type<int>();
|
||||
command.visit(
|
||||
[&](auto& command) {
|
||||
if constexpr (requires { command.translate_by(scroll_offset); }) {
|
||||
command.translate_by(scroll_offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
auto bounding_rect = command_bounding_rectangle(command);
|
||||
if (bounding_rect.has_value() && (bounding_rect->is_empty() || would_be_fully_clipped_by_painter(*bounding_rect))) {
|
||||
continue;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <LibWeb/Painting/Command.h>
|
||||
#include <LibWeb/Painting/GradientData.h>
|
||||
#include <LibWeb/Painting/PaintBoxShadowParams.h>
|
||||
#include <LibWeb/Painting/ScrollFrame.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
|
@ -83,8 +84,6 @@ public:
|
|||
|
||||
void append(Command&& command, Optional<i32> scroll_frame_id);
|
||||
|
||||
void apply_scroll_offsets(Vector<Gfx::IntPoint> const& offsets_by_frame_id);
|
||||
|
||||
struct CommandListItem {
|
||||
Optional<i32> scroll_frame_id;
|
||||
Command command;
|
||||
|
@ -92,10 +91,19 @@ public:
|
|||
|
||||
AK::SegmentedVector<CommandListItem, 512> const& commands() const { return m_commands; }
|
||||
|
||||
void set_scroll_state(Vector<RefPtr<ScrollFrame>> scroll_state) { m_scroll_state = move(scroll_state); }
|
||||
|
||||
Vector<RefPtr<ScrollFrame>> 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; }
|
||||
|
||||
private:
|
||||
DisplayList() = default;
|
||||
|
||||
AK::SegmentedVector<CommandListItem, 512> m_commands;
|
||||
Vector<RefPtr<ScrollFrame>> m_scroll_state;
|
||||
double m_device_pixels_per_css_pixel;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue