Bug 1523071 - Use Rust lengths for margin / padding / inset. r=jwatt

Also for the intersection observer root margin, since it was easier to fix it
up and clean it up than not doing it.

This is the first big step to get rid of nscoord. It duplicates a bit of logic
in nsLayoutUtils since for now max/min-width/height are still represented with
nsStyleCoord, but I think I prefer to land this incrementally.

I didn't add helpers for the physical accessors of the style rect sides that
nsStyleSides has (top/bottom/left/right) since I think we generally should
encourage the logical versions, but let me know if you want me to do that.

Differential Revision: https://phabricator.services.mozilla.com/D17739
This commit is contained in:
Emilio Cobos Álvarez
2019-01-26 11:00:44 +01:00
parent 1e1ca69054
commit ce3d5d43c1
29 changed files with 417 additions and 287 deletions

View File

@@ -285,9 +285,8 @@ void DOMIntersectionObserver::Update(Document* aDocument,
NS_FOR_CSS_SIDES(side) {
nscoord basis = side == eSideTop || side == eSideBottom ? rootRect.Height()
: rootRect.Width();
nsStyleCoord coord = mRootMargin.Get(side);
rootMargin.Side(side) =
nsLayoutUtils::ComputeCBDependentValue(basis, coord);
nsLayoutUtils::ComputeCBDependentValue(basis, mRootMargin.Get(side));
}
for (size_t i = 0; i < mObservationTargets.Length(); ++i) {

View File

@@ -147,7 +147,7 @@ class DOMIntersectionObserver final : public nsISupports,
RefPtr<Document> mDocument;
RefPtr<mozilla::dom::IntersectionCallback> mCallback;
RefPtr<Element> mRoot;
nsStyleSides mRootMargin;
StyleRect<LengthPercentage> mRootMargin;
nsTArray<double> mThresholds;
// Holds raw pointers which are explicitly cleared by UnlinkTarget().

View File

@@ -1761,26 +1761,26 @@ nsIScrollableFrame* nsLayoutUtils::GetScrollableFrameFor(
int32_t sides = eSideBitsNone;
if (aFixedPosFrame != aViewportFrame) {
const nsStylePosition* position = aFixedPosFrame->StylePosition();
if (position->mOffset.GetRightUnit() != eStyleUnit_Auto) {
if (!position->mOffset.Get(eSideRight).IsAuto()) {
sides |= eSideBitsRight;
if (position->mOffset.GetLeftUnit() != eStyleUnit_Auto) {
if (!position->mOffset.Get(eSideLeft).IsAuto()) {
sides |= eSideBitsLeft;
anchor.x = anchorRect.x + anchorRect.width / 2.f;
} else {
anchor.x = anchorRect.XMost();
}
} else if (position->mOffset.GetLeftUnit() != eStyleUnit_Auto) {
} else if (!position->mOffset.Get(eSideLeft).IsAuto()) {
sides |= eSideBitsLeft;
}
if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto) {
if (!position->mOffset.Get(eSideBottom).IsAuto()) {
sides |= eSideBitsBottom;
if (position->mOffset.GetTopUnit() != eStyleUnit_Auto) {
if (!position->mOffset.Get(eSideTop).IsAuto()) {
sides |= eSideBitsTop;
anchor.y = anchorRect.y + anchorRect.height / 2.f;
} else {
anchor.y = anchorRect.YMost();
}
} else if (position->mOffset.GetTopUnit() != eStyleUnit_Auto) {
} else if (!position->mOffset.Get(eSideTop).IsAuto()) {
sides |= eSideBitsTop;
}
}
@@ -4611,6 +4611,15 @@ bool nsLayoutUtils::IsViewportScrollbarFrame(nsIFrame* aFrame) {
IsProperAncestorFrame(rootScrolledFrame, aFrame));
}
// Use only for paddings, since it clamps negative calc() to 0.
static bool GetAbsoluteCoord(const LengthPercentage& aStyle, nscoord& aResult) {
if (!aStyle.ConvertsToLength()) {
return false;
}
aResult = std::max(0, aStyle.ToLength());
return true;
}
// Use only for widths/heights (or their min/max), since it clamps
// negative calc() results to 0.
static bool GetAbsoluteCoord(const nsStyleCoord& aStyle, nscoord& aResult) {
@@ -4727,6 +4736,54 @@ static bool GetPercentBSize(const nsStyleCoord& aStyle, nsIFrame* aFrame,
return true;
}
static bool GetPercentBSize(const LengthPercentage& aStyle, nsIFrame* aFrame,
bool aHorizontalAxis, nscoord& aResult) {
if (!aStyle.HasPercent()) {
return false;
}
// TODO(emilio): Temporary until I convert width / height to Servo too.
nsStyleCoord coord;
if (aStyle.was_calc) {
nscoord length = CSSPixel::ToAppUnits(aStyle.LengthInCSSPixels());
float percent = aStyle.Percentage();
auto* calc = new nsStyleCoord::Calc();
calc->mLength = length;
calc->mPercent = percent;
calc->mHasPercent = true;
coord.SetCalcValue(calc); // Takes ownership.
} else {
coord.SetPercentValue(aStyle.Percentage());
}
return GetPercentBSize(coord, aFrame, aHorizontalAxis, aResult);
}
// Return true if aStyle can be resolved to a definite value and if so
// return that value in aResult.
static bool GetDefiniteSize(const LengthPercentage& aStyle, nsIFrame* aFrame,
bool aIsInlineAxis,
const Maybe<LogicalSize>& aPercentageBasis,
nscoord* aResult) {
if (aStyle.ConvertsToLength()) {
*aResult = aStyle.ToLength();
return true;
}
if (!aPercentageBasis) {
return false;
}
auto wm = aFrame->GetWritingMode();
nscoord pb = aIsInlineAxis ? aPercentageBasis.value().ISize(wm)
: aPercentageBasis.value().BSize(wm);
if (pb == NS_UNCONSTRAINEDSIZE) {
return false;
}
*aResult = std::max(0, aStyle.Resolve(pb));
return true;
}
// Return true if aStyle can be resolved to a definite value and if so
// return that value in aResult.
static bool GetDefiniteSize(const nsStyleCoord& aStyle, nsIFrame* aFrame,
@@ -4795,10 +4852,10 @@ static nscoord GetBSizeTakenByBoxSizing(StyleBoxSizing aBoxSizing,
? styleBorder->GetComputedBorder().TopBottom()
: styleBorder->GetComputedBorder().LeftRight();
if (!aIgnorePadding) {
const nsStyleSides& stylePadding = aFrame->StylePadding()->mPadding;
const nsStyleCoord& paddingStart =
const auto& stylePadding = aFrame->StylePadding()->mPadding;
const LengthPercentage& paddingStart =
stylePadding.Get(aHorizontalAxis ? eSideTop : eSideLeft);
const nsStyleCoord& paddingEnd =
const LengthPercentage& paddingEnd =
stylePadding.Get(aHorizontalAxis ? eSideBottom : eSideRight);
nscoord pad;
// XXXbz Calling GetPercentBSize on padding values looks bogus, since
@@ -4837,10 +4894,10 @@ static nscoord GetDefiniteSizeTakenByBoxSizing(
? styleBorder->GetComputedBorder().LeftRight()
: styleBorder->GetComputedBorder().TopBottom();
if (!aIgnorePadding) {
const nsStyleSides& stylePadding = aFrame->StylePadding()->mPadding;
const nsStyleCoord& pStart =
const auto& stylePadding = aFrame->StylePadding()->mPadding;
const LengthPercentage& pStart =
stylePadding.Get(isHorizontalAxis ? eSideLeft : eSideTop);
const nsStyleCoord& pEnd =
const LengthPercentage& pEnd =
stylePadding.Get(isHorizontalAxis ? eSideRight : eSideBottom);
nscoord pad;
// XXXbz Calling GetPercentBSize on padding values looks bogus, since
@@ -5478,24 +5535,8 @@ static void AddStateBitToAncestors(nsIFrame* aFrame, nsFrameState aBit) {
return result;
}
/* static */ nscoord nsLayoutUtils::ComputeCBDependentValue(
nscoord aPercentBasis, const nsStyleCoord& aCoord) {
NS_WARNING_ASSERTION(
aPercentBasis != NS_UNCONSTRAINEDSIZE,
"have unconstrained width or height; this should only result from very "
"large sizes, not attempts at intrinsic size calculation");
if (aCoord.IsCoordPercentCalcUnit()) {
return aCoord.ComputeCoordPercentCalc(aPercentBasis);
}
NS_ASSERTION(aCoord.GetUnit() == eStyleUnit_None ||
aCoord.GetUnit() == eStyleUnit_Auto,
"unexpected width value");
return 0;
}
/* static */ nscoord nsLayoutUtils::ComputeBSizeDependentValue(
nscoord aContainingBlockBSize, const nsStyleCoord& aCoord) {
nscoord aContainingBlockBSize, const LengthPercentageOrAuto& aCoord) {
// XXXldb Some callers explicitly check aContainingBlockBSize
// against NS_AUTOHEIGHT *and* unit against eStyleUnit_Percent or
// calc()s containing percents before calling this function.
@@ -5506,14 +5547,11 @@ static void AddStateBitToAncestors(nsIFrame* aFrame, nsFrameState aBit) {
MOZ_ASSERT(NS_AUTOHEIGHT != aContainingBlockBSize || !aCoord.HasPercent(),
"unexpected containing block block-size");
if (aCoord.IsCoordPercentCalcUnit()) {
return aCoord.ComputeCoordPercentCalc(aContainingBlockBSize);
if (aCoord.IsAuto()) {
return 0;
}
NS_ASSERTION(aCoord.GetUnit() == eStyleUnit_None ||
aCoord.GetUnit() == eStyleUnit_Auto,
"unexpected block-size value");
return 0;
return aCoord.AsLengthPercentage().Resolve(aContainingBlockBSize);
}
/* static */ void nsLayoutUtils::MarkDescendantsDirty(nsIFrame* aSubtreeRoot) {

View File

@@ -147,6 +147,7 @@ enum class ReparentingDirection {
class nsLayoutUtils {
typedef mozilla::ComputedStyle ComputedStyle;
typedef mozilla::LengthPercentage LengthPercentage;
typedef mozilla::LengthPercentageOrAuto LengthPercentageOrAuto;
typedef mozilla::dom::DOMRectList DOMRectList;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::StackingContextHelper StackingContextHelper;
@@ -1462,16 +1463,29 @@ class nsLayoutUtils {
uint32_t aFlags = 0);
/*
* Convert nsStyleCoord to nscoord when percentages depend on the
* Convert LengthPercentage to nscoord when percentages depend on the
* containing block size.
* @param aPercentBasis The width or height of the containing block
* (whichever the client wants to use for resolving percentages).
*/
static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
const nsStyleCoord& aCoord);
const LengthPercentage& aCoord) {
NS_WARNING_ASSERTION(
aPercentBasis != NS_UNCONSTRAINEDSIZE,
"have unconstrained width or height; this should only result from very "
"large sizes, not attempts at intrinsic size calculation");
return aCoord.Resolve(aPercentBasis);
}
static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
const LengthPercentageOrAuto& aCoord) {
if (aCoord.IsAuto()) {
return 0;
}
return ComputeCBDependentValue(aPercentBasis, aCoord.AsLengthPercentage());
}
static nscoord ComputeBSizeDependentValue(nscoord aContainingBlockBSize,
const nsStyleCoord& aCoord);
const LengthPercentageOrAuto&);
static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize,
nscoord aContentEdgeToBoxSizingBoxEdge,
@@ -1502,25 +1516,13 @@ class nsLayoutUtils {
(aCBBSize == nscoord_MAX && aCoord.HasPercent());
}
static bool IsPaddingZero(const nsStyleCoord& aCoord) {
return (aCoord.GetUnit() == eStyleUnit_Coord &&
aCoord.GetCoordValue() == 0) ||
(aCoord.GetUnit() == eStyleUnit_Percent &&
aCoord.GetPercentValue() == 0.0f) ||
(aCoord.IsCalcUnit() &&
static bool IsPaddingZero(const LengthPercentage& aLength) {
// clamp negative calc() to 0
aCoord.ComputeCoordPercentCalc(nscoord_MAX) <= 0 &&
aCoord.ComputeCoordPercentCalc(0) <= 0);
return aLength.Resolve(nscoord_MAX) <= 0 && aLength.Resolve(0) <= 0;
}
static bool IsMarginZero(const nsStyleCoord& aCoord) {
return (aCoord.GetUnit() == eStyleUnit_Coord &&
aCoord.GetCoordValue() == 0) ||
(aCoord.GetUnit() == eStyleUnit_Percent &&
aCoord.GetPercentValue() == 0.0f) ||
(aCoord.IsCalcUnit() &&
aCoord.ComputeCoordPercentCalc(nscoord_MAX) == 0 &&
aCoord.ComputeCoordPercentCalc(0) == 0);
static bool IsMarginZero(const LengthPercentage& aLength) {
return aLength.Resolve(nscoord_MAX) == 0 && aLength.Resolve(0) == 0;
}
static void MarkDescendantsDirty(nsIFrame* aSubtreeRoot);

View File

@@ -87,11 +87,11 @@ nscoord CSSAlignUtils::AlignJustifySelf(uint8_t aAlignment, LogicalAxis aAxis,
// don't need to do anything special to avoid expanding them.)
hasAutoMarginStart = hasAutoMarginEnd = false;
} else if (aAxis == eLogicalAxisBlock) {
hasAutoMarginStart = styleMargin.GetBStartUnit(wm) == eStyleUnit_Auto;
hasAutoMarginEnd = styleMargin.GetBEndUnit(wm) == eStyleUnit_Auto;
hasAutoMarginStart = styleMargin.GetBStart(wm).IsAuto();
hasAutoMarginEnd = styleMargin.GetBEnd(wm).IsAuto();
} else { /* aAxis == eLogicalAxisInline */
hasAutoMarginStart = styleMargin.GetIStartUnit(wm) == eStyleUnit_Auto;
hasAutoMarginEnd = styleMargin.GetIEndUnit(wm) == eStyleUnit_Auto;
hasAutoMarginStart = styleMargin.GetIStart(wm).IsAuto();
hasAutoMarginEnd = styleMargin.GetIEnd(wm).IsAuto();
}
// https://drafts.csswg.org/css-align-3/#overflow-values

View File

@@ -732,8 +732,7 @@ void ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
mStylePosition->MinBSizeDependsOnContainer(wm) ||
mStylePosition->MaxBSizeDependsOnContainer(wm) ||
mStylePosition->OffsetHasPercent(wm.PhysicalSide(eLogicalSideBStart)) ||
mStylePosition->mOffset.GetBEndUnit(wm) != eStyleUnit_Auto ||
mFrame->IsXULBoxFrame();
!mStylePosition->mOffset.GetBEnd(wm).IsAuto() || mFrame->IsXULBoxFrame();
if (mStyleText->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(mStyleText->mLineHeight.GetIntValue() ==
@@ -1016,10 +1015,8 @@ void ReflowInput::InitFrameType(LayoutFrameType aFrameType) {
// 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
bool inlineStartIsAuto =
eStyleUnit_Auto == position->mOffset.GetUnit(inlineStart);
bool inlineEndIsAuto =
eStyleUnit_Auto == position->mOffset.GetUnit(inlineEnd);
bool inlineStartIsAuto = position->mOffset.Get(inlineStart).IsAuto();
bool inlineEndIsAuto = position->mOffset.Get(inlineEnd).IsAuto();
// If neither 'inlineStart' nor 'inlineEnd' is auto, then we're
// over-constrained and we ignore one of them
@@ -1055,9 +1052,8 @@ void ReflowInput::InitFrameType(LayoutFrameType aFrameType) {
// and 'blockEnd' properties move relatively positioned elements in
// the block progression direction. They also must be each other's
// negative
bool blockStartIsAuto =
eStyleUnit_Auto == position->mOffset.GetUnit(blockStart);
bool blockEndIsAuto = eStyleUnit_Auto == position->mOffset.GetUnit(blockEnd);
bool blockStartIsAuto = position->mOffset.Get(blockStart).IsAuto();
bool blockEndIsAuto = position->mOffset.Get(blockEnd).IsAuto();
// Check for percentage based values and a containing block block-size
// that depends on the content block-size. Treat them like 'auto'
@@ -1281,7 +1277,7 @@ void ReflowInput::CalculateBorderPaddingMargin(
} else {
nscoord start, end;
// We have to compute the start and end values
if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(startSide)) {
if (mStyleMargin->mMargin.Get(startSide).IsAuto()) {
// We set this to 0 for now, and fix it up later in
// InitAbsoluteConstraints (which is caller of this function, via
// CalculateHypotheticalPosition).
@@ -1290,7 +1286,7 @@ void ReflowInput::CalculateBorderPaddingMargin(
start = nsLayoutUtils::ComputeCBDependentValue(
aContainingBlockSize, mStyleMargin->mMargin.Get(startSide));
}
if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(endSide)) {
if (mStyleMargin->mMargin.Get(endSide).IsAuto()) {
// We set this to 0 for now, and fix it up later in
// InitAbsoluteConstraints (which is caller of this function, via
// CalculateHypotheticalPosition).
@@ -1643,10 +1639,10 @@ void ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext,
"Why are we here?");
const auto& styleOffset = mStylePosition->mOffset;
bool iStartIsAuto = styleOffset.GetIStartUnit(cbwm) == eStyleUnit_Auto;
bool iEndIsAuto = styleOffset.GetIEndUnit(cbwm) == eStyleUnit_Auto;
bool bStartIsAuto = styleOffset.GetBStartUnit(cbwm) == eStyleUnit_Auto;
bool bEndIsAuto = styleOffset.GetBEndUnit(cbwm) == eStyleUnit_Auto;
bool iStartIsAuto = styleOffset.GetIStart(cbwm).IsAuto();
bool iEndIsAuto = styleOffset.GetIEnd(cbwm).IsAuto();
bool bStartIsAuto = styleOffset.GetBStart(cbwm).IsAuto();
bool bEndIsAuto = styleOffset.GetBEnd(cbwm).IsAuto();
// If both 'left' and 'right' are 'auto' or both 'top' and 'bottom' are
// 'auto', then compute the hypothetical box position where the element would
@@ -1886,10 +1882,8 @@ void ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext,
nscoord availMarginSpace =
aCBSize.ISize(cbwm) - offsets.IStartEnd(cbwm) - margin.IStartEnd(cbwm) -
borderPadding.IStartEnd(cbwm) - computedSize.ISize(cbwm);
marginIStartIsAuto =
eStyleUnit_Auto == mStyleMargin->mMargin.GetIStartUnit(cbwm);
marginIEndIsAuto =
eStyleUnit_Auto == mStyleMargin->mMargin.GetIEndUnit(cbwm);
marginIStartIsAuto = mStyleMargin->mMargin.GetIStart(cbwm).IsAuto();
marginIEndIsAuto = mStyleMargin->mMargin.GetIEnd(cbwm).IsAuto();
if (marginIStartIsAuto) {
if (marginIEndIsAuto) {
@@ -1974,10 +1968,8 @@ void ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext,
// * we're dealing with a replaced element
// * bsize was constrained by min- or max-bsize.
nscoord availMarginSpace = autoBSize - computedSize.BSize(cbwm);
marginBStartIsAuto =
eStyleUnit_Auto == mStyleMargin->mMargin.GetBStartUnit(cbwm);
marginBEndIsAuto =
eStyleUnit_Auto == mStyleMargin->mMargin.GetBEndUnit(cbwm);
marginBStartIsAuto = mStyleMargin->mMargin.GetBStart(cbwm).IsAuto();
marginBEndIsAuto = mStyleMargin->mMargin.GetBEnd(cbwm).IsAuto();
if (marginBStartIsAuto) {
if (marginBEndIsAuto) {
@@ -2482,8 +2474,8 @@ void ReflowInput::InitConstraints(nsPresContext* aPresContext,
: mStylePosition->UsedJustifySelf(alignCB->Style());
if ((inlineAxisAlignment != NS_STYLE_ALIGN_STRETCH &&
inlineAxisAlignment != NS_STYLE_ALIGN_NORMAL) ||
mStyleMargin->mMargin.GetIStartUnit(wm) == eStyleUnit_Auto ||
mStyleMargin->mMargin.GetIEndUnit(wm) == eStyleUnit_Auto) {
mStyleMargin->mMargin.GetIStart(wm).IsAuto() ||
mStyleMargin->mMargin.GetIEnd(wm).IsAuto()) {
computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
ComputeSizeFlags::eShrinkWrap);
}
@@ -2747,9 +2739,9 @@ void ReflowInput::CalculateBlockSideMargins(LayoutFrameType aFrameType) {
// The css2 spec clearly defines how block elements should behave
// in section 10.3.3.
const nsStyleSides& styleSides = mStyleMargin->mMargin;
bool isAutoStartMargin = eStyleUnit_Auto == styleSides.GetIStartUnit(cbWM);
bool isAutoEndMargin = eStyleUnit_Auto == styleSides.GetIEndUnit(cbWM);
const auto& styleSides = mStyleMargin->mMargin;
bool isAutoStartMargin = styleSides.GetIStart(cbWM).IsAuto();
bool isAutoEndMargin = styleSides.GetIEnd(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

View File

@@ -92,14 +92,14 @@ StickyScrollContainer::GetStickyScrollContainerForScrollFrame(
return aFrame->GetProperty(StickyScrollContainerProperty());
}
static nscoord ComputeStickySideOffset(Side aSide, const nsStyleSides& aOffset,
static nscoord ComputeStickySideOffset(
Side aSide, const StyleRect<LengthPercentageOrAuto>& aOffset,
nscoord aPercentBasis) {
if (eStyleUnit_Auto == aOffset.GetUnit(aSide)) {
auto& side = aOffset.Get(aSide);
if (side.IsAuto()) {
return NS_AUTOOFFSET;
} else {
return nsLayoutUtils::ComputeCBDependentValue(aPercentBasis,
aOffset.Get(aSide));
}
return nsLayoutUtils::ComputeCBDependentValue(aPercentBasis, side);
}
// static

View File

@@ -1896,6 +1896,32 @@ class LogicalRect {
nscoord mBSize; // block-size
};
template <typename T>
const T& StyleRect<T>::Get(mozilla::WritingMode aWM,
mozilla::LogicalSide aSide) const {
return Get(aWM.PhysicalSide(aSide));
}
template <typename T>
const T& StyleRect<T>::GetIStart(mozilla::WritingMode aWM) const {
return Get(aWM, mozilla::eLogicalSideIStart);
}
template <typename T>
const T& StyleRect<T>::GetBStart(mozilla::WritingMode aWM) const {
return Get(aWM, mozilla::eLogicalSideBStart);
}
template <typename T>
const T& StyleRect<T>::GetIEnd(mozilla::WritingMode aWM) const {
return Get(aWM, mozilla::eLogicalSideIEnd);
}
template <typename T>
const T& StyleRect<T>::GetBEnd(mozilla::WritingMode aWM) const {
return Get(aWM, mozilla::eLogicalSideBEnd);
}
} // namespace mozilla
// Definitions of inline methods for nsStyleSides, declared in nsStyleCoord.h
@@ -2043,10 +2069,11 @@ inline bool nsStylePosition::MaxBSizeDependsOnContainer(
}
inline bool nsStyleMargin::HasBlockAxisAuto(mozilla::WritingMode aWM) const {
return mMargin.HasBlockAxisAuto(aWM);
return mMargin.GetBStart(aWM).IsAuto() || mMargin.GetBEnd(aWM).IsAuto();
}
inline bool nsStyleMargin::HasInlineAxisAuto(mozilla::WritingMode aWM) const {
return mMargin.HasInlineAxisAuto(aWM);
return mMargin.GetIStart(aWM).IsAuto() || mMargin.GetIEnd(aWM).IsAuto();
}
#endif // WritingModes_h_

View File

@@ -218,13 +218,13 @@ void nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame,
aReflowStatus.MergeCompletionStatusFrom(reflowStatus);
}
static inline bool IsFixedPaddingSize(const nsStyleCoord& aCoord) {
static inline bool IsFixedPaddingSize(const LengthPercentage& aCoord) {
return aCoord.ConvertsToLength();
}
static inline bool IsFixedMarginSize(const nsStyleCoord& aCoord) {
static inline bool IsFixedMarginSize(const LengthPercentageOrAuto& aCoord) {
return aCoord.ConvertsToLength();
}
static inline bool IsFixedOffset(const nsStyleCoord& aCoord) {
static inline bool IsFixedOffset(const LengthPercentageOrAuto& aCoord) {
return aCoord.ConvertsToLength();
}
@@ -243,10 +243,10 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// whichever of them is not auto and the width).
// See ReflowInput::InitAbsoluteConstraints -- these are the
// only cases when we call CalculateHypotheticalBox().
if ((pos->mOffset.GetTopUnit() == eStyleUnit_Auto &&
pos->mOffset.GetBottomUnit() == eStyleUnit_Auto) ||
(pos->mOffset.GetLeftUnit() == eStyleUnit_Auto &&
pos->mOffset.GetRightUnit() == eStyleUnit_Auto)) {
if ((pos->mOffset.Get(eSideTop).IsAuto() &&
pos->mOffset.Get(eSideBottom).IsAuto()) ||
(pos->mOffset.Get(eSideLeft).IsAuto() ||
pos->mOffset.Get(eSideRight).IsAuto())) {
return true;
}
if (!aCBWidthChanged && !aCBHeightChanged) {
@@ -288,8 +288,8 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// Note that borders never depend on the parent bsize.
if ((pos->BSizeDependsOnContainer(wm) &&
!(pos->BSize(wm).GetUnit() == eStyleUnit_Auto &&
pos->mOffset.GetBEndUnit(wm) == eStyleUnit_Auto &&
pos->mOffset.GetBStartUnit(wm) != eStyleUnit_Auto)) ||
pos->mOffset.GetBEnd(wm).IsAuto() &&
!pos->mOffset.GetBStart(wm).IsAuto())) ||
pos->MinBSizeDependsOnContainer(wm) ||
pos->MaxBSizeDependsOnContainer(wm) ||
!IsFixedPaddingSize(padding->mPadding.GetBStart(wm)) ||
@@ -311,7 +311,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->mOffset.GetLeft())) {
if (!IsFixedOffset(pos->mOffset.Get(eSideLeft))) {
return true;
}
// Note that even if 'left' is a length, our position can still
@@ -323,17 +323,17 @@ bool nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// sure of.
if ((wm.GetInlineDir() == WritingMode::eInlineRTL ||
wm.GetBlockDir() == WritingMode::eBlockRL) &&
pos->mOffset.GetRightUnit() != eStyleUnit_Auto) {
!pos->mOffset.Get(eSideRight).IsAuto()) {
return true;
}
}
if (aCBHeightChanged) {
if (!IsFixedOffset(pos->mOffset.GetTop())) {
if (!IsFixedOffset(pos->mOffset.Get(eSideTop))) {
return true;
}
// See comment above for width changes.
if (wm.GetInlineDir() == WritingMode::eInlineBTT &&
pos->mOffset.GetBottomUnit() != eStyleUnit_Auto) {
!pos->mOffset.Get(eSideBottom).IsAuto()) {
return true;
}
}

View File

@@ -1900,10 +1900,11 @@ static inline bool IsAlignedLeft(uint8_t aAlignment, uint8_t aDirection,
void nsBlockFrame::PrepareResizeReflow(BlockReflowInput& aState) {
// See if we can try and avoid marking all the lines as dirty
// FIXME(emilio): This should be writing-mode aware, I guess.
bool tryAndSkipLines =
// The left content-edge must be a constant distance from the left
// border-edge.
!StylePadding()->mPadding.GetLeft().HasPercent();
!StylePadding()->mPadding.Get(eSideLeft).HasPercent();
#ifdef DEBUG
if (gDisableResizeOpt) {

View File

@@ -674,13 +674,21 @@ void nsContainerFrame::SyncFrameViewAfterReflow(
}
}
static nscoord GetCoord(const nsStyleCoord& aCoord, nscoord aIfNotCoord) {
static nscoord GetCoord(const LengthPercentage& aCoord, nscoord aIfNotCoord) {
if (aCoord.ConvertsToLength()) {
return aCoord.ComputeCoordPercentCalc(0);
return aCoord.ToLength();
}
return aIfNotCoord;
}
static nscoord GetCoord(const LengthPercentageOrAuto& aCoord,
nscoord aIfNotCoord) {
if (aCoord.IsAuto()) {
return aIfNotCoord;
}
return GetCoord(aCoord.AsLengthPercentage(), aIfNotCoord);
}
void nsContainerFrame::DoInlineIntrinsicISize(
gfxContext* aRenderingContext, InlineIntrinsicISizeData* aData,
nsLayoutUtils::IntrinsicISizeType aType) {

View File

@@ -1937,16 +1937,16 @@ FlexItem::FlexItem(ReflowInput& aFlexItemReflowInput, float aFlexGrow,
SetFlexBaseSizeAndMainSize(aFlexBaseSize);
CheckForMinSizeAuto(aFlexItemReflowInput, aAxisTracker);
const nsStyleSides& styleMargin = aFlexItemReflowInput.mStyleMargin->mMargin;
const nsStyleMargin* styleMargin = aFlexItemReflowInput.mStyleMargin;
mHasAnyAutoMargin =
styleMargin.HasInlineAxisAuto(mWM) || styleMargin.HasBlockAxisAuto(mWM);
styleMargin->HasInlineAxisAuto(mWM) || styleMargin->HasBlockAxisAuto(mWM);
// Assert that any "auto" margin components are set to 0.
// (We'll resolve them later; until then, we want to treat them as 0-sized.)
#ifdef DEBUG
{
NS_FOR_CSS_SIDES(side) {
if (styleMargin.GetUnit(side) == eStyleUnit_Auto) {
if (styleMargin->mMargin.Get(side).IsAuto()) {
MOZ_ASSERT(GetMarginComponentForSide(side) == 0,
"Someone else tried to resolve our auto margin");
}
@@ -2090,10 +2090,10 @@ bool FlexItem::IsCrossSizeAuto() const {
uint32_t FlexItem::GetNumAutoMarginsInAxis(AxisOrientationType aAxis) const {
uint32_t numAutoMargins = 0;
const nsStyleSides& styleMargin = mFrame->StyleMargin()->mMargin;
const auto& styleMargin = mFrame->StyleMargin()->mMargin;
for (uint32_t i = 0; i < eNumAxisEdges; i++) {
mozilla::Side side = kAxisOrientationToSidesMap[aAxis][i];
if (styleMargin.GetUnit(side) == eStyleUnit_Auto) {
if (styleMargin.Get(side).IsAuto()) {
numAutoMargins++;
}
}
@@ -3002,10 +3002,10 @@ MainAxisPositionTracker::MainAxisPositionTracker(
void MainAxisPositionTracker::ResolveAutoMarginsInMainAxis(FlexItem& aItem) {
if (mNumAutoMarginsInMainAxis) {
const nsStyleSides& styleMargin = aItem.Frame()->StyleMargin()->mMargin;
const auto& styleMargin = aItem.Frame()->StyleMargin()->mMargin;
for (uint32_t i = 0; i < eNumAxisEdges; i++) {
mozilla::Side side = kAxisOrientationToSidesMap[mAxis][i];
if (styleMargin.GetUnit(side) == eStyleUnit_Auto) {
if (styleMargin.Get(side).IsAuto()) {
// NOTE: This integer math will skew the distribution of remainder
// app-units towards the end, which is fine.
nscoord curAutoMarginSize =
@@ -3385,10 +3385,10 @@ 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 nsStyleSides& styleMargin = aItem.Frame()->StyleMargin()->mMargin;
const auto& styleMargin = aItem.Frame()->StyleMargin()->mMargin;
for (uint32_t i = 0; i < eNumAxisEdges; i++) {
mozilla::Side side = kAxisOrientationToSidesMap[mAxis][i];
if (styleMargin.GetUnit(side) == eStyleUnit_Auto) {
if (styleMargin.Get(side).IsAuto()) {
MOZ_ASSERT(aItem.GetMarginComponentForSide(side) == 0,
"Expecting auto margins to have value '0' before we "
"update them");
@@ -4209,8 +4209,8 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
const nsStyleCoord& bsize = stylePos->BSize(wm);
if (bsize.HasPercent() ||
(StyleDisplay()->IsAbsolutelyPositionedStyle() && bsize.IsAutoOrEnum() &&
eStyleUnit_Auto != stylePos->mOffset.GetBStartUnit(wm) &&
eStyleUnit_Auto != stylePos->mOffset.GetBEndUnit(wm))) {
!stylePos->mOffset.GetBStart(wm).IsAuto() &&
!stylePos->mOffset.GetBEnd(wm).IsAuto())) {
AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
}

View File

@@ -1104,8 +1104,7 @@ void nsIFrame::MarkNeedsDisplayItemRebuild() {
}
if (mInScrollAnchorChain) {
const nsStylePosition* oldPosition =
aOldComputedStyle->StylePosition();
const nsStylePosition* oldPosition = aOldComputedStyle->StylePosition();
if (oldPosition->mOffset != StylePosition()->mOffset ||
oldPosition->mWidth != StylePosition()->mWidth ||
oldPosition->mMinWidth != StylePosition()->mMinWidth ||
@@ -5256,15 +5255,16 @@ void nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aBreakType) {
mLineIsEmpty = true;
}
static nscoord ResolveMargin(const nsStyleCoord& aStyle,
static nscoord ResolveMargin(const LengthPercentageOrAuto& aStyle,
nscoord aPercentageBasis) {
if (aStyle.GetUnit() == eStyleUnit_Auto) {
if (aStyle.IsAuto()) {
return nscoord(0);
}
return nsLayoutUtils::ResolveToLength<false>(aStyle, aPercentageBasis);
return nsLayoutUtils::ResolveToLength<false>(aStyle.AsLengthPercentage(),
aPercentageBasis);
}
static nscoord ResolvePadding(const nsStyleCoord& aStyle,
static nscoord ResolvePadding(const LengthPercentage& aStyle,
nscoord aPercentageBasis) {
return nsLayoutUtils::ResolveToLength<true>(aStyle, aPercentageBasis);
}
@@ -5276,20 +5276,22 @@ static nsIFrame::IntrinsicISizeOffsetData IntrinsicSizeOffsets(
const auto& margin = aFrame->StyleMargin()->mMargin;
bool verticalAxis = aForISize == wm.IsVertical();
if (verticalAxis) {
result.hMargin += ResolveMargin(margin.GetTop(), aPercentageBasis);
result.hMargin += ResolveMargin(margin.GetBottom(), aPercentageBasis);
result.hMargin += ResolveMargin(margin.Get(eSideTop), aPercentageBasis);
result.hMargin += ResolveMargin(margin.Get(eSideBottom), aPercentageBasis);
} else {
result.hMargin += ResolveMargin(margin.GetLeft(), aPercentageBasis);
result.hMargin += ResolveMargin(margin.GetRight(), aPercentageBasis);
result.hMargin += ResolveMargin(margin.Get(eSideLeft), aPercentageBasis);
result.hMargin += ResolveMargin(margin.Get(eSideRight), aPercentageBasis);
}
const auto& padding = aFrame->StylePadding()->mPadding;
if (verticalAxis) {
result.hPadding += ResolvePadding(padding.GetTop(), aPercentageBasis);
result.hPadding += ResolvePadding(padding.GetBottom(), aPercentageBasis);
result.hPadding += ResolvePadding(padding.Get(eSideTop), aPercentageBasis);
result.hPadding +=
ResolvePadding(padding.Get(eSideBottom), aPercentageBasis);
} else {
result.hPadding += ResolvePadding(padding.GetLeft(), aPercentageBasis);
result.hPadding += ResolvePadding(padding.GetRight(), aPercentageBasis);
result.hPadding += ResolvePadding(padding.Get(eSideLeft), aPercentageBasis);
result.hPadding +=
ResolvePadding(padding.Get(eSideRight), aPercentageBasis);
}
const nsStyleBorder* styleBorder = aFrame->StyleBorder();

View File

@@ -75,9 +75,9 @@ void nsInlineFrame::InvalidateFrameWithRect(const nsRect& aRect,
aRebuildDisplayItems);
}
static inline bool IsMarginZero(const nsStyleCoord& aCoord) {
return aCoord.GetUnit() == eStyleUnit_Auto ||
nsLayoutUtils::IsMarginZero(aCoord);
static inline bool IsMarginZero(const LengthPercentageOrAuto& aLength) {
return aLength.IsAuto() ||
nsLayoutUtils::IsMarginZero(aLength.AsLengthPercentage());
}
/* virtual */ bool nsInlineFrame::IsSelfEmpty() {
@@ -96,23 +96,21 @@ static inline bool IsMarginZero(const nsStyleCoord& aCoord) {
// ZeroEffectiveSpanBox, anymore, so what should this really be?
WritingMode wm = GetWritingMode();
bool haveStart, haveEnd;
auto HaveSide = [&](mozilla::Side aSide) -> bool {
return border->GetComputedBorderWidth(aSide) != 0 ||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.Get(aSide)) ||
!IsMarginZero(margin->mMargin.Get(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
// get logical start and end flags.
if (wm.IsVertical()) {
haveStart = border->GetComputedBorderWidth(eSideTop) != 0 ||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetTop()) ||
!IsMarginZero(margin->mMargin.GetTop());
haveEnd = border->GetComputedBorderWidth(eSideBottom) != 0 ||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetBottom()) ||
!IsMarginZero(margin->mMargin.GetBottom());
haveStart = HaveSide(eSideTop);
haveEnd = HaveSide(eSideBottom);
} else {
haveStart = border->GetComputedBorderWidth(eSideLeft) != 0 ||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
!IsMarginZero(margin->mMargin.GetLeft());
haveEnd = border->GetComputedBorderWidth(eSideRight) != 0 ||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetRight()) ||
!IsMarginZero(margin->mMargin.GetRight());
haveStart = HaveSide(eSideLeft);
haveEnd = HaveSide(eSideRight);
}
if (haveStart || haveEnd) {
// We skip this block and return false for box-decoration-break:clone since

View File

@@ -666,11 +666,9 @@ bool nsLineLayout::LineIsBreakable() const {
// only be used for things (margin, padding) where percentages on top
// and bottom depend on the *width* just like percentages on left and
// right.
static bool HasPercentageUnitSide(const nsStyleSides& aSides) {
NS_FOR_CSS_SIDES(side) {
if (aSides.Get(side).HasPercent()) return true;
}
return false;
template <typename T>
static bool HasPercentageUnitSide(const StyleRect<T>& aSides) {
return aSides.Any([](const auto& aLength) { return aLength.HasPercent(); });
}
static bool IsPercentageAware(const nsIFrame* aFrame, WritingMode aWM) {

View File

@@ -94,9 +94,9 @@ void nsPageFrame::Reflow(nsPresContext* aPresContext,
// Use the margins given in the @page rule.
// If a margin is 'auto', use the margin from the print settings for that
// side.
const nsStyleSides& marginStyle = kidReflowInput.mStyleMargin->mMargin;
const auto& marginStyle = kidReflowInput.mStyleMargin->mMargin;
NS_FOR_CSS_SIDES(side) {
if (marginStyle.GetUnit(side) == eStyleUnit_Auto) {
if (marginStyle.Get(side).IsAuto()) {
mPageContentMargin.Side(side) = mPD->mReflowMargin.Side(side);
} else {
mPageContentMargin.Side(side) =

View File

@@ -1866,11 +1866,12 @@ 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 nsStyleCoord& margin = ctx->StyleMargin()->mMargin.Get(aSide);
if (!margin.ConvertsToLength() || margin.ToLength() != 0) {
const auto& margin = ctx->StyleMargin()->mMargin.Get(aSide);
if (!margin.ConvertsToLength() ||
margin.AsLengthPercentage().ToLength() != 0) {
return true;
}
const nsStyleCoord& padding = ctx->StylePadding()->mPadding.Get(aSide);
const auto& padding = ctx->StylePadding()->mPadding.Get(aSide);
if (!padding.ConvertsToLength() || padding.ToLength() != 0) {
return true;
}

View File

@@ -933,11 +933,12 @@ bool Servo_ComputeColor(RawServoStyleSetBorrowedOrNull set,
nscolor* result_color, bool* was_current_color,
mozilla::css::Loader* loader);
bool Servo_IntersectionObserverRootMargin_Parse(const nsAString* value,
nsStyleSides* result);
bool Servo_IntersectionObserverRootMargin_Parse(
const nsAString* value,
mozilla::StyleIntersectionObserverRootMargin* result);
void Servo_IntersectionObserverRootMargin_ToString(const nsStyleSides* rect,
nsAString* result);
void Servo_IntersectionObserverRootMargin_ToString(
const mozilla::StyleIntersectionObserverRootMargin*, nsAString* result);
// Returning false means the parsed transform contains relative lengths or
// percentage value, so we cannot compute the matrix. In this case, we keep

View File

@@ -415,6 +415,10 @@ cbindgen-types = [
{ gecko = "StyleOverflow", servo = "values::computed::Overflow" },
{ gecko = "StyleOverflowAnchor", servo = "values::computed::OverflowAnchor" },
{ gecko = "StyleLengthPercentage", servo = "values::computed::LengthPercentage" },
{ gecko = "StyleNonNegativeLengthPercentage", servo = "values::computed::NonNegativeLengthPercentage" },
{ gecko = "StyleLengthPercentageOrAuto", servo = "values::computed::LengthPercentageOrAuto" },
{ gecko = "StyleRect", servo = "values::generics::rect::Rect" },
{ gecko = "StyleIntersectionObserverRootMargin", servo = "values::specified::gecko::IntersectionObserverRootMargin" },
]
mapped-generic-types = [
@@ -474,6 +478,7 @@ structs-types = [
"mozilla::StyleMotion",
"mozilla::UniquePtr",
"mozilla::StyleDisplayMode",
"mozilla::StyleIntersectionObserverRootMargin",
"mozilla::StyleComputedFontStretchRange",
"mozilla::StyleComputedFontStyleDescriptor",
"mozilla::StyleComputedFontWeightRange",

View File

@@ -2614,6 +2614,32 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetOffsetWidthFor(
return nullptr;
}
}
// FIXME(emilio): Remove these when nsStyleCoord is gone.
static nsStyleCoord ToCoord(const LengthPercentage& aLength) {
nsStyleCoord ret;
if (aLength.was_calc) {
auto* calc = new nsStyleCoord::Calc();
calc->mLength = CSSPixel::ToAppUnits(aLength.LengthInCSSPixels());
calc->mPercent = aLength.Percentage();
calc->mHasPercent = aLength.HasPercent();
ret.SetCalcValue(calc); // takes ownership.
return ret;
}
if (aLength.HasPercent()) {
ret.SetPercentValue(aLength.Percentage());
} else {
ret.SetCoordValue(aLength.ToLength());
}
return ret;
}
static nsStyleCoord ToCoord(const LengthPercentageOrAuto& aLength) {
if (aLength.IsAuto()) {
return nsStyleCoord(eStyleUnit_Auto);
}
return ToCoord(aLength.AsLengthPercentage());
}
static_assert(eSideTop == 0 && eSideRight == 1 && eSideBottom == 2 &&
eSideLeft == 3,
@@ -2627,14 +2653,9 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
const nsStylePosition* positionData = StylePosition();
int32_t sign = 1;
nsStyleCoord coord = positionData->mOffset.Get(aSide);
LengthPercentageOrAuto coord = positionData->mOffset.Get(aSide);
NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
coord.GetUnit() == eStyleUnit_Percent ||
coord.GetUnit() == eStyleUnit_Auto || coord.IsCalcUnit(),
"Unexpected unit");
if (coord.GetUnit() == eStyleUnit_Auto) {
if (coord.IsAuto()) {
if (!aResolveAuto) {
val->SetIdent(eCSSKeyword_auto);
return val.forget();
@@ -2647,18 +2668,18 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
? aWidthGetter
: aHeightGetter;
val->SetAppUnits(sign * StyleCoordToNSCoord(coord, baseGetter, 0, false));
val->SetAppUnits(sign *
StyleCoordToNSCoord(ToCoord(coord), baseGetter, 0, false));
return val.forget();
}
already_AddRefed<CSSValue> nsComputedDOMStyle::GetAbsoluteOffset(
mozilla::Side aSide) {
const auto& offset = StylePosition()->mOffset;
const nsStyleCoord& coord = offset.Get(aSide);
const nsStyleCoord& oppositeCoord = offset.Get(NS_OPPOSITE_SIDE(aSide));
const auto& coord = offset.Get(aSide);
const auto& oppositeCoord = offset.Get(NS_OPPOSITE_SIDE(aSide));
if (coord.GetUnit() == eStyleUnit_Auto ||
oppositeCoord.GetUnit() == eStyleUnit_Auto) {
if (coord.IsAuto() || oppositeCoord.IsAuto()) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(GetUsedAbsoluteOffset(aSide));
return val.forget();
@@ -2728,7 +2749,7 @@ nscoord nsComputedDOMStyle::GetUsedAbsoluteOffset(mozilla::Side aSide) {
already_AddRefed<CSSValue> nsComputedDOMStyle::GetStaticOffset(
mozilla::Side aSide) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, StylePosition()->mOffset.Get(aSide), false);
SetValueToCoord(val, ToCoord(StylePosition()->mOffset.Get(aSide)), false);
return val.forget();
}
@@ -2737,7 +2758,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetPaddingWidthFor(
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
if (!mInnerFrame) {
SetValueToCoord(val, StylePadding()->mPadding.Get(aSide), true);
SetValueToCoord(val, ToCoord(StylePadding()->mPadding.Get(aSide)), true);
} else {
AssertFlushedPendingReflows();
@@ -2812,7 +2833,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetMarginWidthFor(
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
if (!mInnerFrame) {
SetValueToCoord(val, StyleMargin()->mMargin.Get(aSide), false);
SetValueToCoord(val, ToCoord(StyleMargin()->mMargin.Get(aSide)), false);
} else {
AssertFlushedPendingReflows();

View File

@@ -15,7 +15,6 @@
#include "mozilla/gfx/Types.h"
#include "Units.h"
#include "nsCoord.h"
#include "LayoutConstants.h"
#include "nsISupportsImpl.h"
#include "nsStyleConsts.h"
@@ -26,7 +25,7 @@ class WritingMode;
// Logical axis, edge, side and corner constants for use in various places.
enum LogicalAxis { eLogicalAxisBlock = 0x0, eLogicalAxisInline = 0x1 };
enum LogicalEdge { eLogicalEdgeStart = 0x0, eLogicalEdgeEnd = 0x1 };
enum LogicalSide {
enum LogicalSide : uint8_t {
eLogicalSideBStart = (eLogicalAxisBlock << 1) | eLogicalEdgeStart, // 0x0
eLogicalSideBEnd = (eLogicalAxisBlock << 1) | eLogicalEdgeEnd, // 0x1
eLogicalSideIStart = (eLogicalAxisInline << 1) | eLogicalEdgeStart, // 0x2
@@ -41,8 +40,10 @@ enum LogicalCorner {
};
using LengthPercentage = StyleLengthPercentage;
using LengthPercentageOrAuto = StyleLengthPercentageOrAuto;
using NonNegativeLengthPercentage = StyleNonNegativeLengthPercentage;
LengthPercentage LengthPercentage::Zero() {
constexpr LengthPercentage LengthPercentage::Zero() {
return {{0.}, {0.}, StyleAllowedNumericType::All, false, false};
}
@@ -84,8 +85,6 @@ CSSCoord LengthPercentage::ResolveToCSSPixelsWith(T aPercentageGetter) const {
nscoord LengthPercentage::Resolve(nscoord aPercentageBasis) const {
NS_WARNING_ASSERTION(aPercentageBasis >= 0, "nscoord overflow?");
NS_WARNING_ASSERTION(aPercentageBasis != NS_UNCONSTRAINEDSIZE,
"Should handle that somewhere else");
return CSSPixel::ToAppUnits(LengthInCSSPixels()) +
NSToCoordFloorClamped(aPercentageBasis * Percentage());
}
@@ -100,6 +99,38 @@ nscoord LengthPercentage::ResolveWith(T aPercentageGetter) const {
return Resolve(aPercentageGetter());
}
const LengthPercentage& LengthPercentageOrAuto::AsLengthPercentage() const {
MOZ_ASSERT(IsLengthPercentage());
return length_percentage._0;
}
bool LengthPercentageOrAuto::ConvertsToLength() const {
return IsLengthPercentage() && AsLengthPercentage().ConvertsToLength();
}
bool LengthPercentageOrAuto::HasPercent() const {
return IsLengthPercentage() && AsLengthPercentage().HasPercent();
}
template <typename T>
const T& StyleRect<T>::Get(mozilla::Side aSide) const {
static_assert(sizeof(StyleRect<T>) == sizeof(T) * 4, "");
static_assert(alignof(StyleRect<T>) == alignof(T), "");
return reinterpret_cast<const T*>(this)[aSide];
}
template <typename T>
template <typename Predicate>
bool StyleRect<T>::All(Predicate aPredicate) const {
return aPredicate(_0) && aPredicate(_1) && aPredicate(_2) && aPredicate(_3);
}
template <typename T>
template <typename Predicate>
bool StyleRect<T>::Any(Predicate aPredicate) const {
return aPredicate(_0) || aPredicate(_1) || aPredicate(_2) || aPredicate(_3);
}
} // namespace mozilla
enum nsStyleUnit : uint8_t {

View File

@@ -182,10 +182,15 @@ nscoord nsStyleFont::ZoomText(const Document& aDocument, nscoord aSize) {
return NSToCoordTruncClamped(float(aSize) * textZoom);
}
nsStyleMargin::nsStyleMargin(const Document& aDocument) {
template <typename T>
static StyleRect<T> StyleRectWithAllSides(const T& aSide) {
return {aSide, aSide, aSide, aSide};
}
nsStyleMargin::nsStyleMargin(const Document& aDocument)
: mMargin(StyleRectWithAllSides(
LengthPercentageOrAuto::LengthPercentage(LengthPercentage::Zero()))) {
MOZ_COUNT_CTOR(nsStyleMargin);
nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
NS_FOR_CSS_SIDES(side) { mMargin.Set(side, zero); }
}
nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc)
@@ -204,10 +209,9 @@ nsChangeHint nsStyleMargin::CalcDifference(
nsChangeHint_ClearAncestorIntrinsics;
}
nsStylePadding::nsStylePadding(const Document& aDocument) {
nsStylePadding::nsStylePadding(const Document& aDocument)
: mPadding(StyleRectWithAllSides(LengthPercentage::Zero())) {
MOZ_COUNT_CTOR(nsStylePadding);
nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
NS_FOR_CSS_SIDES(side) { mPadding.Set(side, zero); }
}
nsStylePadding::nsStylePadding(const nsStylePadding& aSrc)
@@ -1291,7 +1295,8 @@ bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const {
// nsStylePosition
//
nsStylePosition::nsStylePosition(const Document& aDocument)
: mWidth(eStyleUnit_Auto),
: mOffset(StyleRectWithAllSides(LengthPercentageOrAuto::Auto())),
mWidth(eStyleUnit_Auto),
mMinWidth(eStyleUnit_Auto),
mMaxWidth(eStyleUnit_None),
mHeight(eStyleUnit_Auto),
@@ -1326,9 +1331,6 @@ nsStylePosition::nsStylePosition(const Document& aDocument)
mObjectPosition.SetInitialPercentValues(0.5f);
nsStyleCoord autoCoord(eStyleUnit_Auto);
NS_FOR_CSS_SIDES(side) { mOffset.Set(side, autoCoord); }
// The initial value of grid-auto-columns and grid-auto-rows is 'auto',
// which computes to 'minmax(auto, auto)'.
@@ -1390,11 +1392,10 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
}
}
static bool IsAutonessEqual(const nsStyleSides& aSides1,
const nsStyleSides& aSides2) {
static bool IsAutonessEqual(const StyleRect<LengthPercentageOrAuto>& aSides1,
const StyleRect<LengthPercentageOrAuto>& aSides2) {
NS_FOR_CSS_SIDES(side) {
if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
(aSides2.GetUnit(side) == eStyleUnit_Auto)) {
if (aSides1.Get(side).IsAuto() != aSides2.Get(side).IsAuto()) {
return false;
}
}

View File

@@ -772,11 +772,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin {
nsChangeHint CalcDifference(const nsStyleMargin& aNewData) const;
bool GetMargin(nsMargin& aMargin) const {
if (!mMargin.ConvertsToLength()) {
bool convertsToLength = mMargin.All(
[](const auto& aLength) { return aLength.ConvertsToLength(); });
if (!convertsToLength) {
return false;
}
NS_FOR_CSS_SIDES(side) { aMargin.Side(side) = mMargin.ToLength(side); }
NS_FOR_CSS_SIDES(side) {
aMargin.Side(side) = mMargin.Get(side).AsLengthPercentage().ToLength();
}
return true;
}
@@ -785,7 +790,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin {
inline bool HasBlockAxisAuto(mozilla::WritingMode aWM) const;
inline bool HasInlineAxisAuto(mozilla::WritingMode aWM) const;
nsStyleSides mMargin; // coord, percent, calc, auto
mozilla::StyleRect<mozilla::LengthPercentageOrAuto> mMargin;
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding {
@@ -797,18 +802,21 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding {
nsChangeHint CalcDifference(const nsStylePadding& aNewData) const;
nsStyleSides mPadding; // coord, percent, calc
mozilla::StyleRect<mozilla::NonNegativeLengthPercentage> mPadding;
bool IsWidthDependent() const { return !mPadding.ConvertsToLength(); }
inline bool IsWidthDependent() const {
return !mPadding.All(
[](const auto& aLength) { return aLength.ConvertsToLength(); });
}
bool GetPadding(nsMargin& aPadding) const {
if (!mPadding.ConvertsToLength()) {
if (IsWidthDependent()) {
return false;
}
NS_FOR_CSS_SIDES(side) {
// Clamp negative calc() to 0.
aPadding.Side(side) = std::max(mPadding.ToLength(side), 0);
aPadding.Side(side) = std::max(mPadding.Get(side).ToLength(), 0);
}
return true;
}
@@ -1314,7 +1322,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
uint8_t UsedJustifySelf(mozilla::ComputedStyle* aParent) const;
mozilla::Position mObjectPosition;
nsStyleSides mOffset; // coord, percent, calc, auto
mozilla::StyleRect<mozilla::LengthPercentageOrAuto> mOffset;
nsStyleCoord mWidth; // coord, percent, enum, calc, auto
nsStyleCoord mMinWidth; // coord, percent, enum, calc
nsStyleCoord mMaxWidth; // coord, percent, enum, calc, none

View File

@@ -9,11 +9,15 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi
*/
#include "nsCoord.h"
#include "Units.h"
#include "mozilla/gfx/Types.h"
class nsAtom;
namespace mozilla {
class WritingMode;
enum LogicalSide : uint8_t;
namespace css {
struct URLValue;
}
// Work-around weird cbindgen renaming.
typedef css::URLValue StyleURLValue;
typedef nsAtom StylensAtom;
@@ -71,13 +75,17 @@ include = [
"Resize",
"Overflow",
"LengthPercentage",
"NonNegativeLengthPercentage",
"LengthPercentageOrAuto",
"Rect",
"IntersectionObserverRootMargin",
]
item_types = ["enums", "structs", "typedefs"]
[export.body]
"LengthPercentage" = """
// Defined in nsStyleCoord.h
static inline StyleLengthPercentage Zero();
static constexpr inline StyleLengthPercentage Zero();
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
@@ -90,3 +98,23 @@ item_types = ["enums", "structs", "typedefs"]
inline nscoord Resolve(nscoord aPercentageBasis) const;
template<typename T> inline nscoord ResolveWith(T aPercentageGetter) const;
"""
"LengthPercentageOrAuto" = """
inline const StyleLengthPercentage& AsLengthPercentage() const;
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
"""
"Rect" = """
// Defined in nsStyleCoord.h
template<typename Predicate> inline bool All(Predicate) const;
template<typename Predicate> inline bool Any(Predicate) const;
// Defined in WritingModes.h
inline const T& Get(mozilla::Side) const;
inline const T& Get(mozilla::WritingMode, mozilla::LogicalSide) const;
inline const T& GetIStart(mozilla::WritingMode) const;
inline const T& GetBStart(mozilla::WritingMode) const;
inline const T& GetIEnd(mozilla::WritingMode) const;
inline const T& GetBEnd(mozilla::WritingMode) const;
"""

View File

@@ -772,11 +772,12 @@ def set_gecko_property(ffi_name, expr):
<%def name="impl_split_style_coord(ident, gecko_ffi_name, index)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
v.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${index}));
self.gecko.${gecko_ffi_name}.${index} = v;
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
self.gecko.${gecko_ffi_name}.data_at_mut(${index}).copy_from(&other.gecko.${gecko_ffi_name}.data_at(${index}));
self.gecko.${gecko_ffi_name}.${index} =
other.gecko.${gecko_ffi_name}.${index};
}
#[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) {
@@ -785,9 +786,7 @@ def set_gecko_property(ffi_name, expr):
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use crate::properties::longhands::${ident}::computed_value::T;
T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}.data_at(${index}))
.expect("clone for ${ident} failed")
self.gecko.${gecko_ffi_name}.${index}
}
</%def>

View File

@@ -457,6 +457,7 @@ impl IsZeroLength for LengthPercentage {
#[derive(
Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss,
)]
#[repr(C, u8)]
pub enum LengthPercentageOrAuto {
LengthPercentage(LengthPercentage),
Auto,

View File

@@ -23,6 +23,7 @@ use style_traits::{CssWriter, ParseError, ToCss};
ToAnimatedValue,
ToComputedValue,
)]
#[repr(C)]
pub struct Rect<T>(pub T, pub T, pub T, pub T);
impl<T> Rect<T> {

View File

@@ -4,21 +4,19 @@
//! Specified types for legacy Gecko-only properties.
use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut};
use crate::parser::{Parse, ParserContext};
use crate::values::computed;
use crate::values::computed::{self, LengthPercentage};
use crate::values::computed::length::CSSPixelLength;
use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use crate::values::generics::rect::Rect;
use crate::values::specified::length::LengthPercentage;
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
use cssparser::{Parser, Token};
use std::fmt;
use style_traits::values::SequenceWriter;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// A specified type for scroll snap points.
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthPercentage>;
pub type ScrollSnapPoint = GenericScrollSnapPoint<SpecifiedLengthPercentage>;
impl Parse for ScrollSnapPoint {
fn parse<'i, 't>(
@@ -29,26 +27,17 @@ impl Parse for ScrollSnapPoint {
return Ok(GenericScrollSnapPoint::None);
}
input.expect_function_matching("repeat")?;
// FIXME(emilio): This won't clamp properly when animating.
let length =
input.parse_nested_block(|i| LengthPercentage::parse_non_negative(context, i))?;
input.parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?;
Ok(GenericScrollSnapPoint::Repeat(length))
}
}
/// A component of an IntersectionObserverRootMargin.
#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
pub enum PixelOrPercentage {
/// An absolute length in pixels (px)
Pixel(CSSPixelLength),
/// A percentage (%)
Percentage(computed::Percentage),
}
impl Parse for PixelOrPercentage {
fn parse<'i, 't>(
fn parse_pixel_or_percent<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
) -> Result<LengthPercentage, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
let value = match *token {
@@ -56,36 +45,17 @@ impl Parse for PixelOrPercentage {
value, ref unit, ..
} => {
match_ignore_ascii_case! { unit,
"px" => Ok(PixelOrPercentage::Pixel(CSSPixelLength::new(value))),
"px" => Ok(LengthPercentage::new(CSSPixelLength::new(value), None)),
_ => Err(()),
}
},
Token::Percentage { unit_value, .. } => Ok(PixelOrPercentage::Percentage(
computed::Percentage(unit_value),
)),
Token::Percentage { unit_value, .. } => Ok(
LengthPercentage::new_percent(computed::Percentage(unit_value))
),
_ => Err(()),
};
value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
impl GeckoStyleCoordConvertible for PixelOrPercentage {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
PixelOrPercentage::Pixel(ref l) => l.to_gecko_style_coord(coord),
PixelOrPercentage::Percentage(ref pc) => pc.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
CSSPixelLength::from_gecko_style_coord(coord)
.map(PixelOrPercentage::Pixel)
.or_else(|| {
computed::Percentage::from_gecko_style_coord(coord)
.map(PixelOrPercentage::Percentage)
})
}
}
/// The value of an IntersectionObserver's rootMargin property.
///
@@ -93,14 +63,15 @@ impl GeckoStyleCoordConvertible for PixelOrPercentage {
/// calc() values are not allowed.
///
/// <https://w3c.github.io/IntersectionObserver/#parse-a-root-margin>
pub struct IntersectionObserverRootMargin(pub Rect<PixelOrPercentage>);
#[repr(transparent)]
pub struct IntersectionObserverRootMargin(pub Rect<LengthPercentage>);
impl Parse for IntersectionObserverRootMargin {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, PixelOrPercentage::parse)?;
let rect = Rect::parse_with(context, input, parse_pixel_or_percent)?;
Ok(IntersectionObserverRootMargin(rect))
}
}

View File

@@ -201,9 +201,8 @@ use style::use_counters::UseCounters;
use style::values::animated::{Animate, Procedure, ToAnimatedZero};
use style::values::computed::{self, Context, QuotePair, ToComputedValue};
use style::values::distance::ComputeSquaredDistance;
use style::values::generics::rect::Rect;
use style::values::specified;
use style::values::specified::gecko::{IntersectionObserverRootMargin, PixelOrPercentage};
use style::values::specified::gecko::IntersectionObserverRootMargin;
use style::values::specified::source_size_list::SourceSizeList;
use style::values::{CustomIdent, KeyframesName};
use style_traits::{CssType, CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
@@ -6002,7 +6001,7 @@ pub extern "C" fn Servo_ComputeColor(
#[no_mangle]
pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_Parse(
value: *const nsAString,
result: *mut structs::nsStyleSides,
result: *mut IntersectionObserverRootMargin,
) -> bool {
let value = value.as_ref().unwrap().to_string();
let result = result.as_mut().unwrap();
@@ -6024,7 +6023,7 @@ pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_Parse(
let margin = parser.parse_entirely(|p| IntersectionObserverRootMargin::parse(&context, p));
match margin {
Ok(margin) => {
margin.0.to_gecko_rect(result);
*result = margin;
true
},
Err(..) => false,
@@ -6033,13 +6032,11 @@ pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_Parse(
#[no_mangle]
pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_ToString(
rect: *const structs::nsStyleSides,
root_margin: *const IntersectionObserverRootMargin,
result: *mut nsAString,
) {
let rect = Rect::<PixelOrPercentage>::from_gecko_rect(rect.as_ref().unwrap()).unwrap();
let root_margin = IntersectionObserverRootMargin(rect);
let mut writer = CssWriter::new(result.as_mut().unwrap());
root_margin.to_css(&mut writer).unwrap();
let mut writer = CssWriter::new(&mut *result);
(*root_margin).to_css(&mut writer).unwrap();
}
#[no_mangle]