mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:27:35 +00:00
LibWeb: Use rect of containing block instead of parent to clip overflow
Move overflow clipping from `before_children_paint` into separate method and call this method on containing block instead of parent. Example that got fixed: ```html <!DOCTYPE html><html><head><style> * { border: 2px solid black; } body { overflow: hidden; } .inner { position: absolute; width: 100px; height: 100px; background: lime; } </style></head><body><div class=inner></div> ```
This commit is contained in:
parent
ee4ba7617c
commit
08f217526a
4 changed files with 37 additions and 16 deletions
|
@ -88,6 +88,9 @@ public:
|
||||||
virtual void before_children_paint(PaintContext&, PaintPhase) const { }
|
virtual void before_children_paint(PaintContext&, PaintPhase) const { }
|
||||||
virtual void after_children_paint(PaintContext&, PaintPhase) const { }
|
virtual void after_children_paint(PaintContext&, PaintPhase) const { }
|
||||||
|
|
||||||
|
virtual void apply_clip_overflow_rect(PaintContext&, PaintPhase) const { }
|
||||||
|
virtual void clear_clip_overflow_rect(PaintContext&, PaintPhase) const { }
|
||||||
|
|
||||||
virtual Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const;
|
virtual Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const;
|
||||||
|
|
||||||
virtual bool wants_mouse_events() const { return false; }
|
virtual bool wants_mouse_events() const { return false; }
|
||||||
|
|
|
@ -318,7 +318,7 @@ Optional<Gfx::IntRect> PaintableBox::clip_rect() const
|
||||||
return m_clip_rect;
|
return m_clip_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase) const
|
void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase phase) const
|
||||||
{
|
{
|
||||||
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
|
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
|
||||||
return;
|
return;
|
||||||
|
@ -364,7 +364,7 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase) const
|
void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase phase) const
|
||||||
{
|
{
|
||||||
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
|
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -114,8 +114,8 @@ public:
|
||||||
DOM::Document const& document() const { return layout_box().document(); }
|
DOM::Document const& document() const { return layout_box().document(); }
|
||||||
DOM::Document& document() { return layout_box().document(); }
|
DOM::Document& document() { return layout_box().document(); }
|
||||||
|
|
||||||
virtual void before_children_paint(PaintContext&, PaintPhase) const override;
|
virtual void apply_clip_overflow_rect(PaintContext&, PaintPhase) const override;
|
||||||
virtual void after_children_paint(PaintContext&, PaintPhase) const override;
|
virtual void clear_clip_overflow_rect(PaintContext&, PaintPhase) const override;
|
||||||
|
|
||||||
virtual Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const override;
|
virtual Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const override;
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,10 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas
|
||||||
|
|
||||||
void StackingContext::paint_descendants(PaintContext& context, Layout::Node const& box, StackingContextPaintPhase phase) const
|
void StackingContext::paint_descendants(PaintContext& context, Layout::Node const& box, StackingContextPaintPhase phase) const
|
||||||
{
|
{
|
||||||
if (auto* paintable = box.paintable())
|
if (auto* paintable = box.paintable()) {
|
||||||
paintable->before_children_paint(context, to_paint_phase(phase));
|
paintable->before_children_paint(context, to_paint_phase(phase));
|
||||||
|
paintable->apply_clip_overflow_rect(context, to_paint_phase(phase));
|
||||||
|
}
|
||||||
|
|
||||||
box.for_each_child([&](auto& child) {
|
box.for_each_child([&](auto& child) {
|
||||||
// If `child` establishes its own stacking context, skip over it.
|
// If `child` establishes its own stacking context, skip over it.
|
||||||
|
@ -124,8 +126,10 @@ void StackingContext::paint_descendants(PaintContext& context, Layout::Node cons
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (auto* paintable = box.paintable())
|
if (auto* paintable = box.paintable()) {
|
||||||
|
paintable->clear_clip_overflow_rect(context, to_paint_phase(phase));
|
||||||
paintable->after_children_paint(context, to_paint_phase(phase));
|
paintable->after_children_paint(context, to_paint_phase(phase));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackingContext::paint_internal(PaintContext& context) const
|
void StackingContext::paint_internal(PaintContext& context) const
|
||||||
|
@ -137,12 +141,20 @@ void StackingContext::paint_internal(PaintContext& context) const
|
||||||
|
|
||||||
auto paint_child = [&](auto* child) {
|
auto paint_child = [&](auto* child) {
|
||||||
auto parent = child->m_box.parent();
|
auto parent = child->m_box.parent();
|
||||||
auto* paintable = parent ? parent->paintable() : nullptr;
|
auto* parent_paintable = parent ? parent->paintable() : nullptr;
|
||||||
if (paintable)
|
if (parent_paintable)
|
||||||
paintable->before_children_paint(context, PaintPhase::Foreground);
|
parent_paintable->before_children_paint(context, PaintPhase::Foreground);
|
||||||
|
auto containing_block = child->m_box.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);
|
||||||
|
|
||||||
child->paint(context);
|
child->paint(context);
|
||||||
if (paintable)
|
|
||||||
paintable->after_children_paint(context, PaintPhase::Foreground);
|
if (parent_paintable)
|
||||||
|
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
|
||||||
|
if (containing_block_paintable)
|
||||||
|
containing_block_paintable->clear_clip_overflow_rect(context, PaintPhase::Foreground);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Draw positioned descendants with negative z-indices (step 3)
|
// Draw positioned descendants with negative z-indices (step 3)
|
||||||
|
@ -178,9 +190,13 @@ void StackingContext::paint_internal(PaintContext& context) const
|
||||||
// but no stacking context of its own.
|
// 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.
|
// FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant.
|
||||||
auto parent = paint_box.layout_node().parent();
|
auto parent = paint_box.layout_node().parent();
|
||||||
auto* paintable = parent ? parent->paintable() : nullptr;
|
auto* parent_paintable = parent ? parent->paintable() : nullptr;
|
||||||
if (paintable)
|
if (parent_paintable)
|
||||||
paintable->before_children_paint(context, PaintPhase::Foreground);
|
parent_paintable->before_children_paint(context, PaintPhase::Foreground);
|
||||||
|
auto containing_block = paint_box.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(paint_box.layout_box(), context, PaintPhase::Background);
|
paint_node(paint_box.layout_box(), context, PaintPhase::Background);
|
||||||
paint_node(paint_box.layout_box(), context, PaintPhase::Border);
|
paint_node(paint_box.layout_box(), context, PaintPhase::Border);
|
||||||
paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::BackgroundAndBorders);
|
paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::BackgroundAndBorders);
|
||||||
|
@ -191,8 +207,10 @@ void StackingContext::paint_internal(PaintContext& context) const
|
||||||
paint_node(paint_box.layout_box(), context, PaintPhase::FocusOutline);
|
paint_node(paint_box.layout_box(), context, PaintPhase::FocusOutline);
|
||||||
paint_node(paint_box.layout_box(), context, PaintPhase::Overlay);
|
paint_node(paint_box.layout_box(), context, PaintPhase::Overlay);
|
||||||
paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::FocusAndOverlay);
|
paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::FocusAndOverlay);
|
||||||
if (paintable)
|
if (parent_paintable)
|
||||||
paintable->after_children_paint(context, PaintPhase::Foreground);
|
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
|
||||||
|
if (containing_block_paintable)
|
||||||
|
containing_block_paintable->clear_clip_overflow_rect(context, PaintPhase::Foreground);
|
||||||
|
|
||||||
return TraversalDecision::Continue;
|
return TraversalDecision::Continue;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue