1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:27:45 +00:00

LibWeb: Add PaintableBox::absolute_paint_rect()

This method returns the total area this element will paint to.
Currently, this just means accounting for box-shadows, though
there are likely more effects that need to be accounted for here.
This commit is contained in:
MacDue 2022-09-25 15:13:31 +01:00 committed by Andreas Kling
parent 0843960235
commit 8967fe9d92
2 changed files with 40 additions and 3 deletions

View file

@ -13,7 +13,6 @@
#include <LibWeb/Painting/BackgroundPainting.h> #include <LibWeb/Painting/BackgroundPainting.h>
#include <LibWeb/Painting/FilterPainting.h> #include <LibWeb/Painting/FilterPainting.h>
#include <LibWeb/Painting/PaintableBox.h> #include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/ShadowPainting.h>
#include <LibWeb/Painting/StackingContext.h> #include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Platform/FontPlugin.h> #include <LibWeb/Platform/FontPlugin.h>
@ -92,6 +91,28 @@ Gfx::FloatRect PaintableBox::absolute_rect() const
return *m_absolute_rect; return *m_absolute_rect;
} }
Gfx::FloatRect PaintableBox::compute_absolute_paint_rect() const
{
// FIXME: This likely incomplete:
auto rect = absolute_border_box_rect();
auto resolved_box_shadow_data = resolve_box_shadow_data();
for (auto const& shadow : resolved_box_shadow_data) {
if (shadow.placement == ShadowPlacement::Inner)
continue;
auto inflate = shadow.spread_distance + shadow.blur_radius;
auto shadow_rect = rect.inflated(inflate, inflate, inflate, inflate).translated(shadow.offset_x, shadow.offset_y);
rect = rect.united(shadow_rect);
}
return rect;
}
Gfx::FloatRect PaintableBox::absolute_paint_rect() const
{
if (!m_absolute_paint_rect.has_value())
m_absolute_paint_rect = compute_absolute_paint_rect();
return *m_absolute_paint_rect;
}
void PaintableBox::set_containing_line_box_fragment(Optional<Layout::LineBoxFragmentCoordinate> fragment_coordinate) void PaintableBox::set_containing_line_box_fragment(Optional<Layout::LineBoxFragmentCoordinate> fragment_coordinate)
{ {
m_containing_line_box_fragment = fragment_coordinate; m_containing_line_box_fragment = fragment_coordinate;
@ -235,11 +256,11 @@ void PaintableBox::paint_background(PaintContext& context) const
Painting::paint_background(context, layout_box(), background_rect, background_color, computed_values().image_rendering(), background_layers, normalized_border_radii_data()); Painting::paint_background(context, layout_box(), background_rect, background_color, computed_values().image_rendering(), background_layers, normalized_border_radii_data());
} }
void PaintableBox::paint_box_shadow(PaintContext& context) const Vector<ShadowData> PaintableBox::resolve_box_shadow_data() const
{ {
auto box_shadow_data = computed_values().box_shadow(); auto box_shadow_data = computed_values().box_shadow();
if (box_shadow_data.is_empty()) if (box_shadow_data.is_empty())
return; return {};
Vector<ShadowData> resolved_box_shadow_data; Vector<ShadowData> resolved_box_shadow_data;
resolved_box_shadow_data.ensure_capacity(box_shadow_data.size()); resolved_box_shadow_data.ensure_capacity(box_shadow_data.size());
@ -252,6 +273,15 @@ void PaintableBox::paint_box_shadow(PaintContext& context) const
static_cast<int>(layer.spread_distance.to_px(layout_box())), static_cast<int>(layer.spread_distance.to_px(layout_box())),
layer.placement == CSS::ShadowPlacement::Outer ? ShadowPlacement::Outer : ShadowPlacement::Inner); layer.placement == CSS::ShadowPlacement::Outer ? ShadowPlacement::Outer : ShadowPlacement::Inner);
} }
return resolved_box_shadow_data;
}
void PaintableBox::paint_box_shadow(PaintContext& context) const
{
auto resolved_box_shadow_data = resolve_box_shadow_data();
if (resolved_box_shadow_data.is_empty())
return;
Painting::paint_box_shadow(context, absolute_border_box_rect().to_rounded<int>(), normalized_border_radii_data(), resolved_box_shadow_data); Painting::paint_box_shadow(context, absolute_border_box_rect().to_rounded<int>(), normalized_border_radii_data(), resolved_box_shadow_data);
} }

View file

@ -9,6 +9,7 @@
#include <LibWeb/Painting/BorderPainting.h> #include <LibWeb/Painting/BorderPainting.h>
#include <LibWeb/Painting/BorderRadiusCornerClipper.h> #include <LibWeb/Painting/BorderRadiusCornerClipper.h>
#include <LibWeb/Painting/Paintable.h> #include <LibWeb/Painting/Paintable.h>
#include <LibWeb/Painting/ShadowPainting.h>
namespace Web::Painting { namespace Web::Painting {
@ -68,6 +69,8 @@ public:
return rect; return rect;
} }
Gfx::FloatRect absolute_paint_rect() const;
float border_box_width() const float border_box_width() const
{ {
auto border_box = box_model().border_box(); auto border_box = box_model().border_box();
@ -123,6 +126,7 @@ protected:
virtual void paint_box_shadow(PaintContext&) const; virtual void paint_box_shadow(PaintContext&) const;
virtual Gfx::FloatRect compute_absolute_rect() const; virtual Gfx::FloatRect compute_absolute_rect() const;
virtual Gfx::FloatRect compute_absolute_paint_rect() const;
enum class ShrinkRadiiForBorders { enum class ShrinkRadiiForBorders {
Yes, Yes,
@ -131,6 +135,8 @@ protected:
Painting::BorderRadiiData normalized_border_radii_data(ShrinkRadiiForBorders shrink = ShrinkRadiiForBorders::No) const; Painting::BorderRadiiData normalized_border_radii_data(ShrinkRadiiForBorders shrink = ShrinkRadiiForBorders::No) const;
Vector<ShadowData> resolve_box_shadow_data() const;
private: private:
Optional<OverflowData> m_overflow_data; Optional<OverflowData> m_overflow_data;
@ -143,6 +149,7 @@ private:
OwnPtr<Painting::StackingContext> m_stacking_context; OwnPtr<Painting::StackingContext> m_stacking_context;
Optional<Gfx::FloatRect> mutable m_absolute_rect; Optional<Gfx::FloatRect> mutable m_absolute_rect;
Optional<Gfx::FloatRect> mutable m_absolute_paint_rect;
mutable bool m_clipping_overflow { false }; mutable bool m_clipping_overflow { false };
Optional<BorderRadiusCornerClipper> mutable m_overflow_corner_radius_clipper; Optional<BorderRadiusCornerClipper> mutable m_overflow_corner_radius_clipper;