From 1902424bff4285a2fc295ba9ac1a71b1b895005e Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Wed, 25 Aug 2021 06:43:33 +0000 Subject: [PATCH] Bug 1469649 Part 1 - Promote floating point precision when computing the weight of flex items. r=dholbert The precision of `double` is needed when we are distributing large `sizeDelta` via `availableFreeSpace * myShareOfRemainingSpace`. Without this patch, the wpt test added in Part 2 will fail. Differential Revision: https://phabricator.services.mozilla.com/D123267 --- layout/generic/nsFlexContainerFrame.cpp | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 796d1a421479..e6b470909351 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -464,7 +464,7 @@ class nsFlexContainerFrame::FlexItem final { nscoord BaselineOffsetFromOuterCrossEdge(mozilla::Side aStartSide, bool aUseFirstLineBaseline) const; - float ShareOfWeightSoFar() const { return mShareOfWeightSoFar; } + double ShareOfWeightSoFar() const { return mShareOfWeightSoFar; } bool IsFrozen() const { return mIsFrozen; } @@ -676,8 +676,8 @@ class nsFlexContainerFrame::FlexItem final { mMainSize = aNewMainSize; } - void SetShareOfWeightSoFar(float aNewShare) { - MOZ_ASSERT(!mIsFrozen || aNewShare == 0.0f, + void SetShareOfWeightSoFar(double aNewShare) { + MOZ_ASSERT(!mIsFrozen || aNewShare == 0.0, "shouldn't be giving this item any share of the weight " "after it's frozen"); mShareOfWeightSoFar = aNewShare; @@ -876,7 +876,7 @@ class nsFlexContainerFrame::FlexItem final { // overlay the same memory as some other member vars that aren't touched // until after main-size has been resolved. In particular, these could share // memory with mMainPosn through mAscent, and mIsStretched. - float mShareOfWeightSoFar = 0.0f; + double mShareOfWeightSoFar = 0.0; bool mIsFrozen = false; bool mHadMinViolation = false; @@ -3100,14 +3100,14 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, // its "share" multiplied by the remaining available space. // // SPECIAL CASE: If the sum of the weights is larger than the - // maximum representable float (overflowing to infinity), then we can't + // maximum representable double (overflowing to infinity), then we can't // sensibly divide out proportional shares anymore. In that case, we // simply treat the flex item(s) with the largest weights as if // their weights were infinite (dwarfing all the others), and we // distribute all of the available space among them. - float weightSum = 0.0f; - float flexFactorSum = 0.0f; - float largestWeight = 0.0f; + double weightSum = 0.0; + double flexFactorSum = 0.0; + double largestWeight = 0.0; uint32_t numItemsWithLargestWeight = 0; // Since this loop only operates on unfrozen flex items, we can break as @@ -3121,17 +3121,17 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, if (!item.IsFrozen()) { numUnfrozenItemsToBeSeen--; - float curWeight = item.GetWeight(isUsingFlexGrow); - float curFlexFactor = item.GetFlexFactor(isUsingFlexGrow); - MOZ_ASSERT(curWeight >= 0.0f, "weights are non-negative"); - MOZ_ASSERT(curFlexFactor >= 0.0f, "flex factors are non-negative"); + const double curWeight = item.GetWeight(isUsingFlexGrow); + const double curFlexFactor = item.GetFlexFactor(isUsingFlexGrow); + MOZ_ASSERT(curWeight >= 0.0, "weights are non-negative"); + MOZ_ASSERT(curFlexFactor >= 0.0, "flex factors are non-negative"); weightSum += curWeight; flexFactorSum += curFlexFactor; if (IsFinite(weightSum)) { - if (curWeight == 0.0f) { - item.SetShareOfWeightSoFar(0.0f); + if (curWeight == 0.0) { + item.SetShareOfWeightSoFar(0.0); } else { item.SetShareOfWeightSoFar(curWeight / weightSum); } @@ -3152,11 +3152,11 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, MOZ_ASSERT(numUnfrozenItemsToBeSeen == 0, "miscounted frozen items?"); - if (weightSum != 0.0f) { - MOZ_ASSERT(flexFactorSum != 0.0f, + if (weightSum != 0.0) { + MOZ_ASSERT(flexFactorSum != 0.0, "flex factor sum can't be 0, if a weighted sum " "of its components (weightSum) is nonzero"); - if (flexFactorSum < 1.0f) { + if (flexFactorSum < 1.0) { // Our unfrozen flex items don't want all of the original free space! // (Their flex factors add up to something less than 1.) // Hence, make sure we don't distribute any more than the portion of @@ -3204,17 +3204,17 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, // item, and then subtract it from the remaining available space. nscoord sizeDelta = 0; if (IsFinite(weightSum)) { - float myShareOfRemainingSpace = item.ShareOfWeightSoFar(); + double myShareOfRemainingSpace = item.ShareOfWeightSoFar(); - MOZ_ASSERT(myShareOfRemainingSpace >= 0.0f && - myShareOfRemainingSpace <= 1.0f, + MOZ_ASSERT(myShareOfRemainingSpace >= 0.0 && + myShareOfRemainingSpace <= 1.0, "my share should be nonnegative fractional amount"); - if (myShareOfRemainingSpace == 1.0f) { - // (We special-case 1.0f to avoid float error from converting - // availableFreeSpace from integer*1.0f --> float --> integer) + if (myShareOfRemainingSpace == 1.0) { + // (We special-case 1.0 to avoid float error from converting + // availableFreeSpace from integer*1.0 --> double --> integer) sizeDelta = availableFreeSpace; - } else if (myShareOfRemainingSpace > 0.0f) { + } else if (myShareOfRemainingSpace > 0.0) { sizeDelta = NSToCoordRound(availableFreeSpace * myShareOfRemainingSpace); } @@ -3223,7 +3223,7 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, // the available space equally among the items that are tied for // having the largest weight (and this is one of those items). sizeDelta = NSToCoordRound(availableFreeSpace / - float(numItemsWithLargestWeight)); + double(numItemsWithLargestWeight)); numItemsWithLargestWeight--; }