infrastructure to recover overflow area during incremental reflow, bug 197581, r=kin sr=dbaron

This commit is contained in:
bmlk%gmx.de 2003-05-31 10:32:19 +00:00
parent 799cc4775c
commit 838f8ce8ad
10 changed files with 234 additions and 160 deletions

View File

@ -1245,6 +1245,15 @@ public:
void* aPropertyValue) = 0;
#endif // IBMBIDI
/** Create or retrieve the previously stored overflow area, if the frame does
* not overflow and no creation is required return nsnull.
* @param aPresContext PresContext
* @param aCreateIfNecessary create a new nsRect for the overflow area
* @return pointer to the overflow area rectangle
*/
virtual nsRect* GetOverflowAreaProperty(nsIPresContext* aPresContext,
PRBool aCreateIfNecessary = PR_FALSE) = 0;
/**
* Return PR_TRUE if and only if this frame obeys visibility:hidden.
* if it does not, then nsContainerFrame will hide its view even though

View File

@ -156,52 +156,6 @@ nsAbsoluteContainingBlock::ReplaceFrame(nsIFrame* aDelegatingFrame,
return result ? NS_OK : NS_ERROR_FAILURE;
}
// Destructor function for the collapse offset frame property
static void
DestroyRectFunc(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
delete (nsRect*)aPropertyValue;
}
static nsRect*
GetOverflowAreaProperty(nsIPresContext* aPresContext,
nsIFrame* aFrame,
PRBool aCreateIfNecessary = PR_FALSE)
{
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
void* value;
frameManager->GetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty,
0, &value);
if (value) {
return (nsRect*)value; // the property already exists
} else if (aCreateIfNecessary) {
// The property isn't set yet, so allocate a new rect, set the property,
// and return the newly allocated rect
nsRect* overflow = new nsRect(0, 0, 0, 0);
frameManager->SetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty,
overflow, DestroyRectFunc);
return overflow;
}
}
}
return nsnull;
}
nsresult
nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
nsIPresContext* aPresContext,
@ -257,7 +211,7 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
kidFrame->GetFrameState(&kidFrameState);
if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) {
// Get the property
nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, kidFrame);
nsRect* overflowArea = kidFrame->GetOverflowAreaProperty(aPresContext);
if (overflowArea) {
// The overflow area is in the child's coordinate space, so translate
@ -291,7 +245,7 @@ nsAbsoluteContainingBlock::CalculateChildBounds(nsIPresContext* aPresContext,
f->GetFrameState(&frameState);
if (frameState & NS_FRAME_OUTSIDE_CHILDREN) {
// Get the property
nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, f);
nsRect* overflowArea = f->GetOverflowAreaProperty(aPresContext);
if (overflowArea) {
// The overflow area is in the child's coordinate space, so translate
@ -550,7 +504,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
aKidFrame->GetFrameState(&kidFrameState);
if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) {
// Get the property (creating a rect struct if necessary)
nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, aKidFrame, PR_TRUE);
nsRect* overflowArea = aKidFrame->GetOverflowAreaProperty(aPresContext, PR_TRUE);
NS_ASSERTION(overflowArea, "should have created rect");
if (overflowArea) {

View File

@ -686,15 +686,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
} else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
StoreOverflow(aPresContext, aMetrics);
return NS_OK;
}
@ -952,6 +944,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
StoreOverflow(aPresContext, aMetrics);
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
@ -1012,17 +1005,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Factor the absolutely positioned child bounds into the overflow area
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
} else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
StoreOverflow(aPresContext, aMetrics);
}
// Clear the space manager pointer in the block reflow state so we
// don't waste time translating the coordinate system back on a dead
// space manager.
@ -1430,18 +1414,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
ComputeCombinedArea(aReflowState, aMetrics);
// If the combined area of our children exceeds our bounding box
// then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it.
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
}
else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
}
void

View File

@ -4549,6 +4549,87 @@ GetIBSpecialSibling(nsIPresContext* aPresContext,
return NS_OK;
}
// Destructor function for the overflow area property
static void
DestroyRectFunc(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
delete (nsRect*)aPropertyValue;
}
nsRect*
nsFrame::GetOverflowAreaProperty(nsIPresContext* aPresContext,
PRBool aCreateIfNecessary)
{
nsFrameState frameState;
GetFrameState(&frameState);
if (!((frameState & NS_FRAME_OUTSIDE_CHILDREN) || aCreateIfNecessary)) {
return nsnull;
}
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
void* value;
frameManager->GetFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty,
0, &value);
if (value) {
return (nsRect*)value; // the property already exists
} else if (aCreateIfNecessary) {
// The property isn't set yet, so allocate a new rect, set the property,
// and return the newly allocated rect
nsRect* overflow = new nsRect(0, 0, 0, 0);
frameManager->SetFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty,
overflow, DestroyRectFunc);
return overflow;
}
}
}
return nsnull;
}
void
nsFrame::StoreOverflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics)
{
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
nsRect* overflowArea = GetOverflowAreaProperty(aPresContext, PR_TRUE);
NS_ASSERTION(overflowArea, "should have created rect");
if (overflowArea) {
*overflowArea = aMetrics.mOverflowArea;
}
}
else {
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
// remove the previously stored overflow area
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
frameManager->RemoveFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty);
}
}
}
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
}
nsresult
nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
@ -5634,6 +5715,16 @@ void nsFrame::DisplayReflowExit(nsIPresContext* aPresContext,
DR_state->PrettyUC(aMetrics.mOverflowArea.width, width);
DR_state->PrettyUC(aMetrics.mOverflowArea.height, height);
printf("o=(%s,%s) %s x %s", x, y, width, height);
nsRect* storedOverflow = aFrame->GetOverflowAreaProperty(aPresContext);
if (storedOverflow) {
if (aMetrics.mOverflowArea != *storedOverflow) {
DR_state->PrettyUC(storedOverflow->x, x);
DR_state->PrettyUC(storedOverflow->y, y);
DR_state->PrettyUC(storedOverflow->width, width);
DR_state->PrettyUC(storedOverflow->height, height);
printf("sto=(%s,%s) %s x %s", x, y, width, height);
}
}
}
printf("\n");
if (DR_state->mDisplayPixelErrors) {

View File

@ -381,6 +381,17 @@ public:
nsresult GetIBSpecialParent(nsIPresContext* aPresContext,
nsIFrame** aSpecialParent);
// Return the previously stored overflow area, if the frame does not
// overflow and a creation is not requested it will return nsnull
virtual nsRect* GetOverflowAreaProperty(nsIPresContext* aPresContext,
PRBool aCreateIfNecessary = PR_FALSE);
// Set/unset the NS_FRAME_OUTSIDE_CHILDREN flag and store the overflow area
// as a frame property in the frame manager so that it can be retrieved
// later without reflowing the frame.
void StoreOverflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics);
//Mouse Capturing code used by the frames to tell the view to capture all the following events
NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
PRBool IsMouseCaptured(nsIPresContext* aPresContext);

View File

@ -1245,6 +1245,15 @@ public:
void* aPropertyValue) = 0;
#endif // IBMBIDI
/** Create or retrieve the previously stored overflow area, if the frame does
* not overflow and no creation is required return nsnull.
* @param aPresContext PresContext
* @param aCreateIfNecessary create a new nsRect for the overflow area
* @return pointer to the overflow area rectangle
*/
virtual nsRect* GetOverflowAreaProperty(nsIPresContext* aPresContext,
PRBool aCreateIfNecessary = PR_FALSE) = 0;
/**
* Return PR_TRUE if and only if this frame obeys visibility:hidden.
* if it does not, then nsContainerFrame will hide its view even though

View File

@ -156,52 +156,6 @@ nsAbsoluteContainingBlock::ReplaceFrame(nsIFrame* aDelegatingFrame,
return result ? NS_OK : NS_ERROR_FAILURE;
}
// Destructor function for the collapse offset frame property
static void
DestroyRectFunc(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
delete (nsRect*)aPropertyValue;
}
static nsRect*
GetOverflowAreaProperty(nsIPresContext* aPresContext,
nsIFrame* aFrame,
PRBool aCreateIfNecessary = PR_FALSE)
{
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
void* value;
frameManager->GetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty,
0, &value);
if (value) {
return (nsRect*)value; // the property already exists
} else if (aCreateIfNecessary) {
// The property isn't set yet, so allocate a new rect, set the property,
// and return the newly allocated rect
nsRect* overflow = new nsRect(0, 0, 0, 0);
frameManager->SetFrameProperty(aFrame, nsLayoutAtoms::overflowAreaProperty,
overflow, DestroyRectFunc);
return overflow;
}
}
}
return nsnull;
}
nsresult
nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
nsIPresContext* aPresContext,
@ -257,7 +211,7 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
kidFrame->GetFrameState(&kidFrameState);
if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) {
// Get the property
nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, kidFrame);
nsRect* overflowArea = kidFrame->GetOverflowAreaProperty(aPresContext);
if (overflowArea) {
// The overflow area is in the child's coordinate space, so translate
@ -291,7 +245,7 @@ nsAbsoluteContainingBlock::CalculateChildBounds(nsIPresContext* aPresContext,
f->GetFrameState(&frameState);
if (frameState & NS_FRAME_OUTSIDE_CHILDREN) {
// Get the property
nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, f);
nsRect* overflowArea = f->GetOverflowAreaProperty(aPresContext);
if (overflowArea) {
// The overflow area is in the child's coordinate space, so translate
@ -550,7 +504,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
aKidFrame->GetFrameState(&kidFrameState);
if (kidFrameState & NS_FRAME_OUTSIDE_CHILDREN) {
// Get the property (creating a rect struct if necessary)
nsRect* overflowArea = ::GetOverflowAreaProperty(aPresContext, aKidFrame, PR_TRUE);
nsRect* overflowArea = aKidFrame->GetOverflowAreaProperty(aPresContext, PR_TRUE);
NS_ASSERTION(overflowArea, "should have created rect");
if (overflowArea) {

View File

@ -686,15 +686,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
} else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
StoreOverflow(aPresContext, aMetrics);
return NS_OK;
}
@ -952,6 +944,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
StoreOverflow(aPresContext, aMetrics);
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
@ -1012,17 +1005,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Factor the absolutely positioned child bounds into the overflow area
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
} else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
StoreOverflow(aPresContext, aMetrics);
}
// Clear the space manager pointer in the block reflow state so we
// don't waste time translating the coordinate system back on a dead
// space manager.
@ -1430,18 +1414,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
ComputeCombinedArea(aReflowState, aMetrics);
// If the combined area of our children exceeds our bounding box
// then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it.
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
}
else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
}
void

View File

@ -4549,6 +4549,87 @@ GetIBSpecialSibling(nsIPresContext* aPresContext,
return NS_OK;
}
// Destructor function for the overflow area property
static void
DestroyRectFunc(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
delete (nsRect*)aPropertyValue;
}
nsRect*
nsFrame::GetOverflowAreaProperty(nsIPresContext* aPresContext,
PRBool aCreateIfNecessary)
{
nsFrameState frameState;
GetFrameState(&frameState);
if (!((frameState & NS_FRAME_OUTSIDE_CHILDREN) || aCreateIfNecessary)) {
return nsnull;
}
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
void* value;
frameManager->GetFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty,
0, &value);
if (value) {
return (nsRect*)value; // the property already exists
} else if (aCreateIfNecessary) {
// The property isn't set yet, so allocate a new rect, set the property,
// and return the newly allocated rect
nsRect* overflow = new nsRect(0, 0, 0, 0);
frameManager->SetFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty,
overflow, DestroyRectFunc);
return overflow;
}
}
}
return nsnull;
}
void
nsFrame::StoreOverflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics)
{
if ((aMetrics.mOverflowArea.x < 0) ||
(aMetrics.mOverflowArea.y < 0) ||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
nsRect* overflowArea = GetOverflowAreaProperty(aPresContext, PR_TRUE);
NS_ASSERTION(overflowArea, "should have created rect");
if (overflowArea) {
*overflowArea = aMetrics.mOverflowArea;
}
}
else {
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
// remove the previously stored overflow area
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
frameManager->RemoveFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty);
}
}
}
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
}
nsresult
nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
@ -5634,6 +5715,16 @@ void nsFrame::DisplayReflowExit(nsIPresContext* aPresContext,
DR_state->PrettyUC(aMetrics.mOverflowArea.width, width);
DR_state->PrettyUC(aMetrics.mOverflowArea.height, height);
printf("o=(%s,%s) %s x %s", x, y, width, height);
nsRect* storedOverflow = aFrame->GetOverflowAreaProperty(aPresContext);
if (storedOverflow) {
if (aMetrics.mOverflowArea != *storedOverflow) {
DR_state->PrettyUC(storedOverflow->x, x);
DR_state->PrettyUC(storedOverflow->y, y);
DR_state->PrettyUC(storedOverflow->width, width);
DR_state->PrettyUC(storedOverflow->height, height);
printf("sto=(%s,%s) %s x %s", x, y, width, height);
}
}
}
printf("\n");
if (DR_state->mDisplayPixelErrors) {

View File

@ -381,6 +381,17 @@ public:
nsresult GetIBSpecialParent(nsIPresContext* aPresContext,
nsIFrame** aSpecialParent);
// Return the previously stored overflow area, if the frame does not
// overflow and a creation is not requested it will return nsnull
virtual nsRect* GetOverflowAreaProperty(nsIPresContext* aPresContext,
PRBool aCreateIfNecessary = PR_FALSE);
// Set/unset the NS_FRAME_OUTSIDE_CHILDREN flag and store the overflow area
// as a frame property in the frame manager so that it can be retrieved
// later without reflowing the frame.
void StoreOverflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics);
//Mouse Capturing code used by the frames to tell the view to capture all the following events
NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
PRBool IsMouseCaptured(nsIPresContext* aPresContext);