Bug 1791760 - Move GetContainSizeAxes to nsIFrame r=emilio

This will allow this function to eventually return an appropriate value
depending on whether or not content is skipped via `content-visibility:
auto`. This change also starts looking directly at whether
content-visibility is skipping content or not, which should make it
compatible with a future `content-visibility: auto` implementation.

Differential Revision: https://phabricator.services.mozilla.com/D157831
This commit is contained in:
Martin Robinson 2022-09-22 12:11:09 +00:00
parent a26af613a4
commit 3b0ff9fae9
12 changed files with 58 additions and 51 deletions

View File

@ -565,7 +565,7 @@ static void LastRememberedSizeCallback(
"Should have removed the last remembered block size.");
MOZ_ASSERT(canRememberISize || !target->HasLastRememberedISize(),
"Should have removed the last remembered inline size.");
const auto containAxes = frame->StyleDisplay()->GetContainSizeAxes();
const auto containAxes = frame->GetContainSizeAxes();
bool canUpdateBSize = canRememberBSize && !containAxes.mBContained;
bool canUpdateISize = canRememberISize && !containAxes.mIContained;
MOZ_ASSERT(canUpdateBSize || canUpdateISize,

View File

@ -213,7 +213,7 @@ nscoord nsListControlFrame::CalcBSizeOfARow() {
// either of which may be visible or invisible, may use different
// fonts, etc.
nscoord rowBSize(0);
if (StyleDisplay()->GetContainSizeAxes().mBContained ||
if (GetContainSizeAxes().mBContained ||
!GetMaxRowBSize(GetOptionsContainer(), GetWritingMode(), &rowBSize)) {
// We don't have any <option>s or <optgroup> labels with a frame.
// (Or we're size-contained in block axis, which has the same outcome for

View File

@ -427,7 +427,7 @@ void ReflowInput::Init(nsPresContext* aPresContext,
}
}
if (mStyleDisplay->GetContainSizeAxes().mBContained) {
if (mFrame->GetContainSizeAxes().mBContained) {
// In the case that a box is size contained in block axis, we want to ensure
// that it is also monolithic. We do this by setting AvailableBSize() to an
// unconstrained size to avoid fragmentation.

View File

@ -584,9 +584,8 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
// First, compute our inside-border size and scrollport size
// XXXldb Can we depend more on ComputeSize here?
nsSize kidSize =
aState.mReflowInput.mStyleDisplay->GetContainSizeAxes().ContainSize(
aKidMetrics->PhysicalSize(), *aState.mReflowInput.mFrame);
nsSize kidSize = GetContainSizeAxes().ContainSize(
aKidMetrics->PhysicalSize(), *aState.mReflowInput.mFrame);
const nsSize desiredInsideBorderSize = kidSize + scrollbarGutterSize;
aState.mInsideBorderSize =
ComputeInsideBorderSize(aState, desiredInsideBorderSize);
@ -997,9 +996,8 @@ void nsHTMLScrollFrame::ReflowContents(ScrollReflowInput& aState,
aState.mReflowedContentsWithVScrollbar) &&
aState.mVScrollbar != ShowScrollbar::Always &&
aState.mHScrollbar != ShowScrollbar::Always) {
nsSize kidSize =
aState.mReflowInput.mStyleDisplay->GetContainSizeAxes().ContainSize(
kidDesiredSize.PhysicalSize(), *aState.mReflowInput.mFrame);
nsSize kidSize = GetContainSizeAxes().ContainSize(
kidDesiredSize.PhysicalSize(), *aState.mReflowInput.mFrame);
nsSize insideBorderSize = ComputeInsideBorderSize(aState, kidSize);
nsRect scrolledRect = mHelper.GetUnsnappedScrolledRectInternal(
kidDesiredSize.ScrollableOverflow(), insideBorderSize);

View File

@ -437,7 +437,7 @@ nscoord nsHTMLCanvasFrame::GetPrefISize(gfxContext* aRenderingContext) {
/* virtual */
IntrinsicSize nsHTMLCanvasFrame::GetIntrinsicSize() {
const auto containAxes = StyleDisplay()->GetContainSizeAxes();
const auto containAxes = GetContainSizeAxes();
IntrinsicSize size = containAxes.IsBoth()
? IntrinsicSize(0, 0)
: IntrinsicSizeFromCanvasSize(GetCanvasSize());
@ -446,7 +446,7 @@ IntrinsicSize nsHTMLCanvasFrame::GetIntrinsicSize() {
/* virtual */
AspectRatio nsHTMLCanvasFrame::GetIntrinsicRatio() const {
if (StyleDisplay()->GetContainSizeAxes().IsAny()) {
if (GetContainSizeAxes().IsAny()) {
return AspectRatio();
}

View File

@ -724,9 +724,7 @@ void nsIFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
PresContext()->RegisterContainerQueryFrame(this);
}
if (disp->IsContainLayout() && disp->GetContainSizeAxes().IsBoth() &&
// All frames that support contain:layout also support contain:size.
IsFrameOfType(eSupportsContainLayoutAndPaint) && !IsTableWrapperFrame()) {
if (disp->IsContainLayout() && GetContainSizeAxes().IsBoth()) {
// In general, frames that have contain:layout+size can be reflow roots.
// (One exception: table-wrapper frames don't work well as reflow roots,
// because their inner-table ReflowInput init path tries to reuse & deref
@ -1445,7 +1443,7 @@ void nsIFrame::HandleLastRememberedSize() {
element->RemoveLastRememberedISize();
}
if (canRememberBSize || canRememberISize) {
const auto containAxes = StyleDisplay()->GetContainSizeAxes();
const auto containAxes = GetContainSizeAxes();
if ((canRememberBSize && !containAxes.mBContained) ||
(canRememberISize && !containAxes.mIContained)) {
bool isNonReplacedInline = IsFrameOfType(nsIFrame::eLineParticipant) &&
@ -11354,6 +11352,33 @@ gfx::Matrix nsIFrame::ComputeWidgetTransform() {
return result2d;
}
ContainSizeAxes nsIFrame::GetContainSizeAxes() const {
auto contain = StyleDisplay()->EffectiveContainment();
// Short circuit for no containment whatsoever
if (MOZ_LIKELY(!contain)) {
return ContainSizeAxes(false, false);
}
// Note: The spec for size containment says it should have no effect on
// non-atomic, inline-level boxes.
bool isNonReplacedInline = IsFrameOfType(nsIFrame::eLineParticipant) &&
!IsFrameOfType(nsIFrame::eReplaced);
if (isNonReplacedInline || StyleDisplay()->PrecludesSizeContainment()) {
return ContainSizeAxes(false, false);
}
// https://drafts.csswg.org/css-contain-2/#content-visibility
// If this content skips its content via content-visibility, it always has
// size containment.
if (MOZ_LIKELY(!(contain & StyleContain::SIZE)) &&
MOZ_UNLIKELY(HidesContent())) {
contain |= StyleContain::SIZE;
}
return ContainSizeAxes(static_cast<bool>(contain & StyleContain::INLINE_SIZE),
static_cast<bool>(contain & StyleContain::BLOCK_SIZE));
}
void nsIFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoRestyleState& aRestyleState) {
// As a special case, we check for {ib}-split block frames here, rather
// than have an nsInlineFrame::AppendDirectlyOwnedAnonBoxes implementation

View File

@ -3988,14 +3988,14 @@ class nsIFrame : public nsQueryFrame {
}
}
mozilla::ContainSizeAxes GetContainSizeAxes() const;
Maybe<nscoord> ContainIntrinsicBSize(nscoord aNoneValue = 0) const {
return StyleDisplay()->GetContainSizeAxes().ContainIntrinsicBSize(
*this, aNoneValue);
return GetContainSizeAxes().ContainIntrinsicBSize(*this, aNoneValue);
}
Maybe<nscoord> ContainIntrinsicISize(nscoord aNoneValue = 0) const {
return StyleDisplay()->GetContainSizeAxes().ContainIntrinsicISize(
*this, aNoneValue);
return GetContainSizeAxes().ContainIntrinsicISize(*this, aNoneValue);
}
protected:

View File

@ -623,7 +623,7 @@ static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage,
bool aUseMappedRatio,
nsImageFrame::Kind aKind,
const nsImageFrame& aFrame) {
const auto containAxes = aFrame.StyleDisplay()->GetContainSizeAxes();
const auto containAxes = aFrame.GetContainSizeAxes();
if (containAxes.IsBoth()) {
return containAxes.ContainIntrinsicSize(IntrinsicSize(0, 0), aFrame);
}
@ -703,8 +703,7 @@ bool nsImageFrame::UpdateIntrinsicSize() {
static AspectRatio ComputeIntrinsicRatio(imgIContainer* aImage,
bool aUseMappedRatio,
const nsImageFrame& aFrame) {
const ComputedStyle& style = *aFrame.Style();
if (style.StyleDisplay()->GetContainSizeAxes().IsAny()) {
if (aFrame.GetContainSizeAxes().IsAny()) {
return AspectRatio();
}
@ -714,7 +713,7 @@ static AspectRatio ComputeIntrinsicRatio(imgIContainer* aImage,
}
}
if (aUseMappedRatio) {
const StyleAspectRatio& ratio = style.StylePosition()->mAspectRatio;
const StyleAspectRatio& ratio = aFrame.StylePosition()->mAspectRatio;
if (ratio.auto_ && ratio.HasRatio()) {
// Return the mapped intrinsic aspect ratio stored in
// nsStylePosition::mAspectRatio.
@ -1202,7 +1201,7 @@ bool nsImageFrame::IsForMarkerPseudo() const {
}
void nsImageFrame::EnsureIntrinsicSizeAndRatio() {
const auto containAxes = StyleDisplay()->GetContainSizeAxes();
const auto containAxes = GetContainSizeAxes();
if (containAxes.IsBoth()) {
// If we have 'contain:size', then we have no intrinsic aspect ratio,
// and the intrinsic size is determined by contain-intrinsic-size,

View File

@ -623,7 +623,7 @@ nscoord nsSubDocumentFrame::GetPrefISize(gfxContext* aRenderingContext) {
/* virtual */
IntrinsicSize nsSubDocumentFrame::GetIntrinsicSize() {
const auto containAxes = StyleDisplay()->GetContainSizeAxes();
const auto containAxes = GetContainSizeAxes();
if (containAxes.IsBoth()) {
// Intrinsic size of 'contain:size' replaced elements is determined by
// contain-intrinsic-size.

View File

@ -311,7 +311,7 @@ void nsVideoFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
// Resolve our own BSize based on the controls' size in the
// same axis. Unless we're size-contained, in which case we
// have to behave as if we have an intrinsic size of 0.
if (aReflowInput.mStyleDisplay->GetContainSizeAxes().mBContained) {
if (GetContainSizeAxes().mBContained) {
contentBoxBSize = 0;
} else {
contentBoxBSize = myWM.IsOrthogonalTo(wm) ? kidDesiredSize.ISize(wm)
@ -420,7 +420,7 @@ AspectRatio nsVideoFrame::GetIntrinsicRatio() const {
}
// 'contain:[inline-]size' replaced elements have no intrinsic ratio.
if (StyleDisplay()->GetContainSizeAxes().IsAny()) {
if (GetContainSizeAxes().IsAny()) {
return AspectRatio();
}
@ -470,7 +470,7 @@ bool nsVideoFrame::ShouldDisplayPoster() const {
}
IntrinsicSize nsVideoFrame::GetIntrinsicSize() {
const auto containAxes = StyleDisplay()->GetContainSizeAxes();
const auto containAxes = GetContainSizeAxes();
const auto isVideo = HasVideoElement();
// Intrinsic size will be given by contain-intrinsic-size if the element is
// size-contained. If both axes have containment, ContainIntrinsicSize() will

View File

@ -1543,27 +1543,10 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
bool IsContainAny() const { return !!EffectiveContainment(); }
mozilla::ContainSizeAxes GetContainSizeAxes() const {
const auto contain = EffectiveContainment();
// Short circuit for no containment whatsoever
if (!contain) {
return mozilla::ContainSizeAxes(false, false);
}
// Note: The spec for size containment says it should
// have no effect on non-atomic, inline-level boxes. We
// don't check for these here because we don't know
// what type of element is involved. Callers are
// responsible for checking if the box in question is
// non-atomic and inline-level, and creating an
// exemption as necessary.
if (IsInternalRubyDisplayType() ||
DisplayInside() == mozilla::StyleDisplayInside::Table ||
IsInnerTableStyle()) {
return mozilla::ContainSizeAxes(false, false);
}
return mozilla::ContainSizeAxes(
static_cast<bool>(contain & StyleContain::INLINE_SIZE),
static_cast<bool>(contain & StyleContain::BLOCK_SIZE));
bool PrecludesSizeContainment() const {
return IsInternalRubyDisplayType() ||
DisplayInside() == mozilla::StyleDisplayInside::Table ||
IsInnerTableStyle();
}
bool IsContentVisibilityVisible() const {
@ -1685,7 +1668,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const;
inline bool IsFixedPosContainingBlockForTransformSupportingFrames() const;
private:
StyleContain EffectiveContainment() const {
auto contain = mContain;
// content-visibility and container-type implicitly enable some containment
@ -1699,6 +1681,9 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
case StyleContentVisibility::Visible:
break;
case StyleContentVisibility::Auto:
// `content-visibility:auto` also applies size containment when content
// is not relevant (and therefore skipped). This is checked in
// nsIFrame::GetContainSizeAxes.
contain |=
StyleContain::LAYOUT | StyleContain::PAINT | StyleContain::STYLE;
break;

View File

@ -95,7 +95,7 @@ static inline ContainSizeAxes ContainSizeAxesIfApplicable(
if (!aFrame->GetContent()->GetParent()) {
return ContainSizeAxes(false, false);
}
return aFrame->StyleDisplay()->GetContainSizeAxes();
return aFrame->GetContainSizeAxes();
}
void SVGOuterSVGFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,