From b2abd1dd051ae4c943ee64168c0014dd6a688234 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Tue, 19 Dec 2023 19:42:00 +0100 Subject: [PATCH] LibWeb: Resolve box shadow data for paintable boxes during layout Step towards making the paintable tree independent of the layout tree. --- .../Libraries/LibWeb/Layout/LayoutState.cpp | 28 +++++++++++++++++++ .../Libraries/LibWeb/Layout/LayoutState.h | 1 + .../LibWeb/Painting/PaintableBox.cpp | 26 ++--------------- .../Libraries/LibWeb/Painting/PaintableBox.h | 6 ++-- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index ef3f3ec9dd..c236fb2b6c 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -336,6 +336,33 @@ void LayoutState::resolve_border_radii() } } +void LayoutState::resolve_box_shadow_data() +{ + for (auto& it : used_values_per_layout_node) { + auto& used_values = *it.value; + auto& node = const_cast(used_values.node()); + auto* paintable = node.paintable(); + if (paintable && is(*paintable)) { + auto box_shadow_data = node.computed_values().box_shadow(); + if (box_shadow_data.is_empty()) + continue; + auto& paintable_box = static_cast(*paintable); + Vector resolved_box_shadow_data; + resolved_box_shadow_data.ensure_capacity(box_shadow_data.size()); + for (auto const& layer : box_shadow_data) { + resolved_box_shadow_data.empend( + layer.color, + layer.offset_x.to_px(node), + layer.offset_y.to_px(node), + layer.blur_radius.to_px(node), + layer.spread_distance.to_px(node), + layer.placement == CSS::ShadowPlacement::Outer ? Painting::ShadowPlacement::Outer : Painting::ShadowPlacement::Inner); + } + paintable_box.set_box_shadow_data(move(resolved_box_shadow_data)); + } + } +} + void LayoutState::commit(Box& root) { // Only the top-level LayoutState should ever be committed. @@ -432,6 +459,7 @@ void LayoutState::commit(Box& root) } resolve_border_radii(); + resolve_box_shadow_data(); } void LayoutState::UsedValues::set_node(NodeWithStyle& node, UsedValues const* containing_block_used_values) diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.h b/Userland/Libraries/LibWeb/Layout/LayoutState.h index f93815d909..a28a49034b 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.h +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.h @@ -187,6 +187,7 @@ struct LayoutState { private: void resolve_relative_positions(Vector const&); void resolve_border_radii(); + void resolve_box_shadow_data(); }; } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 48dd128da3..35273d00c3 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -148,8 +148,7 @@ CSSPixelRect PaintableBox::compute_absolute_paint_rect() const if (computed_values().overflow_y() == CSS::Overflow::Visible) rect.unite_vertically(scrollable_overflow_rect); } - auto resolved_box_shadow_data = resolve_box_shadow_data(); - for (auto const& shadow : resolved_box_shadow_data) { + for (auto const& shadow : box_shadow_data()) { if (shadow.placement == ShadowPlacement::Inner) continue; auto inflate = shadow.spread_distance + shadow.blur_radius; @@ -355,30 +354,9 @@ 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()); } -Vector PaintableBox::resolve_box_shadow_data() const -{ - auto box_shadow_data = computed_values().box_shadow(); - if (box_shadow_data.is_empty()) - return {}; - - Vector resolved_box_shadow_data; - resolved_box_shadow_data.ensure_capacity(box_shadow_data.size()); - for (auto const& layer : box_shadow_data) { - resolved_box_shadow_data.empend( - layer.color, - layer.offset_x.to_px(layout_box()), - layer.offset_y.to_px(layout_box()), - layer.blur_radius.to_px(layout_box()), - layer.spread_distance.to_px(layout_box()), - 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(); + auto const& resolved_box_shadow_data = box_shadow_data(); if (resolved_box_shadow_data.is_empty()) return; auto borders_data = BordersData { diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 82cf7b786a..adf447e34e 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -191,6 +191,9 @@ public: BorderRadiiData const& border_radii_data() const { return m_border_radii_data; } void set_border_radii_data(BorderRadiiData const& border_radii_data) { m_border_radii_data = border_radii_data; } + void set_box_shadow_data(Vector box_shadow_data) { m_box_shadow_data = move(box_shadow_data); } + Vector const& box_shadow_data() const { return m_box_shadow_data; } + PaintableBox const* nearest_scrollable_ancestor() const; protected: @@ -206,8 +209,6 @@ protected: virtual CSSPixelRect compute_absolute_rect() const; virtual CSSPixelRect compute_absolute_paint_rect() const; - Vector resolve_box_shadow_data() const; - private: [[nodiscard]] virtual bool is_paintable_box() const final { return true; } @@ -230,6 +231,7 @@ private: Optional m_table_cell_coordinates; BorderRadiiData m_border_radii_data; + Vector m_box_shadow_data; }; class PaintableWithLines : public PaintableBox {