mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 02:57:42 +00:00
LibWeb: Move layout box rect helpers into FormattingContext
These are only used during layout, and always within formatting context code, so we might as well put them in FormattingContext and avoid having to pass the LayoutState around all the time.
This commit is contained in:
parent
4f08fcde29
commit
42470d837e
10 changed files with 155 additions and 152 deletions
|
@ -355,7 +355,7 @@ CSSPixels FormattingContext::compute_auto_height_for_block_formatting_context_ro
|
|||
for (auto floating_box : m_state.get(root).floating_descendants()) {
|
||||
// NOTE: Floating box coordinates are relative to their own containing block,
|
||||
// which may or may not be the BFC root.
|
||||
auto margin_box = margin_box_rect_in_ancestor_coordinate_space(*floating_box, root, m_state);
|
||||
auto margin_box = margin_box_rect_in_ancestor_coordinate_space(*floating_box, root);
|
||||
CSSPixels floating_box_bottom_margin_edge = margin_box.bottom();
|
||||
if (!bottom.has_value() || floating_box_bottom_margin_edge > bottom.value())
|
||||
bottom = floating_box_bottom_margin_edge;
|
||||
|
@ -913,15 +913,15 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
|||
}
|
||||
|
||||
// NOTE: This is different from content_box_rect_in_ancestor_coordinate_space() as this does *not* follow the containing block chain up, but rather the parent() chain.
|
||||
static CSSPixelRect content_box_rect_in_static_position_ancestor_coordinate_space(Box const& box, Box const& ancestor_box, LayoutState const& state)
|
||||
CSSPixelRect FormattingContext::content_box_rect_in_static_position_ancestor_coordinate_space(Box const& box, Box const& ancestor_box) const
|
||||
{
|
||||
auto rect = content_box_rect(box, state);
|
||||
auto rect = content_box_rect(box);
|
||||
if (&box == &ancestor_box)
|
||||
return rect;
|
||||
for (auto const* current = box.parent(); current; current = current->parent()) {
|
||||
if (current == &ancestor_box)
|
||||
return rect;
|
||||
auto const& current_state = state.get(static_cast<Box const&>(*current));
|
||||
auto const& current_state = m_state.get(static_cast<Box const&>(*current));
|
||||
rect.translate_by(current_state.offset);
|
||||
}
|
||||
// If we get here, ancestor_box was not an ancestor of `box`!
|
||||
|
@ -968,7 +968,7 @@ CSSPixelPoint FormattingContext::calculate_static_position(Box const& box) const
|
|||
// We're among block siblings, Y can be calculated easily.
|
||||
y = m_state.get(box).margin_box_top();
|
||||
}
|
||||
auto offset_to_static_parent = content_box_rect_in_static_position_ancestor_coordinate_space(box, *box.containing_block(), m_state);
|
||||
auto offset_to_static_parent = content_box_rect_in_static_position_ancestor_coordinate_space(box, *box.containing_block());
|
||||
return offset_to_static_parent.location().translated(x, y);
|
||||
}
|
||||
|
||||
|
@ -1490,4 +1490,123 @@ bool FormattingContext::can_skip_is_anonymous_text_run(Box& box)
|
|||
return false;
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::absolute_content_rect(Box const& box) const
|
||||
{
|
||||
auto const& box_state = m_state.get(box);
|
||||
CSSPixelRect rect { box_state.offset, { box_state.content_width(), box_state.content_height() } };
|
||||
for (auto* block = box.containing_block(); block; block = block->containing_block())
|
||||
rect.translate_by(m_state.get(*block).offset);
|
||||
return rect;
|
||||
}
|
||||
|
||||
CSSPixels FormattingContext::box_baseline(Box const& box) const
|
||||
{
|
||||
auto const& box_state = m_state.get(box);
|
||||
|
||||
// https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align
|
||||
auto const& vertical_align = box.computed_values().vertical_align();
|
||||
if (vertical_align.has<CSS::VerticalAlign>()) {
|
||||
switch (vertical_align.get<CSS::VerticalAlign>()) {
|
||||
case CSS::VerticalAlign::Top:
|
||||
// Top: Align the top of the aligned subtree with the top of the line box.
|
||||
return box_state.border_box_top();
|
||||
case CSS::VerticalAlign::Bottom:
|
||||
// Bottom: Align the bottom of the aligned subtree with the bottom of the line box.
|
||||
return box_state.content_height() + box_state.margin_box_top();
|
||||
case CSS::VerticalAlign::TextTop:
|
||||
// TextTop: Align the top of the box with the top of the parent's content area (see 10.6.1).
|
||||
return box.computed_values().font_size();
|
||||
case CSS::VerticalAlign::TextBottom:
|
||||
// TextTop: Align the bottom of the box with the bottom of the parent's content area (see 10.6.1).
|
||||
return box_state.content_height() - (box.containing_block()->font().pixel_metrics().descent * 2);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!box_state.line_boxes.is_empty())
|
||||
return box_state.margin_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline();
|
||||
if (box.has_children() && !box.children_are_inline()) {
|
||||
auto const* child_box = box.last_child_of_type<Box>();
|
||||
VERIFY(child_box);
|
||||
return box_baseline(*child_box);
|
||||
}
|
||||
return box_state.margin_box_height();
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::margin_box_rect(Box const& box) const
|
||||
{
|
||||
auto const& box_state = m_state.get(box);
|
||||
return {
|
||||
box_state.offset.translated(-box_state.margin_box_left(), -box_state.margin_box_top()),
|
||||
{
|
||||
box_state.margin_box_left() + box_state.content_width() + box_state.margin_box_right(),
|
||||
box_state.margin_box_top() + box_state.content_height() + box_state.margin_box_bottom(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::border_box_rect(Box const& box) const
|
||||
{
|
||||
auto const& box_state = m_state.get(box);
|
||||
return {
|
||||
box_state.offset.translated(-box_state.border_box_left(), -box_state.border_box_top()),
|
||||
{
|
||||
box_state.border_box_left() + box_state.content_width() + box_state.border_box_right(),
|
||||
box_state.border_box_top() + box_state.content_height() + box_state.border_box_bottom(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::border_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box) const
|
||||
{
|
||||
auto rect = border_box_rect(box);
|
||||
if (&box == &ancestor_box)
|
||||
return rect;
|
||||
for (auto const* current = box.containing_block(); current; current = current->containing_block()) {
|
||||
if (current == &ancestor_box)
|
||||
return rect;
|
||||
auto const& current_state = m_state.get(static_cast<Box const&>(*current));
|
||||
rect.translate_by(current_state.offset);
|
||||
}
|
||||
// If we get here, ancestor_box was not a containing block ancestor of `box`!
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::content_box_rect(Box const& box) const
|
||||
{
|
||||
auto const& box_state = m_state.get(box);
|
||||
return CSSPixelRect { box_state.offset, { box_state.content_width(), box_state.content_height() } };
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::content_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box) const
|
||||
{
|
||||
auto rect = content_box_rect(box);
|
||||
if (&box == &ancestor_box)
|
||||
return rect;
|
||||
for (auto const* current = box.containing_block(); current; current = current->containing_block()) {
|
||||
if (current == &ancestor_box)
|
||||
return rect;
|
||||
auto const& current_state = m_state.get(static_cast<Box const&>(*current));
|
||||
rect.translate_by(current_state.offset);
|
||||
}
|
||||
// If we get here, ancestor_box was not a containing block ancestor of `box`!
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
CSSPixelRect FormattingContext::margin_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box) const
|
||||
{
|
||||
auto rect = margin_box_rect(box);
|
||||
if (&box == &ancestor_box)
|
||||
return rect;
|
||||
for (auto const* current = box.containing_block(); current; current = current->containing_block()) {
|
||||
if (current == &ancestor_box)
|
||||
return rect;
|
||||
auto const& current_state = m_state.get(static_cast<Box const&>(*current));
|
||||
rect.translate_by(current_state.offset);
|
||||
}
|
||||
// If we get here, ancestor_box was not a containing block ancestor of `box`!
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue