mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 22:32:51 +00:00
Bug 383883: {inc} issues with block moving through non-moving float. r+sr+a=dbaron
This commit is contained in:
parent
20b0394d68
commit
ded759b0cc
@ -1577,10 +1577,17 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine,
|
||||
nscoord aDeltaY)
|
||||
{
|
||||
NS_PRECONDITION(!aLine->IsDirty(), "should never be called on dirty lines");
|
||||
nsSpaceManager *spaceManager = aState.mReflowState.mSpaceManager;
|
||||
NS_ASSERTION((aState.mReflowState.parentReflowState &&
|
||||
aState.mReflowState.parentReflowState->mSpaceManager == spaceManager) ||
|
||||
aState.mReflowState.mBlockDelta == 0, "Bad block delta passed in");
|
||||
|
||||
// Check to see if there are any floats; if there aren't, there can't
|
||||
// be any float damage
|
||||
if (!spaceManager->HasAnyFloats())
|
||||
return;
|
||||
|
||||
// Check the damage region recorded in the float damage.
|
||||
nsSpaceManager *spaceManager = aState.mReflowState.mSpaceManager;
|
||||
if (spaceManager->HasFloatDamage()) {
|
||||
nscoord lineYA = aLine->mBounds.y + aDeltaY;
|
||||
nscoord lineYB = lineYA + aLine->mBounds.height;
|
||||
@ -1590,39 +1597,32 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
|
||||
}
|
||||
}
|
||||
|
||||
if (aDeltaY) {
|
||||
// Cases we need to find:
|
||||
//
|
||||
// 1. the line was impacted by a float and now isn't
|
||||
// 2. the line wasn't impacted by a float and now is
|
||||
// 3. the line is impacted by a float both before and after and
|
||||
// the float has changed position relative to the line (or it's
|
||||
// a different float). (XXXPerf we don't currently
|
||||
// check whether the float changed size. We currently just
|
||||
// mark blocks dirty and ignore any possibility of damage to
|
||||
// inlines by it being a different float with a different
|
||||
// size.)
|
||||
//
|
||||
// XXXPerf: An optimization: if the line was and is completely
|
||||
// impacted by a float and the float hasn't changed size,
|
||||
// then we don't need to mark the line dirty.
|
||||
aState.GetAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
|
||||
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
|
||||
PRBool isImpactedByFloat = aState.IsImpactedByFloat();
|
||||
// Check if the line is moving relative to the space manager
|
||||
if (aDeltaY + aState.mReflowState.mBlockDelta != 0) {
|
||||
if (aLine->IsBlock()) {
|
||||
// Unconditionally reflow sliding blocks; we only really need to reflow
|
||||
// if there's a float impacting this block, but the current space manager
|
||||
// makes it difficult to check that. Therefore, we let the child block
|
||||
// decide what it needs to reflow.
|
||||
aLine->MarkDirty();
|
||||
} else {
|
||||
// Note that this check will become incorrect once bug 25888 is fixed
|
||||
// because we are only checking the top of the line
|
||||
aState.GetAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
|
||||
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
|
||||
PRBool isImpactedByFloat = aState.IsImpactedByFloat();
|
||||
|
||||
#ifdef REALLY_NOISY_REFLOW
|
||||
printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n",
|
||||
this, wasImpactedByFloat, isImpactedByFloat);
|
||||
#endif
|
||||
// Mark the line dirty if:
|
||||
// 1. It used to be impacted by a float and now isn't, or vice
|
||||
// versa.
|
||||
// 2. It is impacted by a float and it is a block, which means
|
||||
// that more or less of the line could be impacted than was in
|
||||
// the past. (XXXPerf This could be optimized further, since
|
||||
// we're marking the whole line dirty.)
|
||||
if ((wasImpactedByFloat != isImpactedByFloat) ||
|
||||
(isImpactedByFloat && aLine->IsBlock())) {
|
||||
aLine->MarkDirty();
|
||||
|
||||
// Mark the line dirty if it was or is affected by a float
|
||||
// We actually only really need to reflow if the amount of impact
|
||||
// changes, but that's not straightforward to check
|
||||
if (wasImpactedByFloat || isImpactedByFloat) {
|
||||
aLine->MarkDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2919,7 +2919,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||
nsReflowStatus frameReflowStatus = NS_FRAME_COMPLETE;
|
||||
rv = brc.ReflowBlock(availSpace, applyTopMargin, aState.mPrevBottomMargin,
|
||||
clearance, aState.IsAdjacentWithTop(), computedOffsets,
|
||||
blockHtmlRS, frameReflowStatus);
|
||||
aLine.get(), blockHtmlRS, frameReflowStatus);
|
||||
|
||||
// If this was a second-pass reflow and the block's vertical position
|
||||
// changed, invalidates from the first pass might have happened in the
|
||||
@ -5484,7 +5484,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||
// on a frame property anyawy
|
||||
rv = brc.ReflowBlock(availSpace, PR_TRUE, margin,
|
||||
0, isAdjacentWithTop,
|
||||
offsets, floatRS,
|
||||
offsets, nsnull, floatRS,
|
||||
aReflowStatus);
|
||||
} while (NS_SUCCEEDED(rv) && clearanceFrame);
|
||||
|
||||
@ -5526,7 +5526,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||
}
|
||||
|
||||
// Capture the margin information for the caller
|
||||
const nsMargin& m = brc.GetMargin();
|
||||
const nsMargin& m = floatRS.mComputedMargin;
|
||||
aFloatMargin.top = brc.GetTopMargin();
|
||||
aFloatMargin.right = m.right;
|
||||
// Only last in flows get a bottom margin
|
||||
|
@ -72,9 +72,6 @@ nsBlockReflowContext::nsBlockReflowContext(nsPresContext* aPresContext,
|
||||
mOuterReflowState(aParentRS),
|
||||
mMetrics()
|
||||
{
|
||||
mStyleBorder = nsnull;
|
||||
mStyleMargin = nsnull;
|
||||
mStylePadding = nsnull;
|
||||
}
|
||||
|
||||
static nsIFrame* DescendIntoBlockLevelFrame(nsIFrame* aFrame)
|
||||
@ -251,6 +248,7 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
nscoord aClearance,
|
||||
PRBool aIsAdjacentWithTop,
|
||||
nsMargin& aComputedOffsets,
|
||||
nsLineBox* aLine,
|
||||
nsHTMLReflowState& aFrameRS,
|
||||
nsReflowStatus& aFrameReflowStatus)
|
||||
{
|
||||
@ -280,7 +278,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
if (!aIsAdjacentWithTop) {
|
||||
aFrameRS.mFlags.mIsTopOfPage = PR_FALSE; // make sure this is cleared
|
||||
}
|
||||
mComputedWidth = aFrameRS.ComputedWidth();
|
||||
|
||||
if (aApplyTopMargin) {
|
||||
mTopMargin = aPrevMargin;
|
||||
@ -299,68 +296,39 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
}
|
||||
}
|
||||
|
||||
// Compute x/y coordinate where reflow will begin. Use the rules
|
||||
// from 10.3.3 to determine what to apply. At this point in the
|
||||
// reflow auto left/right margins will have a zero value.
|
||||
mMargin = aFrameRS.mComputedMargin;
|
||||
mStyleBorder = aFrameRS.mStyleBorder;
|
||||
mStyleMargin = aFrameRS.mStyleMargin;
|
||||
mStylePadding = aFrameRS.mStylePadding;
|
||||
nscoord x;
|
||||
nscoord y = mSpace.y + mTopMargin.get() + aClearance;
|
||||
nscoord tx = 0, ty = 0;
|
||||
// The values of x and y do not matter for floats, so don't bother calculating
|
||||
// them. Floats are guaranteed to have their own space manager, so tx and ty
|
||||
// don't matter. mX and mY don't matter becacuse they are only used in
|
||||
// PlaceBlock, which is not used for floats.
|
||||
if (aLine) {
|
||||
// Compute x/y coordinate where reflow will begin. Use the rules
|
||||
// from 10.3.3 to determine what to apply. At this point in the
|
||||
// reflow auto left/right margins will have a zero value.
|
||||
|
||||
// If it's a right floated element, then calculate the x-offset
|
||||
// differently
|
||||
if (NS_STYLE_FLOAT_RIGHT == aFrameRS.mStyleDisplay->mFloats) {
|
||||
nscoord frameWidth;
|
||||
|
||||
if (NS_UNCONSTRAINEDSIZE == aFrameRS.ComputedWidth()) {
|
||||
// Use the current frame width
|
||||
frameWidth = mFrame->GetSize().width;
|
||||
} else {
|
||||
frameWidth = aFrameRS.ComputedWidth() +
|
||||
aFrameRS.mComputedBorderPadding.left +
|
||||
aFrameRS.mComputedBorderPadding.right;
|
||||
}
|
||||
nscoord x = mSpace.x + aFrameRS.mComputedMargin.left;
|
||||
nscoord y = mSpace.y + mTopMargin.get() + aClearance;
|
||||
|
||||
// if this is an unconstrained width reflow, then just place the float at the left margin
|
||||
if (NS_UNCONSTRAINEDSIZE == mSpace.width)
|
||||
x = mSpace.x;
|
||||
else
|
||||
x = mSpace.XMost() - mMargin.right - frameWidth;
|
||||
if ((mFrame->GetStateBits() & NS_BLOCK_SPACE_MGR) == 0)
|
||||
aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + y - aLine->mBounds.y;
|
||||
|
||||
} else {
|
||||
x = mSpace.x + mMargin.left;
|
||||
}
|
||||
mX = x;
|
||||
mY = y;
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
// Compute the translation to be used for adjusting the spacemanagager
|
||||
// coordinate system for the frame. The spacemanager coordinates are
|
||||
// <b>inside</b> the callers border+padding, but the x/y coordinates
|
||||
// are not (recall that frame coordinates are relative to the parents
|
||||
// origin and that the parents border/padding is <b>inside</b> the
|
||||
// parent frame. Therefore we have to subtract out the parents
|
||||
// border+padding before translating.
|
||||
nscoord tx = x - mOuterReflowState.mComputedBorderPadding.left;
|
||||
nscoord ty = y - mOuterReflowState.mComputedBorderPadding.top;
|
||||
|
||||
// If the element is relatively positioned, then adjust x and y accordingly
|
||||
if (NS_STYLE_POSITION_RELATIVE == aFrameRS.mStyleDisplay->mPosition) {
|
||||
x += aFrameRS.mComputedOffsets.left;
|
||||
y += aFrameRS.mComputedOffsets.top;
|
||||
// Compute the translation to be used for adjusting the spacemanagager
|
||||
// coordinate system for the frame. The spacemanager coordinates are
|
||||
// <b>inside</b> the callers border+padding, but the x/y coordinates
|
||||
// are not (recall that frame coordinates are relative to the parents
|
||||
// origin and that the parents border/padding is <b>inside</b> the
|
||||
// parent frame. Therefore we have to subtract out the parents
|
||||
// border+padding before translating.
|
||||
tx = x - mOuterReflowState.mComputedBorderPadding.left;
|
||||
ty = y - mOuterReflowState.mComputedBorderPadding.top;
|
||||
}
|
||||
|
||||
// Let frame know that we are reflowing it
|
||||
mFrame->WillReflow(mPresContext);
|
||||
|
||||
// Position it and its view (if it has one)
|
||||
// Note: Use "x" and "y" and not "mX" and "mY" because they more accurately
|
||||
// represents where we think the block will be placed
|
||||
// XXXldb That's fine for view positioning, but not for reflow!
|
||||
mFrame->SetPosition(nsPoint(x, y));
|
||||
nsContainerFrame::PositionFrameView(mFrame);
|
||||
|
||||
#ifdef DEBUG
|
||||
mMetrics.width = nscoord(0xdeadbeef);
|
||||
mMetrics.height = nscoord(0xdeadbeef);
|
||||
@ -436,7 +404,7 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
||||
// Compute collapsed bottom margin value.
|
||||
if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
|
||||
aBottomMarginResult = mMetrics.mCarriedOutBottomMargin;
|
||||
aBottomMarginResult.Include(mMargin.bottom);
|
||||
aBottomMarginResult.Include(aReflowState.mComputedMargin.bottom);
|
||||
} else {
|
||||
// The used bottom-margin is set to zero above a break.
|
||||
aBottomMarginResult.Zero();
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
nscoord aClearance,
|
||||
PRBool aIsAdjacentWithTop,
|
||||
nsMargin& aComputedOffsets,
|
||||
nsLineBox* aLine,
|
||||
nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aReflowStatus);
|
||||
|
||||
@ -89,10 +90,6 @@ public:
|
||||
return mTopMargin.get();
|
||||
}
|
||||
|
||||
const nsMargin& GetMargin() const {
|
||||
return mMargin;
|
||||
}
|
||||
|
||||
const nsHTMLReflowMetrics& GetMetrics() const {
|
||||
return mMetrics;
|
||||
}
|
||||
@ -122,13 +119,6 @@ protected:
|
||||
nsIFrame* mFrame;
|
||||
nsRect mSpace;
|
||||
|
||||
// Spacing style for the frame we are reflowing; only valid after reflow
|
||||
const nsStyleBorder* mStyleBorder;
|
||||
const nsStyleMargin* mStyleMargin;
|
||||
const nsStylePadding* mStylePadding;
|
||||
|
||||
nscoord mComputedWidth; // copy of reflowstate's computedWidth
|
||||
nsMargin mMargin;
|
||||
nscoord mX, mY;
|
||||
nsHTMLReflowMetrics mMetrics;
|
||||
nsCollapsingMargin mTopMargin;
|
||||
|
@ -90,6 +90,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
const nsSize& aAvailableSpace)
|
||||
: nsCSSOffsetState(aFrame, aRenderingContext)
|
||||
, mReflowDepth(0)
|
||||
, mBlockDelta(0)
|
||||
{
|
||||
NS_PRECONDITION(aPresContext, "no pres context");
|
||||
NS_PRECONDITION(aRenderingContext, "no rendering context");
|
||||
@ -134,6 +135,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
: nsCSSOffsetState(aFrame, aParentReflowState.rendContext)
|
||||
, mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
, mFlags(aParentReflowState.mFlags)
|
||||
, mBlockDelta(0)
|
||||
{
|
||||
NS_PRECONDITION(aPresContext, "no pres context");
|
||||
NS_PRECONDITION(aFrame, "no frame");
|
||||
|
@ -168,10 +168,6 @@ public:
|
||||
InitOffsets(aContainingBlockWidth);
|
||||
}
|
||||
|
||||
void InitOffsets(nscoord aContainingBlockWidth,
|
||||
const nsMargin *aBorder = nsnull,
|
||||
const nsMargin *aPadding = nsnull);
|
||||
|
||||
// Destructor for usedPaddingProperty
|
||||
static void DestroyMarginFunc(void* aFrame,
|
||||
nsIAtom* aPropertyName,
|
||||
@ -189,6 +185,10 @@ private:
|
||||
|
||||
protected:
|
||||
|
||||
void InitOffsets(nscoord aContainingBlockWidth,
|
||||
const nsMargin *aBorder = nsnull,
|
||||
const nsMargin *aPadding = nsnull);
|
||||
|
||||
/*
|
||||
* Convert nsStyleCoord to nscoord when percentages depend on the
|
||||
* containing block width.
|
||||
@ -260,6 +260,16 @@ struct nsHTMLReflowState : public nsCSSOffsetState {
|
||||
// pointer to the space manager associated with this area
|
||||
nsSpaceManager* mSpaceManager;
|
||||
|
||||
// The amount the in-flow position of the block is moving vertically relative
|
||||
// to its previous in-flow position (i.e. the amount the line containing the
|
||||
// block is moving).
|
||||
// This should be zero for anything which is not a block outside, and it
|
||||
// should be zero for anything which has a non-block parent.
|
||||
// The intended use of this value is to allow the accurate determination
|
||||
// of the potential impact of a float
|
||||
// This takes on an arbitrary value the first time a block is reflowed
|
||||
nscoord mBlockDelta;
|
||||
|
||||
// LineLayout object (only for inline reflow; set to NULL otherwise)
|
||||
nsLineLayout* mLineLayout;
|
||||
|
||||
@ -416,16 +426,12 @@ public:
|
||||
static nscoord CalcLineHeight(nsStyleContext* aStyleContext,
|
||||
nsIDeviceContext* aDeviceContext);
|
||||
|
||||
void InitFrameType();
|
||||
|
||||
void ComputeContainingBlockRectangle(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState* aContainingBlockRS,
|
||||
nscoord& aContainingBlockWidth,
|
||||
nscoord& aContainingBlockHeight);
|
||||
|
||||
void CalculateBlockSideMargins(nscoord aAvailWidth,
|
||||
nscoord aComputedWidth);
|
||||
|
||||
/**
|
||||
* Apply the mComputed(Min/Max)(Width/Height) values to the content
|
||||
* size computed so far. If a passed-in pointer is null, we skip
|
||||
@ -457,7 +463,7 @@ public:
|
||||
void SetTruncated(const nsHTMLReflowMetrics& aMetrics, nsReflowStatus* aStatus) const;
|
||||
|
||||
protected:
|
||||
|
||||
void InitFrameType();
|
||||
void InitCBReflowState();
|
||||
void InitResizeFlags(nsPresContext* aPresContext);
|
||||
|
||||
@ -501,6 +507,8 @@ protected:
|
||||
nscoord* aInsideBoxSizing,
|
||||
nscoord* aOutsideBoxSizing);
|
||||
|
||||
void CalculateBlockSideMargins(nscoord aAvailWidth,
|
||||
nscoord aComputedWidth);
|
||||
};
|
||||
|
||||
#endif /* nsHTMLReflowState_h___ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user