Skip to content

Commit

Permalink
Use dynamicDowncast<T> more in layout code
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=265504

Reviewed by Alan Baradlay.

* Source/WebCore/layout/Verification.cpp:
(WebCore::Layout::collectInlineBoxes):
(WebCore::Layout::outputMismatchingBlockBoxInformationIfNeeded):
(WebCore::Layout::verifyAndOutputSubtree):
* Source/WebCore/layout/formattingContexts/FormattingContext.cpp:
(WebCore::Layout::FormattingContext::initialContainingBlock):
* Source/WebCore/layout/formattingContexts/FormattingGeometry.cpp:
(WebCore::Layout::FormattingGeometry::computedWidthValue const):
(WebCore::Layout::FormattingGeometry::shrinkToFitWidth const):
(WebCore::Layout::FormattingGeometry::complicatedCases const):
* Source/WebCore/layout/formattingContexts/block/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::layoutOutOfFlowContent):

Canonical link: https://commits.webkit.org/271274@main
  • Loading branch information
cdumez committed Nov 29, 2023
1 parent b8cd89e commit d2b97ed
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 49 deletions.
48 changes: 25 additions & 23 deletions Source/WebCore/layout/Verification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,10 @@ static void collectInlineBoxes(const RenderBlockFlow& root, Vector<WebCore::Lega
{
for (auto* rootLine = root.firstRootBox(); rootLine; rootLine = rootLine->nextRootBox()) {
for (auto* inlineBox = rootLine->firstChild(); inlineBox; inlineBox = inlineBox->nextOnLine()) {
if (!is<LegacyInlineFlowBox>(inlineBox)) {
if (auto* legacyInlineFlowBox = dynamicDowncast<LegacyInlineFlowBox>(inlineBox))
collectFlowBoxSubtree(*legacyInlineFlowBox, inlineBoxes);
else
inlineBoxes.append(inlineBox);
continue;
}
collectFlowBoxSubtree(downcast<LegacyInlineFlowBox>(*inlineBox), inlineBoxes);
}
}
}
Expand Down Expand Up @@ -228,12 +227,14 @@ static bool outputMismatchingBlockBoxInformationIfNeeded(TextStream& stream, con
boxGeometry.setVerticalMargin(tableWrapperBoxGeometry.verticalMargin());
}

if (is<RenderTableRow>(renderer) || is<RenderTableSection>(renderer)) {
auto* renderTableRow = dynamicDowncast<RenderTableRow>(renderer);
auto* renderTableSection = dynamicDowncast<RenderTableSection>(renderer);
if (renderTableRow || renderTableSection) {
// Table rows and tbody have 0 width for some reason when border collapsing is on.
if (is<RenderTableRow>(renderer) && downcast<RenderTableRow>(renderer).table()->collapseBorders())
if (renderTableRow && renderTableRow->table()->collapseBorders())
return false;
// Section borders are either collapsed or ignored. However they may produce negative padding boxes.
if (is<RenderTableSection>(renderer) && (downcast<RenderTableSection>(renderer).table()->collapseBorders() || renderer.style().hasBorder()))
if (renderTableSection && (renderTableSection->table()->collapseBorders() || renderer.style().hasBorder()))
return false;
}
if (!areEssentiallyEqual(frameRect, BoxGeometry::borderBoxRect(boxGeometry))) {
Expand All @@ -260,7 +261,8 @@ static bool outputMismatchingBlockBoxInformationIfNeeded(TextStream& stream, con
if (is<RenderTableCell>(renderer) || is<RenderTableSection>(renderer))
return false;
// Tables have 0 content box size for some reason when border collapsing is on.
return !is<RenderTable>(renderer) || !downcast<RenderTable>(renderer).collapseBorders();
auto* renderTable = dynamicDowncast<RenderTable>(renderer);
return !renderTable || !renderTable->collapseBorders();
}();
if (shouldCheckContentBox && !areEssentiallyEqual(renderer.contentBoxRect(), boxGeometry.contentBox())) {
outputRect("contentBox"_s, renderer.contentBoxRect(), boxGeometry.contentBox());
Expand Down Expand Up @@ -290,17 +292,18 @@ static bool verifyAndOutputSubtree(TextStream& stream, const LayoutState& contex
if (layoutBox.isTableWrapperBox())
return verifyAndOutputSubtree(stream, context, renderer, *downcast<ElementBox>(layoutBox).firstChild());

auto mismtachingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, renderer, layoutBox);
auto mismatchingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, renderer, layoutBox);

if (!is<ElementBox>(layoutBox))
return mismtachingGeometry;
auto* elementBox = dynamicDowncast<ElementBox>(layoutBox);
if (!elementBox)
return mismatchingGeometry;

auto& elementBox = downcast<ElementBox>(layoutBox);
auto* childLayoutBox = elementBox.firstChild();
auto* childLayoutBox = elementBox->firstChild();
auto* childRenderer = renderer.firstChild();

while (childRenderer) {
if (!is<RenderBox>(*childRenderer)) {
auto* childRenderBox = dynamicDowncast<RenderBox>(*childRenderer);
if (!childRenderBox) {
childRenderer = childRenderer->nextSibling();
continue;
}
Expand All @@ -311,25 +314,24 @@ static bool verifyAndOutputSubtree(TextStream& stream, const LayoutState& contex
return true;
}

if (is<RenderBlockFlow>(*childRenderer) && childLayoutBox->establishesInlineFormattingContext()) {
ASSERT(childRenderer->childrenInline());
auto mismtachingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, downcast<RenderBox>(*childRenderer), *childLayoutBox);
if (mismtachingGeometry)
if (auto* blockFlow = dynamicDowncast<RenderBlockFlow>(*childRenderBox); blockFlow && childLayoutBox->establishesInlineFormattingContext()) {
ASSERT(blockFlow->childrenInline());
auto mismatchingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, *blockFlow, *childLayoutBox);
if (mismatchingGeometry)
return true;

auto& blockFlow = downcast<RenderBlockFlow>(*childRenderer);
auto& formattingRoot = downcast<ElementBox>(*childLayoutBox);
mismtachingGeometry |= outputMismatchingComplexLineInformationIfNeeded(stream, context, blockFlow, formattingRoot);
mismatchingGeometry |= outputMismatchingComplexLineInformationIfNeeded(stream, context, *blockFlow, formattingRoot);
} else {
auto mismatchingSubtreeGeometry = verifyAndOutputSubtree(stream, context, downcast<RenderBox>(*childRenderer), *childLayoutBox);
mismtachingGeometry |= mismatchingSubtreeGeometry;
auto mismatchingSubtreeGeometry = verifyAndOutputSubtree(stream, context, *childRenderBox, *childLayoutBox);
mismatchingGeometry |= mismatchingSubtreeGeometry;
}

childLayoutBox = childLayoutBox->nextSibling();
childRenderer = childRenderer->nextSibling();
}

return mismtachingGeometry;
return mismatchingGeometry;
}

void LayoutContext::verifyAndOutputMismatchingLayoutTree(const LayoutState& layoutState, const RenderView& rootRenderer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ const BoxGeometry& FormattingContext::geometryForBox(const Box& layoutBox, std::

const InitialContainingBlock& FormattingContext::initialContainingBlock(const Box& layoutBox)
{
if (is<InitialContainingBlock>(layoutBox))
return downcast<InitialContainingBlock>(layoutBox);
if (auto* initialContainingBlock = dynamicDowncast<InitialContainingBlock>(layoutBox))
return *initialContainingBlock;

auto* ancestor = &layoutBox.parent();
for (; !is<InitialContainingBlock>(*ancestor); ancestor = &ancestor->parent()) { }
Expand Down
34 changes: 17 additions & 17 deletions Source/WebCore/layout/formattingContexts/FormattingGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,20 @@ std::optional<LayoutUnit> FormattingGeometry::computedWidthValue(const Box& layo
return computedValue;

if (width.isMinContent() || width.isMaxContent() || width.isFitContent()) {
if (!is<ElementBox>(layoutBox))
auto* elementBox = dynamicDowncast<ElementBox>(layoutBox);
if (!elementBox)
return { };
auto& elementBox = downcast<ElementBox>(layoutBox);
// FIXME: Consider splitting up computedIntrinsicWidthConstraints so that we could computed the min and max values separately.
auto intrinsicWidthConstraints = [&] {
if (!elementBox.hasInFlowOrFloatingChild())
if (!elementBox->hasInFlowOrFloatingChild())
return IntrinsicWidthConstraints { 0_lu, containingBlockWidth };
ASSERT(elementBox.establishesFormattingContext());
ASSERT(elementBox->establishesFormattingContext());
auto& layoutState = this->layoutState();
if (layoutState.hasFormattingState(elementBox)) {
if (auto intrinsicWidthConstraints = layoutState.formattingStateForFormattingContext(elementBox).intrinsicWidthConstraints())
if (layoutState.hasFormattingState(*elementBox)) {
if (auto intrinsicWidthConstraints = layoutState.formattingStateForFormattingContext(*elementBox).intrinsicWidthConstraints())
return *intrinsicWidthConstraints;
}
return LayoutContext::createFormattingContext(elementBox, const_cast<LayoutState&>(layoutState))->computedIntrinsicWidthConstraints();
return LayoutContext::createFormattingContext(*elementBox, const_cast<LayoutState&>(layoutState))->computedIntrinsicWidthConstraints();
}();
if (width.isMinContent())
return intrinsicWidthConstraints.minimum;
Expand Down Expand Up @@ -302,20 +302,20 @@ LayoutUnit FormattingGeometry::shrinkToFitWidth(const Box& formattingContextRoot
// 'padding-left', 'padding-right', 'border-right-width', 'margin-right', and the widths of any relevant scroll bars.

// Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).
auto hasContent = is<ElementBox>(formattingContextRoot) && downcast<ElementBox>(formattingContextRoot).hasInFlowOrFloatingChild();
auto* root = dynamicDowncast<ElementBox>(formattingContextRoot);
auto hasContent = root && root->hasInFlowOrFloatingChild();
// The used width of the containment box is determined as if performing a normal layout of the box, except that it is treated as having no content.
auto shouldIgnoreContent = formattingContextRoot.isSizeContainmentBox();
if (!hasContent || shouldIgnoreContent)
return { };

auto computedIntrinsicWidthConstraints = [&] {
auto& layoutState = this->layoutState();
auto& root = downcast<ElementBox>(formattingContextRoot);
if (layoutState.hasFormattingState(root)) {
if (auto intrinsicWidthConstraints = layoutState.formattingStateForFormattingContext(root).intrinsicWidthConstraints())
if (layoutState.hasFormattingState(*root)) {
if (auto intrinsicWidthConstraints = layoutState.formattingStateForFormattingContext(*root).intrinsicWidthConstraints())
return *intrinsicWidthConstraints;
}
return LayoutContext::createFormattingContext(root, const_cast<LayoutState&>(layoutState))->computedIntrinsicWidthConstraints();
return LayoutContext::createFormattingContext(*root, const_cast<LayoutState&>(layoutState))->computedIntrinsicWidthConstraints();
}();
return std::min(std::max(computedIntrinsicWidthConstraints.minimum, availableWidth), computedIntrinsicWidthConstraints.maximum);
}
Expand Down Expand Up @@ -788,15 +788,15 @@ ContentHeightAndMargin FormattingGeometry::complicatedCases(const Box& layoutBox
// #2
if (!height) {
ASSERT(isHeightAuto(layoutBox));
if (!is<ElementBox>(layoutBox) || !downcast<ElementBox>(layoutBox).hasInFlowOrFloatingChild())
auto* elementBox = dynamicDowncast<ElementBox>(layoutBox);
if (!elementBox || !elementBox->hasInFlowOrFloatingChild())
height = 0_lu;
else if (layoutBox.isDocumentBox() && !layoutBox.establishesFormattingContext()) {
auto& documentBox = downcast<ElementBox>(layoutBox);
auto top = BoxGeometry::marginBoxRect(formattingContext().geometryForBox(*documentBox.firstInFlowChild())).top();
auto bottom = BoxGeometry::marginBoxRect(formattingContext().geometryForBox(*documentBox.lastInFlowChild())).bottom();
auto top = BoxGeometry::marginBoxRect(formattingContext().geometryForBox(*elementBox->firstInFlowChild())).top();
auto bottom = BoxGeometry::marginBoxRect(formattingContext().geometryForBox(*elementBox->lastInFlowChild())).bottom();
// This is a special (quirk?) behavior since the document box is not a formatting context root and
// all the float boxes end up at the ICB level.
auto& initialContainingBlock = FormattingContext::initialContainingBlock(documentBox);
auto& initialContainingBlock = FormattingContext::initialContainingBlock(*elementBox);
auto floatingContext = FloatingContext { formattingContext().root(), layoutState(), downcast<BlockFormattingState>(layoutState().formattingStateForFormattingContext(initialContainingBlock)).placedFloats() };
if (auto floatBottom = floatingContext.bottom()) {
bottom = std::max<LayoutUnit>(*floatBottom, bottom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,12 @@ void BlockFormattingContext::layoutOutOfFlowContent(const ConstraintsForOutOfFlo
computeBorderAndPadding(outOfFlowBox, horizontalConstraintsForBorderAndPadding);

computeOutOfFlowHorizontalGeometry(outOfFlowBox, containingBlockConstraints);
auto outOfFlowBoxHasContent = is<ElementBox>(outOfFlowBox.get()) && downcast<ElementBox>(outOfFlowBox.get()).hasChild();
if (outOfFlowBoxHasContent) {
auto& elementBox = downcast<ElementBox>(outOfFlowBox.get());
auto formattingContext = LayoutContext::createFormattingContext(elementBox, layoutState());
if (elementBox.hasInFlowOrFloatingChild())
formattingContext->layoutInFlowContent(formattingGeometry().constraintsForInFlowContent(elementBox));
computeOutOfFlowVerticalGeometry(elementBox, containingBlockConstraints);
auto* elementBox = dynamicDowncast<ElementBox>(outOfFlowBox.get());
if (elementBox && elementBox->hasChild()) {
auto formattingContext = LayoutContext::createFormattingContext(*elementBox, layoutState());
if (elementBox->hasInFlowOrFloatingChild())
formattingContext->layoutInFlowContent(formattingGeometry().constraintsForInFlowContent(*elementBox));
computeOutOfFlowVerticalGeometry(*elementBox, containingBlockConstraints);
} else
computeOutOfFlowVerticalGeometry(outOfFlowBox, containingBlockConstraints);
}
Expand Down

0 comments on commit d2b97ed

Please sign in to comment.