PrecomputedBlockMarginCollapse.cpp [plain text]
#include "config.h"
#include "BlockFormattingContext.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "BlockFormattingState.h"
#include "LayoutBox.h"
#include "LayoutContainerBox.h"
#include "LayoutState.h"
#include "LayoutUnit.h"
#include "RenderStyle.h"
namespace WebCore {
namespace Layout {
UsedVerticalMargin::PositiveAndNegativePair::Values BlockFormattingContext::MarginCollapse::precomputedPositiveNegativeValues(const Box& layoutBox) const
{
auto& blockFormattingState = downcast<BlockFormattingState>(layoutState().formattingStateForBox(layoutBox));
if (blockFormattingState.hasUsedVerticalMargin(layoutBox))
return blockFormattingState.usedVerticalMargin(layoutBox).positiveAndNegativeValues.before;
auto geometry = formattingContext().geometry();
auto horizontalConstraints = geometry.constraintsForInFlowContent(layoutBox.containingBlock()).horizontal;
auto computedVerticalMargin = geometry.computedVerticalMargin(layoutBox, horizontalConstraints);
auto nonCollapsedMargin = UsedVerticalMargin::NonCollapsedValues { computedVerticalMargin.before.valueOr(0), computedVerticalMargin.after.valueOr(0) };
return precomputedPositiveNegativeMarginBefore(layoutBox, nonCollapsedMargin);
}
UsedVerticalMargin::PositiveAndNegativePair::Values BlockFormattingContext::MarginCollapse::precomputedPositiveNegativeMarginBefore(const Box& layoutBox, UsedVerticalMargin::NonCollapsedValues nonCollapsedValues) const
{
auto firstChildCollapsedMarginBefore = [&]() -> UsedVerticalMargin::PositiveAndNegativePair::Values {
if (!marginBeforeCollapsesWithFirstInFlowChildMarginBefore(layoutBox))
return { };
return precomputedPositiveNegativeValues(*downcast<ContainerBox>(layoutBox).firstInFlowChild());
};
auto previouSiblingCollapsedMarginAfter = [&]() -> UsedVerticalMargin::PositiveAndNegativePair::Values {
if (!marginBeforeCollapsesWithPreviousSiblingMarginAfter(layoutBox))
return { };
auto& previousInFlowSibling = *layoutBox.previousInFlowSibling();
auto& blockFormattingState = downcast<BlockFormattingState>(layoutState().formattingStateForBox(previousInFlowSibling));
return blockFormattingState.usedVerticalMargin(previousInFlowSibling).positiveAndNegativeValues.after;
};
auto collapsedMarginBefore = computedPositiveAndNegativeMargin(firstChildCollapsedMarginBefore(), previouSiblingCollapsedMarginAfter());
if (collapsedMarginBefore.isQuirk && formattingContext().quirks().shouldIgnoreCollapsedQuirkMargin(layoutBox))
collapsedMarginBefore = { };
auto nonCollapsedBefore = UsedVerticalMargin::PositiveAndNegativePair::Values { };
if (nonCollapsedValues.before > 0)
nonCollapsedBefore = { nonCollapsedValues.before, { }, layoutBox.style().hasMarginBeforeQuirk() };
else if (nonCollapsedValues.before < 0)
nonCollapsedBefore = { { }, nonCollapsedValues.before, layoutBox.style().hasMarginBeforeQuirk() };
return computedPositiveAndNegativeMargin(collapsedMarginBefore, nonCollapsedBefore);
}
PrecomputedMarginBefore BlockFormattingContext::MarginCollapse::precomputedMarginBefore(const Box& layoutBox, UsedVerticalMargin::NonCollapsedValues usedNonCollapsedMargin)
{
ASSERT(layoutBox.isBlockLevelBox());
ASSERT(layoutBox.isInFlow() || layoutBox.isFloatingPositioned());
ASSERT(!layoutBox.isReplacedBox());
auto positiveNegativeMarginBefore = precomputedPositiveNegativeMarginBefore(layoutBox, usedNonCollapsedMargin);
auto collapsedMarginBefore = marginValue(positiveNegativeMarginBefore);
return { usedNonCollapsedMargin.before, collapsedMarginBefore, positiveNegativeMarginBefore };
}
}
}
#endif