mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 17:40:27 +00:00
LibWeb: Paint relatively positioned inline-level elements
Since we deliberately skip positioned elements in paint_descendants(), we have to make sure we actually paint them in the subsequent paint_internal() pass. Before this change, we were only painting positioned elements whose paintable was a PaintableBox, neglecting inline-level relpos elements.
This commit is contained in:
parent
268492413a
commit
2d6c1bbf88
Notes:
sideshowbarker
2024-07-16 23:51:07 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/2d6c1bbf88 Pull-request: https://github.com/SerenityOS/serenity/pull/20019
2 changed files with 40 additions and 16 deletions
|
@ -83,6 +83,28 @@ public:
|
|||
return TraversalDecision::Continue;
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
TraversalDecision for_each_in_inclusive_subtree(Callback callback) const
|
||||
{
|
||||
if (auto decision = callback(*this); decision != TraversalDecision::Continue)
|
||||
return decision;
|
||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||
if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
TraversalDecision for_each_in_subtree(Callback callback) const
|
||||
{
|
||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||
if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
|
||||
virtual void paint(PaintContext&, PaintPhase) const { }
|
||||
|
||||
virtual void before_children_paint(PaintContext&, PaintPhase) const { }
|
||||
|
|
|
@ -182,38 +182,40 @@ void StackingContext::paint_internal(PaintContext& context) const
|
|||
// Draw positioned descendants with z-index `0` or `auto` in tree order. (step 8)
|
||||
// NOTE: Non-positioned descendants that establish stacking contexts with z-index `0` or `auto` are also painted here.
|
||||
// FIXME: There's more to this step that we have yet to understand and implement.
|
||||
m_box->paintable_box()->for_each_in_subtree_of_type<PaintableBox>([&](PaintableBox const& paintable_box) {
|
||||
auto const& z_index = paintable_box.computed_values().z_index();
|
||||
if (auto* child = paintable_box.stacking_context()) {
|
||||
m_box->paintable_box()->for_each_in_subtree([&](Paintable const& paintable) {
|
||||
auto const& layout_node = paintable.layout_node();
|
||||
auto const& z_index = paintable.computed_values().z_index();
|
||||
|
||||
if (auto const* child = paintable.stacking_context_rooted_here()) {
|
||||
if (!z_index.has_value() || z_index.value() == 0)
|
||||
paint_child(child);
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
if (z_index.has_value() && z_index.value() != 0)
|
||||
return TraversalDecision::Continue;
|
||||
if (!paintable_box.layout_box().is_positioned())
|
||||
if (!layout_node.is_positioned())
|
||||
return TraversalDecision::Continue;
|
||||
// At this point, `paintable_box` is a positioned descendant with z-index: auto
|
||||
// but no stacking context of its own.
|
||||
// FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant.
|
||||
auto parent = paintable_box.layout_node().parent();
|
||||
auto parent = layout_node.parent();
|
||||
auto* parent_paintable = parent ? parent->paintable() : nullptr;
|
||||
if (parent_paintable)
|
||||
parent_paintable->before_children_paint(context, PaintPhase::Foreground);
|
||||
auto containing_block = paintable_box.layout_node().containing_block();
|
||||
auto containing_block = layout_node.containing_block();
|
||||
auto* containing_block_paintable = containing_block ? containing_block->paintable() : nullptr;
|
||||
if (containing_block_paintable)
|
||||
containing_block_paintable->apply_clip_overflow_rect(context, PaintPhase::Foreground);
|
||||
paint_node(paintable_box.layout_box(), context, PaintPhase::Background);
|
||||
paint_node(paintable_box.layout_box(), context, PaintPhase::Border);
|
||||
paint_descendants(context, paintable_box.layout_box(), StackingContextPaintPhase::BackgroundAndBorders);
|
||||
paint_descendants(context, paintable_box.layout_box(), StackingContextPaintPhase::Floats);
|
||||
paint_descendants(context, paintable_box.layout_box(), StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced);
|
||||
paint_node(paintable_box.layout_box(), context, PaintPhase::Foreground);
|
||||
paint_descendants(context, paintable_box.layout_box(), StackingContextPaintPhase::Foreground);
|
||||
paint_node(paintable_box.layout_box(), context, PaintPhase::FocusOutline);
|
||||
paint_node(paintable_box.layout_box(), context, PaintPhase::Overlay);
|
||||
paint_descendants(context, paintable_box.layout_box(), StackingContextPaintPhase::FocusAndOverlay);
|
||||
paint_node(layout_node, context, PaintPhase::Background);
|
||||
paint_node(layout_node, context, PaintPhase::Border);
|
||||
paint_descendants(context, layout_node, StackingContextPaintPhase::BackgroundAndBorders);
|
||||
paint_descendants(context, layout_node, StackingContextPaintPhase::Floats);
|
||||
paint_descendants(context, layout_node, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced);
|
||||
paint_node(layout_node, context, PaintPhase::Foreground);
|
||||
paint_descendants(context, layout_node, StackingContextPaintPhase::Foreground);
|
||||
paint_node(layout_node, context, PaintPhase::FocusOutline);
|
||||
paint_node(layout_node, context, PaintPhase::Overlay);
|
||||
paint_descendants(context, layout_node, StackingContextPaintPhase::FocusAndOverlay);
|
||||
if (parent_paintable)
|
||||
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
|
||||
if (containing_block_paintable)
|
||||
|
|
Loading…
Reference in a new issue