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:
fantasai
2010-08-11 12:32:53 -07:00
parent 4b7700da27
commit 3e2b1c5256
7 changed files with 78 additions and 145 deletions

View File

@@ -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