Bug 1923763: Part 5 - Replace inset evaluations with anchor-resolved inset evaluations. r=layout-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D231259
This commit is contained in:
David Shin
2025-01-21 15:11:25 +00:00
parent 7e571d68da
commit 3d615cb7f6
16 changed files with 211 additions and 138 deletions

View File

@@ -3793,8 +3793,10 @@ bool PresShell::ScrollFrameIntoView(
// If we're targetting a sticky element, make sure not to apply // If we're targetting a sticky element, make sure not to apply
// scroll-padding on the direction we're stuck. // scroll-padding on the direction we're stuck.
const auto* stylePosition = aFrame->StylePosition(); const auto* stylePosition = aFrame->StylePosition();
const auto positionProperty = aFrame->StyleDisplay()->mPosition;
for (auto side : AllPhysicalSides()) { for (auto side : AllPhysicalSides()) {
if (stylePosition->GetInset(side).IsAuto()) { if (stylePosition->GetAnchorResolvedInset(side, positionProperty)
.IsAuto()) {
continue; continue;
} }
// See if this axis is stuck. // See if this axis is stuck.

View File

@@ -1263,16 +1263,24 @@ SideBits nsLayoutUtils::GetSideBitsForFixedPositionContent(
SideBits sides = SideBits::eNone; SideBits sides = SideBits::eNone;
if (aFixedPosFrame) { if (aFixedPosFrame) {
const nsStylePosition* position = aFixedPosFrame->StylePosition(); const nsStylePosition* position = aFixedPosFrame->StylePosition();
if (!position->GetInset(eSideRight).IsAuto()) { if (!position
->GetAnchorResolvedInset(eSideRight, StylePositionProperty::Fixed)
.IsAuto()) {
sides |= SideBits::eRight; sides |= SideBits::eRight;
} }
if (!position->GetInset(eSideLeft).IsAuto()) { if (!position
->GetAnchorResolvedInset(eSideLeft, StylePositionProperty::Fixed)
.IsAuto()) {
sides |= SideBits::eLeft; sides |= SideBits::eLeft;
} }
if (!position->GetInset(eSideBottom).IsAuto()) { if (!position
->GetAnchorResolvedInset(eSideBottom, StylePositionProperty::Fixed)
.IsAuto()) {
sides |= SideBits::eBottom; sides |= SideBits::eBottom;
} }
if (!position->GetInset(eSideTop).IsAuto()) { if (!position
->GetAnchorResolvedInset(eSideTop, StylePositionProperty::Fixed)
.IsAuto()) {
sides |= SideBits::eTop; sides |= SideBits::eTop;
} }
} }

View File

@@ -742,8 +742,9 @@ void ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
!mStylePosition->BSize(wm).IsAuto()) || !mStylePosition->BSize(wm).IsAuto()) ||
mStylePosition->MinBSizeDependsOnContainer(wm) || mStylePosition->MinBSizeDependsOnContainer(wm) ||
mStylePosition->MaxBSizeDependsOnContainer(wm) || mStylePosition->MaxBSizeDependsOnContainer(wm) ||
mStylePosition->GetInset(LogicalSide::BStart, wm).HasPercent() || mStylePosition->mOffset.Get(LogicalSide::BStart, wm)
!mStylePosition->GetInset(LogicalSide::BEnd, wm).IsAuto(); .MaybePercentageAware() ||
!mStylePosition->mOffset.Get(LogicalSide::BEnd, wm).MaybeAuto();
// If mFrame is a flex item, and mFrame's block axis is the flex container's // If mFrame is a flex item, and mFrame's block axis is the flex container's
// main axis (e.g. in a column-oriented flex container with same // main axis (e.g. in a column-oriented flex container with same
@@ -852,15 +853,18 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
const LogicalSize& aCBSize) { const LogicalSize& aCBSize) {
LogicalMargin offsets(aWM); LogicalMargin offsets(aWM);
const nsStylePosition* position = aFrame->StylePosition(); const nsStylePosition* position = aFrame->StylePosition();
const auto positionProperty = aFrame->StyleDisplay()->mPosition;
// Compute the 'inlineStart' and 'inlineEnd' values. 'inlineStart' // Compute the 'inlineStart' and 'inlineEnd' values. 'inlineStart'
// moves the boxes to the end of the line, and 'inlineEnd' moves the // moves the boxes to the end of the line, and 'inlineEnd' moves the
// boxes to the start of the line. The computed values are always: // boxes to the start of the line. The computed values are always:
// inlineStart=-inlineEnd // inlineStart=-inlineEnd
const auto& inlineStart = position->GetInset(LogicalSide::IStart, aWM); const auto& inlineStart = position->GetAnchorResolvedInset(
const auto& inlineEnd = position->GetInset(LogicalSide::IEnd, aWM); LogicalSide::IStart, aWM, positionProperty);
bool inlineStartIsAuto = !inlineStart.IsLengthPercentage(); const auto& inlineEnd = position->GetAnchorResolvedInset(
bool inlineEndIsAuto = !inlineEnd.IsLengthPercentage(); LogicalSide::IEnd, aWM, positionProperty);
bool inlineStartIsAuto = inlineStart.IsAuto();
bool inlineEndIsAuto = inlineEnd.IsAuto();
// If neither 'inlineStart' nor 'inlineEnd' is auto, then we're // If neither 'inlineStart' nor 'inlineEnd' is auto, then we're
// over-constrained and we ignore one of them // over-constrained and we ignore one of them
@@ -873,9 +877,12 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
// If both are 'auto' (their initial values), the computed values are 0 // If both are 'auto' (their initial values), the computed values are 0
offsets.IStart(aWM) = offsets.IEnd(aWM) = 0; offsets.IStart(aWM) = offsets.IEnd(aWM) = 0;
} else { } else {
// 'inlineEnd' isn't 'auto' so compute its value // 'inlineEnd' isn't being treated as 'auto' so compute its value
offsets.IEnd(aWM) = offsets.IEnd(aWM) =
nsLayoutUtils::ComputeCBDependentValue(aCBSize.ISize(aWM), inlineEnd); inlineEnd.IsAuto()
? 0
: nsLayoutUtils::ComputeCBDependentValue(
aCBSize.ISize(aWM), inlineEnd.AsLengthPercentage());
// Computed value for 'inlineStart' is minus the value of 'inlineEnd' // Computed value for 'inlineStart' is minus the value of 'inlineEnd'
offsets.IStart(aWM) = -offsets.IEnd(aWM); offsets.IStart(aWM) = -offsets.IEnd(aWM);
@@ -885,8 +892,8 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
NS_ASSERTION(inlineEndIsAuto, "unexpected specified constraint"); NS_ASSERTION(inlineEndIsAuto, "unexpected specified constraint");
// 'InlineStart' isn't 'auto' so compute its value // 'InlineStart' isn't 'auto' so compute its value
offsets.IStart(aWM) = offsets.IStart(aWM) = nsLayoutUtils::ComputeCBDependentValue(
nsLayoutUtils::ComputeCBDependentValue(aCBSize.ISize(aWM), inlineStart); aCBSize.ISize(aWM), inlineStart.AsLengthPercentage());
// Computed value for 'inlineEnd' is minus the value of 'inlineStart' // Computed value for 'inlineEnd' is minus the value of 'inlineStart'
offsets.IEnd(aWM) = -offsets.IStart(aWM); offsets.IEnd(aWM) = -offsets.IStart(aWM);
@@ -896,8 +903,10 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
// and 'blockEnd' properties move relatively positioned elements in // and 'blockEnd' properties move relatively positioned elements in
// the block progression direction. They also must be each other's // the block progression direction. They also must be each other's
// negative // negative
const auto& blockStart = position->GetInset(LogicalSide::BStart, aWM); const auto& blockStart = position->GetAnchorResolvedInset(
const auto& blockEnd = position->GetInset(LogicalSide::BEnd, aWM); LogicalSide::BStart, aWM, positionProperty);
const auto& blockEnd = position->GetAnchorResolvedInset(
LogicalSide::BEnd, aWM, positionProperty);
bool blockStartIsAuto = blockStart.IsAuto(); bool blockStartIsAuto = blockStart.IsAuto();
bool blockEndIsAuto = blockEnd.IsAuto(); bool blockEndIsAuto = blockEnd.IsAuto();
@@ -922,9 +931,12 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
// If both are 'auto' (their initial values), the computed values are 0 // If both are 'auto' (their initial values), the computed values are 0
offsets.BStart(aWM) = offsets.BEnd(aWM) = 0; offsets.BStart(aWM) = offsets.BEnd(aWM) = 0;
} else { } else {
// 'blockEnd' isn't 'auto' so compute its value // 'blockEnd' isn't being treated as 'auto' so compute its value
offsets.BEnd(aWM) = offsets.BEnd(aWM) =
nsLayoutUtils::ComputeCBDependentValue(aCBSize.BSize(aWM), blockEnd); blockEnd.IsAuto()
? 0
: nsLayoutUtils::ComputeCBDependentValue(
aCBSize.BSize(aWM), blockEnd.AsLengthPercentage());
// Computed value for 'blockStart' is minus the value of 'blockEnd' // Computed value for 'blockStart' is minus the value of 'blockEnd'
offsets.BStart(aWM) = -offsets.BEnd(aWM); offsets.BStart(aWM) = -offsets.BEnd(aWM);
@@ -934,8 +946,8 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
NS_ASSERTION(blockEndIsAuto, "unexpected specified constraint"); NS_ASSERTION(blockEndIsAuto, "unexpected specified constraint");
// 'blockStart' isn't 'auto' so compute its value // 'blockStart' isn't 'auto' so compute its value
offsets.BStart(aWM) = offsets.BStart(aWM) = nsLayoutUtils::ComputeCBDependentValue(
nsLayoutUtils::ComputeCBDependentValue(aCBSize.BSize(aWM), blockStart); aCBSize.BSize(aWM), blockStart.AsLengthPercentage());
// Computed value for 'blockEnd' is minus the value of 'blockStart' // Computed value for 'blockEnd' is minus the value of 'blockStart'
offsets.BEnd(aWM) = -offsets.BStart(aWM); offsets.BEnd(aWM) = -offsets.BStart(aWM);
@@ -1554,8 +1566,8 @@ void ReflowInput::CalculateHypotheticalPosition(
bool ReflowInput::IsInlineSizeComputableByBlockSizeAndAspectRatio( bool ReflowInput::IsInlineSizeComputableByBlockSizeAndAspectRatio(
nscoord aBlockSize) const { nscoord aBlockSize) const {
WritingMode wm = GetWritingMode(); WritingMode wm = GetWritingMode();
MOZ_ASSERT(!mStylePosition->GetInset(LogicalSide::BStart, wm).IsAuto() && MOZ_ASSERT(!mStylePosition->mOffset.Get(LogicalSide::BStart, wm).IsAuto() &&
!mStylePosition->GetInset(LogicalSide::BEnd, wm).IsAuto(), !mStylePosition->mOffset.Get(LogicalSide::BEnd, wm).IsAuto(),
"If any of the block-start and block-end are auto, aBlockSize " "If any of the block-start and block-end are auto, aBlockSize "
"doesn't make sense"); "doesn't make sense");
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
@@ -1578,10 +1590,22 @@ bool ReflowInput::IsInlineSizeComputableByBlockSizeAndAspectRatio(
return false; return false;
} }
const auto position = mStyleDisplay->mPosition;
// If both inline insets are non-auto, mFrame->ComputeSize() should get a // If both inline insets are non-auto, mFrame->ComputeSize() should get a
// possible inline size by those insets, so we don't rely on aspect-ratio. // possible inline size by those insets, so we don't rely on aspect-ratio.
if (!mStylePosition->GetInset(LogicalSide::IStart, wm).IsAuto() && if (!mStylePosition->GetAnchorResolvedInset(LogicalSide::IStart, wm, position)
!mStylePosition->GetInset(LogicalSide::IEnd, wm).IsAuto()) { .IsAuto() &&
!mStylePosition->GetAnchorResolvedInset(LogicalSide::IEnd, wm, position)
.IsAuto()) {
return false;
}
// If block direction insets reference use any anchor positioning function
// that does not resolve, we can't rely on them.
if (mStylePosition->GetAnchorResolvedInset(LogicalSide::BStart, wm, position)
.IsAuto() ||
mStylePosition->GetAnchorResolvedInset(LogicalSide::BEnd, wm, position)
.IsAuto()) {
return false; return false;
} }
@@ -1661,12 +1685,14 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
NS_ASSERTION(mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW), NS_ASSERTION(mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW),
"Why are we here?"); "Why are we here?");
const auto& iStartOffset = const auto& iStartOffset = mStylePosition->GetAnchorResolvedInset(
mStylePosition->GetInset(LogicalSide::IStart, cbwm); LogicalSide::IStart, cbwm, StylePositionProperty::Absolute);
const auto& iEndOffset = mStylePosition->GetInset(LogicalSide::IEnd, cbwm); const auto& iEndOffset = mStylePosition->GetAnchorResolvedInset(
const auto& bStartOffset = LogicalSide::IEnd, cbwm, StylePositionProperty::Absolute);
mStylePosition->GetInset(LogicalSide::BStart, cbwm); const auto& bStartOffset = mStylePosition->GetAnchorResolvedInset(
const auto& bEndOffset = mStylePosition->GetInset(LogicalSide::BEnd, cbwm); LogicalSide::BStart, cbwm, StylePositionProperty::Absolute);
const auto& bEndOffset = mStylePosition->GetAnchorResolvedInset(
LogicalSide::BEnd, cbwm, StylePositionProperty::Absolute);
bool iStartIsAuto = iStartOffset.IsAuto(); bool iStartIsAuto = iStartOffset.IsAuto();
bool iEndIsAuto = iEndOffset.IsAuto(); bool iEndIsAuto = iEndOffset.IsAuto();
bool bStartIsAuto = bStartOffset.IsAuto(); bool bStartIsAuto = bStartOffset.IsAuto();
@@ -1752,13 +1778,13 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
offsets.IStart(cbwm) = 0; offsets.IStart(cbwm) = 0;
} else { } else {
offsets.IStart(cbwm) = nsLayoutUtils::ComputeCBDependentValue( offsets.IStart(cbwm) = nsLayoutUtils::ComputeCBDependentValue(
cbSize.ISize(cbwm), iStartOffset); cbSize.ISize(cbwm), iStartOffset.AsLengthPercentage());
} }
if (iEndIsAuto) { if (iEndIsAuto) {
offsets.IEnd(cbwm) = 0; offsets.IEnd(cbwm) = 0;
} else { } else {
offsets.IEnd(cbwm) = offsets.IEnd(cbwm) =
nsLayoutUtils::ComputeCBDependentValue(cbSize.ISize(cbwm), iEndOffset); nsLayoutUtils::ComputeCBDependentValue(cbSize.ISize(cbwm), iEndOffset.AsLengthPercentage());
} }
if (iStartIsAuto && iEndIsAuto) { if (iStartIsAuto && iEndIsAuto) {
@@ -1775,13 +1801,13 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
offsets.BStart(cbwm) = 0; offsets.BStart(cbwm) = 0;
} else { } else {
offsets.BStart(cbwm) = nsLayoutUtils::ComputeCBDependentValue( offsets.BStart(cbwm) = nsLayoutUtils::ComputeCBDependentValue(
cbSize.BSize(cbwm), bStartOffset); cbSize.BSize(cbwm), bStartOffset.AsLengthPercentage());
} }
if (bEndIsAuto) { if (bEndIsAuto) {
offsets.BEnd(cbwm) = 0; offsets.BEnd(cbwm) = 0;
} else { } else {
offsets.BEnd(cbwm) = offsets.BEnd(cbwm) =
nsLayoutUtils::ComputeCBDependentValue(cbSize.BSize(cbwm), bEndOffset); nsLayoutUtils::ComputeCBDependentValue(cbSize.BSize(cbwm), bEndOffset.AsLengthPercentage());
} }
if (bStartIsAuto && bEndIsAuto) { if (bStartIsAuto && bEndIsAuto) {

View File

@@ -65,8 +65,9 @@ StickyScrollContainer::GetStickyScrollContainerForScrollFrame(
static nscoord ComputeStickySideOffset(Side aSide, static nscoord ComputeStickySideOffset(Side aSide,
const nsStylePosition& aPosition, const nsStylePosition& aPosition,
nscoord aPercentBasis) { nscoord aPercentBasis) {
const auto& side = aPosition.GetInset(aSide); const auto& side =
if (!side.IsLengthPercentage()) { aPosition.GetAnchorResolvedInset(aSide, StylePositionProperty::Sticky);
if (side.IsAuto()) {
return NS_AUTOOFFSET; return NS_AUTOOFFSET;
} }
return nsLayoutUtils::ComputeCBDependentValue(aPercentBasis, return nsLayoutUtils::ComputeCBDependentValue(aPercentBasis,

View File

@@ -2125,11 +2125,6 @@ inline const mozilla::StyleMaxSize& nsStylePosition::MaxSize(
return aAxis == mozilla::LogicalAxis::Inline ? MaxISize(aWM) : MaxBSize(aWM); return aAxis == mozilla::LogicalAxis::Inline ? MaxISize(aWM) : MaxBSize(aWM);
} }
inline const mozilla::StyleInset& nsStylePosition::GetInset(
mozilla::LogicalSide aSide, mozilla::WritingMode aWM) const {
return GetInset(aWM.PhysicalSide(aSide));
}
inline bool nsStylePosition::ISizeDependsOnContainer(WritingMode aWM) const { inline bool nsStylePosition::ISizeDependsOnContainer(WritingMode aWM) const {
const auto& iSize = ISize(aWM); const auto& iSize = ISize(aWM);
return iSize.IsAuto() || ISizeCoordDependsOnContainer(iSize); return iSize.IsAuto() || ISizeCoordDependsOnContainer(iSize);

View File

@@ -286,6 +286,8 @@ static inline bool IsFixedMarginSize(const StyleMargin& aCoord) {
return aCoord.ConvertsToLength(); return aCoord.ConvertsToLength();
} }
static inline bool IsFixedOffset(const StyleInset& aInset) { static inline bool IsFixedOffset(const StyleInset& aInset) {
// For anchor positioning functions, even if the computed value may be a
// fixed length, it depends on the absolute containing block's size.
return aInset.ConvertsToLength(); return aInset.ConvertsToLength();
} }
@@ -340,8 +342,8 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// lengths? // lengths?
if ((pos->BSizeDependsOnContainer(wm) && if ((pos->BSizeDependsOnContainer(wm) &&
!(pos->BSize(wm).IsAuto() && !(pos->BSize(wm).IsAuto() &&
pos->GetInset(LogicalSide::BEnd, wm).IsAuto() && pos->mOffset.Get(LogicalSide::BEnd, wm).MaybeAuto() &&
!pos->GetInset(LogicalSide::BStart, wm).IsAuto())) || !pos->mOffset.Get(LogicalSide::BStart, wm).MaybeAuto())) ||
pos->MinBSizeDependsOnContainer(wm) || pos->MinBSizeDependsOnContainer(wm) ||
pos->MaxBSizeDependsOnContainer(wm) || pos->MaxBSizeDependsOnContainer(wm) ||
!IsFixedPaddingSize(padding->mPadding.GetBStart(wm)) || !IsFixedPaddingSize(padding->mPadding.GetBStart(wm)) ||
@@ -363,7 +365,7 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// sides (left and top) that we use to store coordinates, these tests // sides (left and top) that we use to store coordinates, these tests
// are easier to do using physical coordinates rather than logical. // are easier to do using physical coordinates rather than logical.
if (aCBWidthChanged) { if (aCBWidthChanged) {
if (!IsFixedOffset(pos->GetInset(eSideLeft))) { if (!IsFixedOffset(pos->mOffset.Get(eSideLeft))) {
return true; return true;
} }
// Note that even if 'left' is a length, our position can still // Note that even if 'left' is a length, our position can still
@@ -375,17 +377,17 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// sure of. // sure of.
if ((wm.GetInlineDir() == WritingMode::InlineDir::RTL || if ((wm.GetInlineDir() == WritingMode::InlineDir::RTL ||
wm.GetBlockDir() == WritingMode::BlockDir::RL) && wm.GetBlockDir() == WritingMode::BlockDir::RL) &&
!pos->GetInset(eSideRight).IsAuto()) { !pos->mOffset.Get(eSideRight).MaybeAuto()) {
return true; return true;
} }
} }
if (aCBHeightChanged) { if (aCBHeightChanged) {
if (!IsFixedOffset(pos->GetInset(eSideTop))) { if (!IsFixedOffset(pos->mOffset.Get(eSideTop))) {
return true; return true;
} }
// See comment above for width changes. // See comment above for width changes.
if (wm.GetInlineDir() == WritingMode::InlineDir::BTT && if (wm.GetInlineDir() == WritingMode::InlineDir::BTT &&
!pos->GetInset(eSideBottom).IsAuto()) { !pos->mOffset.Get(eSideBottom).MaybeAuto()) {
return true; return true;
} }
} }
@@ -925,12 +927,25 @@ void nsAbsoluteContainingBlock::ReflowAbsoluteFrame(
// align the child by its margin box: // align the child by its margin box:
// https://drafts.csswg.org/css-position-3/#abspos-layout // https://drafts.csswg.org/css-position-3/#abspos-layout
const auto* stylePos = aKidFrame->StylePosition(); const auto* stylePos = aKidFrame->StylePosition();
auto positionProperty = aKidFrame->StyleDisplay()->mPosition;
const bool iInsetAuto = const bool iInsetAuto =
stylePos->GetInset(LogicalSide::IStart, outerWM).IsAuto() || stylePos
stylePos->GetInset(LogicalSide::IEnd, outerWM).IsAuto(); ->GetAnchorResolvedInset(LogicalSide::IStart, outerWM,
positionProperty)
.IsAuto() ||
stylePos
->GetAnchorResolvedInset(LogicalSide::IEnd, outerWM,
positionProperty)
.IsAuto();
const bool bInsetAuto = const bool bInsetAuto =
stylePos->GetInset(LogicalSide::BStart, outerWM).IsAuto() || stylePos
stylePos->GetInset(LogicalSide::BEnd, outerWM).IsAuto(); ->GetAnchorResolvedInset(LogicalSide::BStart, outerWM,
positionProperty)
.IsAuto() ||
stylePos
->GetAnchorResolvedInset(LogicalSide::BEnd, outerWM,
positionProperty)
.IsAuto();
const LogicalSize logicalCBSizeOuterWM(outerWM, aContainingBlock.Size()); const LogicalSize logicalCBSizeOuterWM(outerWM, aContainingBlock.Size());
const LogicalSize kidMarginBox{ const LogicalSize kidMarginBox{
outerWM, margin.IStartEnd(outerWM) + kidSize.ISize(outerWM), outerWM, margin.IStartEnd(outerWM) + kidSize.ISize(outerWM),

View File

@@ -4640,8 +4640,8 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
if (bsize.HasPercent() || if (bsize.HasPercent() ||
(StyleDisplay()->IsAbsolutelyPositionedStyle() && (StyleDisplay()->IsAbsolutelyPositionedStyle() &&
(bsize.IsAuto() || !bsize.IsLengthPercentage()) && (bsize.IsAuto() || !bsize.IsLengthPercentage()) &&
!stylePos->GetInset(LogicalSide::BStart, wm).IsAuto() && !stylePos->mOffset.Get(LogicalSide::BStart, wm).MaybeAuto() &&
!stylePos->GetInset(LogicalSide::BEnd, wm).IsAuto())) { !stylePos->mOffset.Get(LogicalSide::BEnd, wm).MaybeAuto())) {
AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE); AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
} }

View File

@@ -8434,9 +8434,11 @@ nscoord nsGridContainerFrame::MasonryLayout(GridReflowInput& aState,
? LogicalSide::IStart ? LogicalSide::IStart
: LogicalSide::BStart; : LogicalSide::BStart;
if (masonryStart == 0 || if (masonryStart == 0 ||
(masonryStart == kAutoLine && item->mFrame->StylePosition() (masonryStart == kAutoLine &&
->GetInset(masonrySide, wm) item->mFrame->StylePosition()
.IsAuto())) { ->GetAnchorResolvedInset(
masonrySide, wm, item->mFrame->StyleDisplay()->mPosition)
.IsAuto())) {
sortedItems.AppendElement(item); sortedItems.AppendElement(item);
} else { } else {
item = nullptr; item = nullptr;

View File

@@ -1252,7 +1252,7 @@ void nsIFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
const nsStylePosition* pos = StylePosition(); const nsStylePosition* pos = StylePosition();
const nsStylePosition* oldPos = aOldComputedStyle->StylePosition(); const nsStylePosition* oldPos = aOldComputedStyle->StylePosition();
if (!needAnchorSuppression && if (!needAnchorSuppression &&
(!oldPos->InsetEquals(*pos) || (oldPos->mOffset != pos->mOffset ||
oldPos->GetWidth() != pos->GetWidth() || oldPos->GetWidth() != pos->GetWidth() ||
oldPos->GetMinWidth() != pos->GetMinWidth() || oldPos->GetMinWidth() != pos->GetMinWidth() ||
oldPos->GetMaxWidth() != pos->GetMaxWidth() || oldPos->GetMaxWidth() != pos->GetMaxWidth() ||
@@ -6902,14 +6902,21 @@ LogicalSize nsIFrame::ComputeAbsolutePosAutoSize(
const auto& styleBSize = aSizeOverrides.mStyleBSize const auto& styleBSize = aSizeOverrides.mStyleBSize
? *aSizeOverrides.mStyleBSize ? *aSizeOverrides.mStyleBSize
: stylePos->BSize(aWM); : stylePos->BSize(aWM);
const auto positionProperty = StyleDisplay()->mPosition;
const auto iStartOffsetIsAuto = const auto iStartOffsetIsAuto =
stylePos->GetInset(LogicalSide::IStart, aWM).IsAuto(); stylePos
->GetAnchorResolvedInset(LogicalSide::IStart, aWM, positionProperty)
.IsAuto();
const auto iEndOffsetIsAuto = const auto iEndOffsetIsAuto =
stylePos->GetInset(LogicalSide::IEnd, aWM).IsAuto(); stylePos->GetAnchorResolvedInset(LogicalSide::IEnd, aWM, positionProperty)
.IsAuto();
const auto bStartOffsetIsAuto = const auto bStartOffsetIsAuto =
stylePos->GetInset(LogicalSide::BStart, aWM).IsAuto(); stylePos
->GetAnchorResolvedInset(LogicalSide::BStart, aWM, positionProperty)
.IsAuto();
const auto bEndOffsetIsAuto = const auto bEndOffsetIsAuto =
stylePos->GetInset(LogicalSide::BEnd, aWM).IsAuto(); stylePos->GetAnchorResolvedInset(LogicalSide::BEnd, aWM, positionProperty)
.IsAuto();
const auto boxSizingAdjust = stylePos->mBoxSizing == StyleBoxSizing::Border const auto boxSizingAdjust = stylePos->mBoxSizing == StyleBoxSizing::Border
? aBorderPadding ? aBorderPadding
: LogicalSize(aWM); : LogicalSize(aWM);
@@ -7022,12 +7029,8 @@ LogicalSize nsIFrame::ComputeAbsolutePosAutoSize(
} else if (!iShouldStretch) { } else if (!iShouldStretch) {
// If one axis has `auto` inset, that is the ratio dependent axis, // If one axis has `auto` inset, that is the ratio dependent axis,
// otherwise the block axis is. // otherwise the block axis is.
const bool inlineInsetHasAuto = const bool inlineInsetHasAuto = iStartOffsetIsAuto || iEndOffsetIsAuto;
stylePos->GetInset(LogicalSide::IStart, aWM).IsAuto() || const bool blockInsetHasAuto = bStartOffsetIsAuto || bEndOffsetIsAuto;
stylePos->GetInset(LogicalSide::IEnd, aWM).IsAuto();
const bool blockInsetHasAuto =
stylePos->GetInset(LogicalSide::BStart, aWM).IsAuto() ||
stylePos->GetInset(LogicalSide::BEnd, aWM).IsAuto();
aspectRatioUsage = inlineInsetHasAuto && !blockInsetHasAuto aspectRatioUsage = inlineInsetHasAuto && !blockInsetHasAuto
? AspectRatioUsage::ToComputeISize ? AspectRatioUsage::ToComputeISize
: AspectRatioUsage::ToComputeBSize; : AspectRatioUsage::ToComputeBSize;

View File

@@ -669,8 +669,8 @@ static bool IsPercentageAware(const nsIFrame* aFrame, WritingMode aWM) {
if ((pos->ISizeDependsOnContainer(aWM) && !pos->ISize(aWM).IsAuto()) || if ((pos->ISizeDependsOnContainer(aWM) && !pos->ISize(aWM).IsAuto()) ||
pos->MaxISizeDependsOnContainer(aWM) || pos->MaxISizeDependsOnContainer(aWM) ||
pos->MinISizeDependsOnContainer(aWM) || pos->MinISizeDependsOnContainer(aWM) ||
pos->GetInset(LogicalSide::IStart, aWM).HasPercent() || pos->mOffset.Get(LogicalSide::IStart, aWM).MaybePercentageAware() ||
pos->GetInset(LogicalSide::IEnd, aWM).HasPercent()) { pos->mOffset.Get(LogicalSide::IEnd, aWM).MaybePercentageAware()) {
return true; return true;
} }

View File

@@ -815,6 +815,16 @@ inline bool StyleInset::IsAnchorPositioningFunction() const {
return IsAnchorFunction() || IsAnchorSizeFunction(); return IsAnchorFunction() || IsAnchorSizeFunction();
} }
template <>
inline bool StyleInset::MaybeAuto() const {
return IsAuto() || IsAnchorPositioningFunction();
}
template <>
inline bool StyleInset::MaybePercentageAware() const {
return HasPercent() || IsAnchorPositioningFunction();
}
#undef IMPL_LENGTHPERCENTAGE_FORWARDS #undef IMPL_LENGTHPERCENTAGE_FORWARDS
template <> template <>

View File

@@ -1910,18 +1910,20 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
PercentageBaseGetter aHeightGetter) { PercentageBaseGetter aHeightGetter) {
const nsStylePosition* positionData = StylePosition(); const nsStylePosition* positionData = StylePosition();
int32_t sign = 1; int32_t sign = 1;
auto coord = positionData->GetInset(aSide); const auto positionProperty = StyleDisplay()->mPosition;
auto coord = positionData->GetAnchorResolvedInset(aSide, positionProperty);
if (!coord.IsLengthPercentage()) { if (coord.IsAuto()) {
if (!aResolveAuto) { if (!aResolveAuto) {
auto val = MakeRefPtr<nsROCSSPrimitiveValue>(); auto val = MakeRefPtr<nsROCSSPrimitiveValue>();
val->SetString("auto"); val->SetString("auto");
return val.forget(); return val.forget();
} }
coord = positionData->GetInset(NS_OPPOSITE_SIDE(aSide)); coord = positionData->GetAnchorResolvedInset(NS_OPPOSITE_SIDE(aSide),
positionProperty);
sign = -1; sign = -1;
} }
if (!coord.IsLengthPercentage()) { if (coord.IsAuto()) {
return PixelsToCSSValue(0.0f); return PixelsToCSSValue(0.0f);
} }
@@ -1943,14 +1945,17 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
already_AddRefed<CSSValue> nsComputedDOMStyle::GetAbsoluteOffset( already_AddRefed<CSSValue> nsComputedDOMStyle::GetAbsoluteOffset(
mozilla::Side aSide) { mozilla::Side aSide) {
const auto& coord = StylePosition()->GetInset(aSide); const auto positionProperty = StyleDisplay()->mPosition;
const auto& oppositeCoord = const auto coord =
StylePosition()->GetInset(NS_OPPOSITE_SIDE(aSide)); StylePosition()->GetAnchorResolvedInset(aSide, positionProperty);
const auto oppositeCoord = StylePosition()->GetAnchorResolvedInset(
NS_OPPOSITE_SIDE(aSide), positionProperty);
if (coord.IsAuto() || oppositeCoord.IsAuto()) { if (coord.IsAuto() || oppositeCoord.IsAuto()) {
return AppUnitsToCSSValue(GetUsedAbsoluteOffset(aSide)); return AppUnitsToCSSValue(GetUsedAbsoluteOffset(aSide));
} }
// TODO(dshin): We're resolving anchor offset potentially twice...
return GetNonStaticPositionOffset( return GetNonStaticPositionOffset(
aSide, false, &nsComputedDOMStyle::GetCBPaddingRectWidth, aSide, false, &nsComputedDOMStyle::GetCBPaddingRectWidth,
&nsComputedDOMStyle::GetCBPaddingRectHeight); &nsComputedDOMStyle::GetCBPaddingRectHeight);
@@ -2022,7 +2027,13 @@ nscoord nsComputedDOMStyle::GetUsedAbsoluteOffset(mozilla::Side aSide) {
already_AddRefed<CSSValue> nsComputedDOMStyle::GetStaticOffset( already_AddRefed<CSSValue> nsComputedDOMStyle::GetStaticOffset(
mozilla::Side aSide) { mozilla::Side aSide) {
auto val = MakeRefPtr<nsROCSSPrimitiveValue>(); auto val = MakeRefPtr<nsROCSSPrimitiveValue>();
SetValueToInset(val, StylePosition()->GetInset(aSide)); const auto resolved =
StylePosition()->GetAnchorResolvedInset(aSide, StyleDisplay()->mPosition);
if (resolved.IsAuto()) {
val->SetString("auto");
} else {
SetValueToLengthPercentage(val, resolved.AsLengthPercentage(), false);
}
return val.forget(); return val.forget();
} }
@@ -2148,17 +2159,6 @@ void nsComputedDOMStyle::SetValueToLengthPercentageOrAuto(
aClampNegativeCalc); aClampNegativeCalc);
} }
void nsComputedDOMStyle::SetValueToInset(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleInset& aInset) {
// This function isn't used for absolutely positioned insets, so just assume
// `anchor()` or `anchor-size()` is `auto`.
if (!aInset.IsLengthPercentage()) {
aValue->SetString("auto");
return;
}
SetValueToLengthPercentage(aValue, aInset.AsLengthPercentage(), false);
}
void nsComputedDOMStyle::SetValueToMargin(nsROCSSPrimitiveValue* aValue, void nsComputedDOMStyle::SetValueToMargin(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleMargin& aMargin) { const mozilla::StyleMargin& aMargin) {
// May have to compute `anchor-size()` value here. // May have to compute `anchor-size()` value here.

View File

@@ -287,8 +287,6 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
void SetValueToLengthPercentageOrAuto(nsROCSSPrimitiveValue* aValue, void SetValueToLengthPercentageOrAuto(nsROCSSPrimitiveValue* aValue,
const LengthPercentageOrAuto&, const LengthPercentageOrAuto&,
bool aClampNegativeCalc); bool aClampNegativeCalc);
void SetValueToInset(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleInset&);
void SetValueToMargin(nsROCSSPrimitiveValue* aValue, void SetValueToMargin(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleMargin&); const mozilla::StyleMargin&);

View File

@@ -1309,8 +1309,12 @@ nsChangeHint nsStylePosition::CalcDifference(
// Don't try to handle changes between types efficiently; at least for // Don't try to handle changes between types efficiently; at least for
// changing into/out of `auto`, we will hardly ever be able to avoid a reflow. // changing into/out of `auto`, we will hardly ever be able to avoid a reflow.
// TODO(dshin, Bug 1917695): Re-evaulate this for `anchor()`. // TODO(dshin, Bug 1917695): Re-evaulate this for `anchor()`.
if (!InsetEquals(aNewData)) { if (mOffset != aNewData.mOffset) {
if (IsEqualInsetType(mOffset, aNewData.mOffset)) { if (IsEqualInsetType(mOffset, aNewData.mOffset) &&
aNewData.mOffset.All([](const StyleInset& aInset) {
// Err on the side of triggering reflow for anchor positioning.
return !aInset.IsAnchorPositioningFunction();
})) {
hint |= hint |=
nsChangeHint_RecomputePosition | nsChangeHint_UpdateParentOverflow; nsChangeHint_RecomputePosition | nsChangeHint_UpdateParentOverflow;
} else { } else {
@@ -1378,49 +1382,51 @@ nsStylePosition::AnchorResolvedInset nsStylePosition::GetAnchorResolvedInset(
}; };
switch (inset.tag) { switch (inset.tag) {
case StyleInset::Tag::Auto: case StyleInset::Tag::Auto:
return AnchorResolvedInset{InsetAuto{}}; return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
case StyleInset::Tag::LengthPercentage: { case StyleInset::Tag::LengthPercentage: {
const auto& lp = inset.AsLengthPercentage(); const auto& lp = inset.AsLengthPercentage();
if (lp.IsCalc()) { if (lp.IsCalc()) {
const auto& c = lp.AsCalc(); const auto& c = lp.AsCalc();
if (!c.has_anchor_function) { if (!c.has_anchor_function) {
return AnchorResolvedInset{LengthPercentageReference{lp}}; return AnchorResolvedInset{
AnchorResolvedInset::V{LengthPercentageReference{lp}}};
} }
auto resolved = StyleCalcAnchorPositioningFunctionResolution::Invalid(); auto resolved = StyleCalcAnchorPositioningFunctionResolution::Invalid();
Servo_ResolveAnchorPositioningFunctionInCalc(&c, side(aSide), aPosition, Servo_ResolveAnchorPositioningFunctionInCalc(&c, side(aSide), aPosition,
&resolved); &resolved);
if (resolved.IsInvalid()) { if (resolved.IsInvalid()) {
return AnchorResolvedInset{InsetAuto{}}; return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
} }
return AnchorResolvedInset{resolved.AsValid()}; return AnchorResolvedInset{AnchorResolvedInset::V{resolved.AsValid()}};
} }
return AnchorResolvedInset{LengthPercentageReference{lp}}; return AnchorResolvedInset{
AnchorResolvedInset::V{LengthPercentageReference{lp}}};
} }
case StyleInset::Tag::AnchorFunction: { case StyleInset::Tag::AnchorFunction: {
auto resolved = StyleAnchorPositioningFunctionResolution::Invalid(); auto resolved = StyleAnchorPositioningFunctionResolution::Invalid();
Servo_ResolveAnchorFunction(&*inset.AsAnchorFunction(), side(aSide), Servo_ResolveAnchorFunction(&*inset.AsAnchorFunction(), side(aSide),
aPosition, &resolved); aPosition, &resolved);
if (resolved.IsInvalid()) { if (resolved.IsInvalid()) {
return AnchorResolvedInset{InsetAuto{}}; return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
} }
if (resolved.IsResolvedReference()) { if (resolved.IsResolvedReference()) {
const auto* fallback = resolved.AsResolvedReference(); const auto* fallback = resolved.AsResolvedReference();
return AnchorResolvedInset{LengthPercentageReference{*fallback}}; return AnchorResolvedInset{AnchorResolvedInset::V{LengthPercentageReference{*fallback}}};
} }
return AnchorResolvedInset{resolved.AsResolved()}; return AnchorResolvedInset{AnchorResolvedInset::V{resolved.AsResolved()}};
} }
case StyleInset::Tag::AnchorSizeFunction: { case StyleInset::Tag::AnchorSizeFunction: {
auto resolved = StyleAnchorPositioningFunctionResolution::Invalid(); auto resolved = StyleAnchorPositioningFunctionResolution::Invalid();
Servo_ResolveAnchorSizeFunction(&*inset.AsAnchorSizeFunction(), aPosition, Servo_ResolveAnchorSizeFunction(&*inset.AsAnchorSizeFunction(), aPosition,
&resolved); &resolved);
if (resolved.IsInvalid()) { if (resolved.IsInvalid()) {
return AnchorResolvedInset{InsetAuto{}}; return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
} }
if (resolved.IsResolvedReference()) { if (resolved.IsResolvedReference()) {
const auto* fallback = resolved.AsResolvedReference(); const auto* fallback = resolved.AsResolvedReference();
return AnchorResolvedInset{LengthPercentageReference{*fallback}}; return AnchorResolvedInset{AnchorResolvedInset::V{LengthPercentageReference{*fallback}}};
} }
return AnchorResolvedInset{resolved.AsResolved()}; return AnchorResolvedInset{AnchorResolvedInset::V{resolved.AsResolved()}};
} }
default: default:
MOZ_ASSERT_UNREACHABLE("Unhandled inset type"); MOZ_ASSERT_UNREACHABLE("Unhandled inset type");
@@ -1434,7 +1440,6 @@ nsStylePosition::AnchorResolvedInset nsStylePosition::GetAnchorResolvedInset(
return GetAnchorResolvedInset(aWM.PhysicalSide(aSide), aPosition); return GetAnchorResolvedInset(aWM.PhysicalSide(aSide), aPosition);
} }
MOZ_RUNINIT const StyleInset nsStylePosition::kAutoInset = StyleInset::Auto();
MOZ_RUNINIT const StyleSize nsStylePosition::kAutoSize = StyleSize::Auto(); MOZ_RUNINIT const StyleSize nsStylePosition::kAutoSize = StyleSize::Auto();
MOZ_RUNINIT const StyleMaxSize nsStylePosition::kNoneMaxSize = MOZ_RUNINIT const StyleMaxSize nsStylePosition::kNoneMaxSize =
StyleMaxSize::None(); StyleMaxSize::None();

View File

@@ -726,10 +726,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
// Returns whether we need to compute an hypothetical position if we were // Returns whether we need to compute an hypothetical position if we were
// absolutely positioned. // absolutely positioned.
bool NeedsHypotheticalPositionIfAbsPos() const { bool NeedsHypotheticalPositionIfAbsPos() const {
return (GetInset(mozilla::eSideRight).IsAuto() && return (GetAnchorResolvedInset(mozilla::eSideRight,
GetInset(mozilla::eSideLeft).IsAuto()) || mozilla::StylePositionProperty::Absolute)
(GetInset(mozilla::eSideTop).IsAuto() && .IsAuto() &&
GetInset(mozilla::eSideBottom).IsAuto()); GetAnchorResolvedInset(mozilla::eSideLeft,
mozilla::StylePositionProperty::Absolute)
.IsAuto()) ||
(GetAnchorResolvedInset(mozilla::eSideTop,
mozilla::StylePositionProperty::Absolute)
.IsAuto() &&
GetAnchorResolvedInset(mozilla::eSideBottom,
mozilla::StylePositionProperty::Absolute)
.IsAuto());
} }
const mozilla::StyleContainIntrinsicSize& ContainIntrinsicBSize( const mozilla::StyleContainIntrinsicSize& ContainIntrinsicBSize(
@@ -839,41 +847,39 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
struct InsetAuto {}; struct InsetAuto {};
using LengthPercentageReference = std::reference_wrapper<const mozilla::StyleLengthPercentage>; using LengthPercentageReference = std::reference_wrapper<const mozilla::StyleLengthPercentage>;
using AnchorResolvedInset = struct AnchorResolvedInset {
mozilla::Variant<InsetAuto, LengthPercentageReference, using V = mozilla::Variant<InsetAuto, LengthPercentageReference,
mozilla::StyleLengthPercentage>; mozilla::StyleLengthPercentage>;
V mVariant;
bool IsAuto() const { return mVariant.is<InsetAuto>(); }
const mozilla::StyleLengthPercentage& AsLengthPercentage() const {
const bool isReference = mVariant.is<LengthPercentageReference>();
MOZ_ASSERT(isReference || mVariant.is<mozilla::StyleLengthPercentage>(),
"Not LengthPercentage type");
if (isReference) {
return mVariant.as<LengthPercentageReference>().get();
}
return mVariant.as<mozilla::StyleLengthPercentage>();
}
bool HasPercent() const {
if (IsAuto()) {
return false;
}
return AsLengthPercentage().HasPercent();
}
};
// TODO(dshin): These inset getters are to be removed when
// interleaving computation is implemented.
AnchorResolvedInset GetAnchorResolvedInset( AnchorResolvedInset GetAnchorResolvedInset(
mozilla::Side aSide, mozilla::StylePositionProperty aPosition) const; mozilla::Side aSide, mozilla::StylePositionProperty aPosition) const;
AnchorResolvedInset GetAnchorResolvedInset( AnchorResolvedInset GetAnchorResolvedInset(
mozilla::LogicalSide aSide, WritingMode aWM, mozilla::LogicalSide aSide, WritingMode aWM,
mozilla::StylePositionProperty aPosition) const; mozilla::StylePositionProperty aPosition) const;
// TODO(dshin): The following functions are used as shims to deal
// anchor positioning functions as if it's `auto`, before the computation
// is implemented.
static const mozilla::StyleInset kAutoInset;
const mozilla::StyleInset& GetInset(mozilla::Side aSide) const {
const auto& result = mOffset.Get(aSide);
if (MOZ_UNLIKELY(result.IsAnchorPositioningFunction())) {
return kAutoInset;
}
return result;
}
bool InsetEquals(const nsStylePosition& aOther) const {
for (const auto side : mozilla::AllPhysicalSides()) {
if (GetInset(side) != aOther.GetInset(side)) {
return false;
}
}
return true;
}
// As with other logical-coordinate accessors, definitions for these
// are found in WritingModes.h.
inline const mozilla::StyleInset& GetInset(mozilla::LogicalSide aSide,
WritingMode) const;
// TODO(dshin): These size getters can be removed when anchor // TODO(dshin): These size getters can be removed when anchor
// size is actually calculated. // size is actually calculated.
static const StyleSize kAutoSize; static const StyleSize kAutoSize;

View File

@@ -1154,6 +1154,8 @@ renaming_overrides_prefixing = true
inline nscoord ToLength() const; inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const; inline bool ConvertsToPercentage() const;
inline float ToPercentage() const; inline float ToPercentage() const;
inline bool MaybeAuto() const;
inline bool MaybePercentageAware() const;
""" """
"GenericMargin" = """ "GenericMargin" = """