1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:18:11 +00:00
serenity/Userland/Libraries/LibWeb/Painting/Paintable.h
Andreas Kling b14c6eaef3 LibWeb: Let paintables cache their containing block and absolute rect
The absolute rect of a paintable is somewhat expensive to compute. This
is because all coordinates are relative to the nearest containing block,
so we have to traverse the containing block chain and apply each offset
to get the final rect.

Paintables will never move between containing blocks, nor will their
absolute rect change. If anything changes, we'll simpl make a new
paintable and replace the old one.

Take advantage of this by caching the containing block and absolute rect
after first access.
2022-03-12 00:39:31 +01:00

89 lines
2.8 KiB
C++

/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/NonnullOwnPtr.h>
#include <LibWeb/Layout/Box.h>
#include <LibWeb/Layout/LineBox.h>
#include <LibWeb/Layout/TextNode.h>
namespace Web::Painting {
enum class PaintPhase {
Background,
Border,
Foreground,
FocusOutline,
Overlay,
};
struct HitTestResult {
RefPtr<Painting::Paintable> paintable;
int index_in_node { 0 };
enum InternalPosition {
None,
Before,
Inside,
After,
};
InternalPosition internal_position { None };
};
enum class HitTestType {
Exact, // Exact matches only
TextCursor, // Clicking past the right/bottom edge of text will still hit the text
};
class Paintable : public RefCounted<Paintable> {
AK_MAKE_NONMOVABLE(Paintable);
AK_MAKE_NONCOPYABLE(Paintable);
public:
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 { }
virtual HitTestResult hit_test(Gfx::IntPoint const&, HitTestType) const;
virtual bool wants_mouse_events() const { return false; }
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers);
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers);
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers);
virtual bool handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
Layout::Node const& layout_node() const { return m_layout_node; }
Layout::Node& layout_node() { return const_cast<Layout::Node&>(m_layout_node); }
auto const& computed_values() const { return m_layout_node.computed_values(); }
HTML::BrowsingContext const& browsing_context() const { return m_layout_node.browsing_context(); }
HTML::BrowsingContext& browsing_context() { return layout_node().browsing_context(); }
void set_needs_display() const { const_cast<Layout::Node&>(m_layout_node).set_needs_display(); }
Layout::BlockContainer const* containing_block() const
{
if (!m_containing_block.has_value())
m_containing_block = const_cast<Layout::Node&>(m_layout_node).containing_block();
return *m_containing_block;
}
protected:
explicit Paintable(Layout::Node const& layout_node)
: m_layout_node(layout_node)
{
}
private:
Layout::Node const& m_layout_node;
Optional<Layout::BlockContainer*> mutable m_containing_block;
};
}