зеркало из https://github.com/mozilla/gecko-dev.git
Bug 743402, Part 2: Pull GetEffectiveComputedHeight() into nsSplittableFrame and refactor it to utilize consumed height for paginated content. [r=roc]
This commit is contained in:
Родитель
528cb9f1bf
Коммит
21103de30a
|
@ -907,6 +907,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
#endif
|
||||
|
||||
const nsHTMLReflowState *reflowState = &aReflowState;
|
||||
nscoord consumedHeight = GetConsumedHeight();
|
||||
nscoord effectiveComputedHeight = GetEffectiveComputedHeight(aReflowState,
|
||||
consumedHeight);
|
||||
Maybe<nsHTMLReflowState> mutableReflowState;
|
||||
// If we have non-auto height, we're clipping our kids and we fit,
|
||||
// make sure our kids fit too.
|
||||
|
@ -922,7 +925,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
heightExtras.top += aReflowState.mComputedMargin.top;
|
||||
}
|
||||
|
||||
if (GetEffectiveComputedHeight(aReflowState) + heightExtras.TopBottom() <=
|
||||
if (effectiveComputedHeight + heightExtras.TopBottom() <=
|
||||
aReflowState.availableHeight) {
|
||||
mutableReflowState.construct(aReflowState);
|
||||
mutableReflowState.ref().availableHeight = NS_UNCONSTRAINEDSIZE;
|
||||
|
@ -957,8 +960,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
|
||||
bool topMarginRoot, bottomMarginRoot;
|
||||
IsMarginRoot(&topMarginRoot, &bottomMarginRoot);
|
||||
|
||||
// Cache the consumed height in the block reflow state so that we don't have
|
||||
// to continually recompute it.
|
||||
nsBlockReflowState state(*reflowState, aPresContext, this,
|
||||
topMarginRoot, bottomMarginRoot, needFloatManager);
|
||||
topMarginRoot, bottomMarginRoot, needFloatManager,
|
||||
consumedHeight);
|
||||
|
||||
#ifdef IBMBIDI
|
||||
if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION)
|
||||
|
@ -7078,26 +7085,6 @@ nsBlockFrame::GetNearestAncestorBlock(nsIFrame* aCandidate)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsBlockFrame::GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState) const
|
||||
{
|
||||
nscoord height = aReflowState.ComputedHeight();
|
||||
NS_ABORT_IF_FALSE(height != NS_UNCONSTRAINEDSIZE, "Don't call me!");
|
||||
|
||||
if (GetPrevInFlow()) {
|
||||
// Reduce the height by the computed height of prev-in-flows.
|
||||
for (nsIFrame* prev = GetPrevInFlow(); prev; prev = prev->GetPrevInFlow()) {
|
||||
height -= prev->GetRect().height;
|
||||
}
|
||||
// We just subtracted our top-border padding, since it was included in the
|
||||
// first frame's height. Add it back to get the content height.
|
||||
height += aReflowState.mComputedBorderPadding.top;
|
||||
// We may have stretched the frame beyond its computed height. Oh well.
|
||||
height = std::max(0, height);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
#ifdef IBMBIDI
|
||||
nsresult
|
||||
nsBlockFrame::ResolveBidi()
|
||||
|
|
|
@ -796,13 +796,6 @@ protected:
|
|||
void SetOverflowLines(FrameLines* aOverflowLines);
|
||||
void DestroyOverflowLines();
|
||||
|
||||
// Determine the computed height that's in effect for this block
|
||||
// frame (that is, our computed height minus the heights of our
|
||||
// previous in-flows).
|
||||
// XXXbz this clearly makes laying out a block with N in-flows
|
||||
// O(N^2)! Good thing the constant is tiny.
|
||||
nscoord GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState) const;
|
||||
|
||||
/**
|
||||
* This class is useful for efficiently modifying the out of flow
|
||||
* overflow list. It gives the client direct writable access to
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsSplittableFrame)
|
||||
|
||||
|
@ -216,6 +217,80 @@ nsSplittableFrame::GetConsumedHeight() const
|
|||
return height;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsSplittableFrame::GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState,
|
||||
nscoord aConsumedHeight) const
|
||||
{
|
||||
nscoord height = aReflowState.ComputedHeight();
|
||||
if (height == NS_INTRINSICSIZE) {
|
||||
return NS_INTRINSICSIZE;
|
||||
}
|
||||
|
||||
if (aConsumedHeight == NS_INTRINSICSIZE) {
|
||||
aConsumedHeight = GetConsumedHeight();
|
||||
}
|
||||
|
||||
height -= aConsumedHeight;
|
||||
|
||||
if (aConsumedHeight != NS_INTRINSICSIZE) {
|
||||
// We just subtracted our top-border padding, since it was included in the
|
||||
// first frame's height. Add it back to get the content height.
|
||||
height += aReflowState.mComputedBorderPadding.top;
|
||||
}
|
||||
|
||||
// We may have stretched the frame beyond its computed height. Oh well.
|
||||
height = std::max(0, height);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
void
|
||||
nsSplittableFrame::ComputeFinalHeight(const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus* aStatus,
|
||||
nscoord aContentHeight,
|
||||
const nsMargin& aBorderPadding,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nscoord aConsumed)
|
||||
{
|
||||
|
||||
// Figure out how much of the computed height should be
|
||||
// applied to this frame.
|
||||
nscoord computedHeightLeftOver = GetEffectiveComputedHeight(aReflowState,
|
||||
aConsumed);
|
||||
NS_ASSERTION(!( IS_TRUE_OVERFLOW_CONTAINER(this)
|
||||
&& computedHeightLeftOver ),
|
||||
"overflow container must not have computedHeightLeftOver");
|
||||
|
||||
aMetrics.height =
|
||||
NSCoordSaturatingAdd(NSCoordSaturatingAdd(aBorderPadding.top,
|
||||
computedHeightLeftOver),
|
||||
aBorderPadding.bottom);
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(*aStatus)
|
||||
&& aMetrics.height < aReflowState.availableHeight) {
|
||||
// We ran out of height on this page but we're incomplete
|
||||
// Set status to complete except for overflow
|
||||
NS_FRAME_SET_OVERFLOW_INCOMPLETE(*aStatus);
|
||||
}
|
||||
|
||||
if (NS_FRAME_IS_COMPLETE(*aStatus)) {
|
||||
if (computedHeightLeftOver > 0 &&
|
||||
NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight &&
|
||||
aMetrics.height > aReflowState.availableHeight) {
|
||||
// We don't fit and we consumed some of the computed height,
|
||||
// so we should consume all the available height and then
|
||||
// break. If our bottom border/padding straddles the break
|
||||
// point, then this will increase our height and push the
|
||||
// border/padding to the next page/column.
|
||||
aMetrics.height = std::max(aReflowState.availableHeight,
|
||||
aContentHeight);
|
||||
NS_FRAME_SET_INCOMPLETE(*aStatus);
|
||||
if (!GetNextInFlow())
|
||||
*aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsSplittableFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, int32_t aIndent)
|
||||
|
|
|
@ -85,6 +85,39 @@ protected:
|
|||
*/
|
||||
nscoord GetConsumedHeight() const;
|
||||
|
||||
/**
|
||||
* Retrieve the effective computed height of this frame, which is the computed
|
||||
* height, minus the height consumed by any previous in-flows.
|
||||
*/
|
||||
nscoord GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState,
|
||||
nscoord aConsumed = NS_INTRINSICSIZE) const;
|
||||
|
||||
/**
|
||||
* Compute the final height of this frame.
|
||||
*
|
||||
* @param aReflowState Data structure passed from parent during reflow.
|
||||
* @param aReflowStatus A pointed to the reflow status for when we're finished
|
||||
* doing reflow. this will get set appropriately if the height causes
|
||||
* us to exceed the current available (page) height.
|
||||
* @param aContentHeight The height of content, precomputed outside of this
|
||||
* function. The final height that is used in aMetrics will be set to
|
||||
* either this or the available height, whichever is larger, in the
|
||||
* case where our available height is constrained, and we overflow that
|
||||
* available height.
|
||||
* @param aBorderPadding The margins representing the border padding for block
|
||||
* frames. Can be 0.
|
||||
* @param aMetrics Out parameter for final height. Taken as an
|
||||
* nsHTMLReflowMetrics object so that aMetrics can be passed in
|
||||
* directly during reflow.
|
||||
* @param aConsumed The height already consumed by our previous-in-flows.
|
||||
*/
|
||||
void ComputeFinalHeight(const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus* aStatus,
|
||||
nscoord aContentHeight,
|
||||
const nsMargin& aBorderPadding,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nscoord aConsumed);
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual void DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, int32_t aIndent) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче