TableWrapperBlockFormattingContext.cpp [plain text]
#include "config.h"
#include "TableWrapperBlockFormattingContext.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "BlockFormattingState.h"
#include "InvalidationState.h"
#include "LayoutBoxGeometry.h"
#include "LayoutChildIterator.h"
#include "LayoutContext.h"
#include "LayoutInitialContainingBlock.h"
#include "TableFormattingContext.h"
#include "TableFormattingState.h"
namespace WebCore {
namespace Layout {
WTF_MAKE_ISO_ALLOCATED_IMPL(TableWrapperBlockFormattingContext);
TableWrapperBlockFormattingContext::TableWrapperBlockFormattingContext(const ContainerBox& formattingContextRoot, BlockFormattingState& formattingState)
: BlockFormattingContext(formattingContextRoot, formattingState)
{
}
void TableWrapperBlockFormattingContext::layoutInFlowContent(InvalidationState&, const ConstraintsForInFlowContent& constraints)
{
for (auto& child : childrenOfType<ContainerBox>(root())) {
if (child.isTableBox())
layoutTableBox(child, constraints);
else if (child.isTableCaption())
ASSERT_NOT_IMPLEMENTED_YET();
else
ASSERT_NOT_REACHED();
}
}
void TableWrapperBlockFormattingContext::layoutTableBox(const ContainerBox& tableBox, const ConstraintsForInFlowContent& constraints)
{
layoutState().ensureTableFormattingState(tableBox);
computeBorderAndPaddingForTableBox(tableBox, constraints.horizontal);
computeStaticVerticalPosition(tableBox, constraints.vertical);
computeWidthAndMarginForTableBox(tableBox, constraints.horizontal);
computeStaticHorizontalPosition(tableBox, constraints.horizontal);
if (tableBox.hasChild()) {
auto invalidationState = InvalidationState { };
LayoutContext::createFormattingContext(tableBox, layoutState())->layoutInFlowContent(invalidationState, geometry().constraintsForInFlowContent(tableBox));
}
computeHeightAndMarginForTableBox(tableBox, constraints);
}
void TableWrapperBlockFormattingContext::computeBorderAndPaddingForTableBox(const ContainerBox& tableBox, const HorizontalConstraints& horizontalConstraints)
{
ASSERT(tableBox.isTableBox());
if (!tableBox.hasChild() || tableBox.style().borderCollapse() == BorderCollapse::Separate) {
BlockFormattingContext::computeBorderAndPadding(tableBox, horizontalConstraints);
return;
}
auto& grid = layoutState().establishedTableFormattingState(tableBox).tableGrid();
auto tableBorder = geometry().computedBorder(tableBox);
auto& firstColumnFirstRowBox = grid.slot({ 0 , 0 })->cell().box();
auto leftBorder = std::max(tableBorder.horizontal.left, geometry().computedBorder(firstColumnFirstRowBox).horizontal.left);
auto& lastColumnFirstRow = grid.slot({ grid.columns().size() - 1, 0 })->cell().box();
auto rightBorder = std::max(tableBorder.horizontal.right, geometry().computedBorder(lastColumnFirstRow).horizontal.right);
auto topBorder = tableBorder.vertical.top;
auto bottomBorder = tableBorder.vertical.bottom;
auto lastRowIndex = grid.rows().size() - 1;
for (size_t columnIndex = 0; columnIndex < grid.columns().size(); ++columnIndex) {
auto& boxInFirstRox = grid.slot({ columnIndex, 0 })->cell().box();
auto& boxInLastRow = grid.slot({ columnIndex, lastRowIndex })->cell().box();
topBorder = std::max(topBorder, geometry().computedBorder(boxInFirstRox).vertical.top);
bottomBorder = std::max(bottomBorder, geometry().computedBorder(boxInLastRow).vertical.bottom);
}
topBorder = std::max(topBorder, geometry().computedBorder(*tableBox.firstChild()).vertical.top);
for (auto& section : childrenOfType<ContainerBox>(tableBox)) {
auto horiztonalBorder = geometry().computedBorder(section).horizontal;
leftBorder = std::max(leftBorder, horiztonalBorder.left);
rightBorder = std::max(rightBorder, horiztonalBorder.right);
}
bottomBorder = std::max(bottomBorder, geometry().computedBorder(*tableBox.lastChild()).vertical.bottom);
auto& rows = grid.rows().list();
topBorder = std::max(topBorder, geometry().computedBorder(rows.first().box()).vertical.top);
for (auto& row : rows) {
auto horiztonalBorder = geometry().computedBorder(row.box()).horizontal;
leftBorder = std::max(leftBorder, horiztonalBorder.left);
rightBorder = std::max(rightBorder, horiztonalBorder.right);
}
bottomBorder = std::max(bottomBorder, geometry().computedBorder(rows.last().box()).vertical.bottom);
auto collapsedBorder = Edges { { leftBorder, rightBorder }, { topBorder, bottomBorder } };
grid.setCollapsedBorder(collapsedBorder);
auto& boxGeometry = formattingState().boxGeometry(tableBox);
boxGeometry.setBorder(collapsedBorder / 2);
boxGeometry.setPadding(geometry().computedPadding(tableBox, horizontalConstraints.logicalWidth));
}
void TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox(const ContainerBox& tableBox, const HorizontalConstraints& horizontalConstraints)
{
ASSERT(tableBox.isTableBox());
auto& formattingStateForTableBox = layoutState().establishedTableFormattingState(tableBox);
auto intrinsicWidthConstraints = IntrinsicWidthConstraints { };
if (auto precomputedIntrinsicWidthConstraints = formattingStateForTableBox.intrinsicWidthConstraints())
intrinsicWidthConstraints = *precomputedIntrinsicWidthConstraints;
else {
if (tableBox.hasChild())
intrinsicWidthConstraints = LayoutContext::createFormattingContext(tableBox, layoutState())->computedIntrinsicWidthConstraints();
formattingStateForTableBox.setIntrinsicWidthConstraints(intrinsicWidthConstraints);
}
auto availableHorizontalSpace = horizontalConstraints.logicalWidth;
auto horizontalConstraintForResolvingWidth = m_horizontalConstraintsIgnoringFloats.logicalWidth;
auto geometry = this->geometry();
auto computedWidth = geometry.computedWidth(tableBox, horizontalConstraintForResolvingWidth);
auto computedMaxWidth = geometry.computedMaxWidth(tableBox, horizontalConstraintForResolvingWidth);
auto computedMinWidth = geometry.computedMinWidth(tableBox, horizontalConstraintForResolvingWidth);
auto usedWidth = std::min(std::max(intrinsicWidthConstraints.minimum, availableHorizontalSpace), intrinsicWidthConstraints.maximum);
if (computedWidth || computedMinWidth || computedMaxWidth) {
if (computedWidth) {
if (computedMaxWidth && *computedWidth > *computedMaxWidth)
computedWidth = computedMaxWidth;
if (computedMinWidth && *computedWidth < *computedMinWidth)
computedWidth = computedMinWidth;
usedWidth = *computedWidth < intrinsicWidthConstraints.minimum ? intrinsicWidthConstraints.minimum : *computedWidth;
}
if (computedMaxWidth && *computedMaxWidth < usedWidth)
usedWidth = intrinsicWidthConstraints.minimum;
if (computedMinWidth && *computedMinWidth > usedWidth)
usedWidth = *computedMinWidth;
}
auto contentWidthAndMargin = geometry.inFlowContentWidthAndMargin(tableBox, horizontalConstraints, OverriddenHorizontalValues { usedWidth, { } });
auto& boxGeometry = formattingState().boxGeometry(tableBox);
boxGeometry.setContentBoxWidth(contentWidthAndMargin.contentWidth);
boxGeometry.setHorizontalMargin({ contentWidthAndMargin.usedMargin.start, contentWidthAndMargin.usedMargin.end });
}
void TableWrapperBlockFormattingContext::computeHeightAndMarginForTableBox(const ContainerBox& tableBox, const ConstraintsForInFlowContent& constraints)
{
ASSERT(tableBox.isTableBox());
auto heightAndMargin = geometry().inFlowContentHeightAndMargin(tableBox, constraints.horizontal, { quirks().overriddenTableHeight(tableBox) });
auto marginCollapse = this->marginCollapse();
auto verticalMargin = marginCollapse.collapsedVerticalValues(tableBox, heightAndMargin.nonCollapsedMargin);
formattingState().setUsedVerticalMargin(tableBox, verticalMargin);
auto& boxGeometry = formattingState().boxGeometry(tableBox);
boxGeometry.setLogicalTop(verticalPositionWithMargin(tableBox, verticalMargin, constraints.vertical));
boxGeometry.setContentBoxHeight(heightAndMargin.contentHeight);
boxGeometry.setVerticalMargin({ marginBefore(verticalMargin), marginAfter(verticalMargin) });
MarginCollapse::updateMarginAfterForPreviousSibling(*this, marginCollapse, tableBox);
}
}
}
#endif