зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1675376 - Cache consumed BSize in a frame property for non-first continuations. r=mats
This removes virtually all the time under ConsumedBSize. See the comment for what ensures the correctness of the cache: Basically, we refresh the cache for a frame continuation every time we reflow it, which means that when next continuations go look for it it should be up-to-date (we rely on that already because we're looking at the content rect). Differential Revision: https://phabricator.services.mozilla.com/D97357
This commit is contained in:
Родитель
2892508f9b
Коммит
cdff7e9fe1
|
@ -1251,7 +1251,7 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
|
|||
|
||||
const ReflowInput* reflowInput = &aReflowInput;
|
||||
WritingMode wm = aReflowInput.GetWritingMode();
|
||||
nscoord consumedBSize = ConsumedBSize(wm);
|
||||
nscoord consumedBSize = CalcAndCacheConsumedBSize(wm);
|
||||
nscoord effectiveComputedBSize =
|
||||
GetEffectiveComputedBSize(aReflowInput, consumedBSize);
|
||||
Maybe<ReflowInput> mutableReflowInput;
|
||||
|
|
|
@ -4100,7 +4100,8 @@ void nsFlexContainerFrame::GenerateFlexLines(const SharedFlexData& aData,
|
|||
// reflow input (specifically, the main-size of *this continuation* of the
|
||||
// flex container).
|
||||
nscoord nsFlexContainerFrame::GetMainSizeFromReflowInput(
|
||||
const ReflowInput& aReflowInput, const FlexboxAxisTracker& aAxisTracker) {
|
||||
const ReflowInput& aReflowInput, const FlexboxAxisTracker& aAxisTracker,
|
||||
nscoord aConsumedBSize) {
|
||||
if (aAxisTracker.IsRowOriented()) {
|
||||
// Row-oriented --> our main axis is the inline axis, so our main size
|
||||
// is our inline size (which should already be resolved).
|
||||
|
@ -4112,7 +4113,7 @@ nscoord nsFlexContainerFrame::GetMainSizeFromReflowInput(
|
|||
}
|
||||
|
||||
// Note: This may be unconstrained, if our block size is "auto":
|
||||
return GetEffectiveComputedBSize(aReflowInput);
|
||||
return GetEffectiveComputedBSize(aReflowInput, aConsumedBSize);
|
||||
}
|
||||
|
||||
// Returns the largest outer hypothetical main-size of any line in |aLines|.
|
||||
|
@ -4159,7 +4160,8 @@ nscoord nsFlexContainerFrame::ComputeMainSize(
|
|||
|
||||
nscoord nsFlexContainerFrame::ComputeCrossSize(
|
||||
const ReflowInput& aReflowInput, const FlexboxAxisTracker& aAxisTracker,
|
||||
nscoord aSumLineCrossSizes, bool* aIsDefinite) const {
|
||||
nscoord aSumLineCrossSizes, nscoord aConsumedBSize,
|
||||
bool* aIsDefinite) const {
|
||||
MOZ_ASSERT(aIsDefinite, "outparam pointer must be non-null");
|
||||
|
||||
if (aAxisTracker.IsColumnOriented()) {
|
||||
|
@ -4180,7 +4182,8 @@ nscoord nsFlexContainerFrame::ComputeCrossSize(
|
|||
return aReflowInput.ComputedISize();
|
||||
}
|
||||
|
||||
nscoord effectiveComputedBSize = GetEffectiveComputedBSize(aReflowInput);
|
||||
nscoord effectiveComputedBSize =
|
||||
GetEffectiveComputedBSize(aReflowInput, aConsumedBSize);
|
||||
if (effectiveComputedBSize != NS_UNCONSTRAINEDSIZE) {
|
||||
// Row-oriented case (cross axis is block-axis), with fixed BSize:
|
||||
*aIsDefinite = true;
|
||||
|
@ -4401,8 +4404,10 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||
const LogicalSize availableSizeForItems =
|
||||
ComputeAvailableSizeForItems(aReflowInput, borderPadding);
|
||||
|
||||
const nscoord consumedBSize =
|
||||
CalcAndCacheConsumedBSize(aReflowInput.GetWritingMode());
|
||||
nscoord contentBoxMainSize =
|
||||
GetMainSizeFromReflowInput(aReflowInput, axisTracker);
|
||||
GetMainSizeFromReflowInput(aReflowInput, axisTracker, consumedBSize);
|
||||
nscoord contentBoxCrossSize;
|
||||
nscoord flexContainerAscent;
|
||||
|
||||
|
@ -4413,7 +4418,8 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||
mainGapSize = nsLayoutUtils::ResolveGapToLength(stylePos->mColumnGap,
|
||||
contentBoxMainSize);
|
||||
crossGapSize = nsLayoutUtils::ResolveGapToLength(
|
||||
stylePos->mRowGap, GetEffectiveComputedBSize(aReflowInput));
|
||||
stylePos->mRowGap,
|
||||
GetEffectiveComputedBSize(aReflowInput, consumedBSize));
|
||||
} else {
|
||||
mainGapSize = nsLayoutUtils::ResolveGapToLength(stylePos->mRowGap,
|
||||
contentBoxMainSize);
|
||||
|
@ -4440,7 +4446,7 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||
// layout result closer to the one as if there's no fragmentation.
|
||||
DoFlexLayout(aReflowInput, contentBoxMainSize, contentBoxCrossSize,
|
||||
flexContainerAscent, lines, struts, placeholders, axisTracker,
|
||||
mainGapSize, crossGapSize, hasLineClampEllipsis,
|
||||
mainGapSize, crossGapSize, consumedBSize, hasLineClampEllipsis,
|
||||
containerInfo);
|
||||
|
||||
if (!struts.IsEmpty()) {
|
||||
|
@ -4449,8 +4455,8 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||
placeholders.Clear();
|
||||
DoFlexLayout(aReflowInput, contentBoxMainSize, contentBoxCrossSize,
|
||||
flexContainerAscent, lines, struts, placeholders,
|
||||
axisTracker, mainGapSize, crossGapSize, hasLineClampEllipsis,
|
||||
containerInfo);
|
||||
axisTracker, mainGapSize, crossGapSize, consumedBSize,
|
||||
hasLineClampEllipsis, containerInfo);
|
||||
}
|
||||
} else {
|
||||
auto* data = FirstInFlow()->GetProperty(SharedFlexData::Prop());
|
||||
|
@ -4464,7 +4470,6 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||
const LogicalSize contentBoxSize =
|
||||
axisTracker.LogicalSizeFromFlexRelativeSizes(contentBoxMainSize,
|
||||
contentBoxCrossSize);
|
||||
const nscoord consumedBSize = ConsumedBSize(wm);
|
||||
const nscoord effectiveContentBSize =
|
||||
contentBoxSize.BSize(wm) - consumedBSize;
|
||||
|
||||
|
@ -4875,7 +4880,8 @@ void nsFlexContainerFrame::DoFlexLayout(
|
|||
nscoord& aContentBoxCrossSize, nscoord& aFlexContainerAscent,
|
||||
nsTArray<FlexLine>& aLines, nsTArray<StrutInfo>& aStruts,
|
||||
nsTArray<nsIFrame*>& aPlaceholders, const FlexboxAxisTracker& aAxisTracker,
|
||||
nscoord aMainGapSize, nscoord aCrossGapSize, bool aHasLineClampEllipsis,
|
||||
nscoord aMainGapSize, nscoord aCrossGapSize, nscoord aConsumedBSize,
|
||||
bool aHasLineClampEllipsis,
|
||||
ComputedFlexContainerInfo* const aContainerInfo) {
|
||||
MOZ_ASSERT(aLines.IsEmpty(), "Caller should pass an empty array for lines!");
|
||||
MOZ_ASSERT(aPlaceholders.IsEmpty(),
|
||||
|
@ -4978,8 +4984,9 @@ void nsFlexContainerFrame::DoFlexLayout(
|
|||
}
|
||||
|
||||
bool isCrossSizeDefinite;
|
||||
aContentBoxCrossSize = ComputeCrossSize(
|
||||
aReflowInput, aAxisTracker, sumLineCrossSizes, &isCrossSizeDefinite);
|
||||
aContentBoxCrossSize =
|
||||
ComputeCrossSize(aReflowInput, aAxisTracker, sumLineCrossSizes,
|
||||
aConsumedBSize, &isCrossSizeDefinite);
|
||||
|
||||
// Set up state for cross-axis alignment, at a high level (outside the
|
||||
// scope of a particular flex line)
|
||||
|
|
|
@ -321,7 +321,7 @@ class nsFlexContainerFrame final : public nsContainerFrame {
|
|||
nsTArray<nsIFrame*>& aPlaceholders,
|
||||
const FlexboxAxisTracker& aAxisTracker,
|
||||
nscoord aMainGapSize, nscoord aCrossGapSize,
|
||||
bool aHasLineClampEllipsis,
|
||||
nscoord aConsumedBSize, bool aHasLineClampEllipsis,
|
||||
ComputedFlexContainerInfo* const aContainerInfo);
|
||||
|
||||
/**
|
||||
|
@ -447,7 +447,8 @@ class nsFlexContainerFrame final : public nsContainerFrame {
|
|||
nsTArray<FlexLine>& aLines);
|
||||
|
||||
nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput,
|
||||
const FlexboxAxisTracker& aAxisTracker);
|
||||
const FlexboxAxisTracker& aAxisTracker,
|
||||
nscoord aConsumedBSize);
|
||||
|
||||
/**
|
||||
* Resolves the content-box main-size of a flex container frame,
|
||||
|
@ -477,7 +478,8 @@ class nsFlexContainerFrame final : public nsContainerFrame {
|
|||
|
||||
nscoord ComputeCrossSize(const ReflowInput& aReflowInput,
|
||||
const FlexboxAxisTracker& aAxisTracker,
|
||||
nscoord aSumLineCrossSizes, bool* aIsDefinite) const;
|
||||
nscoord aSumLineCrossSizes, nscoord aConsumedBSize,
|
||||
bool* aIsDefinite) const;
|
||||
|
||||
/**
|
||||
* Compute the size of the available space that we'll give to our children to
|
||||
|
|
|
@ -8532,7 +8532,7 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
consumedBSize = ConsumedBSize(wm);
|
||||
consumedBSize = CalcAndCacheConsumedBSize(wm);
|
||||
gridReflowInput.InitializeForContinuation(this, consumedBSize);
|
||||
// XXX Technically incorrect: We're ignoring our row sizes, when really
|
||||
// we should use them but *they* should be computed as if we had no
|
||||
|
|
|
@ -184,13 +184,27 @@ void nsSplittableFrame::RemoveFromFlow(nsIFrame* aFrame) {
|
|||
aFrame->SetNextInFlow(nullptr);
|
||||
}
|
||||
|
||||
nscoord nsSplittableFrame::ConsumedBSize(WritingMode aWM) const {
|
||||
nscoord bSize = 0;
|
||||
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ConsumedBSizeProperty, nscoord);
|
||||
|
||||
for (nsIFrame* prev = GetPrevContinuation(); prev;
|
||||
prev = prev->GetPrevContinuation()) {
|
||||
bSize += prev->ContentSize(aWM).BSize(aWM);
|
||||
nscoord nsSplittableFrame::CalcAndCacheConsumedBSize(WritingMode aWM) {
|
||||
nsIFrame* prev = GetPrevContinuation();
|
||||
if (!prev) {
|
||||
return 0;
|
||||
}
|
||||
nscoord bSize = 0;
|
||||
for (; prev; prev = prev->GetPrevContinuation()) {
|
||||
bSize += prev->ContentSize(aWM).BSize(aWM);
|
||||
bool found = false;
|
||||
nscoord consumed = prev->GetProperty(ConsumedBSizeProperty(), &found);
|
||||
if (found) {
|
||||
bSize += consumed;
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(!prev->GetPrevContinuation(),
|
||||
"Property should always be set on prev continuation if not "
|
||||
"the first continuation");
|
||||
}
|
||||
SetProperty(ConsumedBSizeProperty(), bSize);
|
||||
return bSize;
|
||||
}
|
||||
|
||||
|
@ -201,10 +215,6 @@ nscoord nsSplittableFrame::GetEffectiveComputedBSize(
|
|||
return NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
|
||||
if (aConsumedBSize == NS_UNCONSTRAINEDSIZE) {
|
||||
aConsumedBSize = ConsumedBSize(aReflowInput.GetWritingMode());
|
||||
}
|
||||
|
||||
bSize -= aConsumedBSize;
|
||||
|
||||
// nsFieldSetFrame's inner frames are special since some of their content-box
|
||||
|
|
|
@ -87,13 +87,16 @@ class nsSplittableFrame : public nsIFrame {
|
|||
* Return the sum of the block-axis content size of our previous
|
||||
* continuations.
|
||||
*
|
||||
* @param aWM a writing-mode to determine the block-axis
|
||||
* Classes that call this are _required_ to call this at least once for each
|
||||
* reflow (unless you're the first continuation, in which case you can skip
|
||||
* it, because as an optimization we don't cache it there).
|
||||
*
|
||||
* @note (bz) This makes laying out a splittable frame with N continuations
|
||||
* O(N^2)! So, use this function with caution and minimize the number
|
||||
* of calls to this method.
|
||||
* This guarantees that the internal cache works, by refreshing it. Calling it
|
||||
* multiple times in the same reflow is wasteful, but not an error.
|
||||
*
|
||||
* @param aWM a writing-mode to determine the block-axis
|
||||
*/
|
||||
nscoord ConsumedBSize(mozilla::WritingMode aWM) const;
|
||||
nscoord CalcAndCacheConsumedBSize(mozilla::WritingMode aWM);
|
||||
|
||||
/**
|
||||
* Retrieve the effective computed block size of this frame, which is the
|
||||
|
@ -101,8 +104,7 @@ class nsSplittableFrame : public nsIFrame {
|
|||
* continuations.
|
||||
*/
|
||||
nscoord GetEffectiveComputedBSize(
|
||||
const ReflowInput& aReflowInput,
|
||||
nscoord aConsumed = NS_UNCONSTRAINEDSIZE) const;
|
||||
const ReflowInput& aReflowInput, nscoord aConsumed) const;
|
||||
|
||||
/**
|
||||
* @see nsIFrame::GetLogicalSkipSides()
|
||||
|
|
Загрузка…
Ссылка в новой задаче