ladybird/Libraries/LibWeb/Painting/PaintableWithLines.h
Andreas Kling 7445cff5e8 LibWeb: Use retained data for hit testing
Build a hit-test display list while recording paint output. Use it as
source of truth for point hit testing instead of recursively walking the
paintable tree in reverse paint order.

The retained list records target paintables, visual context indices,
border radii, caret rects, and line metadata needed by hit testing. It
also keeps a spatial index so point queries inspect nearby items before
checking containment in paint order.

Refresh scroll state before hit testing so visual context transforms use
current scroll offsets. Add text tests for rounded hit regions and
selection across non-text content.
2026-05-30 13:50:48 +02:00

54 lines
1.9 KiB
C++

/*
* Copyright (c) 2022-2025, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Forward.h>
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/PaintableFragment.h>
namespace Web::Painting {
class PaintableWithLines : public PaintableBox {
public:
static NonnullRefPtr<PaintableWithLines> create(Layout::BlockContainer const&);
static NonnullRefPtr<PaintableWithLines> create(Layout::InlineNode const&, size_t line_index);
virtual ~PaintableWithLines() override;
virtual StringView class_name() const override { return "PaintableWithLines"sv; }
virtual void reset_for_relayout() override;
Vector<PaintableFragment> const& fragments() const { return m_fragments; }
Vector<PaintableFragment>& fragments() { return m_fragments; }
void add_fragment(Layout::LineBoxFragment const& fragment, LineBoxData line_box_data)
{
m_fragments.append(PaintableFragment { fragment, line_box_data });
}
virtual void paint(DisplayListRecordingContext&, PaintPhase) const override;
virtual void record_hit_test_items(DisplayListRecordingContext&, PaintPhase) const override;
static void paint_text_fragment_debug_highlight(DisplayListRecordingContext&, PaintableFragment const&);
size_t line_index() const { return m_line_index; }
protected:
PaintableWithLines(Layout::BlockContainer const&);
PaintableWithLines(Layout::InlineNode const&, size_t line_index);
private:
[[nodiscard]] virtual bool is_paintable_with_lines() const final { return true; }
Optional<PaintableFragment const&> fragment_at_position(DOM::Position const&) const;
void paint_cursor(DisplayListRecordingContext&) const;
Vector<PaintableFragment> m_fragments;
size_t m_line_index { 0 };
};
}