ladybird/Libraries/LibWeb/Painting/Paintable.h
Andreas Kling 956a2b96d5 LibWeb: Allocate layout and painting objects with mimalloc
Add class-local allocation macros for operator new/delete through AK's
malloc helpers. The macros can optionally choose a HeapPartition.
Add Layout and Painting partitions, plus basic partition stats helpers.

Use the new partitions for LibWeb layout and painting object hierarchies
and layout-state side data.
2026-06-13 19:08:08 +02:00

187 lines
6.5 KiB
C++

/*
* Copyright (c) 2022-2023, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/RefCounted.h>
#include <AK/WeakPtr.h>
#include <AK/Weakable.h>
#include <AK/kmalloc.h>
#include <LibGC/Ptr.h>
#include <LibWeb/CSS/ComputedValues.h>
#include <LibWeb/CSS/Display.h>
#include <LibWeb/Export.h>
#include <LibWeb/Forward.h>
#include <LibWeb/InvalidateDisplayList.h>
#include <LibWeb/Painting/ChromeWidget.h>
#include <LibWeb/Painting/HitTestResult.h>
#include <LibWeb/Painting/ShadowData.h>
#include <LibWeb/PixelUnits.h>
#include <LibWeb/RefCountedTreeNode.h>
namespace Web::Painting {
enum class PaintPhase {
Background,
Border,
TableCollapsedBorder,
Foreground,
Outline,
Overlay,
};
class WEB_API Paintable
: public RefCounted<Paintable>
, public Weakable<Paintable>
, public RefCountedTreeNode<Paintable> {
public:
AK_ALLOC_WITH_KMALLOC_PARTITION(HeapPartition::Painting);
virtual ~Paintable();
virtual StringView class_name() const { return "Paintable"sv; }
[[nodiscard]] bool is_visible() const
{
auto const& cv = computed_values();
return cv.visibility() == CSS::Visibility::Visible && cv.opacity() != 0;
}
[[nodiscard]] bool is_positioned() const { return m_positioned; }
[[nodiscard]] bool is_fixed_position() const { return m_fixed_position; }
[[nodiscard]] bool is_sticky_position() const { return m_sticky_position; }
[[nodiscard]] bool is_absolutely_positioned() const { return m_absolutely_positioned; }
[[nodiscard]] bool is_floating() const { return m_floating; }
[[nodiscard]] bool is_inline() const { return m_inline; }
[[nodiscard]] CSS::Display display() const { return m_display; }
bool has_stacking_context() const;
RefPtr<StackingContext> enclosing_stacking_context();
virtual void paint(DisplayListRecordingContext&, PaintPhase) const { }
void paint_inspector_overlay(DisplayListRecordingContext&) const;
virtual bool forms_unconnected_subtree() const { return false; }
virtual bool handle_mousewheel(Badge<EventHandler>, CSSPixelPoint, unsigned buttons, unsigned modifiers, double wheel_delta_x, double wheel_delta_y);
Layout::Node const& layout_node() const
{
VERIFY(m_layout_node);
return *m_layout_node;
}
Layout::Node& layout_node() { return const_cast<Layout::Node&>(const_cast<Paintable const&>(*this).layout_node()); }
[[nodiscard]] GC::Ptr<DOM::Node> dom_node();
[[nodiscard]] GC::Ptr<DOM::Node const> dom_node() const;
void set_dom_node(GC::Ptr<DOM::Node>);
CSS::ImmutableComputedValues const& computed_values() const;
bool visible_for_hit_testing() const;
GC::Ptr<HTML::Navigable> navigable() const;
virtual void set_needs_repaint(InvalidateDisplayList = InvalidateDisplayList::Yes);
RefPtr<PaintableBox> containing_block() const;
template<typename T>
bool fast_is() const = delete;
[[nodiscard]] virtual bool is_navigable_container_viewport_paintable() const { return false; }
[[nodiscard]] virtual bool is_viewport_paintable() const { return false; }
[[nodiscard]] virtual bool is_paintable_box() const { return false; }
[[nodiscard]] virtual bool is_paintable_with_lines() const { return false; }
[[nodiscard]] virtual bool is_svg_paintable() const { return false; }
[[nodiscard]] virtual bool is_svg_svg_paintable() const { return false; }
[[nodiscard]] virtual bool is_svg_path_paintable() const { return false; }
[[nodiscard]] virtual bool is_svg_graphics_paintable() const { return false; }
[[nodiscard]] virtual bool is_text_paintable() const { return false; }
DOM::Document const& document() const;
DOM::Document& document();
CSSPixelPoint box_type_agnostic_position() const;
void scroll_ancestor_to_offset_into_view(size_t offset);
enum class SelectionState : u8 {
None, // No selection
Start, // Selection starts in this Node
End, // Selection ends in this Node
StartAndEnd, // Selection starts and ends in this Node
Full, // Selection starts before and ends after this Node
};
SelectionState selection_state() const { return m_selection_state; }
void set_selection_state(SelectionState state);
// https://drafts.csswg.org/css-pseudo-4/#highlight-styling
struct TextDecorationStyle {
Vector<CSS::TextDecorationLine> line;
CSS::TextDecorationStyle style;
Color color;
};
struct SelectionStyle {
Color background_color;
Optional<Color> text_color;
Optional<Vector<ShadowData>> text_shadow;
Optional<TextDecorationStyle> text_decoration;
bool has_styling() const
{
return background_color.alpha() > 0 || text_color.has_value() || text_shadow.has_value() || text_decoration.has_value();
}
};
[[nodiscard]] SelectionStyle selection_style() const;
[[nodiscard]] String debug_description() const;
friend class Layout::Node;
protected:
explicit Paintable(Layout::Node const&);
void paint_with_inspector_overlay_context(DisplayListRecordingContext&, Function<void()> const&) const;
bool has_layout_node() const { return m_layout_node; }
virtual void paint_inspector_overlay_internal(DisplayListRecordingContext&) const { }
Optional<WeakPtr<PaintableBox>> mutable m_containing_block;
private:
void detach_from_layout_node(Badge<Layout::Node>)
{
m_containing_block.clear();
m_layout_node.clear();
}
GC::Weak<DOM::Node> m_dom_node;
WeakPtr<Layout::Node const> m_layout_node;
SelectionState m_selection_state { SelectionState::None };
bool m_positioned : 1 { false };
bool m_fixed_position : 1 { false };
bool m_sticky_position : 1 { false };
bool m_absolutely_positioned : 1 { false };
bool m_floating : 1 { false };
bool m_inline : 1 { false };
CSS::Display m_display;
};
template<>
inline bool Paintable::fast_is<PaintableBox>() const { return is_paintable_box(); }
template<>
inline bool Paintable::fast_is<PaintableWithLines>() const { return is_paintable_with_lines(); }
template<>
inline bool Paintable::fast_is<TextPaintable>() const { return is_text_paintable(); }
WEB_API Painting::BorderRadiiData normalize_border_radii_data(Layout::Node const& node, CSSPixelRect const& border_rect, CSSPixelRect const& reference_rect, CSS::BorderRadiusData const& top_left_radius, CSS::BorderRadiusData const& top_right_radius, CSS::BorderRadiusData const& bottom_right_radius, CSS::BorderRadiusData const& bottom_left_radius);
}