mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:57:44 +00:00
LibWeb: Apply scroll boxes offsets after painting commands recording
With this change, instead of applying scroll offsets during the recording of the painting command list, we do the following: 1. Collect all boxes with scrollable overflow into a PaintContext, each with an id and the total amount of scrolling offset accumulated from ancestor scrollable boxes. 2. During the recording phase assign a corresponding scroll_frame_id to each command that paints content within a scrollable box. 3. Before executing the recorded commands, translate each command that has a scroll_frame_id by the accumulated scroll offset. This approach has following advantages: - Implementing nested scrollables becomes much simpler, as the recording phase only requires the correct assignment of the nearest scrollable's scroll_frame_id, while the accumulated offset from ancestors is applied subsequently. - The recording of painting commands is not tied to a specific offset within scrollable boxes, which means in the future, it will be possible to update the scrolling offset and repaint without the need to re-record painting commands.
This commit is contained in:
parent
d3025668a4
commit
ac6b3c989d
12 changed files with 307 additions and 24 deletions
|
@ -184,8 +184,16 @@ void StackingContext::paint_child(PaintContext& context, StackingContext const&
|
|||
if (parent_paintable)
|
||||
parent_paintable->before_children_paint(context, PaintPhase::Foreground);
|
||||
|
||||
PaintableBox const* nearest_scrollable_ancestor = child.paintable_box().nearest_scrollable_ancestor_within_stacking_context();
|
||||
|
||||
if (nearest_scrollable_ancestor)
|
||||
nearest_scrollable_ancestor->apply_scroll_offset(context, PaintPhase::Foreground);
|
||||
|
||||
child.paint(context);
|
||||
|
||||
if (nearest_scrollable_ancestor)
|
||||
nearest_scrollable_ancestor->reset_scroll_offset(context, PaintPhase::Foreground);
|
||||
|
||||
if (parent_paintable)
|
||||
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
|
||||
}
|
||||
|
@ -229,7 +237,7 @@ void StackingContext::paint_internal(PaintContext& context) const
|
|||
// Apply scroll offset of nearest scrollable ancestor before painting the positioned descendant.
|
||||
PaintableBox const* nearest_scrollable_ancestor = nullptr;
|
||||
if (paintable.is_paintable_box())
|
||||
nearest_scrollable_ancestor = static_cast<PaintableBox const&>(paintable).nearest_scrollable_ancestor();
|
||||
nearest_scrollable_ancestor = static_cast<PaintableBox const&>(paintable).nearest_scrollable_ancestor_within_stacking_context();
|
||||
if (nearest_scrollable_ancestor)
|
||||
nearest_scrollable_ancestor->apply_scroll_offset(context, PaintPhase::Foreground);
|
||||
|
||||
|
@ -265,6 +273,12 @@ void StackingContext::paint_internal(PaintContext& context) const
|
|||
for (auto* child : m_children) {
|
||||
if (!child->paintable_box().is_positioned())
|
||||
continue;
|
||||
|
||||
PaintableBox const* nearest_scrollable_ancestor = child->paintable_box().nearest_scrollable_ancestor_within_stacking_context();
|
||||
|
||||
if (nearest_scrollable_ancestor)
|
||||
nearest_scrollable_ancestor->apply_scroll_offset(context, PaintPhase::Foreground);
|
||||
|
||||
auto containing_block = child->paintable_box().containing_block();
|
||||
auto const* containing_block_paintable = containing_block ? containing_block->paintable() : nullptr;
|
||||
if (containing_block_paintable)
|
||||
|
@ -273,6 +287,9 @@ void StackingContext::paint_internal(PaintContext& context) const
|
|||
paint_child(context, *child);
|
||||
if (containing_block_paintable)
|
||||
containing_block_paintable->clear_clip_overflow_rect(context, PaintPhase::Foreground);
|
||||
|
||||
if (nearest_scrollable_ancestor)
|
||||
nearest_scrollable_ancestor->reset_scroll_offset(context, PaintPhase::Foreground);
|
||||
}
|
||||
|
||||
paint_node(paintable_box(), context, PaintPhase::Outline);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue