bug 29595 (and others)

fixes layout of pages where a single line is impacted by 2 or more floaters
r=troy


git-svn-id: svn://10.0.0.236/trunk@63783 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
buster%netscape.com
2000-03-22 23:19:10 +00:00
parent c285c2a054
commit bf63049426
26 changed files with 972 additions and 198 deletions

View File

@@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);