Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/Layout/FormattingContext.cpp (C++)

Code before:
    // do not set calculated insets or margins on the first pass, there will be a second pass
    if (box.computed_values().height().is_auto() && before_or_after_inside_layout == BeforeOrAfterInsideLayout::Before)
        return;
    box_state.set_has_definite_height(true);
    box_state.inset_top = top.to_px_or_zero(box, height_of_containing_block);
    box_state.inset_bottom = bottom.to_px_or_zero(box, height_of_containing_block);
    box_state.margin_top = margin_top.to_px_or_zero(box, width_of_containing_block);
    box_state.margin_bottom = margin_bottom.to_px_or_zero(box, width_of_containing_block);
}

CSSPixelRect FormattingContext::content_box_rect_in_static_position_ancestor_coordinate_space(Box const& box) const
{
    auto box_used_values = m_state.get(box);
    CSSPixelRect rect = { { 0, 0 }, box_used_values.content_size() };
    // FIXME: ListItemMarkerBox's should also run this assertion once it has a supported FormattingContext type
    VERIFY(box_used_values.offset.is_zero() || box.is_list_item_marker_box()); // Set as result of this calculation
    for (auto const* current = box.static_position_containing_block(); current; current = current->containing_block()) {
        if (current == box.containing_block())
            return rect;
        auto const& current_state = m_state.get(*current);
        rect.translate_by(current_state.offset);
    }
    // If we get here, `ancestor_box` was not in the containing block chain of the static position containing block of `box`!
    // Something about the containing block chain is set up incorrectly then.
    rect.set_location({ 0, 0 });
    return rect;
}

void FormattingContext::layout_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space)
{
    if (box.is_svg_box()) {
        dbgln("FIXME: Implement support for absolutely positioned SVG elements.");
        return;
    }

    auto& containing_block_state = m_state.get_mutable(*box.containing_block());

    // The size of the containing block of an abspos box is always definite from the perspective of the abspos box.
    // Since abspos boxes are laid out last, we can mark the containing block as having definite sizes at this point.
    containing_block_state.set_has_definite_width(true);
    containing_block_state.set_has_definite_height(true);

    auto& box_state = m_state.get_mutable(box);

    // The border computed values are not changed by the compute_height & width calculations below.
    // The spec only adjusts and computes sizes, insets and margins.
    box_state.border_left = box.computed_values().border_left().width;
    box_state.border_right = box.computed_values().border_right().width;
    box_state.border_top = box.computed_values().border_top().width;
    box_state.border_bottom = box.computed_values().border_bottom().width;


Review comment (bug):
@InvalidUsernameException @ayeteadoe @gmta You've all recently touched this method. Is this reasonable? As I posted [on Discord](https://discord.com/channels/1247070541085671459/1247090064480014443/1450493581432455331), assigning fixed-positioning containing blocks causes the loop here to miss the containing block, at least in some cases. I'm not familiar enough with layout to be able to tell if that's something that should happen, or if we're doing something wrong in `static_position_containing_block()`, or we're not assigning containing blocks correctly for anonymous wrappers. (Or if my fixed positioning CB code is just bad and wrong. :sweat_smile: )

Code after:
    // do not set calculated insets or margins on the first pass, there will be a second pass
    if (box.computed_values().height().is_auto() && before_or_after_inside_layout == BeforeOrAfterInsideLayout::Before)
        return;
    box_state.set_has_definite_height(true);
    box_state.inset_top = top.to_px_or_zero(box, height_of_containing_block);
    box_state.inset_bottom = bottom.to_px_or_zero(box, height_of_containing_block);
    box_state.margin_top = margin_top.to_px_or_zero(box, width_of_containing_block);
    box_state.margin_bottom = margin_bottom.to_px_or_zero(box, width_of_containing_block);
}

CSSPixelRect FormattingContext::content_box_rect_in_static_position_ancestor_coordinate_space(Box const& box) const
{
    auto box_used_values = m_state.get(box);
    CSSPixelRect rect = { { 0, 0 }, box_used_values.content_size() };
    // FIXME: ListItemMarkerBox's should also run this assertion once it has a supported FormattingContext type
    VERIFY(box_used_values.offset.is_zero() || box.is_list_item_marker_box()); // Set as result of this calculation
    auto next_containing_block = box.static_position_containing_block();
    for (NodeWithStyle const* current = box.static_position_containing_block(); current; current = current->parent()) {
        if (current == box.containing_block())
            return rect;
        // Whenever we walk past other containing blocks, we need to offset the rect by those.
        if (current == next_containing_block) {
            auto const& current_state = m_state.get(*current);
            rect.translate_by(current_state.offset);
            next_containing_block = next_containing_block->containing_block();
        }
    }
    // If we get here, `ancestor_box` was not in the containing block chain of the static position containing block of `box`!
    // Something about the containing block chain is set up incorrectly then.
    VERIFY_NOT_REACHED();
}

void FormattingContext::layout_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space)
{
    if (box.is_svg_box()) {
        dbgln("FIXME: Implement support for absolutely positioned SVG elements.");
        return;
    }

    auto& containing_block_state = m_state.get_mutable(*box.containing_block());

    // The size of the containing block of an abspos box is always definite from the perspective of the abspos box.
    // Since abspos boxes are laid out last, we can mark the containing block as having definite sizes at this point.
    containing_block_state.set_has_definite_width(true);
    containing_block_state.set_has_definite_height(true);

    auto& box_state = m_state.get_mutable(box);

    // The border computed values are not changed by the compute_height & width calculations below.
    // The spec only adjusts and computes sizes, insets and margins.
    box_state.border_left = box.computed_values().border_left().width;