Bug 230417. When a placeholder frame lands in a block's overflowList, put its out of flow frame in a new child list, overflowOutOfFlowsList

This commit is contained in:
roc+@cs.cmu.edu
2004-05-05 02:30:33 +00:00
parent 50e4738bd9
commit 2f91bec3ca
6 changed files with 238 additions and 62 deletions

View File

@@ -82,6 +82,7 @@ LAYOUT_ATOM(editorDisplayList, "EditorDisplay-List")
LAYOUT_ATOM(fixedList, "Fixed-list") LAYOUT_ATOM(fixedList, "Fixed-list")
LAYOUT_ATOM(floatList, "Float-list") LAYOUT_ATOM(floatList, "Float-list")
LAYOUT_ATOM(overflowList, "Overflow-list") LAYOUT_ATOM(overflowList, "Overflow-list")
LAYOUT_ATOM(overflowOutOfFlowList, "OverflowOutOfFlow-list")
LAYOUT_ATOM(popupList, "Popup-list") LAYOUT_ATOM(popupList, "Popup-list")
LAYOUT_ATOM(commentTagName, "__moz_comment") LAYOUT_ATOM(commentTagName, "__moz_comment")
@@ -139,6 +140,7 @@ LAYOUT_ATOM(maxElementWidthProperty, "MaxElementWidthProperty") // nscoord*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox* LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(overflowOutOfFlowsProperty, "OverflowOutOfFlowsProperty") // nsFrameList*
LAYOUT_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsPlaceholder* LAYOUT_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsPlaceholder*
LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord* LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block

View File

@@ -82,6 +82,7 @@ LAYOUT_ATOM(editorDisplayList, "EditorDisplay-List")
LAYOUT_ATOM(fixedList, "Fixed-list") LAYOUT_ATOM(fixedList, "Fixed-list")
LAYOUT_ATOM(floatList, "Float-list") LAYOUT_ATOM(floatList, "Float-list")
LAYOUT_ATOM(overflowList, "Overflow-list") LAYOUT_ATOM(overflowList, "Overflow-list")
LAYOUT_ATOM(overflowOutOfFlowList, "OverflowOutOfFlow-list")
LAYOUT_ATOM(popupList, "Popup-list") LAYOUT_ATOM(popupList, "Popup-list")
LAYOUT_ATOM(commentTagName, "__moz_comment") LAYOUT_ATOM(commentTagName, "__moz_comment")
@@ -139,6 +140,7 @@ LAYOUT_ATOM(maxElementWidthProperty, "MaxElementWidthProperty") // nscoord*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox* LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(overflowOutOfFlowsProperty, "OverflowOutOfFlowsProperty") // nsFrameList*
LAYOUT_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsPlaceholder* LAYOUT_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsPlaceholder*
LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord* LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block

View File

@@ -304,6 +304,11 @@ nsBlockFrame::Destroy(nsIPresContext* aPresContext)
if (overflowLines) { if (overflowLines) {
nsLineBox::DeleteLineList(aPresContext, *overflowLines); nsLineBox::DeleteLineList(aPresContext, *overflowLines);
} }
nsFrameList* overflowOutOfFlows = GetOverflowOutOfFlows(PR_TRUE);
if (overflowOutOfFlows) {
overflowOutOfFlows->DestroyFrames(aPresContext);
delete overflowOutOfFlows;
}
return nsBlockFrameSuper::Destroy(aPresContext); return nsBlockFrameSuper::Destroy(aPresContext);
} }
@@ -477,6 +482,10 @@ nsBlockFrame::GetFirstChild(nsIAtom* aListName) const
nsLineList* overflowLines = GetOverflowLines(GetPresContext(), PR_FALSE); nsLineList* overflowLines = GetOverflowLines(GetPresContext(), PR_FALSE);
return overflowLines ? overflowLines->front()->mFirstChild : nsnull; return overflowLines ? overflowLines->front()->mFirstChild : nsnull;
} }
else if (aListName == nsLayoutAtoms::overflowOutOfFlowList) {
nsFrameList* oof = GetOverflowOutOfFlows(PR_FALSE);
return oof ? oof->FirstChild() : nsnull;
}
else if (aListName == nsLayoutAtoms::floatList) { else if (aListName == nsLayoutAtoms::floatList) {
return mFloats.FirstChild(); return mFloats.FirstChild();
} }
@@ -498,6 +507,8 @@ nsBlockFrame::GetAdditionalChildListName(PRInt32 aIndex) const
return nsLayoutAtoms::bulletList; return nsLayoutAtoms::bulletList;
case NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX: case NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX:
return nsLayoutAtoms::overflowList; return nsLayoutAtoms::overflowList;
case NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX:
return nsLayoutAtoms::overflowOutOfFlowList;
case NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX: case NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX:
return mAbsoluteContainer.GetChildListName(); return mAbsoluteContainer.GetChildListName();
default: default:
@@ -4205,7 +4216,6 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
#endif #endif
} }
// The overflowLines property is stored as a pointer to a line list, // The overflowLines property is stored as a pointer to a line list,
// which must be deleted. However, the following functions all maintain // which must be deleted. However, the following functions all maintain
// the invariant that the property is never set if the list is empty. // the invariant that the property is never set if the list is empty.
@@ -4240,26 +4250,6 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// present in the lines, so their views can be reparented? // present in the lines, so their views can be reparented?
nsHTMLContainerFrame::ReparentFrameView(aPresContext, frame, prevBlock, this); nsHTMLContainerFrame::ReparentFrameView(aPresContext, frame, prevBlock, this);
// If the frame we are looking at is a placeholder for a float, we
// need to reparent both it's out-of-flow frame and any views it has.
//
// Note: A floating table (example: style="position: relative; float: right")
// is an example of an out-of-flow frame with a view
// XXXldb What about a placeholder within an inline or block descendant?
if (nsLayoutAtoms::placeholderFrame == frame->GetType()) {
nsIFrame *outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*, frame)->GetOutOfFlowFrame();
if (!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
// It's not an absolute or fixed positioned frame, so it
// must be a float!
outOfFlowFrame->SetParent(this);
nsHTMLContainerFrame::ReparentFrameView(aPresContext,
outOfFlowFrame, prevBlock, this);
}
}
// Get the next frame // Get the next frame
lastFrame = frame; lastFrame = frame;
frame = frame->GetNextSibling(); frame = frame->GetNextSibling();
@@ -4275,6 +4265,20 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
mLines.splice(mLines.begin(), *overflowLines); mLines.splice(mLines.begin(), *overflowLines);
NS_ASSERTION(overflowLines->empty(), "splice should empty list"); NS_ASSERTION(overflowLines->empty(), "splice should empty list");
delete overflowLines; delete overflowLines;
// Out-of-flow floats need to be reparented too.
nsFrameList* overflowOutOfFlows = prevBlock->GetOverflowOutOfFlows(PR_TRUE);
if (overflowOutOfFlows) {
for (nsIFrame* f = overflowOutOfFlows->FirstChild(); f;
f = f->GetNextSibling()) {
f->SetParent(this);
// When pushing and pulling frames we need to check for whether any
// views need to be reparented
nsHTMLContainerFrame::ReparentFrameView(aPresContext, f, prevBlock, this);
}
delete overflowOutOfFlows;
}
} }
} }
@@ -4295,6 +4299,14 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
mLines.splice(mLines.end(), *overflowLines); mLines.splice(mLines.end(), *overflowLines);
drained = PR_TRUE; drained = PR_TRUE;
delete overflowLines; delete overflowLines;
// Likewise, drain our own overflow out-of-flows. We don't need to
// reparent them since they're already our children. We don't need
// to put them on any child list since BuildFloatList will put
// them on some child list. All we need to do is remove the
// property.
nsFrameList* overflowOutOfFlows = GetOverflowOutOfFlows(PR_TRUE);
delete overflowOutOfFlows;
} }
return drained; return drained;
} }
@@ -4341,6 +4353,36 @@ nsBlockFrame::SetOverflowLines(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsFrameList*
nsBlockFrame::GetOverflowOutOfFlows(PRBool aRemoveProperty) const
{
return NS_STATIC_CAST(nsFrameList*,
GetProperty(GetPresContext(), nsLayoutAtoms::overflowOutOfFlowsProperty,
aRemoveProperty));
}
// Destructor function for the overflowPlaceholders frame property
static void
DestroyOverflowOOFs(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
NS_NOTREACHED("This helper method should never be called!");
delete NS_STATIC_CAST(nsFrameList*, aPropertyValue);
}
// This takes ownership of aFloaters.
nsresult
nsBlockFrame::SetOverflowOutOfFlows(nsFrameList* aOOFs)
{
nsresult rv = SetProperty(GetPresContext(), nsLayoutAtoms::overflowOutOfFlowsProperty,
aOOFs, DestroyOverflowOOFs);
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow float list");
return rv;
}
nsFrameList* nsFrameList*
nsBlockFrame::GetOverflowPlaceholders(nsIPresContext* aPresContext, nsBlockFrame::GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const PRBool aRemoveProperty) const
@@ -6370,6 +6412,8 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
void void
nsBlockFrame::BuildFloatList() nsBlockFrame::BuildFloatList()
{ {
// Accumulate float list into mFloats.
// Use the float cache to speed up searching the lines for floats.
nsIFrame* head = nsnull; nsIFrame* head = nsnull;
nsIFrame* current = nsnull; nsIFrame* current = nsnull;
for (line_iterator line = begin_lines(), line_end = end_lines(); for (line_iterator line = begin_lines(), line_end = end_lines();
@@ -6379,10 +6423,9 @@ nsBlockFrame::BuildFloatList()
nsFloatCache* fc = line->GetFirstFloat(); nsFloatCache* fc = line->GetFirstFloat();
while (fc) { while (fc) {
nsIFrame* floatFrame = fc->mPlaceholder->GetOutOfFlowFrame(); nsIFrame* floatFrame = fc->mPlaceholder->GetOutOfFlowFrame();
if (nsnull == head) { if (!head) {
current = head = floatFrame; current = head = floatFrame;
} } else {
else {
current->SetNextSibling(floatFrame); current->SetNextSibling(floatFrame);
current = floatFrame; current = floatFrame;
} }
@@ -6392,10 +6435,51 @@ nsBlockFrame::BuildFloatList()
} }
// Terminate end of float list just in case a float was removed // Terminate end of float list just in case a float was removed
if (nsnull != current) { if (current) {
current->SetNextSibling(nsnull); current->SetNextSibling(nsnull);
} }
mFloats.SetFrames(head); mFloats.SetFrames(head);
// ensure that the floats in the overflow lines are put on a child list
// and not dropped from the frame tree!
// Note that overflow lines do not have any float cache set up for them,
// because the float cache contains only laid-out floats
nsLineList* overflowLines = GetOverflowLines(GetPresContext(), PR_FALSE);
if (overflowLines) {
head = nsnull;
current = nsnull;
nsIFrame* frame = overflowLines->front()->mFirstChild;
while (frame) {
if (nsLayoutAtoms::placeholderFrame == frame->GetType()) {
nsIFrame *outOfFlowFrame = NS_STATIC_CAST(nsPlaceholderFrame*, frame)->GetOutOfFlowFrame();
if (outOfFlowFrame &&
!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
// It's not an absolute or fixed positioned frame, so it
// must be a float!
// XXX This is a lame-o way of detecting a float, but it's the only way
// apparently
if (!head) {
head = current = outOfFlowFrame;
} else {
current->SetNextSibling(outOfFlowFrame);
current = outOfFlowFrame;
}
}
}
// XXXldb What about a placeholder within an inline or block descendant?
frame = frame->GetNextSibling();
}
if (current) {
current->SetNextSibling(nsnull);
nsFrameList* frameList = new nsFrameList(head);
if (frameList) {
SetOverflowOutOfFlows(frameList);
}
}
}
} }
// XXX keep the text-run data in the first-in-flow of the block // XXX keep the text-run data in the first-in-flow of the block

View File

@@ -56,10 +56,11 @@ class nsIntervalSet;
* Child list name indices * Child list name indices
* @see #GetAdditionalChildListName() * @see #GetAdditionalChildListName()
*/ */
#define NS_BLOCK_FRAME_FLOAT_LIST_INDEX 0 #define NS_BLOCK_FRAME_FLOAT_LIST_INDEX 0
#define NS_BLOCK_FRAME_BULLET_LIST_INDEX 1 #define NS_BLOCK_FRAME_BULLET_LIST_INDEX 1
#define NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX 2 #define NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX 2
#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX 3 #define NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX 3
#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX 4
#define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX #define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX
#define nsBlockFrameSuper nsHTMLContainerFrame #define nsBlockFrameSuper nsHTMLContainerFrame
@@ -542,16 +543,17 @@ protected:
nsLineList* GetOverflowLines(nsIPresContext* aPresContext, nsLineList* GetOverflowLines(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const; PRBool aRemoveProperty) const;
nsresult SetOverflowLines(nsIPresContext* aPresContext, nsresult SetOverflowLines(nsIPresContext* aPresContext,
nsLineList* aOverflowLines); nsLineList* aOverflowLines);
nsFrameList* GetOverflowPlaceholders(nsIPresContext* aPresContext, nsFrameList* GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const; PRBool aRemoveProperty) const;
nsresult SetOverflowPlaceholders(nsIPresContext* aPresContext, nsresult SetOverflowPlaceholders(nsIPresContext* aPresContext,
nsFrameList* aOverflowPlaceholders); nsFrameList* aOverflowPlaceholders);
nsFrameList* GetOverflowOutOfFlows(PRBool aRemoveProperty) const;
nsresult SetOverflowOutOfFlows(nsFrameList* aFloaters);
nsIFrame* LastChild(); nsIFrame* LastChild();
#ifdef NS_DEBUG #ifdef NS_DEBUG

View File

@@ -304,6 +304,11 @@ nsBlockFrame::Destroy(nsIPresContext* aPresContext)
if (overflowLines) { if (overflowLines) {
nsLineBox::DeleteLineList(aPresContext, *overflowLines); nsLineBox::DeleteLineList(aPresContext, *overflowLines);
} }
nsFrameList* overflowOutOfFlows = GetOverflowOutOfFlows(PR_TRUE);
if (overflowOutOfFlows) {
overflowOutOfFlows->DestroyFrames(aPresContext);
delete overflowOutOfFlows;
}
return nsBlockFrameSuper::Destroy(aPresContext); return nsBlockFrameSuper::Destroy(aPresContext);
} }
@@ -477,6 +482,10 @@ nsBlockFrame::GetFirstChild(nsIAtom* aListName) const
nsLineList* overflowLines = GetOverflowLines(GetPresContext(), PR_FALSE); nsLineList* overflowLines = GetOverflowLines(GetPresContext(), PR_FALSE);
return overflowLines ? overflowLines->front()->mFirstChild : nsnull; return overflowLines ? overflowLines->front()->mFirstChild : nsnull;
} }
else if (aListName == nsLayoutAtoms::overflowOutOfFlowList) {
nsFrameList* oof = GetOverflowOutOfFlows(PR_FALSE);
return oof ? oof->FirstChild() : nsnull;
}
else if (aListName == nsLayoutAtoms::floatList) { else if (aListName == nsLayoutAtoms::floatList) {
return mFloats.FirstChild(); return mFloats.FirstChild();
} }
@@ -498,6 +507,8 @@ nsBlockFrame::GetAdditionalChildListName(PRInt32 aIndex) const
return nsLayoutAtoms::bulletList; return nsLayoutAtoms::bulletList;
case NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX: case NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX:
return nsLayoutAtoms::overflowList; return nsLayoutAtoms::overflowList;
case NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX:
return nsLayoutAtoms::overflowOutOfFlowList;
case NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX: case NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX:
return mAbsoluteContainer.GetChildListName(); return mAbsoluteContainer.GetChildListName();
default: default:
@@ -4205,7 +4216,6 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
#endif #endif
} }
// The overflowLines property is stored as a pointer to a line list, // The overflowLines property is stored as a pointer to a line list,
// which must be deleted. However, the following functions all maintain // which must be deleted. However, the following functions all maintain
// the invariant that the property is never set if the list is empty. // the invariant that the property is never set if the list is empty.
@@ -4240,26 +4250,6 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// present in the lines, so their views can be reparented? // present in the lines, so their views can be reparented?
nsHTMLContainerFrame::ReparentFrameView(aPresContext, frame, prevBlock, this); nsHTMLContainerFrame::ReparentFrameView(aPresContext, frame, prevBlock, this);
// If the frame we are looking at is a placeholder for a float, we
// need to reparent both it's out-of-flow frame and any views it has.
//
// Note: A floating table (example: style="position: relative; float: right")
// is an example of an out-of-flow frame with a view
// XXXldb What about a placeholder within an inline or block descendant?
if (nsLayoutAtoms::placeholderFrame == frame->GetType()) {
nsIFrame *outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*, frame)->GetOutOfFlowFrame();
if (!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
// It's not an absolute or fixed positioned frame, so it
// must be a float!
outOfFlowFrame->SetParent(this);
nsHTMLContainerFrame::ReparentFrameView(aPresContext,
outOfFlowFrame, prevBlock, this);
}
}
// Get the next frame // Get the next frame
lastFrame = frame; lastFrame = frame;
frame = frame->GetNextSibling(); frame = frame->GetNextSibling();
@@ -4275,6 +4265,20 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
mLines.splice(mLines.begin(), *overflowLines); mLines.splice(mLines.begin(), *overflowLines);
NS_ASSERTION(overflowLines->empty(), "splice should empty list"); NS_ASSERTION(overflowLines->empty(), "splice should empty list");
delete overflowLines; delete overflowLines;
// Out-of-flow floats need to be reparented too.
nsFrameList* overflowOutOfFlows = prevBlock->GetOverflowOutOfFlows(PR_TRUE);
if (overflowOutOfFlows) {
for (nsIFrame* f = overflowOutOfFlows->FirstChild(); f;
f = f->GetNextSibling()) {
f->SetParent(this);
// When pushing and pulling frames we need to check for whether any
// views need to be reparented
nsHTMLContainerFrame::ReparentFrameView(aPresContext, f, prevBlock, this);
}
delete overflowOutOfFlows;
}
} }
} }
@@ -4295,6 +4299,14 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
mLines.splice(mLines.end(), *overflowLines); mLines.splice(mLines.end(), *overflowLines);
drained = PR_TRUE; drained = PR_TRUE;
delete overflowLines; delete overflowLines;
// Likewise, drain our own overflow out-of-flows. We don't need to
// reparent them since they're already our children. We don't need
// to put them on any child list since BuildFloatList will put
// them on some child list. All we need to do is remove the
// property.
nsFrameList* overflowOutOfFlows = GetOverflowOutOfFlows(PR_TRUE);
delete overflowOutOfFlows;
} }
return drained; return drained;
} }
@@ -4341,6 +4353,36 @@ nsBlockFrame::SetOverflowLines(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsFrameList*
nsBlockFrame::GetOverflowOutOfFlows(PRBool aRemoveProperty) const
{
return NS_STATIC_CAST(nsFrameList*,
GetProperty(GetPresContext(), nsLayoutAtoms::overflowOutOfFlowsProperty,
aRemoveProperty));
}
// Destructor function for the overflowPlaceholders frame property
static void
DestroyOverflowOOFs(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
NS_NOTREACHED("This helper method should never be called!");
delete NS_STATIC_CAST(nsFrameList*, aPropertyValue);
}
// This takes ownership of aFloaters.
nsresult
nsBlockFrame::SetOverflowOutOfFlows(nsFrameList* aOOFs)
{
nsresult rv = SetProperty(GetPresContext(), nsLayoutAtoms::overflowOutOfFlowsProperty,
aOOFs, DestroyOverflowOOFs);
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow float list");
return rv;
}
nsFrameList* nsFrameList*
nsBlockFrame::GetOverflowPlaceholders(nsIPresContext* aPresContext, nsBlockFrame::GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const PRBool aRemoveProperty) const
@@ -6370,6 +6412,8 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
void void
nsBlockFrame::BuildFloatList() nsBlockFrame::BuildFloatList()
{ {
// Accumulate float list into mFloats.
// Use the float cache to speed up searching the lines for floats.
nsIFrame* head = nsnull; nsIFrame* head = nsnull;
nsIFrame* current = nsnull; nsIFrame* current = nsnull;
for (line_iterator line = begin_lines(), line_end = end_lines(); for (line_iterator line = begin_lines(), line_end = end_lines();
@@ -6379,10 +6423,9 @@ nsBlockFrame::BuildFloatList()
nsFloatCache* fc = line->GetFirstFloat(); nsFloatCache* fc = line->GetFirstFloat();
while (fc) { while (fc) {
nsIFrame* floatFrame = fc->mPlaceholder->GetOutOfFlowFrame(); nsIFrame* floatFrame = fc->mPlaceholder->GetOutOfFlowFrame();
if (nsnull == head) { if (!head) {
current = head = floatFrame; current = head = floatFrame;
} } else {
else {
current->SetNextSibling(floatFrame); current->SetNextSibling(floatFrame);
current = floatFrame; current = floatFrame;
} }
@@ -6392,10 +6435,51 @@ nsBlockFrame::BuildFloatList()
} }
// Terminate end of float list just in case a float was removed // Terminate end of float list just in case a float was removed
if (nsnull != current) { if (current) {
current->SetNextSibling(nsnull); current->SetNextSibling(nsnull);
} }
mFloats.SetFrames(head); mFloats.SetFrames(head);
// ensure that the floats in the overflow lines are put on a child list
// and not dropped from the frame tree!
// Note that overflow lines do not have any float cache set up for them,
// because the float cache contains only laid-out floats
nsLineList* overflowLines = GetOverflowLines(GetPresContext(), PR_FALSE);
if (overflowLines) {
head = nsnull;
current = nsnull;
nsIFrame* frame = overflowLines->front()->mFirstChild;
while (frame) {
if (nsLayoutAtoms::placeholderFrame == frame->GetType()) {
nsIFrame *outOfFlowFrame = NS_STATIC_CAST(nsPlaceholderFrame*, frame)->GetOutOfFlowFrame();
if (outOfFlowFrame &&
!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
// It's not an absolute or fixed positioned frame, so it
// must be a float!
// XXX This is a lame-o way of detecting a float, but it's the only way
// apparently
if (!head) {
head = current = outOfFlowFrame;
} else {
current->SetNextSibling(outOfFlowFrame);
current = outOfFlowFrame;
}
}
}
// XXXldb What about a placeholder within an inline or block descendant?
frame = frame->GetNextSibling();
}
if (current) {
current->SetNextSibling(nsnull);
nsFrameList* frameList = new nsFrameList(head);
if (frameList) {
SetOverflowOutOfFlows(frameList);
}
}
}
} }
// XXX keep the text-run data in the first-in-flow of the block // XXX keep the text-run data in the first-in-flow of the block

View File

@@ -56,10 +56,11 @@ class nsIntervalSet;
* Child list name indices * Child list name indices
* @see #GetAdditionalChildListName() * @see #GetAdditionalChildListName()
*/ */
#define NS_BLOCK_FRAME_FLOAT_LIST_INDEX 0 #define NS_BLOCK_FRAME_FLOAT_LIST_INDEX 0
#define NS_BLOCK_FRAME_BULLET_LIST_INDEX 1 #define NS_BLOCK_FRAME_BULLET_LIST_INDEX 1
#define NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX 2 #define NS_BLOCK_FRAME_OVERFLOW_LIST_INDEX 2
#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX 3 #define NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX 3
#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX 4
#define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX #define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX
#define nsBlockFrameSuper nsHTMLContainerFrame #define nsBlockFrameSuper nsHTMLContainerFrame
@@ -542,16 +543,17 @@ protected:
nsLineList* GetOverflowLines(nsIPresContext* aPresContext, nsLineList* GetOverflowLines(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const; PRBool aRemoveProperty) const;
nsresult SetOverflowLines(nsIPresContext* aPresContext, nsresult SetOverflowLines(nsIPresContext* aPresContext,
nsLineList* aOverflowLines); nsLineList* aOverflowLines);
nsFrameList* GetOverflowPlaceholders(nsIPresContext* aPresContext, nsFrameList* GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const; PRBool aRemoveProperty) const;
nsresult SetOverflowPlaceholders(nsIPresContext* aPresContext, nsresult SetOverflowPlaceholders(nsIPresContext* aPresContext,
nsFrameList* aOverflowPlaceholders); nsFrameList* aOverflowPlaceholders);
nsFrameList* GetOverflowOutOfFlows(PRBool aRemoveProperty) const;
nsresult SetOverflowOutOfFlows(nsFrameList* aFloaters);
nsIFrame* LastChild(); nsIFrame* LastChild();
#ifdef NS_DEBUG #ifdef NS_DEBUG