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
This commit is contained in:
Ting-Yu Lin 2021-08-25 06:43:33 +00:00
Родитель 00be3c92c2
Коммит 1902424bff
1 изменённых файлов: 25 добавлений и 25 удалений

Просмотреть файл

@ -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--;
}