Skip to content

Commit 0fce63b

Browse files
committed
[Cleanup][content-visibility] RenderObject::isSkippedContentRoot has layout dependent state
https://bugs.webkit.org/show_bug.cgi?id=283395 Reviewed by Antti Koivisto. There are isSkippedContentRoot functions atm. 1. WebCore::isSkippedContentRoot(style, element) 2. and RenderObject::isSkippedContentRoot (see ContentVisibilityForceLayoutScope, for cases when we need to look inside c-v subtrees for geometry) and returns false when we are supposed to ignore content-visibility. This is always scoped to a layout frame (as opposed to painting, hittesting etc) The codebase is sprinkled with isSkippedContentRoot() calls, some of which exercise #1 while others call into #2 in a seemingly random fashion (e.g. even painting calls the "let's consult the ignore bit" variant). This patch replaces these 2 functions with 1. LocalFrameViewLayoutContext::isSkippedContentRootForLayout() 2. WebCore::isSkippedContentRoot(renderer) Where during layout we call layoutContext().isSkippedContentRootForLayout() (surprisingly small number) and the rest simply calls #2. (Note, there's a highly specific, 3rd use case in StyleAdjuster, which should be moved out to a place where we could use the WebCore::isSkippedContentRoot(renderer) variant). * Source/WebCore/dom/Document.cpp: (WebCore::CallbackForContainIntrinsicSize): (WebCore::Document::caretPositionFromPoint): * Source/WebCore/editing/TextIterator.cpp: (WebCore::TextIterator::advance): * Source/WebCore/page/LocalFrameViewLayoutContext.cpp: (WebCore::LocalFrameViewLayoutContext::isSkippedContentForLayout const): (WebCore::LocalFrameViewLayoutContext::isSkippedContentRootForLayout const): * Source/WebCore/page/LocalFrameViewLayoutContext.h: * Source/WebCore/rendering/RenderBlock.cpp: (WebCore::RenderBlock::simplifiedLayout): (WebCore::RenderBlock::layoutPositionedObject): (WebCore::RenderBlock::paintContents): (WebCore::RenderBlock::adjustBorderBoxRectForPainting): (WebCore::RenderBlock::paintRectToClipOutFromBorder): (WebCore::RenderBlock::paintExcludedChildrenInBorder): * Source/WebCore/rendering/RenderBlockFlow.cpp: (WebCore::RenderBlockFlow::layoutBlockChildren): * Source/WebCore/rendering/RenderBox.cpp: (WebCore::RenderBox::foregroundIsKnownToBeOpaqueInRect const): (WebCore::RenderBox::explicitIntrinsicInnerWidth const): (WebCore::RenderBox::explicitIntrinsicInnerHeight const): * Source/WebCore/rendering/RenderElement.cpp: (WebCore::RenderElement::styleWillChange): (WebCore::RenderElement::layoutIfNeeded): (WebCore::RenderElement::isSkippedContentRoot const): Deleted. * Source/WebCore/rendering/RenderElement.h: (WebCore::RenderObject::isSkippedContentRoot const): Deleted. * Source/WebCore/rendering/RenderElementInlines.h: (WebCore::RenderElement::shouldApplyInlineSizeContainment const): (WebCore::RenderElement::shouldApplySizeContainment const): (WebCore::RenderElement::shouldApplySizeOrInlineSizeContainment const): (WebCore::isSkippedContentRoot): * Source/WebCore/rendering/RenderGrid.cpp: (WebCore::RenderGrid::layoutPositionedObject): * Source/WebCore/rendering/RenderObject.cpp: (WebCore::RenderObject::isSkippedContentForLayout const): Deleted. * Source/WebCore/rendering/RenderObject.h: * Source/WebCore/rendering/RenderObjectInlines.h: (WebCore::RenderObject::layoutContext const): * Source/WebCore/rendering/RenderReplaced.cpp: (WebCore::RenderReplaced::paint): * Source/WebCore/rendering/RenderWidget.cpp: (WebCore::RenderWidget::paint): * Source/WebCore/rendering/style/RenderStyle.h: * Source/WebCore/rendering/style/RenderStyleInlines.h: (WebCore::doesSizeContainmentApplyByStyle): (WebCore::isSkippedContentRoot): Deleted. * Source/WebCore/rendering/updating/RenderTreeUpdater.cpp: (WebCore::RenderTreeUpdater::updateElementRenderer): * Source/WebCore/style/StyleAdjuster.cpp: (WebCore::Style::Adjuster::adjust const): Canonical link: https://commits.webkit.org/286858@main
1 parent d217834 commit 0fce63b

20 files changed

+91
-78
lines changed

Source/WebCore/dom/Document.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@
216216
#include "RealtimeMediaSourceCenter.h"
217217
#include "RenderBoxInlines.h"
218218
#include "RenderChildIterator.h"
219+
#include "RenderElementInlines.h"
219220
#include "RenderInline.h"
220221
#include "RenderLayerCompositor.h"
221222
#include "RenderLayoutState.h"
@@ -443,7 +444,7 @@ static void CallbackForContainIntrinsicSize(const Vector<Ref<ResizeObserverEntry
443444
observer.unobserve(*target);
444445
continue;
445446
}
446-
ASSERT(!box->isSkippedContentRoot());
447+
ASSERT(!isSkippedContentRoot(*box));
447448
ASSERT(box->style().hasAutoLengthContainIntrinsicSize());
448449

449450
auto contentBoxSize = entry->contentBoxSize().at(0);
@@ -2082,7 +2083,7 @@ std::optional<BoundaryPoint> Document::caretPositionFromPoint(const LayoutPoint&
20822083
if (!renderer)
20832084
return std::nullopt;
20842085

2085-
if (renderer->isSkippedContentRoot())
2086+
if (auto* renderElement = dynamicDowncast<RenderElement>(*renderer); renderElement && isSkippedContentRoot(*renderElement))
20862087
return { { *node, 0 } };
20872088

20882089
auto rangeCompliantPosition = renderer->positionForPoint(localPoint, source).parentAnchoredEquivalent();

Source/WebCore/editing/TextIterator.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "NodeTraversal.h"
5454
#include "Range.h"
5555
#include "RenderBoxInlines.h"
56+
#include "RenderElementInlines.h"
5657
#include "RenderImage.h"
5758
#include "RenderIterator.h"
5859
#include "RenderTableCell.h"
@@ -488,9 +489,9 @@ void TextIterator::advance()
488489
if (!isRendererVisible(renderer.get(), m_behaviors)) {
489490
m_handledNode = true;
490491
m_handledChildren = !hasDisplayContents(*protectedCurrentNode()) && !renderer;
491-
} else if (is<Element>(m_currentNode.get()) && renderer->isSkippedContentRoot()) {
492+
} else if (auto* renderElement = dynamicDowncast<RenderElement>(renderer.get()); renderElement && isSkippedContentRoot(*renderElement))
492493
m_handledChildren = true;
493-
} else {
494+
else {
494495
// handle current node according to its type
495496
if (renderer->isRenderText() && m_currentNode->isTextNode())
496497
m_handledNode = handleTextNode();

Source/WebCore/page/LocalFrameViewLayoutContext.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "Quirks.h"
3636
#include "RenderElement.h"
3737
#include "RenderLayoutState.h"
38+
#include "RenderStyle.h"
3839
#include "RenderStyleInlines.h"
3940
#include "RenderView.h"
4041
#include "ScriptDisallowedScope.h"
@@ -577,7 +578,21 @@ void LocalFrameViewLayoutContext::addLayoutDelta(const LayoutSize& delta)
577578
if (auto* layoutState = this->layoutState())
578579
layoutState->addLayoutDelta(delta);
579580
}
580-
581+
582+
bool LocalFrameViewLayoutContext::isSkippedContentForLayout(const RenderElement& renderer) const
583+
{
584+
if (needsSkippedContentLayout())
585+
return false;
586+
return renderer.isSkippedContent();
587+
}
588+
589+
bool LocalFrameViewLayoutContext::isSkippedContentRootForLayout(const RenderElement& renderer) const
590+
{
591+
if (needsSkippedContentLayout())
592+
return false;
593+
return isSkippedContentRoot(renderer);
594+
}
595+
581596
#if ASSERT_ENABLED
582597
bool LocalFrameViewLayoutContext::layoutDeltaMatches(const LayoutSize& delta)
583598
{

Source/WebCore/page/LocalFrameViewLayoutContext.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,11 @@ class LocalFrameViewLayoutContext final : public CanMakeCheckedPtr<LocalFrameVie
9595
bool isInRenderTreeLayout() const { return layoutPhase() == LayoutPhase::InRenderTreeLayout; }
9696
bool inPaintableState() const { return layoutPhase() != LayoutPhase::InRenderTreeLayout && layoutPhase() != LayoutPhase::InViewSizeAdjust && (layoutPhase() != LayoutPhase::InPostLayout || inAsynchronousTasks()); }
9797

98-
bool needsSkippedContentLayout() const { return m_needsSkippedContentLayout; }
9998
void setNeedsSkippedContentLayout(bool needsSkippedContentLayout) { m_needsSkippedContentLayout = needsSkippedContentLayout; }
10099

100+
bool isSkippedContentForLayout(const RenderElement&) const;
101+
bool isSkippedContentRootForLayout(const RenderElement&) const;
102+
101103
RenderElement* subtreeLayoutRoot() const;
102104
void clearSubtreeLayoutRoot() { m_subtreeLayoutRoot.clear(); }
103105
void convertSubtreeLayoutToFullLayout();
@@ -174,6 +176,8 @@ class LocalFrameViewLayoutContext final : public CanMakeCheckedPtr<LocalFrameVie
174176
void disablePaintOffsetCache() { m_paintOffsetCacheDisableCount++; }
175177
void enablePaintOffsetCache() { ASSERT(m_paintOffsetCacheDisableCount > 0); m_paintOffsetCacheDisableCount--; }
176178

179+
bool needsSkippedContentLayout() const { return m_needsSkippedContentLayout; }
180+
177181
LocalFrame& frame() const;
178182
Ref<LocalFrame> protectedFrame();
179183
LocalFrameView& view() const;

Source/WebCore/rendering/RenderBlock.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ bool RenderBlock::simplifiedLayout()
791791
return false;
792792

793793
bool canContainFixedPosObjects = canContainFixedPositionObjects();
794-
if (isSkippedContentRoot() && (posChildNeedsLayout() || canContainFixedPosObjects))
794+
if (layoutContext().isSkippedContentRootForLayout(*this) && (posChildNeedsLayout() || canContainFixedPosObjects))
795795
return false;
796796

797797
// Lay out positioned descendants or objects that just need to recompute overflow.
@@ -876,7 +876,7 @@ LayoutUnit RenderBlock::marginIntrinsicLogicalWidthForChild(RenderBox& child) co
876876

877877
void RenderBlock::layoutPositionedObject(RenderBox& r, bool relayoutChildren, bool fixedPositionObjectsOnly)
878878
{
879-
if (isSkippedContentRoot()) {
879+
if (layoutContext().isSkippedContentRootForLayout(*this)) {
880880
r.clearNeedsLayoutForSkippedContent();
881881
return;
882882
}
@@ -1029,7 +1029,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
10291029

10301030
void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
10311031
{
1032-
if (isSkippedContentRoot())
1032+
if (isSkippedContentRoot(*this))
10331033
return;
10341034

10351035
if (childrenInline())
@@ -3315,7 +3315,7 @@ RenderBox* RenderBlock::findFieldsetLegend(FieldsetFindLegendOption option) cons
33153315

33163316
void RenderBlock::adjustBorderBoxRectForPainting(LayoutRect& paintRect)
33173317
{
3318-
if (!isFieldset() || isSkippedContentRoot() || !intrinsicBorderForFieldset())
3318+
if (!isFieldset() || isSkippedContentRoot(*this) || !intrinsicBorderForFieldset())
33193319
return;
33203320

33213321
auto* legend = findFieldsetLegend();
@@ -3338,7 +3338,7 @@ void RenderBlock::adjustBorderBoxRectForPainting(LayoutRect& paintRect)
33383338
LayoutRect RenderBlock::paintRectToClipOutFromBorder(const LayoutRect& paintRect)
33393339
{
33403340
LayoutRect clipRect;
3341-
if (!isFieldset() || isSkippedContentRoot())
3341+
if (!isFieldset() || isSkippedContentRoot(*this))
33423342
return clipRect;
33433343
auto* legend = findFieldsetLegend();
33443344
if (!legend)
@@ -3494,7 +3494,7 @@ LayoutUnit RenderBlock::adjustIntrinsicLogicalHeightForBoxSizing(LayoutUnit heig
34943494

34953495
void RenderBlock::paintExcludedChildrenInBorder(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
34963496
{
3497-
if (!isFieldset() || isSkippedContentRoot())
3497+
if (!isFieldset() || isSkippedContentRoot(*this))
34983498
return;
34993499

35003500
RenderBox* box = findFieldsetLegend();

Source/WebCore/rendering/RenderBlockFlow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max
759759
if (child.isExcludedFromNormalLayout())
760760
continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
761761

762-
if (child.isSkippedContentForLayout()) {
762+
if (layoutContext().isSkippedContentForLayout(child)) {
763763
child.clearNeedsLayoutForSkippedContent();
764764
continue;
765765
}

Source/WebCore/rendering/RenderBox.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,7 @@ bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, u
18511851
if (!maxDepthToTest)
18521852
return false;
18531853

1854-
if (isSkippedContentRoot())
1854+
if (isSkippedContentRoot(*this))
18551855
return false;
18561856

18571857
for (auto& childBox : childrenOfType<RenderBox>(*this)) {
@@ -5836,7 +5836,7 @@ std::optional<LayoutUnit> RenderBox::explicitIntrinsicInnerWidth() const
58365836
if (style().containIntrinsicWidthType() == ContainIntrinsicSizeType::None)
58375837
return std::nullopt;
58385838

5839-
if (element() && style().containIntrinsicWidthHasAuto() && WebCore::isSkippedContentRoot(style(), element())) {
5839+
if (element() && style().containIntrinsicWidthHasAuto() && isSkippedContentRoot(*this)) {
58405840
if (auto width = isHorizontalWritingMode() ? element()->lastRememberedLogicalWidth() : element()->lastRememberedLogicalHeight())
58415841
return width;
58425842
}
@@ -5855,7 +5855,7 @@ std::optional<LayoutUnit> RenderBox::explicitIntrinsicInnerHeight() const
58555855
if (style().containIntrinsicHeightType() == ContainIntrinsicSizeType::None)
58565856
return std::nullopt;
58575857

5858-
if (element() && style().containIntrinsicHeightHasAuto() && WebCore::isSkippedContentRoot(style(), element())) {
5858+
if (element() && style().containIntrinsicHeightHasAuto() && isSkippedContentRoot(*this)) {
58595859
if (auto height = isHorizontalWritingMode() ? element()->lastRememberedLogicalHeight() : element()->lastRememberedLogicalWidth())
58605860
return height;
58615861
}

Source/WebCore/rendering/RenderElement.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& new
889889
if (wasVisible != willBeVisible) {
890890
if (CheckedPtr layer = enclosingLayer()) {
891891
if (willBeVisible) {
892-
if (m_style.hasSkippedContent() && isSkippedContentRoot())
892+
if (m_style.hasSkippedContent() && isSkippedContentRoot(*this))
893893
layer->dirtyVisibleContentStatus();
894894
else
895895
layer->setHasVisibleContent();
@@ -2527,11 +2527,6 @@ void RenderElement::markRendererDirtyAfterTopLayerChange(RenderElement* renderer
25272527
renderBox->setNeedsLayout();
25282528
}
25292529

2530-
bool RenderElement::isSkippedContentRoot() const
2531-
{
2532-
return WebCore::isSkippedContentRoot(style(), element()) && !view().frameView().layoutContext().needsSkippedContentLayout();
2533-
}
2534-
25352530
bool RenderElement::hasEligibleContainmentForSizeQuery() const
25362531
{
25372532
switch (style().containerType()) {
@@ -2557,7 +2552,7 @@ void RenderElement::layoutIfNeeded()
25572552
{
25582553
if (!needsLayout())
25592554
return;
2560-
if (isSkippedContentForLayout()) {
2555+
if (layoutContext().isSkippedContentForLayout(*this)) {
25612556
clearNeedsLayoutForSkippedContent();
25622557
return;
25632558
}

Source/WebCore/rendering/RenderElement.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,6 @@ class RenderElement : public RenderObject {
292292

293293
static void markRendererDirtyAfterTopLayerChange(RenderElement* renderer, RenderBlock* containingBlockBeforeStyleResolution);
294294

295-
bool isSkippedContentRoot() const;
296-
297295
void clearNeedsLayoutForSkippedContent();
298296

299297
void setRenderBoxHasShapeOutsideInfo(bool b) { m_renderBoxHasShapeOutsideInfo = b; }
@@ -428,6 +426,7 @@ class RenderElement : public RenderObject {
428426
inline int adjustForAbsoluteZoom(int, const RenderElement&);
429427
inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit, const RenderElement&);
430428
inline LayoutSize adjustLayoutSizeForAbsoluteZoom(LayoutSize, const RenderElement&);
429+
inline bool isSkippedContentRoot(const RenderElement&);
431430

432431
inline void RenderElement::setChildNeedsLayout(MarkingBehavior markParents)
433432
{
@@ -493,13 +492,6 @@ inline RenderObject* RenderElement::lastInFlowChild() const
493492
return nullptr;
494493
}
495494

496-
inline bool RenderObject::isSkippedContentRoot() const
497-
{
498-
if (isRenderText())
499-
return false;
500-
return downcast<RenderElement>(*this).isSkippedContentRoot();
501-
}
502-
503495
inline RenderElement* RenderObject::parent() const
504496
{
505497
return m_parent.get();

Source/WebCore/rendering/RenderElementInlines.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ inline bool RenderElement::shouldApplyAnyContainment() const
7575

7676
inline bool RenderElement::shouldApplyInlineSizeContainment() const
7777
{
78-
return WebCore::isSkippedContentRoot(style(), element()) || shouldApplySizeOrStyleContainment(style().containsInlineSize());
78+
return isSkippedContentRoot(*this) || shouldApplySizeOrStyleContainment(style().containsInlineSize());
7979
}
8080

8181
inline bool RenderElement::shouldApplyLayoutContainment() const
@@ -100,12 +100,12 @@ inline bool RenderElement::shouldApplyPaintContainment() const
100100

101101
inline bool RenderElement::shouldApplySizeContainment() const
102102
{
103-
return WebCore::isSkippedContentRoot(style(), element()) || shouldApplySizeOrStyleContainment(style().containsSize());
103+
return isSkippedContentRoot(*this) || shouldApplySizeOrStyleContainment(style().containsSize());
104104
}
105105

106106
inline bool RenderElement::shouldApplySizeOrInlineSizeContainment() const
107107
{
108-
return WebCore::isSkippedContentRoot(style(), element()) || shouldApplySizeOrStyleContainment(style().containsSizeOrInlineSize());
108+
return isSkippedContentRoot(*this) || shouldApplySizeOrStyleContainment(style().containsSizeOrInlineSize());
109109
}
110110

111111
// FIXME: try to avoid duplication with isSkippedContentRoot.
@@ -142,4 +142,18 @@ inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, const Render
142142
return adjustLayoutUnitForAbsoluteZoom(value, renderer.style());
143143
}
144144

145+
inline bool isSkippedContentRoot(const RenderElement& renderer)
146+
{
147+
auto& style = renderer.style();
148+
if (style.contentVisibility() == ContentVisibility::Visible)
149+
return false;
150+
// content-visibility applies to elements for which size containment can apply (https://drafts.csswg.org/css-contain/#content-visibility)
151+
if (!doesSizeContainmentApplyByDisplayType(style))
152+
return false;
153+
if (style.contentVisibility() == ContentVisibility::Hidden)
154+
return true;
155+
ASSERT(style.contentVisibility() == ContentVisibility::Auto);
156+
return renderer.element() && !renderer.element()->isRelevantToUser();
157+
}
158+
145159
} // namespace WebCore

0 commit comments

Comments
 (0)