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
// scroll-padding on the direction we're stuck.
const auto* stylePosition = aFrame->StylePosition();
const auto positionProperty = aFrame->StyleDisplay()->mPosition;
for (auto side : AllPhysicalSides()) {
if (stylePosition->GetInset(side).IsAuto()) {
if (stylePosition->GetAnchorResolvedInset(side, positionProperty)
.IsAuto()) {
continue;
}
// See if this axis is stuck.

View File

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

View File

@@ -742,8 +742,9 @@ void ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
!mStylePosition->BSize(wm).IsAuto()) ||
mStylePosition->MinBSizeDependsOnContainer(wm) ||
mStylePosition->MaxBSizeDependsOnContainer(wm) ||
mStylePosition->GetInset(LogicalSide::BStart, wm).HasPercent() ||
!mStylePosition->GetInset(LogicalSide::BEnd, wm).IsAuto();
mStylePosition->mOffset.Get(LogicalSide::BStart, wm)
.MaybePercentageAware() ||
!mStylePosition->mOffset.Get(LogicalSide::BEnd, wm).MaybeAuto();
// 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
@@ -852,15 +853,18 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
const LogicalSize& aCBSize) {
LogicalMargin offsets(aWM);
const nsStylePosition* position = aFrame->StylePosition();
const auto positionProperty = aFrame->StyleDisplay()->mPosition;
// Compute the 'inlineStart' and 'inlineEnd' values. 'inlineStart'
// 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:
// inlineStart=-inlineEnd
const auto& inlineStart = position->GetInset(LogicalSide::IStart, aWM);
const auto& inlineEnd = position->GetInset(LogicalSide::IEnd, aWM);
bool inlineStartIsAuto = !inlineStart.IsLengthPercentage();
bool inlineEndIsAuto = !inlineEnd.IsLengthPercentage();
const auto& inlineStart = position->GetAnchorResolvedInset(
LogicalSide::IStart, aWM, positionProperty);
const auto& inlineEnd = position->GetAnchorResolvedInset(
LogicalSide::IEnd, aWM, positionProperty);
bool inlineStartIsAuto = inlineStart.IsAuto();
bool inlineEndIsAuto = inlineEnd.IsAuto();
// If neither 'inlineStart' nor 'inlineEnd' is auto, then we're
// 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
offsets.IStart(aWM) = offsets.IEnd(aWM) = 0;
} else {
// 'inlineEnd' isn't 'auto' so compute its value
// 'inlineEnd' isn't being treated as 'auto' so compute its value
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'
offsets.IStart(aWM) = -offsets.IEnd(aWM);
@@ -885,8 +892,8 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
NS_ASSERTION(inlineEndIsAuto, "unexpected specified constraint");
// 'InlineStart' isn't 'auto' so compute its value
offsets.IStart(aWM) =
nsLayoutUtils::ComputeCBDependentValue(aCBSize.ISize(aWM), inlineStart);
offsets.IStart(aWM) = nsLayoutUtils::ComputeCBDependentValue(
aCBSize.ISize(aWM), inlineStart.AsLengthPercentage());
// Computed value for 'inlineEnd' is minus the value of 'inlineStart'
offsets.IEnd(aWM) = -offsets.IStart(aWM);
@@ -896,8 +903,10 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
// and 'blockEnd' properties move relatively positioned elements in
// the block progression direction. They also must be each other's
// negative
const auto& blockStart = position->GetInset(LogicalSide::BStart, aWM);
const auto& blockEnd = position->GetInset(LogicalSide::BEnd, aWM);
const auto& blockStart = position->GetAnchorResolvedInset(
LogicalSide::BStart, aWM, positionProperty);
const auto& blockEnd = position->GetAnchorResolvedInset(
LogicalSide::BEnd, aWM, positionProperty);
bool blockStartIsAuto = blockStart.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
offsets.BStart(aWM) = offsets.BEnd(aWM) = 0;
} else {
// 'blockEnd' isn't 'auto' so compute its value
// 'blockEnd' isn't being treated as 'auto' so compute its value
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'
offsets.BStart(aWM) = -offsets.BEnd(aWM);
@@ -934,8 +946,8 @@ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
NS_ASSERTION(blockEndIsAuto, "unexpected specified constraint");
// 'blockStart' isn't 'auto' so compute its value
offsets.BStart(aWM) =
nsLayoutUtils::ComputeCBDependentValue(aCBSize.BSize(aWM), blockStart);
offsets.BStart(aWM) = nsLayoutUtils::ComputeCBDependentValue(
aCBSize.BSize(aWM), blockStart.AsLengthPercentage());
// Computed value for 'blockEnd' is minus the value of 'blockStart'
offsets.BEnd(aWM) = -offsets.BStart(aWM);
@@ -1554,8 +1566,8 @@ void ReflowInput::CalculateHypotheticalPosition(
bool ReflowInput::IsInlineSizeComputableByBlockSizeAndAspectRatio(
nscoord aBlockSize) const {
WritingMode wm = GetWritingMode();
MOZ_ASSERT(!mStylePosition->GetInset(LogicalSide::BStart, wm).IsAuto() &&
!mStylePosition->GetInset(LogicalSide::BEnd, wm).IsAuto(),
MOZ_ASSERT(!mStylePosition->mOffset.Get(LogicalSide::BStart, wm).IsAuto() &&
!mStylePosition->mOffset.Get(LogicalSide::BEnd, wm).IsAuto(),
"If any of the block-start and block-end are auto, aBlockSize "
"doesn't make sense");
NS_WARNING_ASSERTION(
@@ -1578,10 +1590,22 @@ bool ReflowInput::IsInlineSizeComputableByBlockSizeAndAspectRatio(
return false;
}
const auto position = mStyleDisplay->mPosition;
// 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.
if (!mStylePosition->GetInset(LogicalSide::IStart, wm).IsAuto() &&
!mStylePosition->GetInset(LogicalSide::IEnd, wm).IsAuto()) {
if (!mStylePosition->GetAnchorResolvedInset(LogicalSide::IStart, wm, position)
.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;
}
@@ -1661,12 +1685,14 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
NS_ASSERTION(mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW),
"Why are we here?");
const auto& iStartOffset =
mStylePosition->GetInset(LogicalSide::IStart, cbwm);
const auto& iEndOffset = mStylePosition->GetInset(LogicalSide::IEnd, cbwm);
const auto& bStartOffset =
mStylePosition->GetInset(LogicalSide::BStart, cbwm);
const auto& bEndOffset = mStylePosition->GetInset(LogicalSide::BEnd, cbwm);
const auto& iStartOffset = mStylePosition->GetAnchorResolvedInset(
LogicalSide::IStart, cbwm, StylePositionProperty::Absolute);
const auto& iEndOffset = mStylePosition->GetAnchorResolvedInset(
LogicalSide::IEnd, cbwm, StylePositionProperty::Absolute);
const auto& bStartOffset = mStylePosition->GetAnchorResolvedInset(
LogicalSide::BStart, cbwm, StylePositionProperty::Absolute);
const auto& bEndOffset = mStylePosition->GetAnchorResolvedInset(
LogicalSide::BEnd, cbwm, StylePositionProperty::Absolute);
bool iStartIsAuto = iStartOffset.IsAuto();
bool iEndIsAuto = iEndOffset.IsAuto();
bool bStartIsAuto = bStartOffset.IsAuto();
@@ -1752,13 +1778,13 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
offsets.IStart(cbwm) = 0;
} else {
offsets.IStart(cbwm) = nsLayoutUtils::ComputeCBDependentValue(
cbSize.ISize(cbwm), iStartOffset);
cbSize.ISize(cbwm), iStartOffset.AsLengthPercentage());
}
if (iEndIsAuto) {
offsets.IEnd(cbwm) = 0;
} else {
offsets.IEnd(cbwm) =
nsLayoutUtils::ComputeCBDependentValue(cbSize.ISize(cbwm), iEndOffset);
nsLayoutUtils::ComputeCBDependentValue(cbSize.ISize(cbwm), iEndOffset.AsLengthPercentage());
}
if (iStartIsAuto && iEndIsAuto) {
@@ -1775,13 +1801,13 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
offsets.BStart(cbwm) = 0;
} else {
offsets.BStart(cbwm) = nsLayoutUtils::ComputeCBDependentValue(
cbSize.BSize(cbwm), bStartOffset);
cbSize.BSize(cbwm), bStartOffset.AsLengthPercentage());
}
if (bEndIsAuto) {
offsets.BEnd(cbwm) = 0;
} else {
offsets.BEnd(cbwm) =
nsLayoutUtils::ComputeCBDependentValue(cbSize.BSize(cbwm), bEndOffset);
nsLayoutUtils::ComputeCBDependentValue(cbSize.BSize(cbwm), bEndOffset.AsLengthPercentage());
}
if (bStartIsAuto && bEndIsAuto) {

View File

@@ -65,8 +65,9 @@ StickyScrollContainer::GetStickyScrollContainerForScrollFrame(
static nscoord ComputeStickySideOffset(Side aSide,
const nsStylePosition& aPosition,
nscoord aPercentBasis) {
const auto& side = aPosition.GetInset(aSide);
if (!side.IsLengthPercentage()) {
const auto& side =
aPosition.GetAnchorResolvedInset(aSide, StylePositionProperty::Sticky);
if (side.IsAuto()) {
return NS_AUTOOFFSET;
}
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);
}
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 {
const auto& iSize = ISize(aWM);
return iSize.IsAuto() || ISizeCoordDependsOnContainer(iSize);

View File

@@ -286,6 +286,8 @@ static inline bool IsFixedMarginSize(const StyleMargin& aCoord) {
return aCoord.ConvertsToLength();
}
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();
}
@@ -340,8 +342,8 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// lengths?
if ((pos->BSizeDependsOnContainer(wm) &&
!(pos->BSize(wm).IsAuto() &&
pos->GetInset(LogicalSide::BEnd, wm).IsAuto() &&
!pos->GetInset(LogicalSide::BStart, wm).IsAuto())) ||
pos->mOffset.Get(LogicalSide::BEnd, wm).MaybeAuto() &&
!pos->mOffset.Get(LogicalSide::BStart, wm).MaybeAuto())) ||
pos->MinBSizeDependsOnContainer(wm) ||
pos->MaxBSizeDependsOnContainer(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
// are easier to do using physical coordinates rather than logical.
if (aCBWidthChanged) {
if (!IsFixedOffset(pos->GetInset(eSideLeft))) {
if (!IsFixedOffset(pos->mOffset.Get(eSideLeft))) {
return true;
}
// Note that even if 'left' is a length, our position can still
@@ -375,17 +377,17 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// sure of.
if ((wm.GetInlineDir() == WritingMode::InlineDir::RTL ||
wm.GetBlockDir() == WritingMode::BlockDir::RL) &&
!pos->GetInset(eSideRight).IsAuto()) {
!pos->mOffset.Get(eSideRight).MaybeAuto()) {
return true;
}
}
if (aCBHeightChanged) {
if (!IsFixedOffset(pos->GetInset(eSideTop))) {
if (!IsFixedOffset(pos->mOffset.Get(eSideTop))) {
return true;
}
// See comment above for width changes.
if (wm.GetInlineDir() == WritingMode::InlineDir::BTT &&
!pos->GetInset(eSideBottom).IsAuto()) {
!pos->mOffset.Get(eSideBottom).MaybeAuto()) {
return true;
}
}
@@ -925,12 +927,25 @@ void nsAbsoluteContainingBlock::ReflowAbsoluteFrame(
// align the child by its margin box:
// https://drafts.csswg.org/css-position-3/#abspos-layout
const auto* stylePos = aKidFrame->StylePosition();
auto positionProperty = aKidFrame->StyleDisplay()->mPosition;
const bool iInsetAuto =
stylePos->GetInset(LogicalSide::IStart, outerWM).IsAuto() ||
stylePos->GetInset(LogicalSide::IEnd, outerWM).IsAuto();
stylePos
->GetAnchorResolvedInset(LogicalSide::IStart, outerWM,
positionProperty)
.IsAuto() ||
stylePos
->GetAnchorResolvedInset(LogicalSide::IEnd, outerWM,
positionProperty)
.IsAuto();
const bool bInsetAuto =
stylePos->GetInset(LogicalSide::BStart, outerWM).IsAuto() ||
stylePos->GetInset(LogicalSide::BEnd, outerWM).IsAuto();
stylePos
->GetAnchorResolvedInset(LogicalSide::BStart, outerWM,
positionProperty)
.IsAuto() ||
stylePos
->GetAnchorResolvedInset(LogicalSide::BEnd, outerWM,
positionProperty)
.IsAuto();
const LogicalSize logicalCBSizeOuterWM(outerWM, aContainingBlock.Size());
const LogicalSize kidMarginBox{
outerWM, margin.IStartEnd(outerWM) + kidSize.ISize(outerWM),

View File

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

View File

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

View File

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

View File

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

View File

@@ -815,6 +815,16 @@ inline bool StyleInset::IsAnchorPositioningFunction() const {
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
template <>

View File

@@ -1910,18 +1910,20 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
PercentageBaseGetter aHeightGetter) {
const nsStylePosition* positionData = StylePosition();
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) {
auto val = MakeRefPtr<nsROCSSPrimitiveValue>();
val->SetString("auto");
return val.forget();
}
coord = positionData->GetInset(NS_OPPOSITE_SIDE(aSide));
coord = positionData->GetAnchorResolvedInset(NS_OPPOSITE_SIDE(aSide),
positionProperty);
sign = -1;
}
if (!coord.IsLengthPercentage()) {
if (coord.IsAuto()) {
return PixelsToCSSValue(0.0f);
}
@@ -1943,14 +1945,17 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
already_AddRefed<CSSValue> nsComputedDOMStyle::GetAbsoluteOffset(
mozilla::Side aSide) {
const auto& coord = StylePosition()->GetInset(aSide);
const auto& oppositeCoord =
StylePosition()->GetInset(NS_OPPOSITE_SIDE(aSide));
const auto positionProperty = StyleDisplay()->mPosition;
const auto coord =
StylePosition()->GetAnchorResolvedInset(aSide, positionProperty);
const auto oppositeCoord = StylePosition()->GetAnchorResolvedInset(
NS_OPPOSITE_SIDE(aSide), positionProperty);
if (coord.IsAuto() || oppositeCoord.IsAuto()) {
return AppUnitsToCSSValue(GetUsedAbsoluteOffset(aSide));
}
// TODO(dshin): We're resolving anchor offset potentially twice...
return GetNonStaticPositionOffset(
aSide, false, &nsComputedDOMStyle::GetCBPaddingRectWidth,
&nsComputedDOMStyle::GetCBPaddingRectHeight);
@@ -2022,7 +2027,13 @@ nscoord nsComputedDOMStyle::GetUsedAbsoluteOffset(mozilla::Side aSide) {
already_AddRefed<CSSValue> nsComputedDOMStyle::GetStaticOffset(
mozilla::Side aSide) {
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();
}
@@ -2148,17 +2159,6 @@ void nsComputedDOMStyle::SetValueToLengthPercentageOrAuto(
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,
const mozilla::StyleMargin& aMargin) {
// May have to compute `anchor-size()` value here.

View File

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

View File

@@ -1309,8 +1309,12 @@ nsChangeHint nsStylePosition::CalcDifference(
// 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.
// TODO(dshin, Bug 1917695): Re-evaulate this for `anchor()`.
if (!InsetEquals(aNewData)) {
if (IsEqualInsetType(mOffset, aNewData.mOffset)) {
if (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 |=
nsChangeHint_RecomputePosition | nsChangeHint_UpdateParentOverflow;
} else {
@@ -1378,49 +1382,51 @@ nsStylePosition::AnchorResolvedInset nsStylePosition::GetAnchorResolvedInset(
};
switch (inset.tag) {
case StyleInset::Tag::Auto:
return AnchorResolvedInset{InsetAuto{}};
return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
case StyleInset::Tag::LengthPercentage: {
const auto& lp = inset.AsLengthPercentage();
if (lp.IsCalc()) {
const auto& c = lp.AsCalc();
if (!c.has_anchor_function) {
return AnchorResolvedInset{LengthPercentageReference{lp}};
return AnchorResolvedInset{
AnchorResolvedInset::V{LengthPercentageReference{lp}}};
}
auto resolved = StyleCalcAnchorPositioningFunctionResolution::Invalid();
Servo_ResolveAnchorPositioningFunctionInCalc(&c, side(aSide), aPosition,
&resolved);
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: {
auto resolved = StyleAnchorPositioningFunctionResolution::Invalid();
Servo_ResolveAnchorFunction(&*inset.AsAnchorFunction(), side(aSide),
aPosition, &resolved);
if (resolved.IsInvalid()) {
return AnchorResolvedInset{InsetAuto{}};
return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
}
if (resolved.IsResolvedReference()) {
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: {
auto resolved = StyleAnchorPositioningFunctionResolution::Invalid();
Servo_ResolveAnchorSizeFunction(&*inset.AsAnchorSizeFunction(), aPosition,
&resolved);
if (resolved.IsInvalid()) {
return AnchorResolvedInset{InsetAuto{}};
return AnchorResolvedInset{AnchorResolvedInset::V{InsetAuto{}}};
}
if (resolved.IsResolvedReference()) {
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:
MOZ_ASSERT_UNREACHABLE("Unhandled inset type");
@@ -1434,7 +1440,6 @@ nsStylePosition::AnchorResolvedInset nsStylePosition::GetAnchorResolvedInset(
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 StyleMaxSize nsStylePosition::kNoneMaxSize =
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
// absolutely positioned.
bool NeedsHypotheticalPositionIfAbsPos() const {
return (GetInset(mozilla::eSideRight).IsAuto() &&
GetInset(mozilla::eSideLeft).IsAuto()) ||
(GetInset(mozilla::eSideTop).IsAuto() &&
GetInset(mozilla::eSideBottom).IsAuto());
return (GetAnchorResolvedInset(mozilla::eSideRight,
mozilla::StylePositionProperty::Absolute)
.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(
@@ -839,41 +847,39 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
struct InsetAuto {};
using LengthPercentageReference = std::reference_wrapper<const mozilla::StyleLengthPercentage>;
using AnchorResolvedInset =
mozilla::Variant<InsetAuto, LengthPercentageReference,
struct AnchorResolvedInset {
using V = mozilla::Variant<InsetAuto, LengthPercentageReference,
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(
mozilla::Side aSide, mozilla::StylePositionProperty aPosition) const;
AnchorResolvedInset GetAnchorResolvedInset(
mozilla::LogicalSide aSide, WritingMode aWM,
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
// size is actually calculated.
static const StyleSize kAutoSize;

View File

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