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
This commit is contained in:
jkeiser%netscape.com
2003-05-22 20:56:35 +00:00
parent 8528871fe1
commit d214c656a8
8 changed files with 220 additions and 190 deletions

View File

@@ -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<nsIPresShell> 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;
}

View File

@@ -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___ */

View File

@@ -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;

View File

@@ -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<nsIPresShell> 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)
{

View File

@@ -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<nsIPresShell> 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;
}

View File

@@ -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___ */

View File

@@ -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<nsIPresShell> 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)
{

View File

@@ -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;