зеркало из https://github.com/mozilla/pjs.git
Bug 626395. Make sure that when we're clipping our kids we don't create overflow containers for their overflow. Force the kids to lay out within our size instead. Also don't include overflowing kids in our overflow area if we're clipping them. r=roc, a=blocker
This commit is contained in:
Родитель
af83f92c66
Коммит
38970ee28a
|
@ -947,6 +947,13 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
|
|||
return cbSize;
|
||||
}
|
||||
|
||||
static inline PRBool IsClippingChildren(nsIFrame* aFrame,
|
||||
const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
return aReflowState.mStyleDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
|
||||
nsFrame::ApplyPaginatedOverflowClipping(aFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
|
@ -972,12 +979,36 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
#endif
|
||||
|
||||
const nsHTMLReflowState *reflowState = &aReflowState;
|
||||
nsAutoPtr<nsHTMLReflowState> mutableReflowState;
|
||||
// If we have non-auto height, we're clipping our kids and we fit,
|
||||
// make sure our kids fit too.
|
||||
if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE &&
|
||||
aReflowState.ComputedHeight() != NS_AUTOHEIGHT &&
|
||||
IsClippingChildren(this, aReflowState)) {
|
||||
nsMargin heightExtras = aReflowState.mComputedBorderPadding;
|
||||
if (GetSkipSides() & NS_SIDE_TOP) {
|
||||
heightExtras.top = 0;
|
||||
} else {
|
||||
// Bottom margin never causes us to create continuations, so we
|
||||
// don't need to worry about whether it fits in its entirety.
|
||||
heightExtras.top += aReflowState.mComputedMargin.top;
|
||||
}
|
||||
|
||||
if (GetEffectiveComputedHeight(aReflowState) + heightExtras.TopBottom() <=
|
||||
aReflowState.availableHeight) {
|
||||
mutableReflowState = new nsHTMLReflowState(aReflowState);
|
||||
mutableReflowState->availableHeight = NS_UNCONSTRAINEDSIZE;
|
||||
reflowState = mutableReflowState;
|
||||
}
|
||||
}
|
||||
|
||||
// See comment below about oldSize. Use *only* for the
|
||||
// abs-pos-containing-block-size-change optimization!
|
||||
nsSize oldSize = GetSize();
|
||||
|
||||
// Should we create a float manager?
|
||||
nsAutoFloatManager autoFloatManager(const_cast<nsHTMLReflowState &>(aReflowState));
|
||||
nsAutoFloatManager autoFloatManager(const_cast<nsHTMLReflowState&>(*reflowState));
|
||||
|
||||
// XXXldb If we start storing the float manager in the frame rather
|
||||
// than keeping it around only during reflow then we should create it
|
||||
|
@ -993,12 +1024,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
// delete the line with the line cursor.
|
||||
ClearLineCursor();
|
||||
|
||||
if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
|
||||
if (IsFrameTreeTooDeep(*reflowState, aMetrics, aStatus)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool marginRoot = BlockIsMarginRoot(this);
|
||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||
nsBlockReflowState state(*reflowState, aPresContext, this, aMetrics,
|
||||
marginRoot, marginRoot, needFloatManager);
|
||||
|
||||
#ifdef IBMBIDI
|
||||
|
@ -1021,7 +1052,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
nsOverflowAreas ocBounds;
|
||||
nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
|
||||
if (GetPrevInFlow()) {
|
||||
ReflowOverflowContainerChildren(aPresContext, aReflowState, ocBounds, 0,
|
||||
ReflowOverflowContainerChildren(aPresContext, *reflowState, ocBounds, 0,
|
||||
ocStatus);
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1071,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
// If we're not dirty (which means we'll mark everything dirty later)
|
||||
// and our width has changed, mark the lines dirty that we need to
|
||||
// mark dirty for a resize reflow.
|
||||
if (aReflowState.mFlags.mHResize)
|
||||
if (reflowState->mFlags.mHResize)
|
||||
PrepareResizeReflow(state);
|
||||
|
||||
mState &= ~NS_FRAME_FIRST_REFLOW;
|
||||
|
@ -1055,7 +1086,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
|
||||
// If we end in a BR with clear and affected floats continue,
|
||||
// we need to continue, too.
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight &&
|
||||
if (NS_UNCONSTRAINEDSIZE != reflowState->availableHeight &&
|
||||
NS_FRAME_IS_COMPLETE(state.mReflowStatus) &&
|
||||
state.mFloatManager->ClearContinues(FindTrailingClear())) {
|
||||
NS_FRAME_SET_INCOMPLETE(state.mReflowStatus);
|
||||
|
@ -1096,7 +1127,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
nsLayoutUtils::LinePosition position;
|
||||
PRBool havePosition = nsLayoutUtils::GetFirstLinePosition(this, &position);
|
||||
nscoord lineTop = havePosition ? position.mTop
|
||||
: aReflowState.mComputedBorderPadding.top;
|
||||
: reflowState->mComputedBorderPadding.top;
|
||||
ReflowBullet(state, metrics, lineTop);
|
||||
NS_ASSERTION(!BulletIsEmpty() || metrics.height == 0,
|
||||
"empty bullet took up space");
|
||||
|
@ -1117,8 +1148,8 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
|
||||
// Compute our final size
|
||||
nscoord bottomEdgeOfChildren;
|
||||
ComputeFinalSize(aReflowState, state, aMetrics, &bottomEdgeOfChildren);
|
||||
ComputeOverflowAreas(aReflowState, aMetrics, bottomEdgeOfChildren);
|
||||
ComputeFinalSize(*reflowState, state, aMetrics, &bottomEdgeOfChildren);
|
||||
ComputeOverflowAreas(*reflowState, aMetrics, bottomEdgeOfChildren);
|
||||
// Factor overflow container child bounds into the overflow area
|
||||
aMetrics.mOverflowAreas.UnionWith(ocBounds);
|
||||
// Factor pushed float child bounds into the overflow area
|
||||
|
@ -1143,7 +1174,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
// will not be our real new size. This also happens to be more efficient.
|
||||
if (mAbsoluteContainer.HasAbsoluteFrames()) {
|
||||
PRBool haveInterrupt = aPresContext->HasPendingInterrupt();
|
||||
if (aReflowState.WillReflowAgainForClearance() ||
|
||||
if (reflowState->WillReflowAgainForClearance() ||
|
||||
haveInterrupt) {
|
||||
// Make sure that when we reflow again we'll actually reflow all the abs
|
||||
// pos frames that might conceivably depend on our size (or all of them,
|
||||
|
@ -1158,7 +1189,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
} else {
|
||||
nsSize containingBlockSize =
|
||||
CalculateContainingBlockSizeForAbsolutes(aReflowState,
|
||||
CalculateContainingBlockSizeForAbsolutes(*reflowState,
|
||||
nsSize(aMetrics.width,
|
||||
aMetrics.height));
|
||||
|
||||
|
@ -1175,10 +1206,10 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
// viewport height, which can't change during incremental
|
||||
// reflow.
|
||||
PRBool cbHeightChanged =
|
||||
!(isRoot && NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) &&
|
||||
!(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) &&
|
||||
aMetrics.height != oldSize.height;
|
||||
|
||||
rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState,
|
||||
rv = mAbsoluteContainer.Reflow(this, aPresContext, *reflowState,
|
||||
state.mReflowStatus,
|
||||
containingBlockSize.width,
|
||||
containingBlockSize.height, PR_TRUE,
|
||||
|
@ -1252,7 +1283,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
#endif
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, (*reflowState), aMetrics);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1352,18 +1383,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
|||
if (NS_UNCONSTRAINEDSIZE != aReflowState.ComputedHeight()) {
|
||||
// Figure out how much of the computed height should be
|
||||
// applied to this frame.
|
||||
nscoord computedHeightLeftOver = aReflowState.ComputedHeight();
|
||||
if (GetPrevInFlow()) {
|
||||
// Reduce the height by the computed height of prev-in-flows.
|
||||
for (nsIFrame* prev = GetPrevInFlow(); prev; prev = prev->GetPrevInFlow()) {
|
||||
computedHeightLeftOver -= 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.
|
||||
computedHeightLeftOver += aReflowState.mComputedBorderPadding.top;
|
||||
// We may have stretched the frame beyond its computed height. Oh well.
|
||||
computedHeightLeftOver = NS_MAX(0, computedHeightLeftOver);
|
||||
}
|
||||
nscoord computedHeightLeftOver = GetEffectiveComputedHeight(aReflowState);
|
||||
NS_ASSERTION(!( IS_TRUE_OVERFLOW_CONTAINER(this)
|
||||
&& computedHeightLeftOver ),
|
||||
"overflow container must not have computedHeightLeftOver");
|
||||
|
@ -1468,7 +1488,7 @@ nsBlockFrame::ComputeOverflowAreas(const nsHTMLReflowState& aReflowState,
|
|||
nsRect bounds(0, 0, aMetrics.width, aMetrics.height);
|
||||
nsOverflowAreas areas(bounds, bounds);
|
||||
|
||||
if (NS_STYLE_OVERFLOW_CLIP != aReflowState.mStyleDisplay->mOverflowX) {
|
||||
if (!IsClippingChildren(this, aReflowState)) {
|
||||
PRBool inQuirks = (PresContext()->CompatibilityMode() == eCompatibility_NavQuirks);
|
||||
for (line_iterator line = begin_lines(), line_end = end_lines();
|
||||
line != line_end;
|
||||
|
@ -7115,6 +7135,26 @@ nsBlockFrame::GetNearestAncestorBlock(nsIFrame* aCandidate)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
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 = NS_MAX(0, height);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
#ifdef IBMBIDI
|
||||
nsresult
|
||||
nsBlockFrame::ResolveBidi()
|
||||
|
|
|
@ -707,6 +707,13 @@ protected:
|
|||
nsLineList* RemoveOverflowLines();
|
||||
nsresult SetOverflowLines(nsLineList* aOverflowLines);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -1228,18 +1228,6 @@ static inline PRBool ApplyOverflowHiddenClipping(nsIFrame* aFrame,
|
|||
type == nsGkAtoms::bcTableCellFrame;
|
||||
}
|
||||
|
||||
static inline PRBool ApplyPaginatedOverflowClipping(nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisp)
|
||||
{
|
||||
// If we're paginated and aFrame is a block, and it has
|
||||
// NS_BLOCK_CLIP_PAGINATED_OVERFLOW set, then we want to clip our
|
||||
// overflow.
|
||||
return
|
||||
aFrame->PresContext()->IsPaginated() &&
|
||||
aFrame->GetType() == nsGkAtoms::blockFrame &&
|
||||
(aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0;
|
||||
}
|
||||
|
||||
static PRBool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisp, nsRect* aRect) {
|
||||
|
@ -1252,7 +1240,7 @@ static PRBool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
|||
// frames, and any non-visible value for blocks in a paginated context).
|
||||
// Other overflow clipping is applied by nsHTML/XULScrollFrame.
|
||||
if (!ApplyOverflowHiddenClipping(aFrame, aDisp) &&
|
||||
!ApplyPaginatedOverflowClipping(aFrame, aDisp)) {
|
||||
!nsFrame::ApplyPaginatedOverflowClipping(aFrame)) {
|
||||
PRBool clip = aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP;
|
||||
if (!clip)
|
||||
return PR_FALSE;
|
||||
|
@ -6129,7 +6117,8 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
|||
NS_ASSERTION((disp->mOverflowY == NS_STYLE_OVERFLOW_CLIP) ==
|
||||
(disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP),
|
||||
"If one overflow is clip, the other should be too");
|
||||
if (disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP) {
|
||||
if (disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
|
||||
nsFrame::ApplyPaginatedOverflowClipping(this)) {
|
||||
// The contents are actually clipped to the padding area
|
||||
aOverflowAreas.SetAllTo(bounds);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "nsFrameSelection.h"
|
||||
#include "nsHTMLReflowState.h"
|
||||
#include "nsHTMLReflowMetrics.h"
|
||||
#include "nsHTMLParts.h"
|
||||
|
||||
/**
|
||||
* nsFrame logging constants. We redefine the nspr
|
||||
|
@ -572,6 +573,17 @@ public:
|
|||
PRBool aLockScroll,
|
||||
nsIFrame** aContainingBlock = nsnull);
|
||||
|
||||
// test whether aFrame should apply paginated overflow clipping.
|
||||
static PRBool ApplyPaginatedOverflowClipping(nsIFrame* aFrame)
|
||||
{
|
||||
// If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW
|
||||
// set, then we want to clip our overflow.
|
||||
return
|
||||
aFrame->PresContext()->IsPaginated() &&
|
||||
aFrame->GetType() == nsGkAtoms::blockFrame &&
|
||||
(aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Test if we are selecting a table object:
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: hidden; height: 3in">
|
||||
</div>
|
||||
Some text
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: hidden; height: 3in;">
|
||||
<div style="height: 10in;"></div>
|
||||
</div>
|
||||
Some text
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: -moz-hidden-unscrollable; height: 3in;">
|
||||
<div style="height: 10in;"></div>
|
||||
</div>
|
||||
Some text
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: hidden; height: 3in">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: hidden; height: 3in;
|
||||
padding-bottom: 0.5in; margin-bottom: 5in">
|
||||
<div style="height: 10in;"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: -moz-hidden-unscrollable; height: 3in;
|
||||
padding-bottom: 0.5in; margin-bottom: 5in">
|
||||
<div style="height: 10in;"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: hidden; height: 1in;
|
||||
padding-bottom: 1in; border-bottom: 1in solid transparent">
|
||||
<div style="height: 10in;"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-print">
|
||||
<body>
|
||||
<div style="overflow: -moz-hidden-unscrollable; height: 1in;
|
||||
padding-bottom: 1in; border-bottom: 1in solid transparent">
|
||||
<div style="height: 10in;"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -10,3 +10,9 @@
|
|||
== 129941-1a.html 129941-1-ref.html
|
||||
== 129941-1b.html 129941-1-ref.html
|
||||
== 577450-1.html 577450-1-ref.html
|
||||
== 626395-1a.html 626395-1-ref.html
|
||||
== 626395-1b.html 626395-1-ref.html
|
||||
== 626395-2a.html 626395-2-ref.html
|
||||
== 626395-2b.html 626395-2-ref.html
|
||||
== 626395-2c.html 626395-2-ref.html
|
||||
== 626395-2d.html 626395-2-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче