From f06e55f8768852ff0cdd72d9bb0dbda58f2baa1f Mon Sep 17 00:00:00 2001 From: "dbaron%fas.harvard.edu" Date: Wed, 12 Jun 2002 03:21:00 +0000 Subject: [PATCH] Fix performance problem on home.netscape.com: Don't do full reflow of all absolutely positioned elements whose containing block is on the path to the target of an incremental reflow. b=146831 sr=waterson r=kin git-svn-id: svn://10.0.0.236/trunk@123125 18797224-902f-48f8-a5cc-f745e15eee43 --- .../generic/nsAbsoluteContainingBlock.cpp | 7 ++++-- mozilla/layout/generic/nsBlockFrame.cpp | 24 +++++++++++++++---- mozilla/layout/generic/nsInlineFrame.cpp | 22 ++++++++++++++--- .../base/src/nsAbsoluteContainingBlock.cpp | 7 ++++-- mozilla/layout/html/base/src/nsBlockFrame.cpp | 24 +++++++++++++++---- .../layout/html/base/src/nsInlineFrame.cpp | 22 ++++++++++++++--- 6 files changed, 88 insertions(+), 18 deletions(-) diff --git a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp index 00073f156c0..720056b27d9 100644 --- a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp @@ -194,8 +194,11 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, // Initialize OUT parameter aChildBounds.SetRect(0, 0, 0, 0); - // Make a copy of the reflow state. If the reason is eReflowReason_Incremental, - // then change it to eReflowReason_Resize + // Make a copy of the reflow state. If the reason is + // eReflowReason_Incremental (which should mean either that the target + // is the frame for which this is the absolute container or that the + // container changed size due to incremental reflow of its children), + // then change it to eReflowReason_Resize. nsHTMLReflowState reflowState(aReflowState); if (eReflowReason_Incremental == reflowState.reason) { reflowState.reason = eReflowReason_Resize; diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index af62f4d6a8f..6a18d06876c 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -729,6 +729,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } #endif + nsRect oldRect(mRect); + // Should we create a space manager? nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState)); @@ -739,8 +741,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, if (NS_BLOCK_SPACE_MGR & mState) autoSpaceManager.CreateSpaceManagerFor(aPresContext, this); - // See if it's an incremental reflow command - if (eReflowReason_Incremental == aReflowState.reason) { + // See if it's an incremental reflow command and we're not the target + if (mAbsoluteContainer.HasAbsoluteFrames() && + eReflowReason_Incremental == aReflowState.reason && + !aReflowState.path->mReflowCommand) { // Give the absolute positioning code a chance to handle it nscoord containingBlockWidth; nscoord containingBlockHeight; @@ -1021,7 +1025,18 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage // based width/height - if (NS_SUCCEEDED(rv) && mAbsoluteContainer.HasAbsoluteFrames()) { + // We want to do this under either of two conditions: + // 1. If we didn't do the incremental reflow above. + // 2. If our size changed. + // Even though it's the padding edge that's the containing block, we + // can use our rect (the border edge) since if the border style + // changed, the reflow would have been targeted at us so we'd satisfy + // condition 1. + if (NS_SUCCEEDED(rv) && + mAbsoluteContainer.HasAbsoluteFrames() && + (eReflowReason_Incremental != aReflowState.reason || + aReflowState.path->mReflowCommand || + mRect != oldRect)) { nscoord containingBlockWidth; nscoord containingBlockHeight; nsRect childBounds; @@ -2168,7 +2183,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) // If we're supposed to update our maximum width, then we'll also need to // reflow this line if it's line wrapped and any of the continuing lines - // are dirty. If we are printing (constrained height), always reflow the line + // are dirty. If we are printing (constrained height), always reflow + // the line. if ((NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight) || (!line->IsDirty() && aState.GetFlag(BRS_COMPUTEMAXWIDTH) && diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index ea49a4fdab9..5fd4ca33b2c 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -45,6 +45,7 @@ #include "nsIFontMetrics.h" #include "nsAbsoluteContainingBlock.h" #include "nsLayoutAtoms.h" +#include "nsReflowPath.h" #ifdef DEBUG #undef NOISY_PUSHING @@ -1204,8 +1205,12 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, { nsresult rv = NS_OK; - // See if it's an incremental reflow command - if (eReflowReason_Incremental == aReflowState.reason) { + nsRect oldRect(mRect); + + // See if it's an incremental reflow command and we're not the target + if (mAbsoluteContainer.HasAbsoluteFrames() && + eReflowReason_Incremental == aReflowState.reason && + !aReflowState.path->mReflowCommand) { // Give the absolute positioning code a chance to handle it PRBool handled; nsRect childBounds; @@ -1252,7 +1257,18 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed - if (NS_SUCCEEDED(rv)) { + // We want to do this under either of two conditions: + // 1. If we didn't do the incremental reflow above. + // 2. If our size changed. + // Even though it's the padding edge that's the containing block, we + // can use our rect (the border edge) since if the border style + // changed, the reflow would have been targeted at us so we'd satisfy + // condition 1. + if (NS_SUCCEEDED(rv) && + mAbsoluteContainer.HasAbsoluteFrames() && + (eReflowReason_Incremental != aReflowState.reason || + aReflowState.path->mReflowCommand || + mRect != oldRect)) { nscoord containingBlockWidth = -1; nscoord containingBlockHeight = -1; nsRect childBounds; diff --git a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp index 00073f156c0..720056b27d9 100644 --- a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -194,8 +194,11 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, // Initialize OUT parameter aChildBounds.SetRect(0, 0, 0, 0); - // Make a copy of the reflow state. If the reason is eReflowReason_Incremental, - // then change it to eReflowReason_Resize + // Make a copy of the reflow state. If the reason is + // eReflowReason_Incremental (which should mean either that the target + // is the frame for which this is the absolute container or that the + // container changed size due to incremental reflow of its children), + // then change it to eReflowReason_Resize. nsHTMLReflowState reflowState(aReflowState); if (eReflowReason_Incremental == reflowState.reason) { reflowState.reason = eReflowReason_Resize; diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index af62f4d6a8f..6a18d06876c 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -729,6 +729,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } #endif + nsRect oldRect(mRect); + // Should we create a space manager? nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState)); @@ -739,8 +741,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, if (NS_BLOCK_SPACE_MGR & mState) autoSpaceManager.CreateSpaceManagerFor(aPresContext, this); - // See if it's an incremental reflow command - if (eReflowReason_Incremental == aReflowState.reason) { + // See if it's an incremental reflow command and we're not the target + if (mAbsoluteContainer.HasAbsoluteFrames() && + eReflowReason_Incremental == aReflowState.reason && + !aReflowState.path->mReflowCommand) { // Give the absolute positioning code a chance to handle it nscoord containingBlockWidth; nscoord containingBlockHeight; @@ -1021,7 +1025,18 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage // based width/height - if (NS_SUCCEEDED(rv) && mAbsoluteContainer.HasAbsoluteFrames()) { + // We want to do this under either of two conditions: + // 1. If we didn't do the incremental reflow above. + // 2. If our size changed. + // Even though it's the padding edge that's the containing block, we + // can use our rect (the border edge) since if the border style + // changed, the reflow would have been targeted at us so we'd satisfy + // condition 1. + if (NS_SUCCEEDED(rv) && + mAbsoluteContainer.HasAbsoluteFrames() && + (eReflowReason_Incremental != aReflowState.reason || + aReflowState.path->mReflowCommand || + mRect != oldRect)) { nscoord containingBlockWidth; nscoord containingBlockHeight; nsRect childBounds; @@ -2168,7 +2183,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) // If we're supposed to update our maximum width, then we'll also need to // reflow this line if it's line wrapped and any of the continuing lines - // are dirty. If we are printing (constrained height), always reflow the line + // are dirty. If we are printing (constrained height), always reflow + // the line. if ((NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight) || (!line->IsDirty() && aState.GetFlag(BRS_COMPUTEMAXWIDTH) && diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp index ea49a4fdab9..5fd4ca33b2c 100644 --- a/mozilla/layout/html/base/src/nsInlineFrame.cpp +++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp @@ -45,6 +45,7 @@ #include "nsIFontMetrics.h" #include "nsAbsoluteContainingBlock.h" #include "nsLayoutAtoms.h" +#include "nsReflowPath.h" #ifdef DEBUG #undef NOISY_PUSHING @@ -1204,8 +1205,12 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, { nsresult rv = NS_OK; - // See if it's an incremental reflow command - if (eReflowReason_Incremental == aReflowState.reason) { + nsRect oldRect(mRect); + + // See if it's an incremental reflow command and we're not the target + if (mAbsoluteContainer.HasAbsoluteFrames() && + eReflowReason_Incremental == aReflowState.reason && + !aReflowState.path->mReflowCommand) { // Give the absolute positioning code a chance to handle it PRBool handled; nsRect childBounds; @@ -1252,7 +1257,18 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext, // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed - if (NS_SUCCEEDED(rv)) { + // We want to do this under either of two conditions: + // 1. If we didn't do the incremental reflow above. + // 2. If our size changed. + // Even though it's the padding edge that's the containing block, we + // can use our rect (the border edge) since if the border style + // changed, the reflow would have been targeted at us so we'd satisfy + // condition 1. + if (NS_SUCCEEDED(rv) && + mAbsoluteContainer.HasAbsoluteFrames() && + (eReflowReason_Incremental != aReflowState.reason || + aReflowState.path->mReflowCommand || + mRect != oldRect)) { nscoord containingBlockWidth = -1; nscoord containingBlockHeight = -1; nsRect childBounds;