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

This commit is contained in:
dbaron@fas.harvard.edu
2002-06-12 03:21:00 +00:00
parent 61a2eed3cd
commit f87e9ee15f
6 changed files with 88 additions and 18 deletions

View File

@@ -194,8 +194,11 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
// Initialize OUT parameter // Initialize OUT parameter
aChildBounds.SetRect(0, 0, 0, 0); aChildBounds.SetRect(0, 0, 0, 0);
// Make a copy of the reflow state. If the reason is eReflowReason_Incremental, // Make a copy of the reflow state. If the reason is
// then change it to eReflowReason_Resize // 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); nsHTMLReflowState reflowState(aReflowState);
if (eReflowReason_Incremental == reflowState.reason) { if (eReflowReason_Incremental == reflowState.reason) {
reflowState.reason = eReflowReason_Resize; reflowState.reason = eReflowReason_Resize;

View File

@@ -729,6 +729,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
} }
#endif #endif
nsRect oldRect(mRect);
// Should we create a space manager? // Should we create a space manager?
nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState)); nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState));
@@ -739,8 +741,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (NS_BLOCK_SPACE_MGR & mState) if (NS_BLOCK_SPACE_MGR & mState)
autoSpaceManager.CreateSpaceManagerFor(aPresContext, this); autoSpaceManager.CreateSpaceManagerFor(aPresContext, this);
// See if it's an incremental reflow command // See if it's an incremental reflow command and we're not the target
if (eReflowReason_Incremental == aReflowState.reason) { if (mAbsoluteContainer.HasAbsoluteFrames() &&
eReflowReason_Incremental == aReflowState.reason &&
!aReflowState.path->mReflowCommand) {
// Give the absolute positioning code a chance to handle it // Give the absolute positioning code a chance to handle it
nscoord containingBlockWidth; nscoord containingBlockWidth;
nscoord containingBlockHeight; nscoord containingBlockHeight;
@@ -1021,7 +1025,18 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Let the absolutely positioned container reflow any absolutely positioned // Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed, e.g., elements with a percentage // child frames that need to be reflowed, e.g., elements with a percentage
// based width/height // 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 containingBlockWidth;
nscoord containingBlockHeight; nscoord containingBlockHeight;
nsRect childBounds; 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 // 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 // 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) || if ((NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight) ||
(!line->IsDirty() && (!line->IsDirty() &&
aState.GetFlag(BRS_COMPUTEMAXWIDTH) && aState.GetFlag(BRS_COMPUTEMAXWIDTH) &&

View File

@@ -45,6 +45,7 @@
#include "nsIFontMetrics.h" #include "nsIFontMetrics.h"
#include "nsAbsoluteContainingBlock.h" #include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h" #include "nsLayoutAtoms.h"
#include "nsReflowPath.h"
#ifdef DEBUG #ifdef DEBUG
#undef NOISY_PUSHING #undef NOISY_PUSHING
@@ -1204,8 +1205,12 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
// See if it's an incremental reflow command nsRect oldRect(mRect);
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 // Give the absolute positioning code a chance to handle it
PRBool handled; PRBool handled;
nsRect childBounds; nsRect childBounds;
@@ -1252,7 +1257,18 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
// Let the absolutely positioned container reflow any absolutely positioned // Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed // 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 containingBlockWidth = -1;
nscoord containingBlockHeight = -1; nscoord containingBlockHeight = -1;
nsRect childBounds; nsRect childBounds;

View File

@@ -194,8 +194,11 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
// Initialize OUT parameter // Initialize OUT parameter
aChildBounds.SetRect(0, 0, 0, 0); aChildBounds.SetRect(0, 0, 0, 0);
// Make a copy of the reflow state. If the reason is eReflowReason_Incremental, // Make a copy of the reflow state. If the reason is
// then change it to eReflowReason_Resize // 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); nsHTMLReflowState reflowState(aReflowState);
if (eReflowReason_Incremental == reflowState.reason) { if (eReflowReason_Incremental == reflowState.reason) {
reflowState.reason = eReflowReason_Resize; reflowState.reason = eReflowReason_Resize;

View File

@@ -729,6 +729,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
} }
#endif #endif
nsRect oldRect(mRect);
// Should we create a space manager? // Should we create a space manager?
nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState)); nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState));
@@ -739,8 +741,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (NS_BLOCK_SPACE_MGR & mState) if (NS_BLOCK_SPACE_MGR & mState)
autoSpaceManager.CreateSpaceManagerFor(aPresContext, this); autoSpaceManager.CreateSpaceManagerFor(aPresContext, this);
// See if it's an incremental reflow command // See if it's an incremental reflow command and we're not the target
if (eReflowReason_Incremental == aReflowState.reason) { if (mAbsoluteContainer.HasAbsoluteFrames() &&
eReflowReason_Incremental == aReflowState.reason &&
!aReflowState.path->mReflowCommand) {
// Give the absolute positioning code a chance to handle it // Give the absolute positioning code a chance to handle it
nscoord containingBlockWidth; nscoord containingBlockWidth;
nscoord containingBlockHeight; nscoord containingBlockHeight;
@@ -1021,7 +1025,18 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Let the absolutely positioned container reflow any absolutely positioned // Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed, e.g., elements with a percentage // child frames that need to be reflowed, e.g., elements with a percentage
// based width/height // 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 containingBlockWidth;
nscoord containingBlockHeight; nscoord containingBlockHeight;
nsRect childBounds; 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 // 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 // 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) || if ((NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight) ||
(!line->IsDirty() && (!line->IsDirty() &&
aState.GetFlag(BRS_COMPUTEMAXWIDTH) && aState.GetFlag(BRS_COMPUTEMAXWIDTH) &&

View File

@@ -45,6 +45,7 @@
#include "nsIFontMetrics.h" #include "nsIFontMetrics.h"
#include "nsAbsoluteContainingBlock.h" #include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h" #include "nsLayoutAtoms.h"
#include "nsReflowPath.h"
#ifdef DEBUG #ifdef DEBUG
#undef NOISY_PUSHING #undef NOISY_PUSHING
@@ -1204,8 +1205,12 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
// See if it's an incremental reflow command nsRect oldRect(mRect);
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 // Give the absolute positioning code a chance to handle it
PRBool handled; PRBool handled;
nsRect childBounds; nsRect childBounds;
@@ -1252,7 +1257,18 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
// Let the absolutely positioned container reflow any absolutely positioned // Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed // 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 containingBlockWidth = -1;
nscoord containingBlockHeight = -1; nscoord containingBlockHeight = -1;
nsRect childBounds; nsRect childBounds;