From d214c656a82edf69f7fd08652ca3205b90c99ec7 Mon Sep 17 00:00:00 2001 From: "jkeiser%netscape.com" Date: Thu, 22 May 2003 20:56:35 +0000 Subject: [PATCH] Fix crash printing fixed-position float elements (bug 200347), r=kin@netscape.com, sr=dbaron@dbaron.org, a=asa git-svn-id: svn://10.0.0.236/trunk@142762 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/src/nsSpaceManager.cpp | 52 ++++++++++ mozilla/layout/base/src/nsSpaceManager.h | 46 +++++++++ mozilla/layout/forms/nsFieldSetFrame.cpp | 13 ++- mozilla/layout/generic/nsBlockFrame.cpp | 94 ------------------- mozilla/layout/generic/nsSpaceManager.cpp | 52 ++++++++++ mozilla/layout/generic/nsSpaceManager.h | 46 +++++++++ mozilla/layout/html/base/src/nsBlockFrame.cpp | 94 ------------------- .../layout/html/forms/src/nsFieldSetFrame.cpp | 13 ++- 8 files changed, 220 insertions(+), 190 deletions(-) diff --git a/mozilla/layout/base/src/nsSpaceManager.cpp b/mozilla/layout/base/src/nsSpaceManager.cpp index 30230e2b35e..65fba6dcd8e 100644 --- a/mozilla/layout/base/src/nsSpaceManager.cpp +++ b/mozilla/layout/base/src/nsSpaceManager.cpp @@ -45,6 +45,7 @@ #include "nsString.h" #include "nsIPresShell.h" #include "nsMemory.h" +#include "nsHTMLReflowState.h" #ifdef DEBUG #include "nsIFrameDebug.h" #endif @@ -1377,3 +1378,54 @@ nsSpaceManager::BandRect::Length() const return len; } + + +//---------------------------------------------------------------------- + +nsAutoSpaceManager::~nsAutoSpaceManager() +{ + // Restore the old space manager in the reflow state if necessary. + if (mNew) { +#ifdef NOISY_SPACEMANAGER + printf("restoring old space manager %p\n", mOld); +#endif + + mReflowState.mSpaceManager = mOld; + +#ifdef NOISY_SPACEMANAGER + if (mOld) { + NS_STATIC_CAST(nsFrame *, mReflowState.frame)->ListTag(stdout); + printf(": space-manager %p after reflow\n", mOld); + mOld->List(stdout); + } +#endif + +#ifdef DEBUG + if (mOwns) +#endif + delete mNew; + } +} + +nsresult +nsAutoSpaceManager::CreateSpaceManagerFor(nsIPresContext *aPresContext, nsIFrame *aFrame) +{ + // Create a new space manager and install it in the reflow + // state. `Remember' the old space manager so we can restore it + // later. + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mNew = new nsSpaceManager(shell, aFrame); + if (! mNew) + return NS_ERROR_OUT_OF_MEMORY; + +#ifdef NOISY_SPACEMANAGER + printf("constructed new space manager %p (replacing %p)\n", + mNew, mReflowState.mSpaceManager); +#endif + + // Set the space manager in the existing reflow state + mOld = mReflowState.mSpaceManager; + mReflowState.mSpaceManager = mNew; + return NS_OK; +} diff --git a/mozilla/layout/base/src/nsSpaceManager.h b/mozilla/layout/base/src/nsSpaceManager.h index 922b46faa73..65b757d9dd1 100644 --- a/mozilla/layout/base/src/nsSpaceManager.h +++ b/mozilla/layout/base/src/nsSpaceManager.h @@ -48,6 +48,8 @@ class nsIPresShell; class nsIFrame; class nsVoidArray; struct nsSize; +struct nsHTMLReflowState; +class nsIPresContext; #define NS_SPACE_MANAGER_CACHE_SIZE 4 @@ -438,5 +440,49 @@ private: void operator=(const nsSpaceManager&); // no implementation }; +/** + * A helper class to manage maintenance of the space manager during + * nsBlockFrame::Reflow. It automatically restores the old space + * manager in the reflow state when the object goes out of scope. + */ +class nsAutoSpaceManager { +public: + nsAutoSpaceManager(nsHTMLReflowState& aReflowState) + : mReflowState(aReflowState), +#ifdef DEBUG + mOwns(PR_TRUE), +#endif + mNew(nsnull), + mOld(nsnull) {} + + ~nsAutoSpaceManager(); + + /** + * Create a new space manager for the specified frame. This will + * `remember' the old space manager, and install the new space + * manager in the reflow state. + */ + nsresult + CreateSpaceManagerFor(nsIPresContext *aPresContext, + nsIFrame *aFrame); + +#ifdef DEBUG + /** + * `Orphan' any space manager that the nsAutoSpaceManager created; + * i.e., make it so that we don't destroy the space manager when we + * go out of scope. + */ + void DebugOrphanSpaceManager() { mOwns = PR_FALSE; } +#endif + +protected: + nsHTMLReflowState &mReflowState; +#ifdef DEBUG + PRBool mOwns; +#endif + nsSpaceManager *mNew; + nsSpaceManager *mOld; +}; + #endif /* nsSpaceManager_h___ */ diff --git a/mozilla/layout/forms/nsFieldSetFrame.cpp b/mozilla/layout/forms/nsFieldSetFrame.cpp index 4a74fbd310f..8bdff25d534 100644 --- a/mozilla/layout/forms/nsFieldSetFrame.cpp +++ b/mozilla/layout/forms/nsFieldSetFrame.cpp @@ -61,6 +61,7 @@ #include "nsIAccessibilityService.h" #endif #include "nsIServiceManager.h" +#include "nsSpaceManager.h" class nsLegendFrame; @@ -302,7 +303,17 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); // Initialize OUT parameter - aStatus = NS_FRAME_COMPLETE; + aStatus = NS_FRAME_COMPLETE; + + // Should we create a space manager? + nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState)); + + // XXXldb If we start storing the space manager in the frame rather + // than keeping it around only during reflow then we should create it + // only when there are actually floats to manage. Otherwise things + // like tables will gain significant bloat. + if (NS_BLOCK_SPACE_MGR & mState) + autoSpaceManager.CreateSpaceManagerFor(aPresContext, this); if (aDesiredSize.mComputeMEW) { aDesiredSize.mMaxElementWidth = 0; diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 36b7d8b3ad2..a25379b2a86 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -253,100 +253,6 @@ RecordReflowStatus(PRBool aChildIsBlock, nsReflowStatus aFrameReflowStatus) //---------------------------------------------------------------------- -/** - * A helper class to manage maintenance of the space manager during - * nsBlockFrame::Reflow. It automatically restores the old space - * manager in the reflow state when the object goes out of scope. - */ -class nsAutoSpaceManager { -public: - nsAutoSpaceManager(nsHTMLReflowState& aReflowState) - : mReflowState(aReflowState), -#ifdef DEBUG - mOwns(PR_TRUE), -#endif - mNew(nsnull), - mOld(nsnull) {} - - ~nsAutoSpaceManager(); - - /** - * Create a new space manager for the specified frame. This will - * `remember' the old space manager, and install the new space - * manager in the reflow state. - */ - nsresult - CreateSpaceManagerFor(nsIPresContext *aPresContext, - nsIFrame *aFrame); - -#ifdef DEBUG - /** - * `Orphan' any space manager that the nsAutoSpaceManager created; - * i.e., make it so that we don't destroy the space manager when we - * go out of scope. - */ - void DebugOrphanSpaceManager() { mOwns = PR_FALSE; } -#endif - -protected: - nsHTMLReflowState &mReflowState; -#ifdef DEBUG - PRBool mOwns; -#endif - nsSpaceManager *mNew; - nsSpaceManager *mOld; -}; - -nsAutoSpaceManager::~nsAutoSpaceManager() -{ - // Restore the old space manager in the reflow state if necessary. - if (mNew) { -#ifdef NOISY_SPACEMANAGER - printf("restoring old space manager %p\n", mOld); -#endif - - mReflowState.mSpaceManager = mOld; - -#ifdef NOISY_SPACEMANAGER - if (mOld) { - NS_STATIC_CAST(nsFrame *, mReflowState.frame)->ListTag(stdout); - printf(": space-manager %p after reflow\n", mOld); - mOld->List(stdout); - } -#endif - -#ifdef DEBUG - if (mOwns) -#endif - delete mNew; - } -} - -nsresult -nsAutoSpaceManager::CreateSpaceManagerFor(nsIPresContext *aPresContext, nsIFrame *aFrame) -{ - // Create a new space manager and install it in the reflow - // state. `Remember' the old space manager so we can restore it - // later. - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - mNew = new nsSpaceManager(shell, aFrame); - if (! mNew) - return NS_ERROR_OUT_OF_MEMORY; - -#ifdef NOISY_SPACEMANAGER - printf("constructed new space manager %p (replacing %p)\n", - mNew, mReflowState.mSpaceManager); -#endif - - // Set the space manager in the existing reflow state - mOld = mReflowState.mSpaceManager; - mReflowState.mSpaceManager = mNew; - return NS_OK; -} - -//---------------------------------------------------------------------- - void nsBlockFrame::CombineRects(const nsRect& r1, nsRect& r2) { diff --git a/mozilla/layout/generic/nsSpaceManager.cpp b/mozilla/layout/generic/nsSpaceManager.cpp index 30230e2b35e..65fba6dcd8e 100644 --- a/mozilla/layout/generic/nsSpaceManager.cpp +++ b/mozilla/layout/generic/nsSpaceManager.cpp @@ -45,6 +45,7 @@ #include "nsString.h" #include "nsIPresShell.h" #include "nsMemory.h" +#include "nsHTMLReflowState.h" #ifdef DEBUG #include "nsIFrameDebug.h" #endif @@ -1377,3 +1378,54 @@ nsSpaceManager::BandRect::Length() const return len; } + + +//---------------------------------------------------------------------- + +nsAutoSpaceManager::~nsAutoSpaceManager() +{ + // Restore the old space manager in the reflow state if necessary. + if (mNew) { +#ifdef NOISY_SPACEMANAGER + printf("restoring old space manager %p\n", mOld); +#endif + + mReflowState.mSpaceManager = mOld; + +#ifdef NOISY_SPACEMANAGER + if (mOld) { + NS_STATIC_CAST(nsFrame *, mReflowState.frame)->ListTag(stdout); + printf(": space-manager %p after reflow\n", mOld); + mOld->List(stdout); + } +#endif + +#ifdef DEBUG + if (mOwns) +#endif + delete mNew; + } +} + +nsresult +nsAutoSpaceManager::CreateSpaceManagerFor(nsIPresContext *aPresContext, nsIFrame *aFrame) +{ + // Create a new space manager and install it in the reflow + // state. `Remember' the old space manager so we can restore it + // later. + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mNew = new nsSpaceManager(shell, aFrame); + if (! mNew) + return NS_ERROR_OUT_OF_MEMORY; + +#ifdef NOISY_SPACEMANAGER + printf("constructed new space manager %p (replacing %p)\n", + mNew, mReflowState.mSpaceManager); +#endif + + // Set the space manager in the existing reflow state + mOld = mReflowState.mSpaceManager; + mReflowState.mSpaceManager = mNew; + return NS_OK; +} diff --git a/mozilla/layout/generic/nsSpaceManager.h b/mozilla/layout/generic/nsSpaceManager.h index 922b46faa73..65b757d9dd1 100644 --- a/mozilla/layout/generic/nsSpaceManager.h +++ b/mozilla/layout/generic/nsSpaceManager.h @@ -48,6 +48,8 @@ class nsIPresShell; class nsIFrame; class nsVoidArray; struct nsSize; +struct nsHTMLReflowState; +class nsIPresContext; #define NS_SPACE_MANAGER_CACHE_SIZE 4 @@ -438,5 +440,49 @@ private: void operator=(const nsSpaceManager&); // no implementation }; +/** + * A helper class to manage maintenance of the space manager during + * nsBlockFrame::Reflow. It automatically restores the old space + * manager in the reflow state when the object goes out of scope. + */ +class nsAutoSpaceManager { +public: + nsAutoSpaceManager(nsHTMLReflowState& aReflowState) + : mReflowState(aReflowState), +#ifdef DEBUG + mOwns(PR_TRUE), +#endif + mNew(nsnull), + mOld(nsnull) {} + + ~nsAutoSpaceManager(); + + /** + * Create a new space manager for the specified frame. This will + * `remember' the old space manager, and install the new space + * manager in the reflow state. + */ + nsresult + CreateSpaceManagerFor(nsIPresContext *aPresContext, + nsIFrame *aFrame); + +#ifdef DEBUG + /** + * `Orphan' any space manager that the nsAutoSpaceManager created; + * i.e., make it so that we don't destroy the space manager when we + * go out of scope. + */ + void DebugOrphanSpaceManager() { mOwns = PR_FALSE; } +#endif + +protected: + nsHTMLReflowState &mReflowState; +#ifdef DEBUG + PRBool mOwns; +#endif + nsSpaceManager *mNew; + nsSpaceManager *mOld; +}; + #endif /* nsSpaceManager_h___ */ diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index 36b7d8b3ad2..a25379b2a86 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -253,100 +253,6 @@ RecordReflowStatus(PRBool aChildIsBlock, nsReflowStatus aFrameReflowStatus) //---------------------------------------------------------------------- -/** - * A helper class to manage maintenance of the space manager during - * nsBlockFrame::Reflow. It automatically restores the old space - * manager in the reflow state when the object goes out of scope. - */ -class nsAutoSpaceManager { -public: - nsAutoSpaceManager(nsHTMLReflowState& aReflowState) - : mReflowState(aReflowState), -#ifdef DEBUG - mOwns(PR_TRUE), -#endif - mNew(nsnull), - mOld(nsnull) {} - - ~nsAutoSpaceManager(); - - /** - * Create a new space manager for the specified frame. This will - * `remember' the old space manager, and install the new space - * manager in the reflow state. - */ - nsresult - CreateSpaceManagerFor(nsIPresContext *aPresContext, - nsIFrame *aFrame); - -#ifdef DEBUG - /** - * `Orphan' any space manager that the nsAutoSpaceManager created; - * i.e., make it so that we don't destroy the space manager when we - * go out of scope. - */ - void DebugOrphanSpaceManager() { mOwns = PR_FALSE; } -#endif - -protected: - nsHTMLReflowState &mReflowState; -#ifdef DEBUG - PRBool mOwns; -#endif - nsSpaceManager *mNew; - nsSpaceManager *mOld; -}; - -nsAutoSpaceManager::~nsAutoSpaceManager() -{ - // Restore the old space manager in the reflow state if necessary. - if (mNew) { -#ifdef NOISY_SPACEMANAGER - printf("restoring old space manager %p\n", mOld); -#endif - - mReflowState.mSpaceManager = mOld; - -#ifdef NOISY_SPACEMANAGER - if (mOld) { - NS_STATIC_CAST(nsFrame *, mReflowState.frame)->ListTag(stdout); - printf(": space-manager %p after reflow\n", mOld); - mOld->List(stdout); - } -#endif - -#ifdef DEBUG - if (mOwns) -#endif - delete mNew; - } -} - -nsresult -nsAutoSpaceManager::CreateSpaceManagerFor(nsIPresContext *aPresContext, nsIFrame *aFrame) -{ - // Create a new space manager and install it in the reflow - // state. `Remember' the old space manager so we can restore it - // later. - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - mNew = new nsSpaceManager(shell, aFrame); - if (! mNew) - return NS_ERROR_OUT_OF_MEMORY; - -#ifdef NOISY_SPACEMANAGER - printf("constructed new space manager %p (replacing %p)\n", - mNew, mReflowState.mSpaceManager); -#endif - - // Set the space manager in the existing reflow state - mOld = mReflowState.mSpaceManager; - mReflowState.mSpaceManager = mNew; - return NS_OK; -} - -//---------------------------------------------------------------------- - void nsBlockFrame::CombineRects(const nsRect& r1, nsRect& r2) { diff --git a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp index 4a74fbd310f..8bdff25d534 100644 --- a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp @@ -61,6 +61,7 @@ #include "nsIAccessibilityService.h" #endif #include "nsIServiceManager.h" +#include "nsSpaceManager.h" class nsLegendFrame; @@ -302,7 +303,17 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); // Initialize OUT parameter - aStatus = NS_FRAME_COMPLETE; + aStatus = NS_FRAME_COMPLETE; + + // Should we create a space manager? + nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState)); + + // XXXldb If we start storing the space manager in the frame rather + // than keeping it around only during reflow then we should create it + // only when there are actually floats to manage. Otherwise things + // like tables will gain significant bloat. + if (NS_BLOCK_SPACE_MGR & mState) + autoSpaceManager.CreateSpaceManagerFor(aPresContext, this); if (aDesiredSize.mComputeMEW) { aDesiredSize.mMaxElementWidth = 0;