Bug 282173. Remove BuildFloatList. r+sr=dbaron
git-svn-id: svn://10.0.0.236/trunk@193974 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
b1fa15f4dc
commit
cbc5855a71
@ -925,8 +925,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
||||
ReparentFrame(oof, this, ancestorRS->frame);
|
||||
// Clear the next-sibling in case the frame wasn't in mFloats
|
||||
oof->SetNextSibling(nsnull);
|
||||
NS_STATIC_CAST(nsBlockFrame*, ancestorRS->frame)
|
||||
->mFloats.AppendFrame(nsnull, oof);
|
||||
// Do not put the float into any child frame list, because
|
||||
// placeholders in the overflow-placeholder block-state list
|
||||
// don't keep their out of flows in a child frame list.
|
||||
}
|
||||
ancestorPlace->AppendFrames(nsnull, state.mOverflowPlaceholders.FirstChild());
|
||||
gaveToAncestor = PR_TRUE;
|
||||
@ -944,6 +945,22 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
||||
if (newLine) {
|
||||
nsLineList* overflowLines = GetOverflowLines();
|
||||
if (overflowLines) {
|
||||
// Need to put the overflow placeholders' floats into our
|
||||
// overflow-out-of-flows list, since the overflow placeholders are
|
||||
// going onto our overflow line list. Put them last, because that's
|
||||
// where the placeholders are going.
|
||||
nsFrameList floats;
|
||||
nsIFrame* lastFloat = nsnull;
|
||||
for (nsIFrame* f = state.mOverflowPlaceholders.FirstChild();
|
||||
f; f = f->GetNextSibling()) {
|
||||
NS_ASSERTION(IsContinuationPlaceholder(f),
|
||||
"Overflow placeholders must be continuation placeholders");
|
||||
nsIFrame* oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
|
||||
// oof is not currently in any child list
|
||||
floats.InsertFrames(nsnull, lastFloat, oof);
|
||||
lastFloat = oof;
|
||||
}
|
||||
|
||||
// Put the new placeholders *last* in the overflow lines
|
||||
// because they might have previnflows in the overflow lines.
|
||||
nsIFrame* lastChild = overflowLines->back()->LastChild();
|
||||
@ -951,6 +968,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
||||
// Create a new line as the last line and put the
|
||||
// placeholders there
|
||||
overflowLines->push_back(newLine);
|
||||
|
||||
nsAutoOOFFrameList oofs(this);
|
||||
oofs.mList.AppendFrames(nsnull, floats.FirstChild());
|
||||
}
|
||||
else {
|
||||
mLines.push_back(newLine);
|
||||
@ -977,9 +997,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// XXX_perf get rid of this! This is one of the things that makes
|
||||
// incremental reflow O(N^2).
|
||||
BuildFloatList(state);
|
||||
CheckFloats(state);
|
||||
|
||||
// Compute our final size
|
||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||
@ -4257,7 +4275,7 @@ nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
|
||||
{
|
||||
nsIFrame* nextInFlow;
|
||||
nsresult rv = CreateNextInFlow(aState.mPresContext, this, aPlaceholder, nextInFlow);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!nextInFlow) {
|
||||
@ -4270,9 +4288,12 @@ nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
|
||||
nsIFrame *next = contFrame->GetNextSibling();
|
||||
aPlaceholder->SetNextSibling(next);
|
||||
contFrame->SetNextSibling(nsnull);
|
||||
|
||||
|
||||
NS_ASSERTION(IsContinuationPlaceholder(contFrame),
|
||||
"Didn't create the right kind of frame");
|
||||
|
||||
// The new out of flow frame does not get put anywhere; the out-of-flows
|
||||
// for placeholders in mOverflowPlaceholders are not kept in any child list
|
||||
aState.mOverflowPlaceholders.AppendFrame(this, contFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -4687,6 +4708,20 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
|
||||
PRBool firstLine = overBegin == begin_lines();
|
||||
|
||||
if (overBegin != end_lines()) {
|
||||
// Remove floats in the lines from mFloats
|
||||
nsFrameList floats;
|
||||
nsIFrame* tail = nsnull;
|
||||
CollectFloats(overBegin->mFirstChild, floats, &tail, PR_FALSE);
|
||||
|
||||
if (floats.NotEmpty()) {
|
||||
// Push the floats onto the front of the overflow out-of-flows list
|
||||
nsFrameList oofs = GetOverflowOutOfFlows();
|
||||
if (oofs.NotEmpty()) {
|
||||
floats.InsertFrames(nsnull, tail, oofs.FirstChild());
|
||||
}
|
||||
SetOverflowOutOfFlows(floats);
|
||||
}
|
||||
|
||||
// overflow lines can already exist in some cases, in particular,
|
||||
// when shrinkwrapping and we discover that the shrinkwap causes
|
||||
// the height of some child block to grow which creates additional
|
||||
@ -4812,11 +4847,11 @@ nsBlockFrame::HandleOverflowPlaceholdersForPulledFrame(
|
||||
}
|
||||
ReparentFrame(outOfFlow, parent, this);
|
||||
|
||||
aState.mOverflowPlaceholders.AppendFrame(nsnull, frame);
|
||||
aState.mOverflowPlaceholders.InsertFrames(nsnull, lastOverflowPlace, frame);
|
||||
// outOfFlow isn't inserted anywhere yet. Eventually the overflow
|
||||
// placeholders get put into the overflow lines, then
|
||||
// BuildFloatList collects their out-of-flows and puts them on the
|
||||
// overflow out-of-flows list.
|
||||
// placeholders get put into the overflow lines, and at the same time we
|
||||
// insert the placeholders' out of flows into the overflow out-of-flows
|
||||
// list.
|
||||
lastOverflowPlace = frame;
|
||||
|
||||
frame = frame->GetNextInFlow();
|
||||
@ -4908,7 +4943,8 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
if (ourOverflowLines) {
|
||||
nsAutoOOFFrameList oofs(this);
|
||||
if (oofs.mList.NotEmpty()) {
|
||||
mFloats.InsertFrames(nsnull, nsnull, oofs.mList.FirstChild());
|
||||
// The overflow floats go after our regular floats
|
||||
mFloats.AppendFrames(nsnull, oofs.mList.FirstChild());
|
||||
oofs.mList.SetFrames(nsnull);
|
||||
}
|
||||
}
|
||||
@ -4921,11 +4957,14 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
NS_ASSERTION(aState.mOverflowPlaceholders.IsEmpty(),
|
||||
"Should have no overflow placeholders yet");
|
||||
|
||||
// HANDLING CONTINUATION PLACEHOLDERS (floats only at the moment, because
|
||||
// abs-pos frames don't have continuations)
|
||||
//
|
||||
// All continuation placeholders need to be moved to the front of
|
||||
// our line list. We also need to maintain the invariant that at
|
||||
// most one frame for a given piece of content is in our normal
|
||||
// child list, by pushing all but the first placeholder to our
|
||||
// overflow placeholders list
|
||||
// overflow placeholders list.
|
||||
//
|
||||
// One problem we have to deal with is that some of these
|
||||
// continuation placeholders may have been donated to us by a
|
||||
@ -4936,9 +4975,16 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
// next in flows. We do not worry about properly ordering the
|
||||
// placeholders for different content relative to each other until
|
||||
// the end. Then we sort them.
|
||||
//
|
||||
// When we're shuffling placeholders we also need to shuffle their out of
|
||||
// flows to match. As we put placeholders into keepPlaceholders, we unhook
|
||||
// their floats from mFloats. Later we put the floats back based on the
|
||||
// order of the placeholders.
|
||||
nsIFrame* lastOP = nsnull;
|
||||
nsFrameList keepPlaceholders;
|
||||
nsFrameList keepOutOfFlows;
|
||||
nsIFrame* lastKP = nsnull;
|
||||
nsIFrame* lastKOOF = nsnull;
|
||||
nsLineList* lineLists[3] = { overflowLines, &mLines, ourOverflowLines };
|
||||
static const PRPackedBool searchFirstLinesOnly[3] = { PR_FALSE, PR_TRUE, PR_FALSE };
|
||||
for (PRInt32 i = 0; i < 3; ++i) {
|
||||
@ -4968,17 +5014,31 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
"Line frames should all be continuation placeholders");
|
||||
next = f->GetNextSibling();
|
||||
nsIFrame* fpif = f->GetPrevInFlow();
|
||||
nsIFrame* oof = f->GetOutOfFlowFrame();
|
||||
|
||||
// Take this out of mFloats for now. We may put it back later in
|
||||
// this function
|
||||
#ifdef DEBUG
|
||||
PRBool found =
|
||||
#endif
|
||||
mFloats.RemoveFrame(oof);
|
||||
NS_ASSERTION(found, "Float should have been put in our mFloats list");
|
||||
|
||||
PRBool isAncestor = nsLayoutUtils::IsProperAncestorFrame(this, fpif);
|
||||
if (isAncestor) {
|
||||
// oops. we already have a prev-in-flow for this
|
||||
// placeholder. We have to move this frame out of here. We
|
||||
// can put it in our overflow placeholders.
|
||||
aState.mOverflowPlaceholders.InsertFrame(nsnull, lastOP, f);
|
||||
// Let oof dangle for now, because placeholders in
|
||||
// mOverflowPlaceholders do not keep their floats in any child list
|
||||
lastOP = f;
|
||||
} else {
|
||||
if (fpif->GetParent() == prevBlock) {
|
||||
keepPlaceholders.InsertFrame(nsnull, lastKP, f);
|
||||
keepOutOfFlows.InsertFrame(nsnull, lastKOOF, oof);
|
||||
lastKP = f;
|
||||
lastKOOF = oof;
|
||||
} else {
|
||||
// Ok, now we're in the tough situation where some child
|
||||
// of prevBlock was complete and pushed its overflow
|
||||
@ -4998,7 +5058,9 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
if (fpAncestor == prevBlock) {
|
||||
// We're still the best parent.
|
||||
keepPlaceholders.InsertFrame(nsnull, lastKP, f);
|
||||
keepOutOfFlows.InsertFrame(nsnull, lastKOOF, oof);
|
||||
lastKP = f;
|
||||
lastKOOF = oof;
|
||||
} else {
|
||||
// Just put it at the front of
|
||||
// fpAncestor->GetNextInFlow()'s lines.
|
||||
@ -5014,12 +5076,6 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
target->mLines.push_front(newLine);
|
||||
ReparentFrame(f, this, target);
|
||||
|
||||
nsIFrame* oof = f->GetOutOfFlowFrame();
|
||||
#ifdef DEBUG
|
||||
PRBool found =
|
||||
#endif
|
||||
mFloats.RemoveFrame(oof);
|
||||
NS_ASSERTION(found, "Float should have been put in our mFloats list");
|
||||
target->mFloats.InsertFrame(nsnull, nsnull, oof);
|
||||
ReparentFrame(oof, this, target);
|
||||
}
|
||||
@ -5078,6 +5134,10 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
||||
}
|
||||
mLines.push_front(newLine);
|
||||
}
|
||||
|
||||
// Put the placeholders' out of flows into the float list
|
||||
keepOutOfFlows.SortByContentOrder();
|
||||
mFloats.InsertFrames(nsnull, nsnull, keepOutOfFlows.FirstChild());
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
@ -5201,8 +5261,8 @@ nsBlockFrame::LastChild()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlockFrame::AppendFrames(nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
nsBlockFrame::AppendFrames(nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
if (nsnull == aFrameList) {
|
||||
return NS_OK;
|
||||
@ -5211,8 +5271,6 @@ nsBlockFrame::AppendFrames(nsIAtom* aListName,
|
||||
return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
|
||||
}
|
||||
else if (nsLayoutAtoms::floatList == aListName) {
|
||||
// XXX we don't *really* care about this right now because we are
|
||||
// BuildFloatList ing still
|
||||
mFloats.AppendFrames(nsnull, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -5247,18 +5305,16 @@ nsBlockFrame::AppendFrames(nsIAtom* aListName,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlockFrame::InsertFrames(nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
nsBlockFrame::InsertFrames(nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
if (mAbsoluteContainer.GetChildListName() == aListName) {
|
||||
return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame,
|
||||
aFrameList);
|
||||
}
|
||||
else if (nsLayoutAtoms::floatList == aListName) {
|
||||
// XXX we don't *really* care about this right now because we are
|
||||
// BuildFloatList'ing still
|
||||
mFloats.AppendFrames(nsnull, aFrameList);
|
||||
mFloats.InsertFrames(this, aPrevFrame, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
#ifdef IBMBIDI
|
||||
@ -5435,9 +5491,10 @@ nsBlockFrame::RemoveFloat(nsIFrame* aFloat) {
|
||||
return line_end;
|
||||
}
|
||||
}
|
||||
|
||||
// If aFloat's parent is being reflowed then mFloats may not be up
|
||||
// to date so we won't find the float above. Just delete it.
|
||||
|
||||
// If this is during reflow, it could be the out-of-flow frame for a
|
||||
// placeholder in our block reflow state's mOverflowPlaceholders. But that's
|
||||
// OK; it's not part of any child list, so we can just go ahead and delete it.
|
||||
aFloat->Destroy(GetPresContext());
|
||||
return line_end;
|
||||
}
|
||||
@ -5501,8 +5558,8 @@ static PRBool BlockHasAnyFloats(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlockFrame::RemoveFrame(nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
nsBlockFrame::RemoveFrame(nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
@ -5940,7 +5997,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||
|
||||
// An incomplete reflow status means we should split the float
|
||||
// if the height is constrained (bug 145305).
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) && (NS_UNCONSTRAINEDSIZE == availHeight))
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) && (NS_UNCONSTRAINEDSIZE == availHeight))
|
||||
aReflowStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
|
||||
@ -6964,7 +7021,6 @@ void nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList, nsIFrame*
|
||||
oofs.mList.RemoveFrame(outOfFlowFrame);
|
||||
} else {
|
||||
mFloats.RemoveFrame(outOfFlowFrame);
|
||||
|
||||
}
|
||||
aList.InsertFrame(nsnull, *aTail, outOfFlowFrame);
|
||||
*aTail = outOfFlowFrame;
|
||||
@ -6977,63 +7033,60 @@ void nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList, nsIFrame*
|
||||
}
|
||||
}
|
||||
|
||||
//XXX get rid of this -- it's slow
|
||||
void
|
||||
nsBlockFrame::BuildFloatList(nsBlockReflowState& aState)
|
||||
nsBlockFrame::CheckFloats(nsBlockReflowState& aState)
|
||||
{
|
||||
// Accumulate float list into mFloats.
|
||||
// Use the float cache to speed up searching the lines for floats.
|
||||
nsIFrame* head = nsnull;
|
||||
nsIFrame* current = nsnull;
|
||||
#ifdef DEBUG
|
||||
// Check that the float list is what we would have built
|
||||
nsAutoVoidArray lineFloats;
|
||||
for (line_iterator line = begin_lines(), line_end = end_lines();
|
||||
line != line_end;
|
||||
++line) {
|
||||
|
||||
line != line_end; ++line) {
|
||||
if (line->HasFloats()) {
|
||||
nsFloatCache* fc = line->GetFirstFloat();
|
||||
while (fc) {
|
||||
nsIFrame* floatFrame = fc->mPlaceholder->GetOutOfFlowFrame();
|
||||
if (!head) {
|
||||
current = head = floatFrame;
|
||||
} else {
|
||||
current->SetNextSibling(floatFrame);
|
||||
current = floatFrame;
|
||||
}
|
||||
lineFloats.AppendElement(floatFrame);
|
||||
fc = fc->Next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate end of float list just in case a float was removed
|
||||
if (current) {
|
||||
current->SetNextSibling(nsnull);
|
||||
}
|
||||
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();
|
||||
if (overflowLines) {
|
||||
nsFrameList oofs;
|
||||
nsIFrame* tail = nsnull;
|
||||
CollectFloats(overflowLines->front()->mFirstChild, oofs, &tail, PR_TRUE);
|
||||
|
||||
if (oofs.NotEmpty()) {
|
||||
// Floats that were pushed should be removed from our space
|
||||
// manager. Otherwise the space manager's YMost or XMost might
|
||||
// be larger than necessary, causing this block to get an
|
||||
// incorrect desired height (or width). Some of these floats
|
||||
// may not actually have been added to the space manager because
|
||||
// they weren't reflowed before being pushed; that's OK,
|
||||
// RemoveRegions will ignore them. It is safe to do this here
|
||||
// because we know from here on the space manager will only be
|
||||
// used for its XMost and YMost, not to place new floats and
|
||||
// lines.
|
||||
aState.mSpaceManager->RemoveTrailingRegions(oofs.FirstChild());
|
||||
SetOverflowOutOfFlows(oofs);
|
||||
|
||||
nsAutoVoidArray storedFloats;
|
||||
PRBool equal = PR_TRUE;
|
||||
PRInt32 i = 0;
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
storedFloats.AppendElement(f);
|
||||
if (i < lineFloats.Count() && lineFloats.ElementAt(i) != f) {
|
||||
equal = PR_FALSE;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!equal || lineFloats.Count() != storedFloats.Count()) {
|
||||
NS_WARNING("nsBlockFrame::CheckFloats: Explicit float list is out of sync with float cache");
|
||||
nsIFrameDebug::RootFrameList(GetPresContext(), stdout, 0);
|
||||
for (i = 0; i < lineFloats.Count(); ++i) {
|
||||
printf("Line float: %p\n", lineFloats.ElementAt(i));
|
||||
}
|
||||
for (i = 0; i < storedFloats.Count(); ++i) {
|
||||
printf("Stored float: %p\n", storedFloats.ElementAt(i));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsFrameList oofs = GetOverflowOutOfFlows();
|
||||
if (oofs.NotEmpty()) {
|
||||
// Floats that were pushed should be removed from our space
|
||||
// manager. Otherwise the space manager's YMost or XMost might
|
||||
// be larger than necessary, causing this block to get an
|
||||
// incorrect desired height (or width). Some of these floats
|
||||
// may not actually have been added to the space manager because
|
||||
// they weren't reflowed before being pushed; that's OK,
|
||||
// RemoveRegions will ignore them. It is safe to do this here
|
||||
// because we know from here on the space manager will only be
|
||||
// used for its XMost and YMost, not to place new floats and
|
||||
// lines.
|
||||
aState.mSpaceManager->RemoveTrailingRegions(oofs.FirstChild());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -525,7 +525,7 @@ protected:
|
||||
nsLineBox* aLine,
|
||||
nscoord aDeltaY);
|
||||
|
||||
void BuildFloatList(nsBlockReflowState& aState);
|
||||
void CheckFloats(nsBlockReflowState& aState);
|
||||
|
||||
//----------------------------------------
|
||||
// List handling kludge
|
||||
|
||||
@ -189,7 +189,11 @@ public:
|
||||
nsSize mContentArea;
|
||||
|
||||
// Placeholders for continuation out-of-flow frames that need to
|
||||
// move to our next in flow are placed here during reflow.
|
||||
// move to our next in flow are placed here during reflow. At the end of reflow
|
||||
// they move to the end of the overflow lines.
|
||||
// Their out-of-flows are not in any child list during reflow, but are added
|
||||
// to the overflow-out-of-flow list when the placeholders are appended to
|
||||
// the overflow lines.
|
||||
nsFrameList mOverflowPlaceholders;
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user