mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 17:25:07 +00:00
LibHTML: Make hit testing work for LayoutText
LayoutText can't simply rely on its LayoutNode::rect() for hit testing. Instead, we have to iterate over the individual runs and see if we're hitting any of them. Also, LayoutNode::hit_test() now always recurses into children, since we can't trust the rect() to tell the truth (inline rects are wrong.)
This commit is contained in:
parent
aac8b091a4
commit
13860e4dd8
3 changed files with 46 additions and 12 deletions
|
@ -222,6 +222,21 @@ void LayoutText::layout()
|
|||
rect().set_bottom(last_run.pos.y() + m_font->glyph_height());
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue