[LFC] Align compute functions styles.
[WebKit-https.git] / Source / WebCore / layout / blockformatting / BlockFormattingContextGeometry.cpp
index d5be6dd..58fa0aa 100644 (file)
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "FormattingContext.h"
+#include "Logging.h"
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 namespace Layout {
 
-LayoutUnit BlockFormattingContext::Geometry::inFlowNonReplacedHeight(LayoutContext& layoutContext, const Box& layoutBox)
+static bool isStretchedToViewport(const LayoutContext& layoutContext, const Box& layoutBox)
+{
+    ASSERT(layoutBox.isInFlow());
+    // In quirks mode, body and html stretch to the viewport.
+    if (!layoutContext.inQuirksMode())
+        return false;
+
+    if (!layoutBox.isDocumentBox() && !layoutBox.isBodyBox())
+        return false;
+
+    return layoutBox.style().logicalHeight().isAuto();
+}
+
+static const Container& initialContainingBlock(const Box& layoutBox)
+{
+    auto* containingBlock = layoutBox.containingBlock();
+    while (containingBlock->containingBlock())
+        containingBlock = containingBlock->containingBlock();
+    return *containingBlock;
+}
+
+FormattingContext::Geometry::HeightAndMargin BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
 {
     ASSERT(layoutBox.isInFlow() && !layoutBox.replaced());
 
-    // https://www.w3.org/TR/CSS22/visudet.html
-    // If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders:
-    // The element's height is the distance from its top content edge to the first applicable of the following:
-    // 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
-    // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin
-    //    does not collapse with the element's bottom margin
-    // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
-    // 4. zero, otherwise
-    // Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored,
-    // and relatively positioned boxes are considered without their offset). Note that the child box may be an anonymous block box.
-    if (!layoutBox.style().logicalHeight().isAuto()) {
-        // FIXME: Only fixed values yet.
-        return layoutBox.style().logicalHeight().value();
-    }
+    auto compute = [&]() -> LayoutUnit {
+        // 10.6.3 Block-level non-replaced elements in normal flow when 'overflow' computes to 'visible'
+        //
+        // If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0.
+        // If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders:
+        // The element's height is the distance from its top content edge to the first applicable of the following:
+        // 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
+        // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin
+        //    does not collapse with the element's bottom margin
+        // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
+        // 4. zero, otherwise
+        // Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored,
+        // and relatively positioned boxes are considered without their offset). Note that the child box may be an anonymous block box.
 
-    if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild())
-        return 0;
+        if (!layoutBox.style().logicalHeight().isAuto()) {
+            // FIXME: Only fixed values yet.
+            return layoutBox.style().logicalHeight().value();
+        }
+
+        if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild())
+            return 0;
+
+        // 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
+        if (layoutBox.establishesInlineFormattingContext()) {
+            // height = lastLineBox().bottom();
+            return 0;
+        }
+
+        // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin...
+        auto* lastInFlowChild = downcast<Container>(layoutBox).lastInFlowChild();
+        ASSERT(lastInFlowChild);
+        if (!MarginCollapse::isMarginBottomCollapsedWithParent(*lastInFlowChild)) {
+            auto* lastInFlowDisplayBox = layoutContext.displayBoxForLayoutBox(*lastInFlowChild);
+            ASSERT(lastInFlowDisplayBox);
+            return lastInFlowDisplayBox->bottom() + lastInFlowDisplayBox->marginBottom();
+        }
 
-    // 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
-    if (layoutBox.establishesInlineFormattingContext()) {
-        // height = lastLineBox().bottom();
+        // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
+        auto* inFlowChild = lastInFlowChild;
+        while (inFlowChild && MarginCollapse::isMarginTopCollapsedWithParentMarginBottom(*inFlowChild))
+            inFlowChild = inFlowChild->previousInFlowSibling();
+        if (inFlowChild) {
+            auto* inFlowDisplayBox = layoutContext.displayBoxForLayoutBox(*inFlowChild);
+            ASSERT(inFlowDisplayBox);
+            return inFlowDisplayBox->top() + inFlowDisplayBox->borderBox().height();
+        }
+
+        // 4. zero, otherwise
         return 0;
-    }
+    };
 
-    // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin...
-    auto* lastInFlowChild = downcast<Container>(layoutBox).lastInFlowChild();
-    ASSERT(lastInFlowChild);
-    if (!BlockFormattingContext::MarginCollapse::isMarginBottomCollapsedWithParent(*lastInFlowChild)) {
-        auto* lastInFlowDisplayBox = layoutContext.displayBoxForLayoutBox(*lastInFlowChild);
-        ASSERT(lastInFlowDisplayBox);
-        return lastInFlowDisplayBox->bottom() + lastInFlowDisplayBox->marginBottom();
-    }
+    auto height = compute();
+    auto marginTop = MarginCollapse::marginTop(layoutContext, layoutBox);
+    auto marginBottom =  MarginCollapse::marginBottom(layoutContext, layoutBox);
 
-    // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
-    auto* inFlowChild = lastInFlowChild;
-    while (inFlowChild && BlockFormattingContext::MarginCollapse::isMarginTopCollapsedWithParentMarginBottom(*inFlowChild))
-        inFlowChild = inFlowChild->previousInFlowSibling();
-    if (inFlowChild) {
-        auto* inFlowDisplayBox = layoutContext.displayBoxForLayoutBox(*inFlowChild);
-        ASSERT(inFlowDisplayBox);
-        return inFlowDisplayBox->top() + inFlowDisplayBox->borderBox().height();
+    if (!isStretchedToViewport(layoutContext, layoutBox)) {
+        LOG_WITH_STREAM(FormattingContextLayout, stream << "[Height][Margin] -> inflow non-replaced -> height(" << height << "px) margin(" << marginTop << "px, " << marginBottom << "px) -> layoutBox(" << &layoutBox << ")");
+        return { height, { marginTop, marginBottom } };
     }
 
-    // 4. zero, otherwise
-    return 0;
+    auto initialContainingBlockHeight = layoutContext.displayBoxForLayoutBox(initialContainingBlock(layoutBox))->contentBox().height();
+    // Stretch but never overstretch with the margins.
+    if (height + marginTop + marginBottom < initialContainingBlockHeight)
+        height = initialContainingBlockHeight - marginTop - marginBottom;
+
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Height][Margin] -> inflow non-replaced -> streched to viewport -> height(" << height << "px) margin(" << marginTop << "px, " << marginBottom << "px) -> layoutBox(" << &layoutBox << ")");
+    return { height, { marginTop, marginBottom } };
 }
 
-LayoutUnit BlockFormattingContext::Geometry::inFlowNonReplacedWidth(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::WidthAndMargin BlockFormattingContext::Geometry::inFlowNonReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox,
+    std::optional<LayoutUnit> precomputedWidth)
 {
     ASSERT(layoutBox.isInFlow() && !layoutBox.replaced());
 
-    // 10.3.3 Block-level, non-replaced elements in normal flow
-    // The following constraints must hold among the used values of the other properties:
-    // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
+    auto compute = [&]() {
+        // 10.3.3 Block-level, non-replaced elements in normal flow
+        // The following constraints must hold among the used values of the other properties:
+        // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
+        //
+        // 1. If 'width' is not 'auto' and 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' 
+        //    (plus any of 'margin-left' or 'margin-right' that are not 'auto') is larger than the width of the containing block, then
+        //    any 'auto' values for 'margin-left' or 'margin-right' are, for the following rules, treated as zero.
+        //
+        // 2. If all of the above have a computed value other than 'auto', the values are said to be "over-constrained" and one of the used values will
+        //    have to be different from its computed value. If the 'direction' property of the containing block has the value 'ltr', the specified value
+        //    of 'margin-right' is ignored and the value is calculated so as to make the equality true. If the value of 'direction' is 'rtl',
+        //    this happens to 'margin-left' instead.
+        //
+        // 3. If there is exactly one value specified as 'auto', its used value follows from the equality.
+        //
+        // 4. If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.
+        //
+        // 5. If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers the element with respect to the
+        //    edges of the containing block.
 
-    // If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.
-    auto& style = layoutBox.style();
-    auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->width();
-
-    LayoutUnit computedWidthValue;
-    auto width = style.logicalWidth();
-    if (width.isAuto()) {
+        auto& style = layoutBox.style();
+        auto width = precomputedWidth ? Length { precomputedWidth.value(), Fixed } : style.logicalWidth();
+        auto* containingBlock = layoutBox.containingBlock();
+        auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(*containingBlock)->width();
         auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
-        auto marginLeft = displayBox.marginLeft();
-        auto marginRight = displayBox.marginRight();
 
-        auto paddingLeft = displayBox.paddingLeft();
-        auto paddingRight = displayBox.paddingRight();
+        LayoutUnit computedWidthValue;
+        std::optional<LayoutUnit> computedMarginLeftValue;
+        std::optional<LayoutUnit> computedMarginRightValue;
+
+        auto marginLeft = style.marginLeft();
+        if (!marginLeft.isAuto())
+            computedMarginLeftValue = valueForLength(marginLeft, containingBlockWidth);
+
+        auto marginRight = style.marginRight();
+        if (!marginRight.isAuto())
+            computedMarginRightValue = valueForLength(marginRight, containingBlockWidth);
 
         auto borderLeft = displayBox.borderLeft();
         auto borderRight = displayBox.borderRight();
+        auto paddingLeft = displayBox.paddingLeft();
+        auto paddingRight = displayBox.paddingRight();
+
+        // #1
+        if (!width.isAuto()) {
+            computedWidthValue = valueForLength(width, containingBlockWidth);
+            auto horizontalSpaceForMargin = containingBlockWidth - (computedMarginLeftValue.value_or(0) + borderLeft + paddingLeft 
+                + computedWidthValue + paddingRight + borderRight + computedMarginRightValue.value_or(0));
+
+            if (horizontalSpaceForMargin < 0) {
+                if (!computedMarginLeftValue)
+                    computedMarginLeftValue = LayoutUnit(0);
+                if (!computedMarginRightValue)
+                    computedMarginRightValue = LayoutUnit(0);
+            }
+        }
+
+        // #2
+        if (!width.isAuto() && !marginLeft.isAuto() && !marginRight.isAuto()) {
+            ASSERT(computedMarginLeftValue);
+            ASSERT(computedMarginRightValue);
+
+            if (containingBlock->style().isLeftToRightDirection())
+                computedMarginRightValue = containingBlockWidth - (*computedMarginLeftValue + borderLeft + paddingLeft  + computedWidthValue + paddingRight + borderRight);
+            else
+                computedMarginLeftValue = containingBlockWidth - (borderLeft + paddingLeft  + computedWidthValue + paddingRight + borderRight + *computedMarginRightValue);
+        }
+
+        // #3
+        if (!computedMarginLeftValue && !marginRight.isAuto() && !width.isAuto()) {
+            ASSERT(computedMarginRightValue);
+            computedMarginLeftValue = containingBlockWidth - (borderLeft + paddingLeft  + computedWidthValue + paddingRight + borderRight + *computedMarginRightValue);
+        } else if (!computedMarginRightValue && !marginLeft.isAuto() && !width.isAuto()) {
+            ASSERT(computedMarginLeftValue);
+            computedMarginRightValue = containingBlockWidth - (*computedMarginLeftValue + borderLeft + paddingLeft  + computedWidthValue + paddingRight + borderRight);
+        }
 
-        computedWidthValue = containingBlockWidth - (marginLeft + borderLeft + paddingLeft + paddingRight + borderRight + marginRight);
-    } else
-        computedWidthValue = valueForLength(width, containingBlockWidth);
+        // #4
+        if (width.isAuto())
+            computedWidthValue = containingBlockWidth - (computedMarginLeftValue.value_or(0) + borderLeft + paddingLeft + paddingRight + borderRight + computedMarginRightValue.value_or(0));
+
+        // #5
+        if (!computedMarginLeftValue && !computedMarginRightValue) {
+            auto horizontalSpaceForMargin = containingBlockWidth - (borderLeft + paddingLeft  + computedWidthValue + paddingRight + borderRight);
+            computedMarginLeftValue = computedMarginRightValue = horizontalSpaceForMargin / 2;
+        }
+
+        ASSERT(computedMarginLeftValue);
+        ASSERT(computedMarginRightValue);
 
-    return computedWidthValue;
+        return FormattingContext::Geometry::WidthAndMargin { computedWidthValue, { *computedMarginLeftValue, *computedMarginRightValue } };
+    };
+
+    auto widthAndMargin = compute();
+    if (!isStretchedToViewport(layoutContext, layoutBox)) {
+        LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width][Margin] -> inflow non-replaced -> width(" << widthAndMargin.width << "px) margin(" << widthAndMargin.margin.left << "px, " << widthAndMargin.margin.right << "px) -> layoutBox(" << &layoutBox << ")");
+        return widthAndMargin;
+    }
+
+    auto initialContainingBlockWidth = layoutContext.displayBoxForLayoutBox(initialContainingBlock(layoutBox))->contentBox().width();
+    auto horizontalMargins = widthAndMargin.margin.left + widthAndMargin.margin.right;
+    // Stretch but never overstretch with the margins.
+    if (widthAndMargin.width + horizontalMargins < initialContainingBlockWidth)
+        widthAndMargin.width = initialContainingBlockWidth - horizontalMargins;
+
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width][Margin] -> inflow non-replaced -> streched to viewport-> width(" << widthAndMargin.width << "px) margin(" << widthAndMargin.margin.left << "px, " << widthAndMargin.margin.right << "px) -> layoutBox(" << &layoutBox << ")");
+    return widthAndMargin;
+}
+
+FormattingContext::Geometry::WidthAndMargin BlockFormattingContext::Geometry::inFlowReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+{
+    ASSERT(layoutBox.isInFlow() && layoutBox.replaced());
+
+    // 10.3.4 Block-level, replaced elements in normal flow
+    //
+    // 1. The used value of 'width' is determined as for inline replaced elements.
+    // 2. Then the rules for non-replaced block-level elements are applied to determine the margins.
+
+    // #1
+    auto width = FormattingContext::Geometry::inlineReplacedWidthAndMargin(layoutContext, layoutBox).width;
+    // #2
+    auto margin = inFlowNonReplacedWidthAndMargin(layoutContext, layoutBox, width).margin;
+
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width][Margin] -> inflow replaced -> width(" << width << "px) margin(" << margin.left << "px, " << margin.left << "px) -> layoutBox(" << &layoutBox << ")");
+    return { width, margin };
 }
 
 LayoutPoint BlockFormattingContext::Geometry::staticPosition(LayoutContext& layoutContext, const Box& layoutBox)
@@ -123,23 +269,23 @@ LayoutPoint BlockFormattingContext::Geometry::staticPosition(LayoutContext& layo
     // The vertical distance between two sibling boxes is determined by the 'margin' properties.
     // Vertical margins between adjacent block-level boxes in a block formatting context collapse.
     // In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch).
+
     auto containingBlockContentBox = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->contentBox();
     // Start from the top of the container's content box.
-    auto top = containingBlockContentBox.y();
-    auto left = containingBlockContentBox.x();
+    auto top = containingBlockContentBox.top();
+    auto left = containingBlockContentBox.left();
     if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) {
         auto& previousInFlowDisplayBox = *layoutContext.displayBoxForLayoutBox(*previousInFlowSibling);
         top = previousInFlowDisplayBox.bottom() + previousInFlowDisplayBox.marginBottom();
     }
-    auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
-    LayoutPoint topLeft = { top, left };
-    topLeft.moveBy({ displayBox.marginLeft(), displayBox.marginTop() });
-    return topLeft;
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Position] -> static -> top(" << top << "px) left(" << left << "px) layoutBox(" << &layoutBox << ")");
+    return { top, left };
 }
 
 LayoutPoint BlockFormattingContext::Geometry::inFlowPositionedPosition(LayoutContext& layoutContext, const Box& layoutBox)
 {
     ASSERT(layoutBox.isInFlowPositioned());
+
     // 9.4.3 Relative positioning
     //
     // The 'top' and 'bottom' properties move relatively positioned element(s) up or down without changing their size.
@@ -148,22 +294,28 @@ LayoutPoint BlockFormattingContext::Geometry::inFlowPositionedPosition(LayoutCon
     // 1. If both are 'auto', their used values are both '0'.
     // 2. If one of them is 'auto', it becomes the negative of the other.
     // 3. If neither is 'auto', 'bottom' is ignored (i.e., the used value of 'bottom' will be minus the value of 'top').
-    auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
+
     auto& style = layoutBox.style();
+    auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
+    auto& containingBlock = *layoutBox.containingBlock();
+    auto& containingBlockDisplayBox = *layoutContext.displayBoxForLayoutBox(containingBlock);
+    auto containingBlockWidth = containingBlockDisplayBox.width();
 
-    auto top = style.logicalTop();
-    auto bottom = style.logicalBottom();
-    LayoutUnit topDelta;
+    auto top = FormattingContext::Geometry::computedValueIfNotAuto(style.logicalTop(), containingBlockWidth);
+    auto bottom = FormattingContext::Geometry::computedValueIfNotAuto(style.logicalBottom(), containingBlockWidth);
 
-    if (top.isAuto() && bottom.isAuto()) {
+    if (!top && !bottom) {
         // #1
-        topDelta = 0;
-    } else if (top.isAuto()) {
+        top = bottom = { 0 };
+    } else if (!top) {
         // #2
-        topDelta = -bottom.value();
-    } else if (bottom.isAuto()) {
-        // #3 #4
-        topDelta = top.value();
+        top = -*bottom;
+    } else if (!bottom) {
+        // #3
+        bottom = -*top;
+    } else {
+        // #4
+        bottom = std::nullopt;
     }
 
     // For relatively positioned elements, 'left' and 'right' move the box(es) horizontally, without changing their size.
@@ -176,40 +328,56 @@ LayoutPoint BlockFormattingContext::Geometry::inFlowPositionedPosition(LayoutCon
     // 4. If neither 'left' nor 'right' is 'auto', the position is over-constrained, and one of them has to be ignored.
     //    If the 'direction' property of the containing block is 'ltr', the value of 'left' wins and 'right' becomes -'left'.
     //    If 'direction' of the containing block is 'rtl', 'right' wins and 'left' is ignored.
-    //
-    auto left = style.logicalLeft();
-    auto right = style.logicalRight();
-    LayoutUnit leftDelta;
 
-    if (left.isAuto() && right.isAuto()) {
+    auto left = FormattingContext::Geometry::computedValueIfNotAuto(style.logicalLeft(), containingBlockWidth);
+    auto right = FormattingContext::Geometry::computedValueIfNotAuto(style.logicalRight(), containingBlockWidth);
+
+    if (!left && !right) {
         // #1
-        leftDelta = 0;
-    } else if (left.isAuto()) {
+        left = right = { 0 };
+    } else if (!left) {
         // #2
-        leftDelta = -right.value();
-    } else if (right.isAuto()) {
+        left = -*right;
+    } else if (!right) {
         // #3
-        leftDelta = left.value();
+        right = -*left;
     } else {
         // #4
-        // FIXME: take direction into account
-        leftDelta = left.value();
+        auto isLeftToRightDirection = containingBlock.style().isLeftToRightDirection();
+        if (isLeftToRightDirection)
+            right = -*left;
+        else
+            left = std::nullopt;
     }
 
-    return { displayBox.left() + leftDelta, displayBox.top() + topDelta };
+    ASSERT(!bottom || *top == -*bottom);
+    ASSERT(!left || *left == -*right);
+
+    auto newTopPosition = displayBox.top() + *top;
+    auto newLeftPosition = displayBox.left() + left.value_or(-*right);
+
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Position] -> positioned inflow -> top(" << newTopPosition << "px) left(" << newLeftPosition << "px) layoutBox(" << &layoutBox << ")");
+    return { newTopPosition, newLeftPosition };
 }
 
-Display::Box::Edges BlockFormattingContext::Geometry::computedMargin(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::HeightAndMargin BlockFormattingContext::Geometry::inFlowHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
 {
-    auto& style = layoutBox.style();
-    auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->width();
-
-    return Display::Box::Edges(
-        BlockFormattingContext::MarginCollapse::marginTop(layoutBox),
-        valueForLength(style.marginLeft(), containingBlockWidth),
-        BlockFormattingContext::MarginCollapse::marginBottom(layoutBox),
-        valueForLength(style.marginRight(), containingBlockWidth)
-    );
+    ASSERT(layoutBox.isInFlow());
+
+    if (!layoutBox.replaced())
+        return inFlowNonReplacedHeightAndMargin(layoutContext, layoutBox);
+    // 10.6.2 Inline replaced elements, block-level replaced elements in normal flow, 'inline-block'
+    // replaced elements in normal flow and floating replaced elements
+    return FormattingContext::Geometry::inlineReplacedHeightAndMargin(layoutContext, layoutBox);
+}
+
+FormattingContext::Geometry::WidthAndMargin BlockFormattingContext::Geometry::inFlowWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+{
+    ASSERT(layoutBox.isInFlow());
+
+    if (!layoutBox.replaced())
+        return inFlowNonReplacedWidthAndMargin(layoutContext, layoutBox);
+    return inFlowReplacedWidthAndMargin(layoutContext, layoutBox);
 }
 
 }