LibWeb: Move painting logic from Layout::Viewport to ViewportPaintable

This commit is contained in:
Andreas Kling 2023-08-19 08:38:51 +02:00
parent c01c4b41e2
commit 8bb275f2ea
Notes: sideshowbarker 2024-07-16 23:57:20 +09:00
9 changed files with 54 additions and 48 deletions

View file

@ -46,6 +46,7 @@
#include <LibWeb/Layout/Viewport.h>
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Painting/ViewportPaintable.h>
namespace Web::CSS {
@ -834,9 +835,9 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
return IdentifierStyleValue::create(ValueID::None);
// The transform matrix is held by the StackingContext, so we need to make sure we have one first.
auto const* viewport = layout_node.document().layout_node();
auto const* viewport = layout_node.document().paintable_box();
VERIFY(viewport);
const_cast<Layout::Viewport&>(*viewport).build_stacking_context_tree_if_needed();
const_cast<Painting::ViewportPaintable&>(verify_cast<Painting::ViewportPaintable>(*viewport)).build_stacking_context_tree_if_needed();
VERIFY(layout_node.paintable());
auto const& paintable_box = verify_cast<Painting::PaintableBox const>(layout_node.paintable());

View file

@ -25,42 +25,6 @@ JS::GCPtr<Selection::Selection> Viewport::selection() const
return const_cast<DOM::Document&>(document()).get_selection();
}
void Viewport::build_stacking_context_tree_if_needed()
{
if (paintable_box()->stacking_context())
return;
build_stacking_context_tree();
}
void Viewport::build_stacking_context_tree()
{
paintable_box()->set_stacking_context(make<Painting::StackingContext>(*this, nullptr, 0));
size_t index_in_tree_order = 1;
for_each_in_subtree_of_type<Box>([&](Box& box) {
if (!box.paintable_box())
return IterationDecision::Continue;
box.paintable_box()->invalidate_stacking_context();
if (!box.establishes_stacking_context()) {
VERIFY(!box.paintable_box()->stacking_context());
return IterationDecision::Continue;
}
auto* parent_context = box.paintable_box()->enclosing_stacking_context();
VERIFY(parent_context);
box.paintable_box()->set_stacking_context(make<Painting::StackingContext>(box, parent_context, index_in_tree_order++));
return IterationDecision::Continue;
});
paintable_box()->stacking_context()->sort();
}
void Viewport::paint_all_phases(PaintContext& context)
{
build_stacking_context_tree_if_needed();
context.painter().translate(-context.device_viewport_rect().location().to_type<int>());
paintable_box()->stacking_context()->paint(context);
}
void Viewport::recompute_selection_states()
{
// 1. Start by resetting the selection state of all layout nodes to None.

View file

@ -21,17 +21,13 @@ public:
const DOM::Document& dom_node() const { return static_cast<const DOM::Document&>(*Node::dom_node()); }
void paint_all_phases(PaintContext&);
JS::GCPtr<Selection::Selection> selection() const;
void build_stacking_context_tree_if_needed();
void recompute_selection_states();
private:
virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
void build_stacking_context_tree();
virtual bool is_viewport() const override { return true; }
};

View file

@ -10,6 +10,7 @@
#include <LibWeb/Layout/Viewport.h>
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
#include <LibWeb/Painting/NestedBrowsingContextPaintable.h>
#include <LibWeb/Painting/ViewportPaintable.h>
namespace Web::Painting {
@ -43,8 +44,8 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha
auto* hosted_document = layout_box().dom_node().content_document_without_origin_check();
if (!hosted_document)
return;
auto* hosted_layout_tree = hosted_document->layout_node();
if (!hosted_layout_tree)
auto* hosted_paint_tree = hosted_document->paintable_box();
if (!hosted_paint_tree)
return;
context.painter().save();
@ -56,7 +57,7 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha
context.painter().translate(absolute_device_rect.x().value(), absolute_device_rect.y().value());
context.set_device_viewport_rect({ {}, context.enclosing_device_size(layout_box().dom_node().nested_browsing_context()->size()) });
const_cast<Layout::Viewport*>(hosted_layout_tree)->paint_all_phases(context);
const_cast<ViewportPaintable&>(verify_cast<ViewportPaintable>(*hosted_paint_tree)).paint_all_phases(context);
context.set_device_viewport_rect(old_viewport_rect);
context.painter().restore();

View file

@ -15,6 +15,7 @@
#include <LibWeb/Painting/FilterPainting.h>
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Painting/ViewportPaintable.h>
#include <LibWeb/Platform/FontPlugin.h>
namespace Web::Painting {
@ -739,7 +740,7 @@ Optional<HitTestResult> PaintableBox::hit_test(CSSPixelPoint position, HitTestTy
return {};
if (layout_box().is_viewport()) {
const_cast<Layout::Viewport&>(static_cast<Layout::Viewport const&>(layout_box())).build_stacking_context_tree_if_needed();
const_cast<ViewportPaintable&>(static_cast<ViewportPaintable const&>(*this)).build_stacking_context_tree_if_needed();
return stacking_context()->hit_test(position, type);
}

View file

@ -5,6 +5,7 @@
*/
#include <LibWeb/Layout/Viewport.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Painting/ViewportPaintable.h>
namespace Web::Painting {
@ -21,4 +22,39 @@ ViewportPaintable::ViewportPaintable(Layout::Viewport const& layout_viewport)
ViewportPaintable::~ViewportPaintable() = default;
void ViewportPaintable::build_stacking_context_tree_if_needed()
{
if (stacking_context())
return;
build_stacking_context_tree();
}
void ViewportPaintable::build_stacking_context_tree()
{
set_stacking_context(make<StackingContext>(layout_box(), nullptr, 0));
size_t index_in_tree_order = 1;
for_each_in_subtree_of_type<PaintableBox>([&](PaintableBox const& paintable) {
auto& paintable_box = const_cast<PaintableBox&>(paintable);
paintable_box.invalidate_stacking_context();
if (!paintable_box.layout_box().establishes_stacking_context()) {
VERIFY(!paintable_box.stacking_context());
return TraversalDecision::Continue;
}
auto* parent_context = paintable_box.enclosing_stacking_context();
VERIFY(parent_context);
paintable_box.set_stacking_context(make<Painting::StackingContext>(paintable_box.layout_box(), parent_context, index_in_tree_order++));
return TraversalDecision::Continue;
});
stacking_context()->sort();
}
void ViewportPaintable::paint_all_phases(PaintContext& context)
{
build_stacking_context_tree_if_needed();
context.painter().translate(-context.device_viewport_rect().location().to_type<int>());
stacking_context()->paint(context);
}
}

View file

@ -17,7 +17,12 @@ public:
static JS::NonnullGCPtr<ViewportPaintable> create(Layout::Viewport const&);
virtual ~ViewportPaintable() override;
void paint_all_phases(PaintContext&);
void build_stacking_context_tree_if_needed();
private:
void build_stacking_context_tree();
explicit ViewportPaintable(Layout::Viewport const&);
};

View file

@ -12,6 +12,7 @@
#include <LibWeb/HTML/Parser/HTMLParser.h>
#include <LibWeb/Layout/Viewport.h>
#include <LibWeb/Painting/PaintContext.h>
#include <LibWeb/Painting/ViewportPaintable.h>
#include <LibWeb/SVG/SVGDecodedImageData.h>
#include <LibWeb/SVG/SVGSVGElement.h>
@ -99,7 +100,7 @@ void SVGDecodedImageData::render(Gfx::IntSize size) const
Gfx::Painter painter(*m_bitmap);
PaintContext context(painter, m_page_client->palette(), m_page_client->device_pixels_per_css_pixel());
m_document->layout_node()->paint_all_phases(context);
verify_cast<Painting::ViewportPaintable>(*m_document->paintable_box()).paint_all_phases(context);
}
RefPtr<Gfx::Bitmap const> SVGDecodedImageData::bitmap(size_t, Gfx::IntSize size) const

View file

@ -14,6 +14,7 @@
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/Layout/Viewport.h>
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/ViewportPaintable.h>
#include <LibWeb/Platform/Timer.h>
#include <WebContent/WebContentClientEndpoint.h>
#include <WebContent/WebDriverConnection.h>
@ -139,7 +140,7 @@ void PageHost::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& targ
context.set_should_show_line_box_borders(m_should_show_line_box_borders);
context.set_device_viewport_rect(content_rect);
context.set_has_focus(m_has_focus);
layout_root->paint_all_phases(context);
verify_cast<Web::Painting::ViewportPaintable>(*layout_root->paintable_box()).paint_all_phases(context);
}
void PageHost::set_viewport_rect(Web::DevicePixelRect const& rect)