diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 0c11c81f6ac8..b7a43813a587 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -2828,48 +2828,28 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } if (aLine->IsBlock()) { - nsRect r; - kid->GetRect(r); if (aDY) { - r.y += aDY; - kid->SetRect(aState.mPresContext, r); + nsPoint p; + kid->GetOrigin(p); + p.y += aDY; + kid->MoveTo(aState.mPresContext, p.x, p.y); } // Make sure the frame's view and any child views are updated ::PlaceFrameView(aState.mPresContext, kid); - - // If the child has any floaters that impact the space-manager, - // place them now so that they are present in the space-manager - // again (they were removed by the space-manager's frame when - // the reflow began). - nsBlockFrame* bf; - nsresult rv = kid->QueryInterface(kBlockFrameCID, (void**) &bf); - if (NS_SUCCEEDED(rv)) { - // Translate spacemanager to the child blocks upper-left corner - // so that when it places its floaters (which are relative to - // it) the right coordinates are used. Note that we have already - // been translated by our border+padding so factor that in to - // get the right translation. - const nsMargin& bp = aState.BorderPadding(); - nscoord dx = r.x - bp.left; - nscoord dy = r.y - bp.top; - aState.mSpaceManager->Translate(dx, dy); - bf->UpdateSpaceManager(aState.mPresContext, aState.mSpaceManager); - aState.mSpaceManager->Translate(-dx, -dy); - } } else { // Adjust the Y coordinate of the frames in the line. // Note: we need to re-position views even if aDY is 0, because // one of our parent frames may have moved and so the view's position // relative to its parent may have changed - nsRect r; PRInt32 n = aLine->GetChildCount(); while (--n >= 0) { if (aDY) { - kid->GetRect(r); - r.y += aDY; - kid->SetRect(aState.mPresContext, r); + nsPoint p; + kid->GetOrigin(p); + p.y += aDY; + kid->MoveTo(aState.mPresContext, p.x, p.y); } // Make sure the frame's view and any child views are updated ::PlaceFrameView(aState.mPresContext, kid); @@ -2878,58 +2858,6 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } -nsresult -nsBlockFrame::UpdateSpaceManager(nsIPresContext* aPresContext, - nsSpaceManager* aSpaceManager) -{ - for (line_iterator line = begin_lines(), line_end = end_lines(); - line != line_end; - ++line) { - // Place the floaters in the spacemanager - if (line->HasFloaters()) { - nsFloaterCache* fc = line->GetFirstFloater(); - while (fc) { - nsIFrame* floater = fc->mPlaceholder->GetOutOfFlowFrame(); - aSpaceManager->AddRectRegion(floater, fc->mRegion); -#ifdef NOISY_SPACEMANAGER - nscoord tx, ty; - aSpaceManager->GetTranslation(tx, ty); - nsFrame::ListTag(stdout, this); - printf(": UpdateSpaceManager: AddRectRegion: txy=%d,%d {%d,%d,%d,%d}\n", - tx, ty, - fc->mRegion.x, fc->mRegion.y, - fc->mRegion.width, fc->mRegion.height); -#endif - fc = fc->Next(); - } - } - - // Tell kids about the move too - if (line->mFirstChild && line->IsBlock()) { - // If the child has any floaters that impact the space-manager, - // place them now so that they are present in the space-manager - // again (they were removed by the space-manager's frame when - // the reflow began). - nsBlockFrame* bf; - nsresult rv = line->mFirstChild->QueryInterface(kBlockFrameCID, - NS_REINTERPRET_CAST(void**, &bf)); - if (NS_SUCCEEDED(rv)) { - nsPoint origin; - bf->GetOrigin(origin); - - // Translate spacemanager to the child blocks upper-left - // corner so that when it places its floaters (which are - // relative to it) the right coordinates are used. - aSpaceManager->Translate(origin.x, origin.y); - bf->UpdateSpaceManager(aPresContext, aSpaceManager); - aSpaceManager->Translate(-origin.x, -origin.y); - } - } - } - - return NS_OK; -} - NS_IMETHODIMP nsBlockFrame::AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index d4d98fddd169..67fa31dd6369 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -188,12 +188,6 @@ public: */ nsIFrame* GetTopBlockChild(); - /** Place the floaters in the spacemanager for all lines in this block. - * recursively adds floaters in child blocks of this frame. - */ - nsresult UpdateSpaceManager(nsIPresContext* aPresContext, - nsSpaceManager* aSpaceManager); - // returns true on success and false if aFoundLine is set to end_lines() PRBool FindLineFor(nsIFrame* aFrame, PRBool* aIsFloaterResult, diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index da944f5f882f..174fbb4608c9 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -474,6 +474,14 @@ nsBlockReflowState::ReconstructMarginAbove(nsLineList::iterator aLine) } } +/** + * Restore information about floaters into the space manager for an + * incremental reflow, and simultaneously push the floaters by + * |aDeltaY|, which is the amount |aLine| was pushed relative to its + * parent. The recovery of state is one of the things that makes + * incremental reflow O(N^2) and this state should really be kept + * around, attached to the frame tree. + */ void nsBlockReflowState::RecoverFloaters(nsLineList::iterator aLine, nscoord aDeltaY) @@ -481,25 +489,26 @@ nsBlockReflowState::RecoverFloaters(nsLineList::iterator aLine, if (aLine->HasFloaters()) { // Place the floaters into the space-manager again. Also slide // them, just like the regular frames on the line. - nsRect r; nsFloaterCache* fc = aLine->GetFirstFloater(); while (fc) { - fc->mRegion.y += aDeltaY; - fc->mCombinedArea.y += aDeltaY; nsIFrame* floater = fc->mPlaceholder->GetOutOfFlowFrame(); - floater->GetRect(r); - floater->MoveTo(mPresContext, r.x, r.y + aDeltaY); + if (aDeltaY != 0) { + fc->mRegion.y += aDeltaY; + fc->mCombinedArea.y += aDeltaY; + nsPoint p; + floater->GetOrigin(p); + floater->MoveTo(mPresContext, p.x, p.y + aDeltaY); + } #ifdef DEBUG if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisySpaceManager) { nscoord tx, ty; mSpaceManager->GetTranslation(tx, ty); nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); - printf("RecoverState: txy=%d,%d (%d,%d) ", + printf("RecoverFloaters: txy=%d,%d (%d,%d) ", tx, ty, mSpaceManagerX, mSpaceManagerY); nsFrame::ListTag(stdout, floater); - printf(" r.y=%d aDeltaY=%d (sum=%d) region={%d,%d,%d,%d}\n", - r.y, aDeltaY, r.y + aDeltaY, - fc->mRegion.x, fc->mRegion.y, + printf(" aDeltaY=%d region={%d,%d,%d,%d}\n", + aDeltaY, fc->mRegion.x, fc->mRegion.y, fc->mRegion.width, fc->mRegion.height); } #endif @@ -511,15 +520,17 @@ nsBlockReflowState::RecoverFloaters(nsLineList::iterator aLine, nsBlockFrame *kid = nsnull; aLine->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&kid); if (kid) { - nsRect kidRect; - kid->GetRect(kidRect); - mSpaceManager->Translate(kidRect.x, kidRect.y); + nscoord kidx = kid->mRect.x, kidy = kid->mRect.y; + mSpaceManager->Translate(kidx, kidy); for (nsBlockFrame::line_iterator line = kid->begin_lines(), line_end = kid->end_lines(); line != line_end; ++line) - RecoverFloaters(line, aDeltaY); - mSpaceManager->Translate(-kidRect.x, -kidRect.y); + // Pass 0, not the real DeltaY, since these floaters aren't + // moving relative to their parent block, only relative to + // the space manager. + RecoverFloaters(line, 0); + mSpaceManager->Translate(-kidx, -kidy); } } } diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index 0c11c81f6ac8..b7a43813a587 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -2828,48 +2828,28 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } if (aLine->IsBlock()) { - nsRect r; - kid->GetRect(r); if (aDY) { - r.y += aDY; - kid->SetRect(aState.mPresContext, r); + nsPoint p; + kid->GetOrigin(p); + p.y += aDY; + kid->MoveTo(aState.mPresContext, p.x, p.y); } // Make sure the frame's view and any child views are updated ::PlaceFrameView(aState.mPresContext, kid); - - // If the child has any floaters that impact the space-manager, - // place them now so that they are present in the space-manager - // again (they were removed by the space-manager's frame when - // the reflow began). - nsBlockFrame* bf; - nsresult rv = kid->QueryInterface(kBlockFrameCID, (void**) &bf); - if (NS_SUCCEEDED(rv)) { - // Translate spacemanager to the child blocks upper-left corner - // so that when it places its floaters (which are relative to - // it) the right coordinates are used. Note that we have already - // been translated by our border+padding so factor that in to - // get the right translation. - const nsMargin& bp = aState.BorderPadding(); - nscoord dx = r.x - bp.left; - nscoord dy = r.y - bp.top; - aState.mSpaceManager->Translate(dx, dy); - bf->UpdateSpaceManager(aState.mPresContext, aState.mSpaceManager); - aState.mSpaceManager->Translate(-dx, -dy); - } } else { // Adjust the Y coordinate of the frames in the line. // Note: we need to re-position views even if aDY is 0, because // one of our parent frames may have moved and so the view's position // relative to its parent may have changed - nsRect r; PRInt32 n = aLine->GetChildCount(); while (--n >= 0) { if (aDY) { - kid->GetRect(r); - r.y += aDY; - kid->SetRect(aState.mPresContext, r); + nsPoint p; + kid->GetOrigin(p); + p.y += aDY; + kid->MoveTo(aState.mPresContext, p.x, p.y); } // Make sure the frame's view and any child views are updated ::PlaceFrameView(aState.mPresContext, kid); @@ -2878,58 +2858,6 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } } -nsresult -nsBlockFrame::UpdateSpaceManager(nsIPresContext* aPresContext, - nsSpaceManager* aSpaceManager) -{ - for (line_iterator line = begin_lines(), line_end = end_lines(); - line != line_end; - ++line) { - // Place the floaters in the spacemanager - if (line->HasFloaters()) { - nsFloaterCache* fc = line->GetFirstFloater(); - while (fc) { - nsIFrame* floater = fc->mPlaceholder->GetOutOfFlowFrame(); - aSpaceManager->AddRectRegion(floater, fc->mRegion); -#ifdef NOISY_SPACEMANAGER - nscoord tx, ty; - aSpaceManager->GetTranslation(tx, ty); - nsFrame::ListTag(stdout, this); - printf(": UpdateSpaceManager: AddRectRegion: txy=%d,%d {%d,%d,%d,%d}\n", - tx, ty, - fc->mRegion.x, fc->mRegion.y, - fc->mRegion.width, fc->mRegion.height); -#endif - fc = fc->Next(); - } - } - - // Tell kids about the move too - if (line->mFirstChild && line->IsBlock()) { - // If the child has any floaters that impact the space-manager, - // place them now so that they are present in the space-manager - // again (they were removed by the space-manager's frame when - // the reflow began). - nsBlockFrame* bf; - nsresult rv = line->mFirstChild->QueryInterface(kBlockFrameCID, - NS_REINTERPRET_CAST(void**, &bf)); - if (NS_SUCCEEDED(rv)) { - nsPoint origin; - bf->GetOrigin(origin); - - // Translate spacemanager to the child blocks upper-left - // corner so that when it places its floaters (which are - // relative to it) the right coordinates are used. - aSpaceManager->Translate(origin.x, origin.y); - bf->UpdateSpaceManager(aPresContext, aSpaceManager); - aSpaceManager->Translate(-origin.x, -origin.y); - } - } - } - - return NS_OK; -} - NS_IMETHODIMP nsBlockFrame::AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, diff --git a/layout/html/base/src/nsBlockFrame.h b/layout/html/base/src/nsBlockFrame.h index d4d98fddd169..67fa31dd6369 100644 --- a/layout/html/base/src/nsBlockFrame.h +++ b/layout/html/base/src/nsBlockFrame.h @@ -188,12 +188,6 @@ public: */ nsIFrame* GetTopBlockChild(); - /** Place the floaters in the spacemanager for all lines in this block. - * recursively adds floaters in child blocks of this frame. - */ - nsresult UpdateSpaceManager(nsIPresContext* aPresContext, - nsSpaceManager* aSpaceManager); - // returns true on success and false if aFoundLine is set to end_lines() PRBool FindLineFor(nsIFrame* aFrame, PRBool* aIsFloaterResult, diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index da944f5f882f..174fbb4608c9 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -474,6 +474,14 @@ nsBlockReflowState::ReconstructMarginAbove(nsLineList::iterator aLine) } } +/** + * Restore information about floaters into the space manager for an + * incremental reflow, and simultaneously push the floaters by + * |aDeltaY|, which is the amount |aLine| was pushed relative to its + * parent. The recovery of state is one of the things that makes + * incremental reflow O(N^2) and this state should really be kept + * around, attached to the frame tree. + */ void nsBlockReflowState::RecoverFloaters(nsLineList::iterator aLine, nscoord aDeltaY) @@ -481,25 +489,26 @@ nsBlockReflowState::RecoverFloaters(nsLineList::iterator aLine, if (aLine->HasFloaters()) { // Place the floaters into the space-manager again. Also slide // them, just like the regular frames on the line. - nsRect r; nsFloaterCache* fc = aLine->GetFirstFloater(); while (fc) { - fc->mRegion.y += aDeltaY; - fc->mCombinedArea.y += aDeltaY; nsIFrame* floater = fc->mPlaceholder->GetOutOfFlowFrame(); - floater->GetRect(r); - floater->MoveTo(mPresContext, r.x, r.y + aDeltaY); + if (aDeltaY != 0) { + fc->mRegion.y += aDeltaY; + fc->mCombinedArea.y += aDeltaY; + nsPoint p; + floater->GetOrigin(p); + floater->MoveTo(mPresContext, p.x, p.y + aDeltaY); + } #ifdef DEBUG if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisySpaceManager) { nscoord tx, ty; mSpaceManager->GetTranslation(tx, ty); nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); - printf("RecoverState: txy=%d,%d (%d,%d) ", + printf("RecoverFloaters: txy=%d,%d (%d,%d) ", tx, ty, mSpaceManagerX, mSpaceManagerY); nsFrame::ListTag(stdout, floater); - printf(" r.y=%d aDeltaY=%d (sum=%d) region={%d,%d,%d,%d}\n", - r.y, aDeltaY, r.y + aDeltaY, - fc->mRegion.x, fc->mRegion.y, + printf(" aDeltaY=%d region={%d,%d,%d,%d}\n", + aDeltaY, fc->mRegion.x, fc->mRegion.y, fc->mRegion.width, fc->mRegion.height); } #endif @@ -511,15 +520,17 @@ nsBlockReflowState::RecoverFloaters(nsLineList::iterator aLine, nsBlockFrame *kid = nsnull; aLine->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&kid); if (kid) { - nsRect kidRect; - kid->GetRect(kidRect); - mSpaceManager->Translate(kidRect.x, kidRect.y); + nscoord kidx = kid->mRect.x, kidy = kid->mRect.y; + mSpaceManager->Translate(kidx, kidy); for (nsBlockFrame::line_iterator line = kid->begin_lines(), line_end = kid->end_lines(); line != line_end; ++line) - RecoverFloaters(line, aDeltaY); - mSpaceManager->Translate(-kidRect.x, -kidRect.y); + // Pass 0, not the real DeltaY, since these floaters aren't + // moving relative to their parent block, only relative to + // the space manager. + RecoverFloaters(line, 0); + mSpaceManager->Translate(-kidx, -kidy); } } }