Bug 1900232: Part 4 - Add anchor-size() to margin properties. r=firefox-style-system-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D222533
This commit is contained in:
David Shin
2024-09-23 13:58:38 +00:00
parent ae690b1c13
commit 1fad4eeb43
30 changed files with 278 additions and 89 deletions

View File

@@ -1248,7 +1248,7 @@ already_AddRefed<AccAttributes> LocalAccessible::NativeAttributes() {
auto GetMargin = [&](mozilla::Side aSide) -> CSSCoord {
// This is here only to guarantee that we do the same as getComputedStyle
// does, so that we don't hit precision errors in tests.
auto& margin = f->StyleMargin()->mMargin.Get(aSide);
const auto& margin = f->StyleMargin()->GetMargin(aSide);
if (margin.ConvertsToLength()) {
return margin.AsLengthPercentage().ToLengthInCSSPixels();
}

View File

@@ -3414,11 +3414,11 @@ struct BoxToRect : public nsLayoutUtils::BoxCallback {
} else if (mFlags.contains(nsLayoutUtils::GetAllInFlowRectsFlag::
UseMarginBoxWithAutoResolvedAsZero)) {
r = aFrame->GetRectRelativeToSelf();
const auto& styleMargin = aFrame->StyleMargin()->mMargin;
nsMargin usedMargin =
aFrame->GetUsedMargin().ApplySkipSides(aFrame->GetSkipSides());
const auto* styleMargin = aFrame->StyleMargin();
for (const Side side : AllPhysicalSides()) {
if (styleMargin.Get(side).IsAuto()) {
if (styleMargin->GetMargin(side).IsAuto()) {
usedMargin.Side(side) = 0;
}
}

View File

@@ -1551,6 +1551,14 @@ class nsLayoutUtils {
return ComputeCBDependentValue(aPercentBasis, aInset.AsLengthPercentage());
}
static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
const mozilla::StyleMargin& aMargin) {
if (!aMargin.IsLengthPercentage()) {
return 0;
}
return ComputeCBDependentValue(aPercentBasis, aMargin.AsLengthPercentage());
}
static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize,
nscoord aContentEdgeToBoxSizingBoxEdge,
const LengthPercentage& aCoord) {

View File

@@ -61,7 +61,6 @@ nscoord CSSAlignUtils::AlignJustifySelf(const StyleAlignFlags& aAlignment,
const auto endSide = GetOppositeSide(startSide);
const nscoord marginEnd = margin.Side(endSide, wm);
const auto& styleMargin = aRI.mStyleMargin->mMargin;
bool hasAutoMarginStart;
bool hasAutoMarginEnd;
if (aFlags & AlignJustifyFlags::IgnoreAutoMargins) {
@@ -69,11 +68,15 @@ nscoord CSSAlignUtils::AlignJustifySelf(const StyleAlignFlags& aAlignment,
// don't need to do anything special to avoid expanding them.)
hasAutoMarginStart = hasAutoMarginEnd = false;
} else if (aAxis == LogicalAxis::Block) {
hasAutoMarginStart = styleMargin.GetBStart(wm).IsAuto();
hasAutoMarginEnd = styleMargin.GetBEnd(wm).IsAuto();
hasAutoMarginStart =
aRI.mStyleMargin->GetMargin(LogicalSide::BStart, wm).IsAuto();
hasAutoMarginEnd =
aRI.mStyleMargin->GetMargin(LogicalSide::BEnd, wm).IsAuto();
} else { /* aAxis == LogicalAxis::Inline */
hasAutoMarginStart = styleMargin.GetIStart(wm).IsAuto();
hasAutoMarginEnd = styleMargin.GetIEnd(wm).IsAuto();
hasAutoMarginStart =
aRI.mStyleMargin->GetMargin(LogicalSide::IStart, wm).IsAuto();
hasAutoMarginEnd =
aRI.mStyleMargin->GetMargin(LogicalSide::IEnd, wm).IsAuto();
}
// https://drafts.csswg.org/css-align-3/#overflow-values

View File

@@ -1135,9 +1135,9 @@ void ReflowInput::CalculateBorderPaddingMargin(
// correct margin value will be computed later in InitAbsoluteConstraints
// (which is caller of this function, via CalculateHypotheticalPosition).
const nscoord start = nsLayoutUtils::ComputeCBDependentValue(
aContainingBlockSize, mStyleMargin->mMargin.Get(startSide));
aContainingBlockSize, mStyleMargin->GetMargin(startSide));
const nscoord end = nsLayoutUtils::ComputeCBDependentValue(
aContainingBlockSize, mStyleMargin->mMargin.Get(endSide));
aContainingBlockSize, mStyleMargin->GetMargin(endSide));
marginStartEnd = start + end;
}
@@ -1865,8 +1865,10 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
nscoord availMarginSpace =
aCBSize.ISize(cbwm) - offsets.IStartEnd(cbwm) - margin.IStartEnd(cbwm) -
borderPadding.IStartEnd(cbwm) - computedSize.ISize(cbwm);
marginIStartIsAuto = mStyleMargin->mMargin.GetIStart(cbwm).IsAuto();
marginIEndIsAuto = mStyleMargin->mMargin.GetIEnd(cbwm).IsAuto();
marginIStartIsAuto =
mStyleMargin->GetMargin(LogicalSide::IStart, cbwm).IsAuto();
marginIEndIsAuto =
mStyleMargin->GetMargin(LogicalSide::IEnd, cbwm).IsAuto();
ComputeAbsPosInlineAutoMargin(availMarginSpace, cbwm, marginIStartIsAuto,
marginIEndIsAuto, margin, offsets);
}
@@ -1920,8 +1922,10 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput,
// * we're dealing with a replaced element
// * bsize was constrained by min- or max-bsize.
nscoord availMarginSpace = autoBSize - computedSize.BSize(cbwm);
marginBStartIsAuto = mStyleMargin->mMargin.GetBStart(cbwm).IsAuto();
marginBEndIsAuto = mStyleMargin->mMargin.GetBEnd(cbwm).IsAuto();
marginBStartIsAuto =
mStyleMargin->GetMargin(LogicalSide::BStart, cbwm).IsAuto();
marginBEndIsAuto =
mStyleMargin->GetMargin(LogicalSide::BEnd, cbwm).IsAuto();
ComputeAbsPosBlockAutoMargin(availMarginSpace, cbwm, marginBStartIsAuto,
marginBEndIsAuto, margin, offsets);
@@ -2663,9 +2667,10 @@ void ReflowInput::CalculateBlockSideMargins() {
// The css2 spec clearly defines how block elements should behave
// in section 10.3.3.
const auto& styleSides = mStyleMargin->mMargin;
bool isAutoStartMargin = styleSides.GetIStart(cbWM).IsAuto();
bool isAutoEndMargin = styleSides.GetIEnd(cbWM).IsAuto();
bool isAutoStartMargin =
mStyleMargin->GetMargin(LogicalSide::IStart, cbWM).IsAuto();
bool isAutoEndMargin =
mStyleMargin->GetMargin(LogicalSide::IEnd, cbWM).IsAuto();
if (!isAutoStartMargin && !isAutoEndMargin) {
// Neither margin is 'auto' so we're over constrained. Use the
// 'direction' property of the parent to tell which margin to
@@ -2895,7 +2900,7 @@ bool SizeComputationInput::ComputeMargin(WritingMode aCBWM,
LogicalMargin m(aCBWM);
for (const LogicalSide side : LogicalSides::All) {
m.Side(side, aCBWM) = nsLayoutUtils::ComputeCBDependentValue(
aPercentBasis, styleMargin->mMargin.Get(side, aCBWM));
aPercentBasis, styleMargin->GetMargin(side, aCBWM));
}
SetComputedLogicalMargin(aCBWM, m);
} else {

View File

@@ -2154,18 +2154,26 @@ inline bool nsStylePosition::MaxBSizeDependsOnContainer(WritingMode aWM) const {
}
inline bool nsStyleMargin::HasBlockAxisAuto(mozilla::WritingMode aWM) const {
return mMargin.GetBStart(aWM).IsAuto() || mMargin.GetBEnd(aWM).IsAuto();
return GetMargin(mozilla::LogicalSide::BStart, aWM).IsAuto() ||
GetMargin(mozilla::LogicalSide::BEnd, aWM).IsAuto();
}
inline bool nsStyleMargin::HasInlineAxisAuto(mozilla::WritingMode aWM) const {
return mMargin.GetIStart(aWM).IsAuto() || mMargin.GetIEnd(aWM).IsAuto();
return GetMargin(mozilla::LogicalSide::IStart, aWM).IsAuto() ||
GetMargin(mozilla::LogicalSide::IEnd, aWM).IsAuto();
}
inline bool nsStyleMargin::HasAuto(mozilla::LogicalAxis aAxis,
mozilla::WritingMode aWM) const {
return aAxis == mozilla::LogicalAxis::Inline ? HasInlineAxisAuto(aWM)
: HasBlockAxisAuto(aWM);
}
inline const mozilla::StyleMargin& nsStyleMargin::GetMargin(
mozilla::LogicalSide aSide, mozilla::WritingMode aWM) const {
return GetMargin(aWM.PhysicalSide(aSide));
}
inline mozilla::StyleAlignFlags nsStylePosition::UsedSelfAlignment(
mozilla::LogicalAxis aAxis, const mozilla::ComputedStyle* aParent) const {
return aAxis == mozilla::LogicalAxis::Block ? UsedAlignSelf(aParent)._0

View File

@@ -282,7 +282,7 @@ void nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame,
static inline bool IsFixedPaddingSize(const LengthPercentage& aCoord) {
return aCoord.ConvertsToLength();
}
static inline bool IsFixedMarginSize(const LengthPercentageOrAuto& aCoord) {
static inline bool IsFixedMarginSize(const StyleMargin& aCoord) {
return aCoord.ConvertsToLength();
}
static inline bool IsFixedOffset(const StyleInset& aInset) {
@@ -323,8 +323,8 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// See if f's position might have changed. If we're RTL then the
// rules are slightly different. We'll assume percentage or auto
// margins will always induce a dependency on the size
if (!IsFixedMarginSize(margin->mMargin.GetIStart(wm)) ||
!IsFixedMarginSize(margin->mMargin.GetIEnd(wm))) {
if (!IsFixedMarginSize(margin->GetMargin(LogicalSide::IStart, wm)) ||
!IsFixedMarginSize(margin->GetMargin(LogicalSide::IEnd, wm))) {
return true;
}
}
@@ -350,8 +350,8 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
}
// See if f's position might have changed.
if (!IsFixedMarginSize(margin->mMargin.GetBStart(wm)) ||
!IsFixedMarginSize(margin->mMargin.GetBEnd(wm))) {
if (!IsFixedMarginSize(margin->GetMargin(LogicalSide::BStart, wm)) ||
!IsFixedMarginSize(margin->GetMargin(LogicalSide::BEnd, wm))) {
return true;
}
}
@@ -680,13 +680,15 @@ void nsAbsoluteContainingBlock::ResolveAutoMarginsAfterLayout(
if (wm.IsOrthogonalTo(outerWM)) {
ReflowInput::ComputeAbsPosInlineAutoMargin(
availMarginSpace, outerWM,
styleMargin->mMargin.GetIStart(outerWM).IsAuto(),
styleMargin->mMargin.GetIEnd(outerWM).IsAuto(), aMargin, aOffsets);
styleMargin->GetMargin(LogicalSide::IStart, outerWM).IsAuto(),
styleMargin->GetMargin(LogicalSide::IEnd, outerWM).IsAuto(), aMargin,
aOffsets);
} else {
ReflowInput::ComputeAbsPosBlockAutoMargin(
availMarginSpace, outerWM,
styleMargin->mMargin.GetBStart(outerWM).IsAuto(),
styleMargin->mMargin.GetBEnd(outerWM).IsAuto(), aMargin, aOffsets);
styleMargin->GetMargin(LogicalSide::BStart, outerWM).IsAuto(),
styleMargin->GetMargin(LogicalSide::BEnd, outerWM).IsAuto(), aMargin,
aOffsets);
}
aKidReflowInput.SetComputedLogicalMargin(outerWM, aMargin);

View File

@@ -14,8 +14,10 @@ void nsContainerFrame::DoInlineIntrinsicISize(ISizeData* aData,
F& aHandleChildren) {
using namespace mozilla;
auto GetMargin = [](const LengthPercentageOrAuto& aCoord) -> nscoord {
return aCoord.IsAuto() ? 0 : aCoord.AsLengthPercentage().Resolve(0);
auto GetMargin = [](const mozilla::StyleMargin& aCoord) -> nscoord {
return !aCoord.IsLengthPercentage()
? 0
: aCoord.AsLengthPercentage().Resolve(0);
};
if (GetPrevInFlow()) return; // Already added.
@@ -45,7 +47,7 @@ void nsContainerFrame::DoInlineIntrinsicISize(ISizeData* aData,
// clamp negative calc() to 0
std::max(stylePadding->mPadding.Get(startSide).Resolve(0), 0) +
styleBorder->GetComputedBorderWidth(startSide) +
GetMargin(styleMargin->mMargin.Get(startSide));
GetMargin(styleMargin->GetMargin(startSide));
if (MOZ_LIKELY(sliceBreak)) {
aData->mCurrentLine += startPBM;
} else {
@@ -57,7 +59,7 @@ void nsContainerFrame::DoInlineIntrinsicISize(ISizeData* aData,
// clamp negative calc() to 0
std::max(stylePadding->mPadding.Get(endSide).Resolve(0), 0) +
styleBorder->GetComputedBorderWidth(endSide) +
GetMargin(styleMargin->mMargin.Get(endSide));
GetMargin(styleMargin->GetMargin(endSide));
if (MOZ_UNLIKELY(!sliceBreak)) {
clonePBM += endPBM;
aData->mCurrentLine += clonePBM;

View File

@@ -170,14 +170,13 @@ bool nsFirstLetterFrame::UseTightBounds() const {
}
const auto wm = GetWritingMode();
const auto& margin = StyleMargin()->mMargin;
const auto& bStart = margin.GetBStart(wm);
const auto& bStart = StyleMargin()->GetMargin(LogicalSide::BStart, wm);
// Currently, we only check for margins with negative *length* values;
// negative percentages seem unlikely to be used/useful in this context.
if (bStart.ConvertsToLength() && bStart.ToLength() < 0) {
return false;
}
const auto& bEnd = margin.GetBEnd(wm);
const auto& bEnd = StyleMargin()->GetMargin(LogicalSide::BEnd, wm);
if (bEnd.ConvertsToLength() && bEnd.ToLength() < 0) {
return false;
}

View File

@@ -2221,7 +2221,7 @@ FlexItem::FlexItem(ReflowInput& aFlexItemReflowInput, float aFlexGrow,
#ifdef DEBUG
{
for (const auto side : LogicalSides::All) {
if (styleMargin->mMargin.Get(side, mCBWM).IsAuto()) {
if (styleMargin->GetMargin(side, mCBWM).IsAuto()) {
MOZ_ASSERT(GetMarginComponentForSide(side) == 0,
"Someone else tried to resolve our auto margin");
}
@@ -2440,10 +2440,10 @@ void FlexItem::ResolveFlexBaseSizeFromAspectRatio(
uint32_t FlexItem::NumAutoMarginsInAxis(LogicalAxis aAxis) const {
uint32_t numAutoMargins = 0;
const auto& styleMargin = mFrame->StyleMargin()->mMargin;
const auto* styleMargin = mFrame->StyleMargin();
for (const auto edge : {LogicalEdge::Start, LogicalEdge::End}) {
const auto side = MakeLogicalSide(aAxis, edge);
if (styleMargin.Get(side, mCBWM).IsAuto()) {
if (styleMargin->GetMargin(side, mCBWM).IsAuto()) {
numAutoMargins++;
}
}
@@ -3522,9 +3522,9 @@ MainAxisPositionTracker::MainAxisPositionTracker(
void MainAxisPositionTracker::ResolveAutoMarginsInMainAxis(FlexItem& aItem) {
if (mNumAutoMarginsInMainAxis) {
const auto& styleMargin = aItem.Frame()->StyleMargin()->mMargin;
const auto* styleMargin = aItem.Frame()->StyleMargin();
for (const auto side : {StartSide(), EndSide()}) {
if (styleMargin.Get(side, mWM).IsAuto()) {
if (styleMargin->GetMargin(side, mWM).IsAuto()) {
// NOTE: This integer math will skew the distribution of remainder
// app-units towards the end, which is fine.
nscoord curAutoMarginSize =
@@ -3918,9 +3918,9 @@ void SingleLineCrossAxisPositionTracker::ResolveAutoMarginsInCrossAxis(
// OK, we have at least one auto margin and we have some available space.
// Give each auto margin a share of the space.
const auto& styleMargin = aItem.Frame()->StyleMargin()->mMargin;
const auto* styleMargin = aItem.Frame()->StyleMargin();
for (const auto side : {StartSide(), EndSide()}) {
if (styleMargin.Get(side, mWM).IsAuto()) {
if (styleMargin->GetMargin(side, mWM).IsAuto()) {
MOZ_ASSERT(aItem.GetMarginComponentForSide(side) == 0,
"Expecting auto margins to have value '0' before we "
"update them");

View File

@@ -1210,7 +1210,7 @@ void nsIFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
bool needAnchorSuppression = false;
const nsStyleMargin* oldMargin = aOldComputedStyle->StyleMargin();
if (oldMargin->mMargin != StyleMargin()->mMargin) {
if (!oldMargin->MarginEquals(*StyleMargin())) {
needAnchorSuppression = true;
}
@@ -6179,9 +6179,9 @@ void nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aClearType) {
mLineIsEmpty = true;
}
static nscoord ResolveMargin(const LengthPercentageOrAuto& aStyle,
static nscoord ResolveMargin(const StyleMargin& aStyle,
nscoord aPercentageBasis) {
if (aStyle.IsAuto()) {
if (!aStyle.IsLengthPercentage()) {
return nscoord(0);
}
return nsLayoutUtils::ResolveToLength<false>(aStyle.AsLengthPercentage(),
@@ -6197,14 +6197,18 @@ static nsIFrame::IntrinsicSizeOffsetData IntrinsicSizeOffsets(
nsIFrame* aFrame, nscoord aPercentageBasis, bool aForISize) {
nsIFrame::IntrinsicSizeOffsetData result;
WritingMode wm = aFrame->GetWritingMode();
const auto& margin = aFrame->StyleMargin()->mMargin;
bool verticalAxis = aForISize == wm.IsVertical();
const auto* styleMargin = aFrame->StyleMargin();
if (verticalAxis) {
result.margin += ResolveMargin(margin.Get(eSideTop), aPercentageBasis);
result.margin += ResolveMargin(margin.Get(eSideBottom), aPercentageBasis);
result.margin +=
ResolveMargin(styleMargin->GetMargin(eSideTop), aPercentageBasis);
result.margin +=
ResolveMargin(styleMargin->GetMargin(eSideBottom), aPercentageBasis);
} else {
result.margin += ResolveMargin(margin.Get(eSideLeft), aPercentageBasis);
result.margin += ResolveMargin(margin.Get(eSideRight), aPercentageBasis);
result.margin +=
ResolveMargin(styleMargin->GetMargin(eSideLeft), aPercentageBasis);
result.margin +=
ResolveMargin(styleMargin->GetMargin(eSideRight), aPercentageBasis);
}
const auto& padding = aFrame->StylePadding()->mPadding;

View File

@@ -77,8 +77,8 @@ void nsInlineFrame::InvalidateFrameWithRect(const nsRect& aRect,
aRebuildDisplayItems);
}
static inline bool IsMarginZero(const LengthPercentageOrAuto& aLength) {
return aLength.IsAuto() ||
static inline bool IsMarginZero(const StyleMargin& aLength) {
return !aLength.IsLengthPercentage() ||
nsLayoutUtils::IsMarginZero(aLength.AsLengthPercentage());
}
@@ -103,7 +103,7 @@ bool nsInlineFrame::IsSelfEmpty() {
auto HaveSide = [&](mozilla::Side aSide) -> bool {
return border->GetComputedBorderWidth(aSide) != 0 ||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.Get(aSide)) ||
!IsMarginZero(margin->mMargin.Get(aSide));
!IsMarginZero(margin->GetMargin(aSide));
};
// Initially set up haveStart and haveEnd in terms of visual (LTR/TTB)
// coordinates; we'll exchange them later if bidi-RTL is in effect to

View File

@@ -629,6 +629,15 @@ static bool HasPercentageUnitSide(const StyleRect<T>& aSides) {
return aSides.Any([](const auto& aLength) { return aLength.HasPercent(); });
}
static bool HasPercentageUnitMargin(const nsStyleMargin& aStyleMargin) {
for (const auto side : AllPhysicalSides()) {
if (aStyleMargin.GetMargin(side).HasPercent()) {
return true;
}
}
return false;
}
static bool IsPercentageAware(const nsIFrame* aFrame, WritingMode aWM) {
MOZ_ASSERT(aFrame, "null frame is not allowed");
@@ -644,7 +653,7 @@ static bool IsPercentageAware(const nsIFrame* aFrame, WritingMode aWM) {
// quite rarely.
const nsStyleMargin* margin = aFrame->StyleMargin();
if (HasPercentageUnitSide(margin->mMargin)) {
if (HasPercentageUnitMargin(*margin)) {
return true;
}

View File

@@ -125,9 +125,8 @@ nsReflowStatus nsPageFrame::ReflowPageContent(
// the document is intended to fit the paper size exactly, and the client is
// taking full responsibility for what happens around the edges.
if (mPD->mPrintSettings->GetHonorPageRuleMargins()) {
const auto& margin = kidReflowInput.mStyleMargin->mMargin;
for (const auto side : mozilla::AllPhysicalSides()) {
if (!margin.Get(side).IsAuto()) {
if (!kidReflowInput.mStyleMargin->GetMargin(side).IsAuto()) {
// Computed margins are already in the coordinate space of the content,
// do not scale.
const nscoord computed =

View File

@@ -1876,7 +1876,7 @@ bool BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1,
//
// 1. Any of margin/border/padding separating the two typographic
// character units in the inline axis is non-zero.
const auto& margin = ctx->StyleMargin()->mMargin.Get(aSide);
const auto& margin = ctx->StyleMargin()->GetMargin(aSide);
if (!margin.ConvertsToLength() ||
margin.AsLengthPercentage().ToLength() != 0) {
return true;

View File

@@ -633,6 +633,7 @@ cbindgen-types = [
{ gecko = "StyleInitialLetter", servo = "crate::values::computed::text::InitialLetter" },
{ gecko = "StylePointerEvents", servo = "crate::values::computed::ui::PointerEvents" },
{ gecko = "StyleInert", servo = "crate::values::computed::ui::Inert" },
{ gecko = "StyleMargin", servo = "crate::values::computed::length::Margin" },
]
mapped-generic-types = [

View File

@@ -808,6 +808,7 @@ IMPL_LENGTHPERCENTAGE_FORWARDS(LengthPercentageOrAuto)
IMPL_LENGTHPERCENTAGE_FORWARDS(StyleSize)
IMPL_LENGTHPERCENTAGE_FORWARDS(StyleMaxSize)
IMPL_LENGTHPERCENTAGE_FORWARDS(StyleInset)
IMPL_LENGTHPERCENTAGE_FORWARDS(StyleMargin)
template <>
inline bool StyleInset::IsAnchorPositioningFunction() const {

View File

@@ -985,7 +985,7 @@ bool nsComputedDOMStyle::NeedsToFlushLayout(nsCSSPropertyID aPropID) const {
// NOTE(emilio): This is dubious, but matches other browsers.
// See https://github.com/w3c/csswg-drafts/issues/2328
Side side = SideForPaddingOrMarginOrInsetProperty(aPropID);
return !style->StyleMargin()->mMargin.Get(side).ConvertsToLength();
return !style->StyleMargin()->GetMargin(side).ConvertsToLength();
}
default:
return false;
@@ -2088,10 +2088,10 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetBorderWidthFor(
}
already_AddRefed<CSSValue> nsComputedDOMStyle::GetMarginFor(Side aSide) {
const auto& margin = StyleMargin()->mMargin.Get(aSide);
const auto& margin = StyleMargin()->GetMargin(aSide);
if (!mInnerFrame || margin.ConvertsToLength()) {
auto val = MakeRefPtr<nsROCSSPrimitiveValue>();
SetValueToLengthPercentageOrAuto(val, margin, false);
SetValueToMargin(val, margin);
return val.forget();
}
AssertFlushedPendingReflows();
@@ -2188,7 +2188,7 @@ void nsComputedDOMStyle::SetValueToLengthPercentageOrAuto(
void nsComputedDOMStyle::SetValueToInset(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleInset& aInset) {
// This function isn't used for absolutely positioned insets, so just assume
// `anchor()` is `auto`.
// `anchor()` or `anchor-size()` is `auto`.
if (!aInset.IsLengthPercentage()) {
aValue->SetString("auto");
return;
@@ -2196,6 +2196,16 @@ void nsComputedDOMStyle::SetValueToInset(nsROCSSPrimitiveValue* aValue,
SetValueToLengthPercentage(aValue, aInset.AsLengthPercentage(), false);
}
void nsComputedDOMStyle::SetValueToMargin(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleMargin& aMargin) {
// May have to compute `anchor-size()` value here.
if (!aMargin.IsLengthPercentage()) {
aValue->SetString("auto");
return;
}
SetValueToLengthPercentage(aValue, aMargin.AsLengthPercentage(), false);
}
void nsComputedDOMStyle::SetValueToLengthPercentage(
nsROCSSPrimitiveValue* aValue, const mozilla::LengthPercentage& aLength,
bool aClampNegativeCalc) {

View File

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

View File

@@ -309,9 +309,12 @@ static StyleRect<T> StyleRectWithAllSides(const T& aSide) {
return {aSide, aSide, aSide, aSide};
}
const StyleMargin nsStyleMargin::kZeroMargin =
StyleMargin::LengthPercentage(StyleLengthPercentage::Zero());
nsStyleMargin::nsStyleMargin()
: mMargin(StyleRectWithAllSides(
LengthPercentageOrAuto::LengthPercentage(LengthPercentage::Zero()))),
StyleMargin::LengthPercentage(LengthPercentage::Zero()))),
mScrollMargin(StyleRectWithAllSides(StyleLength{0.})),
mOverflowClipMargin(StyleLength::Zero()) {
MOZ_COUNT_CTOR(nsStyleMargin);
@@ -328,7 +331,7 @@ nsChangeHint nsStyleMargin::CalcDifference(
const nsStyleMargin& aNewData) const {
nsChangeHint hint = nsChangeHint(0);
if (mMargin != aNewData.mMargin) {
if (!MarginEquals(aNewData)) {
// Margin differences can't affect descendant intrinsic sizes and
// don't need to force children to reflow.
hint |= nsChangeHint_NeedReflow | nsChangeHint_ReflowChangesSizeOrPosition |

View File

@@ -368,7 +368,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin {
}
for (const auto side : mozilla::AllPhysicalSides()) {
aMargin.Side(side) = mMargin.Get(side).AsLengthPercentage().ToLength();
aMargin.Side(side) = GetMargin(side).AsLengthPercentage().ToLength();
}
return true;
}
@@ -386,7 +386,33 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin {
inline bool HasInlineAxisAuto(mozilla::WritingMode aWM) const;
inline bool HasAuto(mozilla::LogicalAxis, mozilla::WritingMode) const;
mozilla::StyleRect<mozilla::LengthPercentageOrAuto> mMargin;
// TODO(dshin): The following functions are used as shims to deal
// anchor size functions as if it's zero, before the computation
// is implemented.
static const mozilla::StyleMargin kZeroMargin;
const mozilla::StyleMargin& GetMargin(mozilla::Side aSide) const {
const auto& result = mMargin.Get(aSide);
if (MOZ_UNLIKELY(result.IsAnchorSizeFunction())) {
return kZeroMargin;
}
return result;
}
bool MarginEquals(const nsStyleMargin& aOther) const {
for (const auto side : mozilla::AllPhysicalSides()) {
if (GetMargin(side) != aOther.GetMargin(side)) {
return false;
}
}
return true;
}
// As with other logical-coordinate accessors, definitions for these
// are found in WritingModes.h.
inline const mozilla::StyleMargin& GetMargin(mozilla::LogicalSide aSide,
mozilla::WritingMode aWM) const;
mozilla::StyleRect<mozilla::StyleMargin> mMargin;
mozilla::StyleRect<mozilla::StyleLength> mScrollMargin;
// TODO: Add support for overflow-clip-margin: <visual-box> and maybe
// per-axis/side clipping, see https://github.com/w3c/csswg-drafts/issues/7245

View File

@@ -13,8 +13,8 @@
%>
${helpers.predefined_type(
"margin-%s" % side[0],
"LengthPercentageOrAuto",
"computed::LengthPercentageOrAuto::zero()",
"Margin",
"computed::Margin::zero()",
engines="gecko servo",
aliases=maybe_moz_logical_alias(engine, side, "-moz-margin-%s"),
allow_quirks="No" if side[1] else "Yes",

View File

@@ -8,7 +8,7 @@
${helpers.four_sides_shorthand(
"margin",
"margin-%s",
"specified::LengthPercentageOrAuto::parse",
"specified::Margin::parse",
engines="gecko servo",
spec="https://drafts.csswg.org/css-box/#propdef-margin",
rule_types_allowed=DEFAULT_RULES_AND_PAGE | POSITION_TRY_RULE,
@@ -19,7 +19,7 @@ ${helpers.two_properties_shorthand(
"margin-block",
"margin-block-start",
"margin-block-end",
"specified::LengthPercentageOrAuto::parse",
"specified::Margin::parse",
engines="gecko servo",
spec="https://drafts.csswg.org/css-logical/#propdef-margin-block",
rule_types_allowed=DEFAULT_RULES_AND_POSITION_TRY
@@ -29,7 +29,7 @@ ${helpers.two_properties_shorthand(
"margin-inline",
"margin-inline-start",
"margin-inline-end",
"specified::LengthPercentageOrAuto::parse",
"specified::Margin::parse",
engines="gecko servo",
spec="https://drafts.csswg.org/css-logical/#propdef-margin-inline",
rule_types_allowed=DEFAULT_RULES_AND_POSITION_TRY

View File

@@ -566,3 +566,6 @@ pub type MaxSize = GenericMaxSize<NonNegativeLengthPercentage>;
/// A computed value for `anchor-size` runction.
pub type AnchorSizeFunction = GenericAnchorSizeFunction<LengthPercentage>;
/// A computed type for `margin` properties.
pub type Margin = generics::GenericMargin<LengthPercentage>;

View File

@@ -74,7 +74,7 @@ pub use self::font::{MathDepth, MozScriptMinSize, MozScriptSizeMultiplier, XLang
pub use self::image::{Gradient, Image, ImageRendering, LineDirection};
pub use self::length::{AnchorSizeFunction, CSSPixelLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage, NonNegativeLengthOrNumber};
pub use self::length::{LengthOrAuto, LengthPercentageOrAuto, MaxSize, Size};
pub use self::length::{LengthOrAuto, LengthPercentageOrAuto, MaxSize, Margin, Size};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;

View File

@@ -11,10 +11,10 @@ use crate::values::DashedIdent;
use crate::Zero;
use cssparser::Parser;
use std::fmt::Write;
use style_traits::CssWriter;
use style_traits::ParseError;
use style_traits::StyleParseErrorKind;
use style_traits::ToCss;
use style_traits::{CssWriter, SpecifiedValueInfo};
/// A `<length-percentage> | auto` value.
#[allow(missing_docs)]
@@ -466,3 +466,64 @@ pub enum AnchorSizeKeyword {
/// Same as `Inline`, resolved against the positioned element's writing mode.
SelfInline,
}
/// Specified type for `margin` properties, which allows
/// the use of the `anchor-size()` function.
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Debug,
MallocSizeOf,
PartialEq,
ToCss,
ToShmem,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToResolvedValue,
)]
#[repr(C)]
pub enum GenericMargin<LP> {
/// A `<length-percentage>` value.
LengthPercentage(LP),
/// An `auto` value.
Auto,
/// Margin size defined by the anchor element.
///
/// https://drafts.csswg.org/css-anchor-position-1/#funcdef-anchor-size
AnchorSizeFunction(
#[animation(field_bound)]
#[distance(field_bound)]
Box<GenericAnchorSizeFunction<LP>>,
),
}
impl<LP> SpecifiedValueInfo for GenericMargin<LP>
where
LP: SpecifiedValueInfo,
{
fn collect_completion_keywords(f: style_traits::KeywordsCollectFn) {
LP::collect_completion_keywords(f);
f(&["auto"]);
if static_prefs::pref!("layout.css.anchor-positioning.enabled") {
f(&["anchor-size"]);
}
}
}
impl<LP> Zero for GenericMargin<LP>
where
LP: Zero,
{
fn is_zero(&self) -> bool {
match self {
Self::LengthPercentage(l) => l.is_zero(),
Self::Auto | Self::AnchorSizeFunction(_) => false,
}
}
fn zero() -> Self {
Self::LengthPercentage(LP::zero())
}
}

View File

@@ -16,7 +16,7 @@ use crate::values::computed::{self, CSSPixelLength, Context};
use crate::values::generics::length as generics;
use crate::values::generics::length::{
GenericAnchorSizeFunction, GenericLengthOrNumber, GenericLengthPercentageOrNormal,
GenericMaxSize, GenericSize,
GenericMargin, GenericMaxSize, GenericSize,
};
use crate::values::generics::NonNegative;
use crate::values::specified::calc::{self, CalcNode};
@@ -2057,3 +2057,36 @@ pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, No
/// A specified value for `anchor-size` function.
pub type AnchorSizeFunction = GenericAnchorSizeFunction<LengthPercentage>;
/// A specified value for `margin` properties.
pub type Margin = GenericMargin<LengthPercentage>;
impl Margin {
/// Parses an inset type, allowing the unitless length quirk.
/// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
#[inline]
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
if let Ok(l) = input.try_parse(|i| LengthPercentage::parse_quirky(context, i, allow_quirks))
{
return Ok(Self::LengthPercentage(l));
}
if input.try_parse(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(Self::Auto);
}
let inner = AnchorSizeFunction::parse(context, input)?;
Ok(Self::AnchorSizeFunction(Box::new(inner)))
}
}
impl Parse for Margin {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}

View File

@@ -66,7 +66,7 @@ pub use self::image::{EndingShape as GradientEndingShape, Gradient, Image, Image
pub use self::length::{AbsoluteLength, AnchorSizeFunction, CalcLengthPercentage, CharacterWidth};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber, NonNegativeLengthOrNumber};
pub use self::length::{LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{MaxSize, Size};
pub use self::length::{Margin, MaxSize, Size};
pub use self::length::{NoCalcLength, ViewportPercentageLength, ViewportVariant};
pub use self::length::{
NonNegativeLength, NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto,

View File

@@ -325,6 +325,7 @@ include = [
"Inset",
"AnchorFunction",
"AnchorSizeFunction",
"Margin",
]
item_types = ["enums", "structs", "unions", "typedefs", "functions", "constants"]
renaming_overrides_prefixing = true
@@ -1142,3 +1143,12 @@ renaming_overrides_prefixing = true
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
"""
"GenericMargin" = """
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
inline bool HasLengthAndPercentage() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
inline float ToPercentage() const;
"""

View File

@@ -5588,7 +5588,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(
) {
use style::properties::longhands::border_spacing::SpecifiedValue as BorderSpacing;
use style::properties::PropertyDeclaration;
use style::values::generics::length::{LengthPercentageOrAuto, Size};
use style::values::generics::length::{GenericMargin, Size};
use style::values::generics::NonNegative;
use style::values::specified::length::{
LengthPercentage, NonNegativeLength, NonNegativeLengthPercentage,
@@ -5598,7 +5598,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(
let long = get_longhand_from_id!(property);
let nocalc = NoCalcLength::from_px(value);
let lp = LengthPercentage::Length(nocalc);
let lp_or_auto = LengthPercentageOrAuto::LengthPercentage(lp.clone());
let margin = GenericMargin::LengthPercentage(lp.clone());
let prop = match_wrap_declared! { long,
Height => Size::LengthPercentage(NonNegative(lp)),
Width => Size::LengthPercentage(NonNegative(lp)),
@@ -5606,10 +5606,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(
BorderRightWidth => BorderSideWidth::from_px(value),
BorderBottomWidth => BorderSideWidth::from_px(value),
BorderLeftWidth => BorderSideWidth::from_px(value),
MarginTop => lp_or_auto,
MarginRight => lp_or_auto,
MarginBottom => lp_or_auto,
MarginLeft => lp_or_auto,
MarginTop => margin,
MarginRight => margin,
MarginBottom => margin,
MarginLeft => margin,
PaddingTop => NonNegative(lp),
PaddingRight => NonNegative(lp),
PaddingBottom => NonNegative(lp),
@@ -5827,7 +5827,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
) {
use style::properties::PropertyDeclaration;
use style::values::computed::Percentage;
use style::values::generics::length::{LengthPercentageOrAuto, Size};
use style::values::generics::length::{GenericMargin, LengthPercentageOrAuto, Size};
use style::values::generics::NonNegative;
use style::values::specified::length::LengthPercentage;
use style::values::specified::FontSize;
@@ -5835,7 +5835,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
let long = get_longhand_from_id!(property);
let pc = Percentage(value);
let lp = LengthPercentage::Percentage(pc);
let lp_or_auto = LengthPercentageOrAuto::LengthPercentage(lp.clone());
let margin = GenericMargin::LengthPercentage(lp.clone());
let prop = match_wrap_declared! { long,
Height => Size::LengthPercentage(NonNegative(lp)),
@@ -5847,10 +5847,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
R => NonNegative(lp),
Rx => LengthPercentageOrAuto::LengthPercentage(NonNegative(lp)),
Ry => LengthPercentageOrAuto::LengthPercentage(NonNegative(lp)),
MarginTop => lp_or_auto,
MarginRight => lp_or_auto,
MarginBottom => lp_or_auto,
MarginLeft => lp_or_auto,
MarginTop => margin,
MarginRight => margin,
MarginBottom => margin,
MarginLeft => margin,
FontSize => FontSize::Length(LengthPercentage::Percentage(pc)),
};
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
@@ -5864,10 +5864,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetAutoValue(
property: nsCSSPropertyID,
) {
use style::properties::PropertyDeclaration;
use style::values::generics::length::{LengthPercentageOrAuto, Size};
use style::values::generics::length::{GenericMargin, Size};
let long = get_longhand_from_id!(property);
let auto = LengthPercentageOrAuto::Auto;
let auto = GenericMargin::Auto;
let prop = match_wrap_declared! { long,
Height => Size::auto(),