1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-17 11:47:37 +00:00

LibWeb: Split Paintable into Paintable and PaintableBox

To prepare for paintable inline content, we take the basic painting
functionality and hoist it into a base class.
This commit is contained in:
Andreas Kling 2022-03-10 15:50:57 +01:00
parent 0500dbc3f6
commit 053766d79c
34 changed files with 133 additions and 95 deletions

View file

@ -1010,7 +1010,7 @@ size_t Node::length() const
return child_count(); return child_count();
} }
Painting::Paintable const* Node::paint_box() const Painting::PaintableBox const* Node::paint_box() const
{ {
if (!layout_node()) if (!layout_node())
return nullptr; return nullptr;

View file

@ -158,7 +158,7 @@ public:
const Layout::Node* layout_node() const { return m_layout_node; } const Layout::Node* layout_node() const { return m_layout_node; }
Layout::Node* layout_node() { return m_layout_node; } Layout::Node* layout_node() { return m_layout_node; }
Painting::Paintable const* paint_box() const; Painting::PaintableBox const* paint_box() const;
void set_layout_node(Badge<Layout::Node>, Layout::Node*) const; void set_layout_node(Badge<Layout::Node>, Layout::Node*) const;

View file

@ -266,6 +266,7 @@ class PerformanceTiming;
namespace Web::Painting { namespace Web::Painting {
enum class PaintPhase; enum class PaintPhase;
class Paintable; class Paintable;
class PaintableBox;
class PaintableWithLines; class PaintableWithLines;
} }

View file

@ -34,11 +34,6 @@ Box::~Box()
{ {
} }
void Box::set_paint_box(OwnPtr<Painting::Paintable> paint_box)
{
m_paint_box = move(paint_box);
}
// https://www.w3.org/TR/css-display-3/#out-of-flow // https://www.w3.org/TR/css-display-3/#out-of-flow
bool Box::is_out_of_flow(FormattingContext const& formatting_context) const bool Box::is_out_of_flow(FormattingContext const& formatting_context) const
{ {
@ -93,7 +88,12 @@ bool Box::is_body() const
OwnPtr<Painting::Paintable> Box::create_paintable() const OwnPtr<Painting::Paintable> Box::create_paintable() const
{ {
return Painting::Paintable::create(*this); return Painting::PaintableBox::create(*this);
}
Painting::PaintableBox const* Box::paint_box() const
{
return static_cast<Painting::PaintableBox const*>(Node::paintable());
} }
} }

View file

@ -20,10 +20,7 @@ struct LineBoxFragmentCoordinate {
class Box : public NodeWithStyleAndBoxModelMetrics { class Box : public NodeWithStyleAndBoxModelMetrics {
public: public:
Painting::Paintable const* paint_box() const { return m_paint_box.ptr(); } Painting::PaintableBox const* paint_box() const;
void set_paint_box(OwnPtr<Painting::Paintable>);
OwnPtr<Painting::Paintable> m_paint_box;
bool is_out_of_flow(FormattingContext const&) const; bool is_out_of_flow(FormattingContext const&) const;
@ -44,7 +41,7 @@ public:
virtual void did_set_rect() { } virtual void did_set_rect() { }
virtual OwnPtr<Painting::Paintable> create_paintable() const; virtual OwnPtr<Painting::Paintable> create_paintable() const override;
protected: protected:
Box(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>); Box(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);

View file

@ -38,17 +38,19 @@ void FormattingState::commit()
node.box_model().border = { node_state.border_top, node_state.border_right, node_state.border_bottom, node_state.border_left }; node.box_model().border = { node_state.border_top, node_state.border_right, node_state.border_bottom, node_state.border_left };
node.box_model().margin = { node_state.margin_top, node_state.margin_right, node_state.margin_bottom, node_state.margin_left }; node.box_model().margin = { node_state.margin_top, node_state.margin_right, node_state.margin_bottom, node_state.margin_left };
node.set_paintable(node.create_paintable());
// For boxes, transfer all the state needed for painting. // For boxes, transfer all the state needed for painting.
if (is<Layout::Box>(node)) { if (is<Layout::Box>(node)) {
auto& box = static_cast<Layout::Box&>(node); auto& box = static_cast<Layout::Box&>(node);
box.set_paint_box(box.create_paintable()); auto& paint_box = const_cast<Painting::PaintableBox&>(*box.paint_box());
box.m_paint_box->set_offset(node_state.offset); paint_box.set_offset(node_state.offset);
box.m_paint_box->set_content_size(node_state.content_width, node_state.content_height); 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)); 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); paint_box.set_containing_line_box_fragment(node_state.containing_line_box_fragment);
if (is<Layout::BlockContainer>(box)) if (is<Layout::BlockContainer>(box))
static_cast<Painting::PaintableWithLines&>(*box.m_paint_box).set_line_boxes(move(node_state.line_boxes)); static_cast<Painting::PaintableWithLines&>(paint_box).set_line_boxes(move(node_state.line_boxes));
} }
} }
} }

View file

@ -55,12 +55,12 @@ struct FormattingState {
float border_box_width() const { return border_box_left() + content_width + border_box_right(); } float border_box_width() const { return border_box_left() + content_width + border_box_right(); }
float border_box_height() const { return border_box_top() + content_height + border_box_bottom(); } float border_box_height() const { return border_box_top() + content_height + border_box_bottom(); }
Optional<Painting::Paintable::OverflowData> overflow_data; Optional<Painting::PaintableBox::OverflowData> overflow_data;
Painting::Paintable::OverflowData& ensure_overflow_data() Painting::PaintableBox::OverflowData& ensure_overflow_data()
{ {
if (!overflow_data.has_value()) if (!overflow_data.has_value())
overflow_data = Painting::Paintable::OverflowData {}; overflow_data = Painting::PaintableBox::OverflowData {};
return *overflow_data; return *overflow_data;
} }

View file

@ -33,9 +33,9 @@ void InitialContainingBlock::build_stacking_context_tree()
VERIFY(!box.paint_box()->stacking_context()); VERIFY(!box.paint_box()->stacking_context());
return IterationDecision::Continue; return IterationDecision::Continue;
} }
auto* parent_context = const_cast<Painting::Paintable*>(box.paint_box())->enclosing_stacking_context(); auto* parent_context = const_cast<Painting::PaintableBox*>(box.paint_box())->enclosing_stacking_context();
VERIFY(parent_context); VERIFY(parent_context);
const_cast<Painting::Paintable*>(box.paint_box())->set_stacking_context(make<Painting::StackingContext>(box, parent_context)); const_cast<Painting::PaintableBox*>(box.paint_box())->set_stacking_context(make<Painting::StackingContext>(box, parent_context));
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
} }

View file

@ -584,4 +584,14 @@ NonnullRefPtr<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
return wrapper; return wrapper;
} }
void Node::set_paintable(OwnPtr<Painting::Paintable> paintable)
{
m_paintable = move(paintable);
}
OwnPtr<Painting::Paintable> Node::create_paintable() const
{
return nullptr;
}
} }

View file

@ -54,6 +54,11 @@ public:
const DOM::Node* dom_node() const { return m_dom_node; } const DOM::Node* dom_node() const { return m_dom_node; }
DOM::Node* dom_node() { return m_dom_node; } DOM::Node* dom_node() { return m_dom_node; }
Painting::Paintable const* paintable() const { return m_paintable; }
void set_paintable(OwnPtr<Painting::Paintable>);
virtual OwnPtr<Painting::Paintable> create_paintable() const;
DOM::Document& document() { return m_document; } DOM::Document& document() { return m_document; }
const DOM::Document& document() const { return m_document; } const DOM::Document& document() const { return m_document; }
@ -219,6 +224,7 @@ private:
NonnullRefPtr<DOM::Document> m_document; NonnullRefPtr<DOM::Document> m_document;
RefPtr<DOM::Node> m_dom_node; RefPtr<DOM::Node> m_dom_node;
OwnPtr<Painting::Paintable> m_paintable;
bool m_inline { false }; bool m_inline { false };
bool m_has_style { false }; bool m_has_style { false };

View file

@ -16,13 +16,13 @@ NonnullOwnPtr<ButtonPaintable> ButtonPaintable::create(Layout::ButtonBox const&
} }
ButtonPaintable::ButtonPaintable(Layout::ButtonBox const& layout_box) ButtonPaintable::ButtonPaintable(Layout::ButtonBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::ButtonBox const& ButtonPaintable::layout_box() const Layout::ButtonBox const& ButtonPaintable::layout_box() const
{ {
return static_cast<Layout::ButtonBox const&>(m_layout_box); return static_cast<Layout::ButtonBox const&>(layout_node());
} }
void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
@ -30,7 +30,7 @@ void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
if (!is_visible()) if (!is_visible())
return; return;
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) { if (phase == PaintPhase::Foreground) {
auto text_rect = enclosing_int_rect(absolute_rect()); auto text_rect = enclosing_int_rect(absolute_rect());

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class ButtonPaintable final : public Paintable { class ButtonPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<ButtonPaintable> create(Layout::ButtonBox const&); static NonnullOwnPtr<ButtonPaintable> create(Layout::ButtonBox const&);

View file

@ -14,13 +14,13 @@ NonnullOwnPtr<CanvasPaintable> CanvasPaintable::create(Layout::CanvasBox const&
} }
CanvasPaintable::CanvasPaintable(Layout::CanvasBox const& layout_box) CanvasPaintable::CanvasPaintable(Layout::CanvasBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::CanvasBox const& CanvasPaintable::layout_box() const Layout::CanvasBox const& CanvasPaintable::layout_box() const
{ {
return static_cast<Layout::CanvasBox const&>(m_layout_box); return static_cast<Layout::CanvasBox const&>(layout_node());
} }
void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const
@ -28,7 +28,7 @@ void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const
if (!layout_box().is_visible()) if (!layout_box().is_visible())
return; return;
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) { if (phase == PaintPhase::Foreground) {
// FIXME: This should be done at a different level. Also rect() does not include padding etc! // FIXME: This should be done at a different level. Also rect() does not include padding etc!

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class CanvasPaintable final : public Paintable { class CanvasPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<CanvasPaintable> create(Layout::CanvasBox const&); static NonnullOwnPtr<CanvasPaintable> create(Layout::CanvasBox const&);

View file

@ -17,13 +17,13 @@ NonnullOwnPtr<CheckBoxPaintable> CheckBoxPaintable::create(Layout::CheckBox cons
} }
CheckBoxPaintable::CheckBoxPaintable(Layout::CheckBox const& layout_box) CheckBoxPaintable::CheckBoxPaintable(Layout::CheckBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::CheckBox const& CheckBoxPaintable::layout_box() const Layout::CheckBox const& CheckBoxPaintable::layout_box() const
{ {
return static_cast<Layout::CheckBox const&>(m_layout_box); return static_cast<Layout::CheckBox const&>(layout_node());
} }
void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const
@ -31,7 +31,7 @@ void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const
if (!is_visible()) if (!is_visible())
return; return;
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) if (phase == PaintPhase::Foreground)
Gfx::StylePainter::paint_check_box(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), layout_box().dom_node().enabled(), layout_box().dom_node().checked(), layout_box().being_pressed()); Gfx::StylePainter::paint_check_box(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), layout_box().dom_node().enabled(), layout_box().dom_node().checked(), layout_box().being_pressed());

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class CheckBoxPaintable final : public Paintable { class CheckBoxPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<CheckBoxPaintable> create(Layout::CheckBox const&); static NonnullOwnPtr<CheckBoxPaintable> create(Layout::CheckBox const&);

View file

@ -17,13 +17,13 @@ NonnullOwnPtr<ImagePaintable> ImagePaintable::create(Layout::ImageBox const& lay
} }
ImagePaintable::ImagePaintable(Layout::ImageBox const& layout_box) ImagePaintable::ImagePaintable(Layout::ImageBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::ImageBox const& ImagePaintable::layout_box() const Layout::ImageBox const& ImagePaintable::layout_box() const
{ {
return static_cast<Layout::ImageBox const&>(m_layout_box); return static_cast<Layout::ImageBox const&>(layout_node());
} }
void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const
@ -35,7 +35,7 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const
if (!context.viewport_rect().intersects(enclosing_int_rect(absolute_rect()))) if (!context.viewport_rect().intersects(enclosing_int_rect(absolute_rect())))
return; return;
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) { if (phase == PaintPhase::Foreground) {
if (layout_box().renders_as_alt_text()) { if (layout_box().renders_as_alt_text()) {

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class ImagePaintable final : public Paintable { class ImagePaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<ImagePaintable> create(Layout::ImageBox const&); static NonnullOwnPtr<ImagePaintable> create(Layout::ImageBox const&);

View file

@ -16,13 +16,13 @@ NonnullOwnPtr<MarkerPaintable> MarkerPaintable::create(Layout::ListItemMarkerBox
} }
MarkerPaintable::MarkerPaintable(Layout::ListItemMarkerBox const& layout_box) MarkerPaintable::MarkerPaintable(Layout::ListItemMarkerBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::ListItemMarkerBox const& MarkerPaintable::layout_box() const Layout::ListItemMarkerBox const& MarkerPaintable::layout_box() const
{ {
return static_cast<Layout::ListItemMarkerBox const&>(m_layout_box); return static_cast<Layout::ListItemMarkerBox const&>(layout_node());
} }
void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class MarkerPaintable final : public Paintable { class MarkerPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<MarkerPaintable> create(Layout::ListItemMarkerBox const&); static NonnullOwnPtr<MarkerPaintable> create(Layout::ListItemMarkerBox const&);

View file

@ -18,18 +18,18 @@ NonnullOwnPtr<NestedBrowsingContextPaintable> NestedBrowsingContextPaintable::cr
} }
NestedBrowsingContextPaintable::NestedBrowsingContextPaintable(Layout::FrameBox const& layout_box) NestedBrowsingContextPaintable::NestedBrowsingContextPaintable(Layout::FrameBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::FrameBox const& NestedBrowsingContextPaintable::layout_box() const Layout::FrameBox const& NestedBrowsingContextPaintable::layout_box() const
{ {
return static_cast<Layout::FrameBox const&>(m_layout_box); return static_cast<Layout::FrameBox const&>(layout_node());
} }
void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase phase) const void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase phase) const
{ {
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) { if (phase == PaintPhase::Foreground) {
auto* hosted_document = layout_box().dom_node().content_document_without_origin_check(); auto* hosted_document = layout_box().dom_node().content_document_without_origin_check();

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class NestedBrowsingContextPaintable final : public Paintable { class NestedBrowsingContextPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<NestedBrowsingContextPaintable> create(Layout::FrameBox const&); static NonnullOwnPtr<NestedBrowsingContextPaintable> create(Layout::FrameBox const&);

View file

@ -13,17 +13,22 @@
namespace Web::Painting { namespace Web::Painting {
Paintable::Paintable(Layout::Box const& layout_box) NonnullOwnPtr<PaintableBox> PaintableBox::create(Layout::Box const& layout_box)
: m_layout_box(layout_box) {
return adopt_own(*new PaintableBox(layout_box));
}
PaintableBox::PaintableBox(Layout::Box const& layout_box)
: Paintable(layout_box)
{ {
} }
Paintable::~Paintable() PaintableBox::~PaintableBox()
{ {
} }
PaintableWithLines::PaintableWithLines(Layout::BlockContainer const& layout_box) PaintableWithLines::PaintableWithLines(Layout::BlockContainer const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
@ -31,7 +36,7 @@ PaintableWithLines::~PaintableWithLines()
{ {
} }
void Paintable::set_offset(const Gfx::FloatPoint& offset) void PaintableBox::set_offset(const Gfx::FloatPoint& offset)
{ {
if (m_offset == offset) if (m_offset == offset)
return; return;
@ -40,7 +45,7 @@ void Paintable::set_offset(const Gfx::FloatPoint& offset)
const_cast<Layout::Box&>(layout_box()).did_set_rect(); const_cast<Layout::Box&>(layout_box()).did_set_rect();
} }
void Paintable::set_content_size(Gfx::FloatSize const& size) void PaintableBox::set_content_size(Gfx::FloatSize const& size)
{ {
if (m_content_size == size) if (m_content_size == size)
return; return;
@ -49,7 +54,7 @@ void Paintable::set_content_size(Gfx::FloatSize const& size)
const_cast<Layout::Box&>(layout_box()).did_set_rect(); const_cast<Layout::Box&>(layout_box()).did_set_rect();
} }
Gfx::FloatPoint Paintable::effective_offset() const Gfx::FloatPoint PaintableBox::effective_offset() const
{ {
if (m_containing_line_box_fragment.has_value()) { if (m_containing_line_box_fragment.has_value()) {
auto const& fragment = layout_box().containing_block()->paint_box()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index]; auto const& fragment = layout_box().containing_block()->paint_box()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index];
@ -58,7 +63,7 @@ Gfx::FloatPoint Paintable::effective_offset() const
return m_offset; return m_offset;
} }
Gfx::FloatRect Paintable::absolute_rect() const Gfx::FloatRect PaintableBox::absolute_rect() const
{ {
Gfx::FloatRect rect { effective_offset(), content_size() }; Gfx::FloatRect rect { effective_offset(), content_size() };
for (auto* block = layout_box().containing_block(); block; block = block->containing_block()) for (auto* block = layout_box().containing_block(); block; block = block->containing_block())
@ -66,12 +71,12 @@ Gfx::FloatRect Paintable::absolute_rect() const
return rect; return rect;
} }
void Paintable::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;
} }
Painting::StackingContext* Paintable::enclosing_stacking_context() Painting::StackingContext* PaintableBox::enclosing_stacking_context()
{ {
for (auto* ancestor = layout_box().parent(); ancestor; ancestor = ancestor->parent()) { for (auto* ancestor = layout_box().parent(); ancestor; ancestor = ancestor->parent()) {
if (!is<Layout::Box>(ancestor)) if (!is<Layout::Box>(ancestor))
@ -86,7 +91,7 @@ Painting::StackingContext* Paintable::enclosing_stacking_context()
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
void Paintable::paint(PaintContext& context, PaintPhase phase) const void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
{ {
if (!is_visible()) if (!is_visible())
return; return;
@ -145,7 +150,7 @@ void Paintable::paint(PaintContext& context, PaintPhase phase) const
} }
} }
void Paintable::paint_border(PaintContext& context) const void PaintableBox::paint_border(PaintContext& context) const
{ {
auto borders_data = BordersData { auto borders_data = BordersData {
.top = computed_values().border_top(), .top = computed_values().border_top(),
@ -156,7 +161,7 @@ void Paintable::paint_border(PaintContext& context) const
paint_all_borders(context, absolute_border_box_rect(), normalized_border_radius_data(), borders_data); paint_all_borders(context, absolute_border_box_rect(), normalized_border_radius_data(), borders_data);
} }
void Paintable::paint_background(PaintContext& context) const void PaintableBox::paint_background(PaintContext& context) const
{ {
// If the body's background properties were propagated to the root element, do no re-paint the body's background. // If the body's background properties were propagated to the root element, do no re-paint the body's background.
if (layout_box().is_body() && document().html_element()->should_use_body_background_properties()) if (layout_box().is_body() && document().html_element()->should_use_body_background_properties())
@ -188,7 +193,7 @@ void Paintable::paint_background(PaintContext& context) const
Painting::paint_background(context, layout_box(), background_rect, background_color, background_layers, normalized_border_radius_data()); Painting::paint_background(context, layout_box(), background_rect, background_color, background_layers, normalized_border_radius_data());
} }
void Paintable::paint_box_shadow(PaintContext& context) const void PaintableBox::paint_box_shadow(PaintContext& context) 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())
@ -208,7 +213,7 @@ void Paintable::paint_box_shadow(PaintContext& context) const
Painting::paint_box_shadow(context, enclosing_int_rect(absolute_border_box_rect()), resolved_box_shadow_data); Painting::paint_box_shadow(context, enclosing_int_rect(absolute_border_box_rect()), resolved_box_shadow_data);
} }
BorderRadiusData Paintable::normalized_border_radius_data() const BorderRadiusData PaintableBox::normalized_border_radius_data() const
{ {
return Painting::normalized_border_radius_data(layout_box(), absolute_border_box_rect(), return Painting::normalized_border_radius_data(layout_box(), absolute_border_box_rect(),
computed_values().border_top_left_radius(), computed_values().border_top_left_radius(),
@ -217,7 +222,7 @@ BorderRadiusData Paintable::normalized_border_radius_data() const
computed_values().border_bottom_left_radius()); computed_values().border_bottom_left_radius());
} }
void Paintable::before_children_paint(PaintContext& context, PaintPhase) const void PaintableBox::before_children_paint(PaintContext& context, PaintPhase) const
{ {
// FIXME: Support more overflow variations. // FIXME: Support more overflow variations.
if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) { if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) {
@ -226,7 +231,7 @@ void Paintable::before_children_paint(PaintContext& context, PaintPhase) const
} }
} }
void Paintable::after_children_paint(PaintContext& context, PaintPhase) const void PaintableBox::after_children_paint(PaintContext& context, PaintPhase) const
{ {
// FIXME: Support more overflow variations. // FIXME: Support more overflow variations.
if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden)
@ -238,7 +243,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
if (!is_visible()) if (!is_visible())
return; return;
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (m_line_boxes.is_empty()) if (m_line_boxes.is_empty())
return; return;

View file

@ -14,21 +14,38 @@
namespace Web::Painting { namespace Web::Painting {
class Paintable { class Paintable {
AK_MAKE_NONMOVABLE(Paintable);
AK_MAKE_NONCOPYABLE(Paintable);
public: public:
static NonnullOwnPtr<Paintable> create(Layout::Box const& layout_box) virtual ~Paintable() = default;
virtual void paint(PaintContext&, PaintPhase) const { }
virtual void before_children_paint(PaintContext&, PaintPhase) const { }
virtual void after_children_paint(PaintContext&, PaintPhase) const { }
Layout::Node const& layout_node() const { return m_layout_node; }
protected:
explicit Paintable(Layout::Node const& layout_node)
: m_layout_node(layout_node)
{ {
return adopt_own(*new Paintable(layout_box));
} }
virtual ~Paintable(); private:
Layout::Node const& m_layout_node;
};
virtual void paint(PaintContext&, PaintPhase) const; class PaintableBox : public Paintable {
public:
static NonnullOwnPtr<PaintableBox> create(Layout::Box const&);
virtual ~PaintableBox();
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(); }
Layout::Box const& m_layout_box; Layout::Box const& layout_box() const { return static_cast<Layout::Box const&>(Paintable::layout_node()); }
Layout::Box const& layout_box() const { return m_layout_box; }
auto const& box_model() const { return layout_box().box_model(); } auto const& box_model() const { return layout_box().box_model(); }
auto const& computed_values() const { return layout_box().computed_values(); } auto const& computed_values() const { return layout_box().computed_values(); }
@ -118,11 +135,11 @@ public:
DOM::Node const* dom_node() const { return layout_box().dom_node(); } DOM::Node const* dom_node() const { return layout_box().dom_node(); }
DOM::Document const& document() const { return layout_box().document(); } DOM::Document const& document() const { return layout_box().document(); }
virtual void before_children_paint(PaintContext&, PaintPhase) const; virtual void before_children_paint(PaintContext&, PaintPhase) const override;
virtual void after_children_paint(PaintContext&, PaintPhase) const; virtual void after_children_paint(PaintContext&, PaintPhase) const override;
protected: protected:
explicit Paintable(Layout::Box const&); explicit PaintableBox(Layout::Box const&);
virtual void paint_border(PaintContext&) const; virtual void paint_border(PaintContext&) const;
virtual void paint_background(PaintContext&) const; virtual void paint_background(PaintContext&) const;
@ -134,7 +151,7 @@ private:
OwnPtr<Painting::StackingContext> m_stacking_context; OwnPtr<Painting::StackingContext> m_stacking_context;
}; };
class PaintableWithLines : public Paintable { class PaintableWithLines : public PaintableBox {
public: public:
static NonnullOwnPtr<PaintableWithLines> create(Layout::BlockContainer const& block_container) static NonnullOwnPtr<PaintableWithLines> create(Layout::BlockContainer const& block_container)
{ {

View file

@ -15,13 +15,13 @@ NonnullOwnPtr<ProgressPaintable> ProgressPaintable::create(Layout::Progress cons
} }
ProgressPaintable::ProgressPaintable(Layout::Progress const& layout_box) ProgressPaintable::ProgressPaintable(Layout::Progress const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::Progress const& ProgressPaintable::layout_box() const Layout::Progress const& ProgressPaintable::layout_box() const
{ {
return static_cast<Layout::Progress const&>(m_layout_box); return static_cast<Layout::Progress const&>(layout_node());
} }
void ProgressPaintable::paint(PaintContext& context, PaintPhase phase) const void ProgressPaintable::paint(PaintContext& context, PaintPhase phase) const

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class ProgressPaintable final : public Paintable { class ProgressPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<ProgressPaintable> create(Layout::Progress const&); static NonnullOwnPtr<ProgressPaintable> create(Layout::Progress const&);

View file

@ -17,13 +17,13 @@ NonnullOwnPtr<RadioButtonPaintable> RadioButtonPaintable::create(Layout::RadioBu
} }
RadioButtonPaintable::RadioButtonPaintable(Layout::RadioButton const& layout_box) RadioButtonPaintable::RadioButtonPaintable(Layout::RadioButton const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::RadioButton const& RadioButtonPaintable::layout_box() const Layout::RadioButton const& RadioButtonPaintable::layout_box() const
{ {
return static_cast<Layout::RadioButton const&>(m_layout_box); return static_cast<Layout::RadioButton const&>(layout_node());
} }
void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
@ -31,7 +31,7 @@ void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
if (!is_visible()) if (!is_visible())
return; return;
Paintable::paint(context, phase); PaintableBox::paint(context, phase);
if (phase == PaintPhase::Foreground) if (phase == PaintPhase::Foreground)
Gfx::StylePainter::paint_radio_button(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), layout_box().dom_node().checked(), layout_box().being_pressed()); Gfx::StylePainter::paint_radio_button(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), layout_box().dom_node().checked(), layout_box().being_pressed());

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class RadioButtonPaintable final : public Paintable { class RadioButtonPaintable final : public PaintableBox {
public: public:
static NonnullOwnPtr<RadioButtonPaintable> create(Layout::RadioButton const&); static NonnullOwnPtr<RadioButtonPaintable> create(Layout::RadioButton const&);

View file

@ -23,7 +23,7 @@ SVGGeometryPaintable::SVGGeometryPaintable(Layout::SVGGeometryBox const& layout_
Layout::SVGGeometryBox const& SVGGeometryPaintable::layout_box() const Layout::SVGGeometryBox const& SVGGeometryPaintable::layout_box() const
{ {
return static_cast<Layout::SVGGeometryBox const&>(m_layout_box); return static_cast<Layout::SVGGeometryBox const&>(layout_node());
} }
void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const

View file

@ -16,7 +16,7 @@ SVGGraphicsPaintable::SVGGraphicsPaintable(Layout::SVGGraphicsBox const& layout_
Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const
{ {
return static_cast<Layout::SVGGraphicsBox const&>(m_layout_box); return static_cast<Layout::SVGGraphicsBox const&>(layout_node());
} }
void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const

View file

@ -10,18 +10,18 @@
namespace Web::Painting { namespace Web::Painting {
SVGPaintable::SVGPaintable(Layout::SVGBox const& layout_box) SVGPaintable::SVGPaintable(Layout::SVGBox const& layout_box)
: Paintable(layout_box) : PaintableBox(layout_box)
{ {
} }
Layout::SVGBox const& SVGPaintable::layout_box() const Layout::SVGBox const& SVGPaintable::layout_box() const
{ {
return static_cast<Layout::SVGBox const&>(m_layout_box); return static_cast<Layout::SVGBox const&>(layout_node());
} }
void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const
{ {
Paintable::before_children_paint(context, phase); PaintableBox::before_children_paint(context, phase);
if (phase != PaintPhase::Foreground) if (phase != PaintPhase::Foreground)
return; return;
context.svg_context().save(); context.svg_context().save();
@ -29,7 +29,7 @@ void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase
void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const
{ {
Paintable::after_children_paint(context, phase); PaintableBox::after_children_paint(context, phase);
if (phase != PaintPhase::Foreground) if (phase != PaintPhase::Foreground)
return; return;
context.svg_context().restore(); context.svg_context().restore();

View file

@ -11,7 +11,7 @@
namespace Web::Painting { namespace Web::Painting {
class SVGPaintable : public Paintable { class SVGPaintable : public PaintableBox {
public: public:
static NonnullOwnPtr<SVGPaintable> create(Layout::SVGBox const&); static NonnullOwnPtr<SVGPaintable> create(Layout::SVGBox const&);

View file

@ -16,7 +16,7 @@ SVGSVGPaintable::SVGSVGPaintable(Layout::SVGSVGBox const& layout_box)
Layout::SVGSVGBox const& SVGSVGPaintable::layout_box() const Layout::SVGSVGBox const& SVGSVGPaintable::layout_box() const
{ {
return static_cast<Layout::SVGSVGBox const&>(m_layout_box); return static_cast<Layout::SVGSVGBox const&>(layout_node());
} }
void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const

View file

@ -47,8 +47,8 @@ StackingContext::StackingContext(Layout::Box& box, StackingContext* parent)
void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const
{ {
if (phase == StackingContextPaintPhase::Foreground) { if (phase == StackingContextPaintPhase::Foreground) {
if (box.is_box()) if (auto* paintable = box.paintable())
static_cast<Layout::Box const&>(box).m_paint_box->before_children_paint(context, PaintPhase::Foreground); paintable->before_children_paint(context, PaintPhase::Foreground);
} }
box.for_each_child([&](auto& child) { box.for_each_child([&](auto& child) {
@ -100,8 +100,8 @@ void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box
}); });
if (phase == StackingContextPaintPhase::Foreground) { if (phase == StackingContextPaintPhase::Foreground) {
if (box.is_box()) if (auto* paintable = box.paintable())
static_cast<Layout::Box const&>(box).m_paint_box->after_children_paint(context, PaintPhase::Foreground); paintable->after_children_paint(context, PaintPhase::Foreground);
} }
} }