зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
56ca776aa1
Коммит
1b55dad02a
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче