diff --git a/Libraries/LibHTML/Layout/LayoutNode.cpp b/Libraries/LibHTML/Layout/LayoutNode.cpp index ba8d19722a..b2f460a31f 100644 --- a/Libraries/LibHTML/Layout/LayoutNode.cpp +++ b/Libraries/LibHTML/Layout/LayoutNode.cpp @@ -1,7 +1,10 @@ +#include #include #include #include +//#define DRAW_BOXES_AROUND_LAYOUT_NODES + LayoutNode::LayoutNode(const Node* node, StyleProperties&& style_properties) : m_node(node) , m_style_properties(style_properties) @@ -30,6 +33,9 @@ const LayoutBlock* LayoutNode::containing_block() const void LayoutNode::render(RenderingContext& context) { +#ifdef DRAW_BOXES_AROUND_LAYOUT_NODES + context.painter().draw_rect(m_rect, Color::Blue); +#endif // TODO: render our background and border for_each_child([&](auto& child) { child.render(context); @@ -38,9 +44,10 @@ void LayoutNode::render(RenderingContext& context) HitTestResult LayoutNode::hit_test(const Point& position) const { - if (!m_rect.contains(position)) - return {}; - HitTestResult result { this }; + // FIXME: It would be nice if we could confidently skip over hit testing + // parts of the layout tree, but currently we can't just check + // m_rect.contains() since inline text rects can't be trusted.. + HitTestResult result { m_rect.contains(position) ? this : nullptr }; for_each_child([&](auto& child) { auto child_result = child.hit_test(position); if (child_result.layout_node) diff --git a/Libraries/LibHTML/Layout/LayoutText.cpp b/Libraries/LibHTML/Layout/LayoutText.cpp index 0f90d96015..9ea5c58a38 100644 --- a/Libraries/LibHTML/Layout/LayoutText.cpp +++ b/Libraries/LibHTML/Layout/LayoutText.cpp @@ -222,6 +222,21 @@ void LayoutText::layout() rect().set_bottom(last_run.pos.y() + m_font->glyph_height()); } +template +void LayoutText::for_each_run(Callback callback) const +{ + for (auto& run : m_runs) { + Rect rect { + run.pos.x(), + run.pos.y(), + m_font->width(run.text), + m_font->glyph_height() + }; + if (callback(run, rect) == IterationDecision::Break) + break; + } +} + void LayoutText::render(RenderingContext& context) { auto& painter = context.painter(); @@ -232,16 +247,23 @@ void LayoutText::render(RenderingContext& context) bool is_underline = text_decoration == "underline"; - for (auto& run : m_runs) { - Rect rect { - run.pos.x(), - run.pos.y(), - m_font->width(run.text), - m_font->glyph_height() - }; + for_each_run([&](auto& run, auto& rect) { painter.draw_text(rect, run.text, TextAlignment::TopLeft, color); - if (is_underline) painter.draw_line(rect.bottom_left().translated(0, 1), rect.bottom_right().translated(0, 1), color); - } + return IterationDecision::Continue; + }); +} + +HitTestResult LayoutText::hit_test(const Point& position) const +{ + HitTestResult result; + for_each_run([&](auto&, auto& rect) { + if (rect.contains(position)) { + result.layout_node = this; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + return result; } diff --git a/Libraries/LibHTML/Layout/LayoutText.h b/Libraries/LibHTML/Layout/LayoutText.h index 48ea4841df..43d0f7265a 100644 --- a/Libraries/LibHTML/Layout/LayoutText.h +++ b/Libraries/LibHTML/Layout/LayoutText.h @@ -26,7 +26,12 @@ public: const Vector& runs() const { return m_runs; } + virtual HitTestResult hit_test(const Point&) const override; + private: + template + void for_each_run(Callback) const; + void load_font(); void compute_runs();