TableFormattingContextGeometry.cpp [plain text]
#include "config.h"
#include "TableFormattingContext.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "InlineFormattingState.h"
#include "LayoutBoxGeometry.h"
#include "LayoutContext.h"
#include "LayoutDescendantIterator.h"
#include "LayoutInitialContainingBlock.h"
#include "TableFormattingState.h"
namespace WebCore {
namespace Layout {
LayoutUnit TableFormattingContext::Geometry::cellHeigh(const ContainerBox& cellBox) const
{
ASSERT(cellBox.isInFlow());
auto contentHeight = LayoutUnit { };
if (formattingContext().quirks().shouldIgnoreChildContentVerticalMargin(cellBox)) {
ASSERT(cellBox.firstInFlowChild());
auto formattingContext = this->formattingContext();
auto& firstInFlowChild = *cellBox.firstInFlowChild();
auto& lastInFlowChild = *cellBox.lastInFlowChild();
auto& firstInFlowChildGeometry = formattingContext.geometryForBox(firstInFlowChild, EscapeReason::TableQuirkNeedsGeometryFromEstablishedFormattingContext);
auto& lastInFlowChildGeometry = formattingContext.geometryForBox(lastInFlowChild, EscapeReason::TableQuirkNeedsGeometryFromEstablishedFormattingContext);
auto top = firstInFlowChild.style().hasMarginBeforeQuirk() ? BoxGeometry::borderBoxRect(firstInFlowChildGeometry).top() : BoxGeometry::marginBoxRect(firstInFlowChildGeometry).top();
auto bottom = lastInFlowChild.style().hasMarginAfterQuirk() ? BoxGeometry::borderBoxRect(lastInFlowChildGeometry).bottom() : BoxGeometry::marginBoxRect(lastInFlowChildGeometry).bottom();
contentHeight = bottom - top;
} else
contentHeight = contentHeightForFormattingContextRoot(cellBox);
return std::max(computedHeight(cellBox).valueOr(0_lu), contentHeight);
}
Edges TableFormattingContext::Geometry::computedCellBorder(const TableGrid::Cell& cell) const
{
auto& cellBox = cell.box();
auto border = computedBorder(cellBox);
auto collapsedBorder = m_grid.collapsedBorder();
if (!collapsedBorder)
return border;
auto cellPosition = cell.position();
if (!cellPosition.column)
border.horizontal.left = collapsedBorder->horizontal.left / 2;
else {
auto adjacentBorderRight = computedBorder(m_grid.slot({ cellPosition.column - 1, cellPosition.row })->cell().box()).horizontal.right;
border.horizontal.left = std::max(border.horizontal.left, adjacentBorderRight) / 2;
}
if (cellPosition.column == m_grid.columns().size() - 1)
border.horizontal.right = collapsedBorder->horizontal.right / 2;
else {
auto adjacentBorderLeft = computedBorder(m_grid.slot({ cellPosition.column + 1, cellPosition.row })->cell().box()).horizontal.left;
border.horizontal.right = std::max(border.horizontal.right, adjacentBorderLeft) / 2;
}
auto& rows = m_grid.rows().list();
if (!cellPosition.row)
border.vertical.top = collapsedBorder->vertical.top / 2;
else {
auto adjacentBorderBottom = computedBorder(m_grid.slot({ cellPosition.column, cellPosition.row - 1 })->cell().box()).vertical.bottom;
auto adjacentRowBottom = computedBorder(rows[cellPosition.row - 1].box()).vertical.bottom;
auto adjacentCollapsedBorder = std::max(adjacentBorderBottom, adjacentRowBottom);
border.vertical.top = std::max(border.vertical.top, adjacentCollapsedBorder) / 2;
}
if (cellPosition.row == m_grid.rows().size() - 1)
border.vertical.bottom = collapsedBorder->vertical.bottom / 2;
else {
auto adjacentBorderTop = computedBorder(m_grid.slot({ cellPosition.column, cellPosition.row + 1 })->cell().box()).vertical.top;
auto adjacentRowTop = computedBorder(rows[cellPosition.row + 1].box()).vertical.top;
auto adjacentCollapsedBorder = std::max(adjacentBorderTop, adjacentRowTop);
border.vertical.bottom = std::max(border.vertical.bottom, adjacentCollapsedBorder) / 2;
}
return border;
}
Optional<LayoutUnit> TableFormattingContext::Geometry::computedColumnWidth(const ContainerBox& columnBox)
{
if (auto computedWidthValue = computedWidth(columnBox, { }))
return computedWidthValue;
return columnBox.columnWidth();
}
FormattingContext::IntrinsicWidthConstraints TableFormattingContext::Geometry::intrinsicWidthConstraintsForCell(const TableGrid::Cell& cell)
{
auto& cellBox = cell.box();
auto& style = cellBox.style();
auto computedIntrinsicWidthConstraints = [&]() -> FormattingContext::IntrinsicWidthConstraints {
auto intrinsicWidthConstraints = FormattingContext::IntrinsicWidthConstraints { };
if (cellBox.hasChild())
intrinsicWidthConstraints = LayoutContext::createFormattingContext(cellBox, layoutState())->computedIntrinsicWidthConstraints();
if (auto fixedWidth = fixedValue(style.logicalWidth()))
return { std::max(intrinsicWidthConstraints.minimum, *fixedWidth), std::max(intrinsicWidthConstraints.minimum, *fixedWidth) };
return intrinsicWidthConstraints;
};
auto intrinsicWidthConstraints = constrainByMinMaxWidth(cellBox, computedIntrinsicWidthConstraints());
intrinsicWidthConstraints.expand(computedCellBorder(cell).width());
intrinsicWidthConstraints.expand(fixedValue(style.paddingLeft()).valueOr(0) + fixedValue(style.paddingRight()).valueOr(0));
intrinsicWidthConstraints.expand(fixedValue(style.marginStart()).valueOr(0) + fixedValue(style.marginEnd()).valueOr(0));
return intrinsicWidthConstraints;
}
InlineLayoutUnit TableFormattingContext::Geometry::usedBaselineForCell(const ContainerBox& cellBox)
{
if (cellBox.establishesInlineFormattingContext())
return layoutState().establishedInlineFormattingState(cellBox).lines()[0].baseline();
for (auto& cellDescendant : descendantsOfType<ContainerBox>(cellBox)) {
if (cellDescendant.establishesInlineFormattingContext()) {
auto& inlineFormattingStateForCell = layoutState().establishedInlineFormattingState(cellDescendant);
if (!inlineFormattingStateForCell.lines().isEmpty())
return inlineFormattingStateForCell.lines()[0].baseline();
}
if (cellDescendant.establishesTableFormattingContext())
return layoutState().establishedTableFormattingState(cellDescendant).tableGrid().rows().list()[0].baseline();
}
return formattingContext().geometryForBox(cellBox).contentBoxBottom();
}
}
}
#endif