FlexFormattingContext.cpp [plain text]
#include "config.h"
#include "FlexFormattingContext.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FlexFormattingState.h"
#include "InlineRect.h"
#include "InvalidationState.h"
#include "LayoutBoxGeometry.h"
#include "LayoutChildIterator.h"
#include "LayoutContext.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
namespace Layout {
WTF_MAKE_ISO_ALLOCATED_IMPL(FlexFormattingContext);
FlexFormattingContext::FlexFormattingContext(const ContainerBox& formattingContextRoot, FlexFormattingState& formattingState)
: FormattingContext(formattingContextRoot, formattingState)
{
}
void FlexFormattingContext::layoutInFlowContent(InvalidationState&, const ConstraintsForInFlowContent& constraints)
{
computeIntrinsicWidthConstraintsForFlexItems();
sizeAndPlaceFlexItems(constraints);
}
LayoutUnit FlexFormattingContext::usedContentHeight() const
{
auto& lines = formattingState().lines();
return LayoutUnit { lines.last().bottom() - lines.first().top() };
}
FormattingContext::IntrinsicWidthConstraints FlexFormattingContext::computedIntrinsicWidthConstraints()
{
return { };
}
void FlexFormattingContext::sizeAndPlaceFlexItems(const ConstraintsForInFlowContent& constraints)
{
auto& formattingState = this->formattingState();
auto geometry = this->geometry();
auto flexItemMainAxisStart = constraints.horizontal.logicalLeft;
auto flexItemMainAxisEnd = flexItemMainAxisStart;
auto flexItemCrosAxisStart = constraints.vertical.logicalTop;
auto flexItemCrosAxisEnd = flexItemCrosAxisStart;
for (auto& flexItem : childrenOfType<ContainerBox>(root())) {
ASSERT(flexItem.establishesFormattingContext());
auto intrinsicWidths = formattingState.intrinsicWidthConstraintsForBox(flexItem);
auto flexItemLogicalWidth = std::min(std::max(intrinsicWidths->minimum, constraints.horizontal.logicalWidth), intrinsicWidths->maximum);
auto flexItemConstraints = ConstraintsForInFlowContent { { { }, flexItemLogicalWidth }, { } };
auto invalidationState = InvalidationState { };
LayoutContext::createFormattingContext(flexItem, layoutState())->layoutInFlowContent(invalidationState, flexItemConstraints);
auto computeFlexItemGeometry = [&] {
auto& flexItemGeometry = formattingState.boxGeometry(flexItem);
flexItemGeometry.setLogicalTopLeft(LayoutPoint { flexItemMainAxisEnd, flexItemCrosAxisStart });
flexItemGeometry.setBorder(geometry.computedBorder(flexItem));
flexItemGeometry.setPadding(geometry.computedPadding(flexItem, constraints.horizontal.logicalWidth));
auto computedHorizontalMargin = geometry.computedHorizontalMargin(flexItem, constraints.horizontal);
flexItemGeometry.setHorizontalMargin({ computedHorizontalMargin.start.valueOr(0_lu), computedHorizontalMargin.end.valueOr(0_lu) });
auto computedVerticalMargin = geometry.computedVerticalMargin(flexItem, constraints.horizontal);
flexItemGeometry.setVerticalMargin({ computedVerticalMargin.before.valueOr(0_lu), computedVerticalMargin.after.valueOr(0_lu) });
flexItemGeometry.setContentBoxHeight(geometry.contentHeightForFormattingContextRoot(flexItem));
flexItemGeometry.setContentBoxWidth(flexItemLogicalWidth);
flexItemMainAxisEnd= BoxGeometry::borderBoxRect(flexItemGeometry).right();
flexItemCrosAxisEnd = std::max(flexItemCrosAxisEnd, BoxGeometry::borderBoxRect(flexItemGeometry).bottom());
};
computeFlexItemGeometry();
}
auto flexLine = InlineRect { flexItemCrosAxisStart, flexItemMainAxisStart, flexItemMainAxisEnd - flexItemMainAxisStart, flexItemCrosAxisEnd - flexItemCrosAxisStart };
formattingState.addLine(flexLine);
}
void FlexFormattingContext::computeIntrinsicWidthConstraintsForFlexItems()
{
auto& formattingState = this->formattingState();
auto geometry = this->geometry();
for (auto& flexItem : childrenOfType<ContainerBox>(root())) {
if (formattingState.intrinsicWidthConstraintsForBox(flexItem))
continue;
formattingState.setIntrinsicWidthConstraintsForBox(flexItem, geometry.intrinsicWidthConstraints(flexItem));
}
}
}
}
#endif