Compute widths for replaced block clearing past floats once we're at the correct vertical position. b=430813 r+sr=roc a=schrep

This commit is contained in:
dbaron@dbaron.org 2008-05-03 16:33:36 -07:00
Родитель 56ca776aa1
Коммит 1b55dad02a
7 изменённых файлов: 70 добавлений и 35 удалений

Просмотреть файл

@ -1770,20 +1770,17 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
line->MarkDirty();
}
ReplacedElementWidthToClear replacedWidthStruct;
ReplacedElementWidthToClear *replacedWidth = nsnull;
nsIFrame *replacedBlock = nsnull;
if (line->IsBlock() &&
!nsBlockFrame::BlockCanIntersectFloats(line->mFirstChild)) {
replacedWidthStruct =
nsBlockFrame::WidthToClearPastFloats(aState, line->mFirstChild);
replacedWidth = &replacedWidthStruct;
replacedBlock = line->mFirstChild;
}
// We have to reflow the line if it's a block whose clearance
// might have changed, so detect that.
if (!line->IsDirty() &&
(line->GetBreakTypeBefore() != NS_STYLE_CLEAR_NONE ||
replacedWidth)) {
replacedBlock)) {
nscoord curY = aState.mY;
// See where we would be after applying any clearance due to
// BRs.
@ -1792,7 +1789,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
}
nscoord newY =
aState.ClearFloats(curY, line->GetBreakTypeBefore(), replacedWidth);
aState.ClearFloats(curY, line->GetBreakTypeBefore(), replacedBlock);
if (line->HasClearance()) {
// Reflow the line if it might not have clearance anymore.
@ -2796,12 +2793,10 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool treatWithClearance = aLine->HasClearance();
PRBool mightClearFloats = breakType != NS_STYLE_CLEAR_NONE;
ReplacedElementWidthToClear replacedWidthStruct;
ReplacedElementWidthToClear *replacedWidth = nsnull;
nsIFrame *replacedBlock = nsnull;
if (!nsBlockFrame::BlockCanIntersectFloats(frame)) {
mightClearFloats = PR_TRUE;
replacedWidthStruct = nsBlockFrame::WidthToClearPastFloats(aState, frame);
replacedWidth = &replacedWidthStruct;
replacedBlock = frame;
}
// If our top margin was counted as part of some parents top-margin
@ -2811,7 +2806,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
if (!treatWithClearance && !applyTopMargin && mightClearFloats &&
aState.mReflowState.mDiscoveredClearance) {
nscoord curY = aState.mY + aState.mPrevBottomMargin.get();
nscoord clearY = aState.ClearFloats(curY, breakType, replacedWidth);
nscoord clearY = aState.ClearFloats(curY, breakType, replacedBlock);
if (clearY != curY) {
// Looks like that assumption was invalid, we do need
// clearance. Tell our ancestor so it can reflow again. It is
@ -2890,7 +2885,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// decision is only allowed to be made under the optimistic
// first pass.
nscoord curY = aState.mY + aState.mPrevBottomMargin.get();
nscoord clearY = aState.ClearFloats(curY, breakType, replacedWidth);
nscoord clearY = aState.ClearFloats(curY, breakType, replacedBlock);
if (clearY != curY) {
// Looks like we need clearance and we didn't know about it already. So
// recompute collapsed margin
@ -2918,7 +2913,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
if (treatWithClearance) {
nscoord currentY = aState.mY;
// advance mY to the clear position.
aState.mY = aState.ClearFloats(aState.mY, breakType, replacedWidth);
aState.mY = aState.ClearFloats(aState.mY, breakType, replacedBlock);
// Compute clearance. It's the amount we need to add to the top
// border-edge of the frame, after applying collapsed margins
@ -2949,7 +2944,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool isImpacted = aState.IsImpactedByFloat() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloat(isImpacted);
nsRect availSpace;
aState.ComputeBlockAvailSpace(frame, display, replacedWidth, availSpace);
aState.ComputeBlockAvailSpace(frame, display, replacedBlock != nsnull,
availSpace);
// Now put the Y coordinate back to the top of the top-margin +
// clearance, and flow the block.
@ -6777,7 +6773,6 @@ nsBlockFrame::ReplacedElementWidthToClear
nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
nsIFrame* aFrame)
{
aState.GetAvailableSpace();
nscoord leftOffset, rightOffset;
nsCSSOffsetState offsetState(aFrame, aState.mReflowState.rendContext,
aState.mContentArea.width);

Просмотреть файл

@ -297,7 +297,9 @@ public:
/**
* Returns the width that needs to be cleared past floats for blocks
* that cannot intersect floats.
* that cannot intersect floats. aState must already have
* GetAvailableSpace called on it for the vertical position that we
* care about (which need not be its current mY)
*/
struct ReplacedElementWidthToClear {
nscoord marginLeft, borderBoxWidth, marginRight;

Просмотреть файл

@ -254,9 +254,7 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
void
nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay,
nsBlockFrame::
ReplacedElementWidthToClear
*aReplacedWidth,
PRBool aBlockAvoidsFloats,
nsRect& aResult)
{
#ifdef REALLY_NOISY_REFLOW
@ -285,9 +283,10 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
// nsBlockFrame::WidthToClearPastFloats would need to use the
// shrink-wrap formula, max(MIN_WIDTH, min(avail width, PREF_WIDTH))
// rather than just using MIN_WIDTH.
NS_ASSERTION(nsBlockFrame::BlockCanIntersectFloats(aFrame) == !aReplacedWidth,
NS_ASSERTION(nsBlockFrame::BlockCanIntersectFloats(aFrame) ==
!aBlockAvoidsFloats,
"unexpected replaced width");
if (!aReplacedWidth) {
if (!aBlockAvoidsFloats) {
if (mBand.GetFloatCount()) {
// Use the float-edge property to determine how the child block
// will interact with the float.
@ -355,9 +354,16 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
}
}
else {
nsBlockFrame::ReplacedElementWidthToClear replacedWidthStruct;
nsBlockFrame::ReplacedElementWidthToClear *replacedWidth = nsnull;
if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
replacedWidth = &replacedWidthStruct;
replacedWidthStruct = nsBlockFrame::WidthToClearPastFloats(*this, aFrame);
}
nscoord leftOffset, rightOffset;
ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset,
aReplacedWidth);
replacedWidth);
aResult.x = borderPadding.left + leftOffset;
aResult.width = mContentArea.width - leftOffset - rightOffset;
}
@ -1099,7 +1105,7 @@ nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList, PRB
nscoord
nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
nsBlockFrame::ReplacedElementWidthToClear *aReplacedWidth)
nsIFrame *aReplacedBlock)
{
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
@ -1122,15 +1128,17 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
newY = bp.top + mSpaceManager->ClearFloats(newY - bp.top, aBreakType);
}
if (aReplacedWidth) {
if (aReplacedBlock) {
for (;;) {
GetAvailableSpace(newY, PR_FALSE);
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
nsBlockFrame::WidthToClearPastFloats(*this, aReplacedBlock);
if (mBand.GetFloatCount() == 0 ||
PR_MAX(mAvailSpaceRect.x, aReplacedWidth->marginLeft) +
aReplacedWidth->borderBoxWidth +
PR_MAX(mAvailSpaceRect.x, replacedWidth.marginLeft) +
replacedWidth.borderBoxWidth +
PR_MAX(mContentArea.width -
PR_MIN(mContentArea.width, mAvailSpaceRect.XMost()),
aReplacedWidth->marginRight) <=
replacedWidth.marginRight) <=
mContentArea.width) {
break;
}

Просмотреть файл

@ -108,9 +108,9 @@ public:
// Returns the first coordinate >= aY that clears the
// floats indicated by aBreakType and has enough width between floats
// (or no floats remaining) to accomodate aReplacedWidth.
// (or no floats remaining) to accomodate aReplacedBlock.
nscoord ClearFloats(nscoord aY, PRUint8 aBreakType,
nsBlockFrame::ReplacedElementWidthToClear *aReplacedWidth = nsnull);
nsIFrame *aReplacedBlock = nsnull);
PRBool IsAdjacentWithTop() const {
return mY ==
@ -140,18 +140,19 @@ public:
// Reconstruct the previous bottom margin that goes above |aLine|.
void ReconstructMarginAbove(nsLineList::iterator aLine);
// Caller must have called GetAvailableSpace for the current mY
// Caller must have called GetAvailableSpace for the correct position
// (which need not be the current mY). Callers need only pass
// aReplacedWidth for outer table frames.
void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
nscoord& aLeftResult,
nscoord& aRightResult,
nsBlockFrame::ReplacedElementWidthToClear
*aReplacedWidth = nsnull);
nsBlockFrame::ReplacedElementWidthToClear
*aReplacedWidth = nsnull);
// Caller must have called GetAvailableSpace for the current mY
void ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay,
nsBlockFrame::ReplacedElementWidthToClear
*aReplacedWidth,
PRBool aBlockAvoidsFloats,
nsRect& aResult);
protected:

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Testcase, bug 430813</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div style="margin-bottom: 1px">text</div>
<div style="float:left;width:90px;height:300px"></div>
<div style="margin-left:90px">
This text should be near the top of the page, not pushed below the float.
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Testcase, bug 430813</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div style="margin-bottom: 1px">text</div>
<div style="float:left;width:90px;height:300px"></div>
<div style="overflow:hidden">
This text should be near the top of the page, not pushed below the float.
</div>
</body>
</html>

Просмотреть файл

@ -819,3 +819,4 @@ fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 424074-1-ref2.xul 424074-1-ref3.xul
== 430412-1.html 430412-1-ref.html
== 430813-1.html 430813-1-ref.html
== 430813-2.html 430813-2-ref.html
== 430813-3.html 430813-3-ref.html