mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:37:43 +00:00
LibWeb: Apply CSS clip
property to an element as well as its children
d06d4eb
made the `clip` property apply to children of an absolute-
positioned element, but caused it not to be applied to the element the
property was applied to directly.
To fix this, apply the clip in new `before_paint()` and `after_paint()`
functions. Doing so keeps painter state from leaking from `paint()`,
but still allows subclasses of `PaintableBox` clip their contents
correctly without repeating the application of the clip rectangle.
This commit is contained in:
parent
2e45306d42
commit
9d4a1ac2b3
4 changed files with 47 additions and 9 deletions
|
@ -109,6 +109,9 @@ public:
|
||||||
return TraversalDecision::Continue;
|
return TraversalDecision::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void before_paint(PaintContext&, PaintPhase) const { }
|
||||||
|
virtual void after_paint(PaintContext&, PaintPhase) const { }
|
||||||
|
|
||||||
virtual void paint(PaintContext&, PaintPhase) const { }
|
virtual void paint(PaintContext&, PaintPhase) const { }
|
||||||
|
|
||||||
virtual void before_children_paint(PaintContext&, PaintPhase) const { }
|
virtual void before_children_paint(PaintContext&, PaintPhase) const { }
|
||||||
|
|
|
@ -176,6 +176,37 @@ StackingContext* PaintableBox::enclosing_stacking_context()
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<CSSPixelRect> PaintableBox::get_clip_rect() const
|
||||||
|
{
|
||||||
|
auto clip = computed_values().clip();
|
||||||
|
if (clip.is_rect() && layout_box().is_absolutely_positioned()) {
|
||||||
|
auto border_box = absolute_border_box_rect();
|
||||||
|
return clip.to_rect().resolved(layout_node(), border_box.to_type<double>()).to_type<CSSPixels>();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaintableBox::before_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const
|
||||||
|
{
|
||||||
|
if (!is_visible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto clip_rect = get_clip_rect();
|
||||||
|
if (clip_rect.has_value()) {
|
||||||
|
context.painter().save();
|
||||||
|
context.painter().add_clip_rect(clip_rect->to_type<int>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaintableBox::after_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const
|
||||||
|
{
|
||||||
|
if (!is_visible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (get_clip_rect().has_value())
|
||||||
|
context.painter().restore();
|
||||||
|
}
|
||||||
|
|
||||||
void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
|
void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
|
||||||
{
|
{
|
||||||
if (!is_visible())
|
if (!is_visible())
|
||||||
|
@ -424,15 +455,12 @@ void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase ph
|
||||||
auto overflow_x = computed_values().overflow_x();
|
auto overflow_x = computed_values().overflow_x();
|
||||||
auto overflow_y = computed_values().overflow_y();
|
auto overflow_y = computed_values().overflow_y();
|
||||||
|
|
||||||
auto clip = computed_values().clip();
|
auto css_clip_property = get_clip_rect();
|
||||||
if (clip.is_rect() && layout_box().is_absolutely_positioned()) {
|
if (css_clip_property.has_value()) {
|
||||||
auto border_box = absolute_border_box_rect();
|
if (clip_rect.has_value())
|
||||||
auto resolved_clip_rect = clip.to_rect().resolved(layout_node(), border_box.to_type<double>()).to_type<CSSPixels>();
|
clip_rect->intersect(css_clip_property.value());
|
||||||
if (clip_rect.has_value()) {
|
else
|
||||||
clip_rect->intersect(resolved_clip_rect);
|
clip_rect = css_clip_property.value();
|
||||||
} else {
|
|
||||||
clip_rect = resolved_clip_rect;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clip_rect.has_value())
|
if (!clip_rect.has_value())
|
||||||
|
|
|
@ -20,6 +20,9 @@ public:
|
||||||
static JS::NonnullGCPtr<PaintableBox> create(Layout::Box const&);
|
static JS::NonnullGCPtr<PaintableBox> create(Layout::Box const&);
|
||||||
virtual ~PaintableBox();
|
virtual ~PaintableBox();
|
||||||
|
|
||||||
|
virtual void before_paint(PaintContext&, PaintPhase) const override;
|
||||||
|
virtual void after_paint(PaintContext&, PaintPhase) const override;
|
||||||
|
|
||||||
virtual void paint(PaintContext&, PaintPhase) const override;
|
virtual void paint(PaintContext&, PaintPhase) const override;
|
||||||
|
|
||||||
bool is_visible() const { return layout_box().is_visible(); }
|
bool is_visible() const { return layout_box().is_visible(); }
|
||||||
|
@ -186,6 +189,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
explicit PaintableBox(Layout::Box const&);
|
explicit PaintableBox(Layout::Box const&);
|
||||||
|
|
||||||
|
Optional<CSSPixelRect> get_clip_rect() const;
|
||||||
|
|
||||||
virtual void paint_border(PaintContext&) const;
|
virtual void paint_border(PaintContext&) const;
|
||||||
virtual void paint_backdrop_filter(PaintContext&) const;
|
virtual void paint_backdrop_filter(PaintContext&) const;
|
||||||
virtual void paint_background(PaintContext&) const;
|
virtual void paint_background(PaintContext&) const;
|
||||||
|
|
|
@ -26,7 +26,9 @@ namespace Web::Painting {
|
||||||
|
|
||||||
static void paint_node(Paintable const& paintable, PaintContext& context, PaintPhase phase)
|
static void paint_node(Paintable const& paintable, PaintContext& context, PaintPhase phase)
|
||||||
{
|
{
|
||||||
|
paintable.before_paint(context, phase);
|
||||||
paintable.paint(context, phase);
|
paintable.paint(context, phase);
|
||||||
|
paintable.after_paint(context, phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
StackingContext::StackingContext(PaintableBox& paintable_box, StackingContext* parent, size_t index_in_tree_order)
|
StackingContext::StackingContext(PaintableBox& paintable_box, StackingContext* parent, size_t index_in_tree_order)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue