mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-28 12:18:25 +00:00
LibWeb: Rework the layout engine to use relative offsets
The box tree and line boxes now all store a relative offset from their containing block, instead of an absolute (document-relative) position. This removes a huge pain point from the layout system which was having to adjust offsets recursively when something moved. It also makes some layout logic significantly simpler. Every box can still find its absolute position by walking its chain of containing blocks and accumulating the translation from the root. This is currently what we do both for rendering and hit testing.
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include <LibWeb/Frame/Frame.h>
|
||||
#include <LibWeb/Layout/LayoutDocument.h>
|
||||
#include <LibWeb/Layout/LayoutImage.h>
|
||||
#include <LibWeb/Layout/LayoutWidget.h>
|
||||
|
||||
namespace Web {
|
||||
|
||||
@@ -43,27 +44,33 @@ LayoutDocument::~LayoutDocument()
|
||||
void LayoutDocument::layout(LayoutMode layout_mode)
|
||||
{
|
||||
ASSERT(document().frame());
|
||||
rect().set_width(document().frame()->size().width());
|
||||
set_width(document().frame()->size().width());
|
||||
|
||||
LayoutNode::layout(layout_mode);
|
||||
|
||||
ASSERT(!children_are_inline());
|
||||
|
||||
int lowest_bottom = 0;
|
||||
float lowest_bottom = 0;
|
||||
for_each_child([&](auto& child) {
|
||||
ASSERT(is<LayoutBlock>(child));
|
||||
auto& child_block = to<LayoutBlock>(child);
|
||||
if (child_block.rect().bottom() > lowest_bottom)
|
||||
lowest_bottom = child_block.rect().bottom();
|
||||
lowest_bottom = max(lowest_bottom, child_block.absolute_rect().bottom());
|
||||
});
|
||||
set_height(lowest_bottom);
|
||||
|
||||
// FIXME: This is a total hack. Make sure any GUI::Widgets are moved into place after layout.
|
||||
// We should stop embedding GUI::Widgets entirely, since that won't work out-of-process.
|
||||
for_each_in_subtree_of_type<LayoutWidget>([&](auto& widget) {
|
||||
widget.update_widget();
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
rect().set_bottom(lowest_bottom);
|
||||
}
|
||||
|
||||
void LayoutDocument::did_set_viewport_rect(Badge<Frame>, const Gfx::Rect& a_viewport_rect)
|
||||
{
|
||||
Gfx::FloatRect viewport_rect(a_viewport_rect.x(), a_viewport_rect.y(), a_viewport_rect.width(), a_viewport_rect.height());
|
||||
for_each_in_subtree_of_type<LayoutImage>([&](auto& layout_image) {
|
||||
const_cast<HTMLImageElement&>(layout_image.node()).set_visible_in_viewport({}, viewport_rect.intersects(layout_image.rect()));
|
||||
const_cast<HTMLImageElement&>(layout_image.node()).set_visible_in_viewport({}, viewport_rect.intersects(layout_image.absolute_rect()));
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user