summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-03-10 11:12:06 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-11 00:21:49 +0100
commit7af03df4c3aa50acb5d73fbc69b1181cfbbed536 (patch)
treedb1fcaa293bbd1313c2777c1895067de84a58156 /Userland
parent9f5cbcaad39aa9df43694140613fdd8b3b2fe5b2 (diff)
downloadserenity-7af03df4c3aa50acb5d73fbc69b1181cfbbed536.zip
LibWeb: Make Painting::Box virtual and add Painting::BoxWithLines
BlockContainer paint boxes are the only ones that have line boxes associated, so let's not waste memory on line boxes in all the other types of boxes. This also adds Layout::Box::paint_box() and the more tightly typed Layout::BlockContainer::paint_box() to get at the paint box from the corresponding layout box.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/Dump.cpp4
-rw-r--r--Userland/Libraries/LibWeb/Forward.h1
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockContainer.cpp13
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockContainer.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/Box.cpp5
-rw-r--r--Userland/Libraries/LibWeb/Layout/Box.h3
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingState.cpp10
-rw-r--r--Userland/Libraries/LibWeb/Layout/InlineNode.cpp2
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.cpp4
-rw-r--r--Userland/Libraries/LibWeb/Painting/Box.cpp20
-rw-r--r--Userland/Libraries/LibWeb/Painting/Box.h41
11 files changed, 79 insertions, 26 deletions
diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp
index ca4c25499b..805c54266e 100644
--- a/Userland/Libraries/LibWeb/Dump.cpp
+++ b/Userland/Libraries/LibWeb/Dump.cpp
@@ -226,8 +226,8 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho
if (is<Layout::BlockContainer>(layout_node) && static_cast<Layout::BlockContainer const&>(layout_node).children_are_inline()) {
auto& block = static_cast<Layout::BlockContainer const&>(layout_node);
- for (size_t line_box_index = 0; line_box_index < block.m_paint_box->line_boxes().size(); ++line_box_index) {
- auto& line_box = block.m_paint_box->line_boxes()[line_box_index];
+ for (size_t line_box_index = 0; line_box_index < block.paint_box()->line_boxes().size(); ++line_box_index) {
+ auto& line_box = block.paint_box()->line_boxes()[line_box_index];
for (size_t i = 0; i < indent; ++i)
builder.append(" ");
builder.appendff(" {}line {}{} width: {}, bottom: {}, baseline: {}\n",
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index f066b6f74a..4e45ae278c 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -266,6 +266,7 @@ class PerformanceTiming;
namespace Web::Painting {
enum class PaintPhase;
class Box;
+class BoxWithLines;
}
namespace Web::RequestIdleCallback {
diff --git a/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp b/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp
index a76b3677b0..9fef64e440 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp
+++ b/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp
@@ -51,11 +51,11 @@ void BlockContainer::paint(PaintContext& context, Painting::PaintPhase phase)
context.painter().translate(-m_scroll_offset.to_type<int>());
}
- for (auto& line_box : m_paint_box->m_line_boxes) {
+ for (auto& line_box : paint_box()->line_boxes()) {
for (auto& fragment : line_box.fragments()) {
if (context.should_show_line_box_borders())
context.painter().draw_rect(enclosing_int_rect(fragment.absolute_rect()), Color::Green);
- fragment.paint(context, phase);
+ const_cast<LineBoxFragment&>(fragment).paint(context, phase);
}
}
@@ -65,7 +65,7 @@ void BlockContainer::paint(PaintContext& context, Painting::PaintPhase phase)
// FIXME: Merge this loop with the above somehow..
if (phase == Painting::PaintPhase::FocusOutline) {
- for (auto& line_box : m_paint_box->m_line_boxes) {
+ for (auto& line_box : paint_box()->line_boxes()) {
for (auto& fragment : line_box.fragments()) {
auto* node = fragment.layout_node().dom_node();
if (!node)
@@ -86,7 +86,7 @@ HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestTyp
return Box::hit_test(position, type);
HitTestResult last_good_candidate;
- for (auto& line_box : m_paint_box->m_line_boxes) {
+ for (auto& line_box : paint_box()->line_boxes()) {
for (auto& fragment : line_box.fragments()) {
if (is<Box>(fragment.layout_node()) && verify_cast<Box>(fragment.layout_node()).m_paint_box->stacking_context())
continue;
@@ -131,4 +131,9 @@ bool BlockContainer::handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&
return true;
}
+Painting::BoxWithLines const* BlockContainer::paint_box() const
+{
+ return static_cast<Painting::BoxWithLines const*>(Box::paint_box());
+}
+
}
diff --git a/Userland/Libraries/LibWeb/Layout/BlockContainer.h b/Userland/Libraries/LibWeb/Layout/BlockContainer.h
index 3cd353a9af..5d96774b8c 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockContainer.h
+++ b/Userland/Libraries/LibWeb/Layout/BlockContainer.h
@@ -31,6 +31,8 @@ public:
const Gfx::FloatPoint& scroll_offset() const { return m_scroll_offset; }
void set_scroll_offset(const Gfx::FloatPoint&);
+ Painting::BoxWithLines const* paint_box() const;
+
private:
virtual bool is_block_container() const final { return true; }
virtual bool wants_mouse_events() const override { return false; }
diff --git a/Userland/Libraries/LibWeb/Layout/Box.cpp b/Userland/Libraries/LibWeb/Layout/Box.cpp
index 05d2cdceb8..8a5a49fe1e 100644
--- a/Userland/Libraries/LibWeb/Layout/Box.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Box.cpp
@@ -34,6 +34,11 @@ Box::~Box()
{
}
+void Box::set_paint_box(OwnPtr<Painting::Box> paint_box)
+{
+ m_paint_box = move(paint_box);
+}
+
void Box::paint(PaintContext& context, Painting::PaintPhase phase)
{
if (!is_visible())
diff --git a/Userland/Libraries/LibWeb/Layout/Box.h b/Userland/Libraries/LibWeb/Layout/Box.h
index 7c7e0a4481..b4764704e9 100644
--- a/Userland/Libraries/LibWeb/Layout/Box.h
+++ b/Userland/Libraries/LibWeb/Layout/Box.h
@@ -20,6 +20,9 @@ struct LineBoxFragmentCoordinate {
class Box : public NodeWithStyleAndBoxModelMetrics {
public:
+ Painting::Box const* paint_box() const { return m_paint_box.ptr(); }
+ void set_paint_box(OwnPtr<Painting::Box>);
+
OwnPtr<Painting::Box> m_paint_box;
bool is_out_of_flow(FormattingContext const&) const;
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingState.cpp b/Userland/Libraries/LibWeb/Layout/FormattingState.cpp
index 3060a3ca34..6f0970faac 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingState.cpp
+++ b/Userland/Libraries/LibWeb/Layout/FormattingState.cpp
@@ -41,12 +41,18 @@ void FormattingState::commit()
// For boxes, transfer all the state needed for painting.
if (is<Layout::Box>(node)) {
auto& box = static_cast<Layout::Box&>(node);
- box.m_paint_box = Painting::Box::create(box);
+ box.set_paint_box([](Layout::Box const& layout_box) -> OwnPtr<Painting::Box> {
+ if (is<Layout::BlockContainer>(layout_box))
+ return Painting::BoxWithLines::create(static_cast<Layout::BlockContainer const&>(layout_box));
+ return Painting::Box::create(static_cast<Layout::Box const&>(layout_box));
+ }(box));
box.m_paint_box->set_offset(node_state.offset);
box.m_paint_box->set_content_size(node_state.content_width, node_state.content_height);
box.m_paint_box->set_overflow_data(move(node_state.overflow_data));
box.m_paint_box->set_containing_line_box_fragment(node_state.containing_line_box_fragment);
- box.m_paint_box->set_line_boxes(move(node_state.line_boxes));
+
+ if (is<Layout::BlockContainer>(box))
+ static_cast<Painting::BoxWithLines&>(*box.m_paint_box).set_line_boxes(move(node_state.line_boxes));
}
}
}
diff --git a/Userland/Libraries/LibWeb/Layout/InlineNode.cpp b/Userland/Libraries/LibWeb/Layout/InlineNode.cpp
index 6771458651..0234d410f1 100644
--- a/Userland/Libraries/LibWeb/Layout/InlineNode.cpp
+++ b/Userland/Libraries/LibWeb/Layout/InlineNode.cpp
@@ -130,7 +130,7 @@ void InlineNode::for_each_fragment(Callback callback)
{
// FIXME: This will be slow if the containing block has a lot of fragments!
Vector<LineBoxFragment const&> fragments;
- containing_block()->m_paint_box->for_each_fragment([&](auto& fragment) {
+ containing_block()->paint_box()->for_each_fragment([&](auto& fragment) {
if (is_inclusive_ancestor_of(fragment.layout_node()))
fragments.append(fragment);
return IterationDecision::Continue;
diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp
index e27ee86c92..835c737cd3 100644
--- a/Userland/Libraries/LibWeb/Layout/Node.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Node.cpp
@@ -112,7 +112,7 @@ InitialContainingBlock& Node::root()
void Node::set_needs_display()
{
if (auto* block = containing_block()) {
- block->m_paint_box->for_each_fragment([&](auto& fragment) {
+ block->paint_box()->for_each_fragment([&](auto& fragment) {
if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) {
browsing_context().set_needs_display(enclosing_int_rect(fragment.absolute_rect()));
}
@@ -128,7 +128,7 @@ Gfx::FloatPoint Node::box_type_agnostic_position() const
VERIFY(is_inline());
Gfx::FloatPoint position;
if (auto* block = containing_block()) {
- block->m_paint_box->for_each_fragment([&](auto& fragment) {
+ block->paint_box()->for_each_fragment([&](auto& fragment) {
if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) {
position = fragment.absolute_rect().location();
return IterationDecision::Break;
diff --git a/Userland/Libraries/LibWeb/Painting/Box.cpp b/Userland/Libraries/LibWeb/Painting/Box.cpp
index cc6e5d8786..a191eb9368 100644
--- a/Userland/Libraries/LibWeb/Painting/Box.cpp
+++ b/Userland/Libraries/LibWeb/Painting/Box.cpp
@@ -9,6 +9,24 @@
namespace Web::Painting {
+Box::Box(Layout::Box const& layout_box)
+ : m_layout_box(layout_box)
+{
+}
+
+Box::~Box()
+{
+}
+
+BoxWithLines::BoxWithLines(Layout::BlockContainer const& layout_box)
+ : Box(layout_box)
+{
+}
+
+BoxWithLines::~BoxWithLines()
+{
+}
+
void Box::set_offset(const Gfx::FloatPoint& offset)
{
if (m_offset == offset)
@@ -30,7 +48,7 @@ void Box::set_content_size(Gfx::FloatSize const& size)
Gfx::FloatPoint Box::effective_offset() const
{
if (m_containing_line_box_fragment.has_value()) {
- auto const& fragment = m_layout_box.containing_block()->m_paint_box->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index];
+ auto const& fragment = m_layout_box.containing_block()->paint_box()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index];
return fragment.offset();
}
return m_offset;
diff --git a/Userland/Libraries/LibWeb/Painting/Box.h b/Userland/Libraries/LibWeb/Painting/Box.h
index 874bb65f69..90a14e2251 100644
--- a/Userland/Libraries/LibWeb/Painting/Box.h
+++ b/Userland/Libraries/LibWeb/Painting/Box.h
@@ -20,10 +20,7 @@ public:
return adopt_own(*new Box(layout_box));
}
- explicit Box(Layout::Box const& layout_box)
- : m_layout_box(layout_box)
- {
- }
+ virtual ~Box();
Layout::Box const& m_layout_box;
@@ -39,11 +36,6 @@ public:
Gfx::FloatPoint m_offset;
Gfx::FloatSize m_content_size;
- Vector<Layout::LineBox> const& line_boxes() const { return m_line_boxes; }
- void set_line_boxes(Vector<Layout::LineBox>&& line_boxes) { m_line_boxes = move(line_boxes); }
-
- Vector<Layout::LineBox> m_line_boxes;
-
// Some boxes hang off of line box fragments. (inline-block, inline-table, replaced, etc)
Optional<Layout::LineBoxFragmentCoordinate> m_containing_line_box_fragment;
@@ -112,6 +104,29 @@ public:
void set_overflow_data(Optional<OverflowData> data) { m_overflow_data = move(data); }
void set_containing_line_box_fragment(Optional<Layout::LineBoxFragmentCoordinate>);
+ StackingContext* stacking_context() { return m_stacking_context; }
+ StackingContext const* stacking_context() const { return m_stacking_context; }
+ void set_stacking_context(NonnullOwnPtr<Painting::StackingContext> context) { m_stacking_context = move(context); }
+ StackingContext* enclosing_stacking_context();
+
+protected:
+ explicit Box(Layout::Box const&);
+
+private:
+ OwnPtr<Painting::StackingContext> m_stacking_context;
+};
+
+class BoxWithLines : public Box {
+public:
+ static NonnullOwnPtr<BoxWithLines> create(Layout::BlockContainer const& block_container)
+ {
+ return adopt_own(*new BoxWithLines(block_container));
+ }
+ virtual ~BoxWithLines() override;
+
+ Vector<Layout::LineBox> const& line_boxes() const { return m_line_boxes; }
+ void set_line_boxes(Vector<Layout::LineBox>&& line_boxes) { m_line_boxes = move(line_boxes); }
+
template<typename Callback>
void for_each_fragment(Callback callback) const
{
@@ -123,12 +138,10 @@ public:
}
}
- StackingContext* stacking_context() { return m_stacking_context; }
- StackingContext const* stacking_context() const { return m_stacking_context; }
- void set_stacking_context(NonnullOwnPtr<Painting::StackingContext> context) { m_stacking_context = move(context); }
- StackingContext* enclosing_stacking_context();
+private:
+ BoxWithLines(Layout::BlockContainer const&);
- OwnPtr<Painting::StackingContext> m_stacking_context;
+ Vector<Layout::LineBox> m_line_boxes;
};
}