Change coordinate system in the float manager from content box (most of the time, but sometimes border box) to always border box. (Bug 551425) r=dbaron a2.0=blocking+
This commit is contained in:
@@ -102,9 +102,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
NS_ASSERTION(mFloatManager,
|
||||
"FloatManager should be set in nsBlockReflowState" );
|
||||
if (mFloatManager) {
|
||||
// Translate into our content area and then save the
|
||||
// coordinate system origin for later.
|
||||
mFloatManager->Translate(borderPadding.left, borderPadding.top);
|
||||
// Save the coordinate system origin for later.
|
||||
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
|
||||
mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
|
||||
}
|
||||
@@ -139,8 +137,8 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
|
||||
mY = borderPadding.top;
|
||||
mContentArea.x = borderPadding.left;
|
||||
mY = mContentArea.y = borderPadding.top;
|
||||
|
||||
mPrevChild = nsnull;
|
||||
mCurrentLine = aFrame->end_lines();
|
||||
@@ -148,16 +146,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
mMinLineHeight = aReflowState.CalcLineHeight();
|
||||
}
|
||||
|
||||
nsBlockReflowState::~nsBlockReflowState()
|
||||
{
|
||||
// Restore the coordinate system, unless the float manager is null,
|
||||
// which means it was just destroyed.
|
||||
if (mFloatManager) {
|
||||
const nsMargin& borderPadding = BorderPadding();
|
||||
mFloatManager->Translate(-borderPadding.left, -borderPadding.top);
|
||||
}
|
||||
}
|
||||
|
||||
nsLineBox*
|
||||
nsBlockReflowState::NewLineBox(nsIFrame* aFrame,
|
||||
PRInt32 aCount,
|
||||
@@ -187,9 +175,9 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
||||
// only give it free space. An example is a table frame - the
|
||||
// tables do not flow around floats.
|
||||
// However, we can let its margins intersect floats.
|
||||
NS_ASSERTION(aFloatAvailableSpace.x >= 0, "bad avail space rect x");
|
||||
NS_ASSERTION(aFloatAvailableSpace.x >= mContentArea.x, "bad avail space rect x");
|
||||
NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
|
||||
aFloatAvailableSpace.XMost() <= mContentArea.width,
|
||||
aFloatAvailableSpace.XMost() <= mContentArea.XMost(),
|
||||
"bad avail space rect width");
|
||||
|
||||
nscoord leftOffset, rightOffset;
|
||||
@@ -210,13 +198,13 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
||||
aReplacedWidth->marginRight == os.mComputedMargin.right),
|
||||
"unexpected aReplacedWidth");
|
||||
|
||||
nscoord leftFloatXOffset = aFloatAvailableSpace.x;
|
||||
nscoord leftFloatXOffset = aFloatAvailableSpace.x - mContentArea.x;
|
||||
leftOffset = NS_MAX(leftFloatXOffset, os.mComputedMargin.left) -
|
||||
(aReplacedWidth ? aReplacedWidth->marginLeft
|
||||
: os.mComputedMargin.left);
|
||||
leftOffset = NS_MAX(leftOffset, 0); // in case of negative margin
|
||||
nscoord rightFloatXOffset =
|
||||
mContentArea.width - aFloatAvailableSpace.XMost();
|
||||
mContentArea.XMost() - aFloatAvailableSpace.XMost();
|
||||
rightOffset = NS_MAX(rightFloatXOffset, os.mComputedMargin.right) -
|
||||
(aReplacedWidth ? aReplacedWidth->marginRight
|
||||
: os.mComputedMargin.right);
|
||||
@@ -248,8 +236,6 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
// it off the page/column. Negative available height can confuse other code
|
||||
// and is nonsense in principle.
|
||||
|
||||
const nsMargin& borderPadding = BorderPadding();
|
||||
|
||||
// XXX Do we really want this condition to be this restrictive (i.e.,
|
||||
// more restrictive than it used to be)? The |else| here is allowed
|
||||
// by the CSS spec, but only out of desperation given implementations,
|
||||
@@ -275,14 +261,14 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floats
|
||||
// The child block will flow around the float. Therefore
|
||||
// give it all of the available space.
|
||||
aResult.x = borderPadding.left;
|
||||
aResult.x = mContentArea.x;
|
||||
aResult.width = mContentArea.width;
|
||||
break;
|
||||
case NS_STYLE_FLOAT_EDGE_MARGIN:
|
||||
{
|
||||
// The child block's margins should be placed adjacent to,
|
||||
// but not overlap the float.
|
||||
aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left;
|
||||
aResult.x = aFloatAvailableSpace.mRect.x;
|
||||
aResult.width = aFloatAvailableSpace.mRect.width;
|
||||
}
|
||||
break;
|
||||
@@ -292,7 +278,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
// Since there are no floats present the float-edge property
|
||||
// doesn't matter therefore give the block element all of the
|
||||
// available space since it will flow around the float itself.
|
||||
aResult.x = borderPadding.left;
|
||||
aResult.x = mContentArea.x;
|
||||
aResult.width = mContentArea.width;
|
||||
}
|
||||
}
|
||||
@@ -310,7 +296,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
|
||||
leftOffset, rightOffset,
|
||||
replacedWidth);
|
||||
aResult.x = borderPadding.left + leftOffset;
|
||||
aResult.x = mContentArea.x + leftOffset;
|
||||
aResult.width = mContentArea.width - leftOffset - rightOffset;
|
||||
}
|
||||
|
||||
@@ -332,12 +318,11 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
||||
"bad coord system");
|
||||
#endif
|
||||
|
||||
nscoord y = aY - BorderPadding().top;
|
||||
nscoord height = (mContentArea.height == nscoord_MAX)
|
||||
? nscoord_MAX : NS_MAX(mContentArea.height - y, 0);
|
||||
? nscoord_MAX : NS_MAX(mContentArea.YMost() - aY, 0);
|
||||
nsFlowAreaRect result =
|
||||
mFloatManager->GetFlowArea(y, nsFloatManager::BAND_FROM_POINT,
|
||||
height, mContentArea.width, aState);
|
||||
mFloatManager->GetFlowArea(aY, nsFloatManager::BAND_FROM_POINT,
|
||||
height, mContentArea, aState);
|
||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||
if (result.mRect.width < 0)
|
||||
result.mRect.width = 0;
|
||||
@@ -367,9 +352,8 @@ nsBlockReflowState::GetFloatAvailableSpaceForHeight(
|
||||
#endif
|
||||
|
||||
nsFlowAreaRect result =
|
||||
mFloatManager->GetFlowArea(aY - BorderPadding().top,
|
||||
nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
||||
aHeight, mContentArea.width, aState);
|
||||
mFloatManager->GetFlowArea(aY, nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
||||
aHeight, mContentArea, aState);
|
||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||
if (result.mRect.width < 0)
|
||||
result.mRect.width = 0;
|
||||
@@ -510,12 +494,6 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
|
||||
|
||||
// Place floats for this line into the float manager
|
||||
if (aLine->HasFloats() || aLine->IsBlock()) {
|
||||
// Undo border/padding translation since the nsFloatCache's
|
||||
// coordinates are relative to the frame not relative to the
|
||||
// border/padding.
|
||||
const nsMargin& bp = BorderPadding();
|
||||
mFloatManager->Translate(-bp.left, -bp.top);
|
||||
|
||||
RecoverFloats(aLine, aDeltaY);
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -523,8 +501,6 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
|
||||
mFloatManager->List(stdout);
|
||||
}
|
||||
#endif
|
||||
// And then put the translation back again
|
||||
mFloatManager->Translate(bp.left, bp.top);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,8 +576,7 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
|
||||
if (placed) {
|
||||
// Pass on updated available space to the current inline reflow engine
|
||||
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
|
||||
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
|
||||
mY),
|
||||
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mY),
|
||||
floatAvailSpace.mRect.Size());
|
||||
aLineLayout->UpdateBand(availSpace, aFloat);
|
||||
// Record this float in the current-line list
|
||||
@@ -681,7 +656,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
|
||||
// Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
|
||||
// ``above'' another float that preceded it in the flow.
|
||||
mY = NS_MAX(mFloatManager->GetLowestFloatTop() + BorderPadding().top, mY);
|
||||
mY = NS_MAX(mFloatManager->GetLowestFloatTop(), mY);
|
||||
|
||||
// See if the float should clear any preceding floats...
|
||||
// XXX We need to mark this float somehow so that it gets reflowed
|
||||
@@ -791,10 +766,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
// We don't worry about the geometry of the prev in flow, let the continuation
|
||||
// place and size itself as required.
|
||||
|
||||
// Assign an x and y coordinate to the float. Note that the x,y
|
||||
// coordinates are computed <b>relative to the translation in the
|
||||
// spacemanager</b> which means that the impacted region will be
|
||||
// <b>inside</b> the border/padding area.
|
||||
// Assign an x and y coordinate to the float.
|
||||
nscoord floatX, floatY;
|
||||
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
|
||||
floatX = floatAvailableSpace.mRect.x;
|
||||
@@ -810,16 +782,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
floatX = floatAvailableSpace.mRect.x;
|
||||
}
|
||||
}
|
||||
const nsMargin& borderPadding = BorderPadding();
|
||||
floatY = mY - borderPadding.top;
|
||||
if (floatY < 0) {
|
||||
// CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
|
||||
// be higher than the top of its containing block." (Since the
|
||||
// containing block is the content edge of the block box, this
|
||||
// means the margin edge of the float can't be higher than the
|
||||
// content edge of the block that contains it.)
|
||||
floatY = 0;
|
||||
}
|
||||
// CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
|
||||
// be higher than the top of its containing block." (Since the
|
||||
// containing block is the content edge of the block box, this
|
||||
// means the margin edge of the float can't be higher than the
|
||||
// content edge of the block that contains it.)
|
||||
floatY = NS_MAX(mY, mContentArea.y);
|
||||
|
||||
// Reflow the float after computing its vertical position so it knows
|
||||
// where to break.
|
||||
@@ -845,7 +813,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
(!mReflowState.mFlags.mIsTopOfPage || !IsAdjacentWithTop() ||
|
||||
pushedDown) &&
|
||||
aFloat->GetSize().height + floatMargin.TopBottom() >
|
||||
mContentArea.height - floatY) ||
|
||||
mContentArea.YMost() - floatY) ||
|
||||
NS_FRAME_IS_TRUNCATED(reflowStatus)) {
|
||||
|
||||
PushFloatPastBreak(aFloat);
|
||||
@@ -853,11 +821,10 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
}
|
||||
|
||||
// Calculate the actual origin of the float frame's border rect
|
||||
// relative to the parent block; floatX/Y must be converted from space-manager
|
||||
// coordinates to parent coordinates, and the margin must be added in
|
||||
// relative to the parent block; the margin must be added in
|
||||
// to get the border rect
|
||||
nsPoint origin(borderPadding.left + floatMargin.left + floatX,
|
||||
borderPadding.top + floatMargin.top + floatY);
|
||||
nsPoint origin(floatMargin.left + floatX,
|
||||
floatMargin.top + floatY);
|
||||
|
||||
// If float is relatively positioned, factor that in as well
|
||||
origin += aFloat->GetRelativeOffset(floatDisplay);
|
||||
@@ -884,9 +851,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
region.height = NS_MAX(region.height, mContentArea.height - floatY);
|
||||
}
|
||||
nsresult rv =
|
||||
// spacemanager translation is inset by the border+padding.
|
||||
mFloatManager->AddFloat(aFloat,
|
||||
region - nsPoint(borderPadding.left, borderPadding.top));
|
||||
mFloatManager->AddFloat(aFloat, region);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
|
||||
// store region
|
||||
rv = nsFloatManager::StoreRegionFor(aFloat, region);
|
||||
@@ -899,8 +864,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
// less damage; e.g., if only height has changed, then only note the
|
||||
// area into which the float has grown or from which the float has
|
||||
// shrunk.
|
||||
nscoord top = NS_MIN(region.y, oldRegion.y) - borderPadding.top;
|
||||
nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost()) - borderPadding.top;
|
||||
nscoord top = NS_MIN(region.y, oldRegion.y);
|
||||
nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost());
|
||||
mFloatManager->IncludeInDamage(top, bottom);
|
||||
}
|
||||
|
||||
@@ -993,8 +958,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("clear floats: in: aY=%d(%d)\n",
|
||||
aY, aY - BorderPadding().top);
|
||||
printf("clear floats: in: aY=%d\n", aY);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1004,12 +968,10 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
||||
mFloatManager->List(stdout);
|
||||
#endif
|
||||
|
||||
const nsMargin& bp = BorderPadding();
|
||||
nscoord newY = aY;
|
||||
|
||||
if (aBreakType != NS_STYLE_CLEAR_NONE) {
|
||||
newY = bp.top +
|
||||
mFloatManager->ClearFloats(newY - bp.top, aBreakType, aFlags);
|
||||
newY = mFloatManager->ClearFloats(newY, aBreakType, aFlags);
|
||||
}
|
||||
|
||||
if (aReplacedBlock) {
|
||||
@@ -1019,11 +981,10 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
||||
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
|
||||
aReplacedBlock);
|
||||
if (!floatAvailableSpace.mHasFloats ||
|
||||
NS_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) +
|
||||
NS_MAX(floatAvailableSpace.mRect.x - mContentArea.x,
|
||||
replacedWidth.marginLeft) +
|
||||
replacedWidth.borderBoxWidth +
|
||||
NS_MAX(mContentArea.width -
|
||||
NS_MIN(mContentArea.width,
|
||||
floatAvailableSpace.mRect.XMost()),
|
||||
NS_MAX(mContentArea.XMost() - floatAvailableSpace.mRect.XMost(),
|
||||
replacedWidth.marginRight) <=
|
||||
mContentArea.width) {
|
||||
break;
|
||||
@@ -1047,7 +1008,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("clear floats: out: y=%d(%d)\n", newY, newY - bp.top);
|
||||
printf("clear floats: out: y=%d\n", newY);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user