From bffd4f08c61ce292f6243384401ccf449071da88 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Mon, 20 Jul 2020 22:28:45 +0000 Subject: [PATCH] Bug 1647520 Part 4 - Stop binary search once the feasible and infeasible block-size is within one device pixel. r=heycam The gist of this patch is: once the feasible and infeasible block-size is within one device pixel, we choose nextGuess to be the greatest multiple of one device pixel below or equal to the feasible block-size. If this nextGuess is infeasible, we will reflow children one last time by using the last feasible block-size and done with the balancing. Differential Revision: https://phabricator.services.mozilla.com/D83732 --- layout/generic/nsColumnSetFrame.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index 8885a520e3f2..7c675e60ee61 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -996,6 +996,7 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput, // that can break anywhere (thus foiling the linear decrease-by-one // search) bool maybeContinuousBreakingDetected = false; + bool possibleOptimalBSizeDetected = false; // This is the extra block-size added to the optimal column block-size // estimation which is calculated in the while-loop by dividing @@ -1008,6 +1009,10 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput, // last column's available block-size is unbounded. bool foundFeasibleBSizeCloserToBest = !aUnboundedLastColumn; + // Stop the binary search when the difference of the feasible and infeasible + // block-size is within this gap. Here we use one device pixel. + const int32_t gapToStop = aPresContext->DevPixelsToAppUnits(1); + while (!aPresContext->HasPendingInterrupt()) { nscoord lastKnownFeasibleBSize = aConfig.mKnownFeasibleBSize; @@ -1067,6 +1072,14 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput, break; } + const nscoord gap = + aConfig.mKnownFeasibleBSize - aConfig.mKnownInfeasibleBSize; + if (gap <= gapToStop && possibleOptimalBSizeDetected) { + // We detected a possible optimal block-size in the last iteration. If it + // is infeasible, we may need to reflow one more time after this loop. + break; + } + if (lastKnownFeasibleBSize - aConfig.mKnownFeasibleBSize == 1) { // We decreased the feasible block-size by one twip only. This could // indicate that there is a continuously breakable child frame @@ -1074,8 +1087,7 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput, maybeContinuousBreakingDetected = true; } - nscoord nextGuess = - (aConfig.mKnownFeasibleBSize + aConfig.mKnownInfeasibleBSize) / 2; + nscoord nextGuess = aConfig.mKnownInfeasibleBSize + gap / 2; if (aConfig.mKnownFeasibleBSize - nextGuess < extraBlockSize && !maybeContinuousBreakingDetected) { // We're close to our target, so just try shrinking just the @@ -1097,7 +1109,13 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput, // want to do an unbounded block-size measuring step. Let's just increase // from the infeasible block-size by some reasonable amount. nextGuess = aConfig.mKnownInfeasibleBSize * 2 + extraBlockSize; + } else if (gap <= gapToStop) { + // Floor nextGuess to the greatest multiple of gapToStop below or equal to + // mKnownFeasibleBSize. + nextGuess = aConfig.mKnownFeasibleBSize / gapToStop * gapToStop; + possibleOptimalBSizeDetected = true; } + // Don't bother guessing more than our block-size constraint. nextGuess = std::min(availableContentBSize, nextGuess);