зеркало из https://github.com/mozilla/gecko-dev.git
Bug 512471. Make nsBlockFrame's mFrames track its principal child list. r=roc,fantasai
This commit is contained in:
Родитель
cc84606bde
Коммит
7761f7af77
|
@ -299,6 +299,8 @@ nsBlockFrame::Destroy()
|
|||
nsPresContext* presContext = PresContext();
|
||||
|
||||
nsLineBox::DeleteLineList(presContext, mLines);
|
||||
// Now clear mFrames, since we've destroyed all the frames in it.
|
||||
mFrames.Clear();
|
||||
|
||||
// destroy overflow lines now
|
||||
nsLineList* overflowLines = RemoveOverflowLines();
|
||||
|
@ -521,14 +523,11 @@ nsBlockFrame::GetChildList(nsIAtom* aListName) const
|
|||
return mAbsoluteContainer.GetChildList();
|
||||
}
|
||||
else if (nsnull == aListName) {
|
||||
// XXXbz once we start using mFrames, or some other sane storage for our
|
||||
// in-flow kids, we could switch GetChildList to returning a |const
|
||||
// nsFrameList&|.
|
||||
return mLines.empty() ? nsFrameList::EmptyList()
|
||||
: nsFrameList(mLines.front()->mFirstChild,
|
||||
mLines.back()->LastChild());
|
||||
return mFrames;
|
||||
}
|
||||
else if (aListName == nsGkAtoms::overflowList) {
|
||||
// XXXbz once we start using nsFrameList for our overflow list, we
|
||||
// could switch GetChildList to returning a |const nsFrameList&|.
|
||||
nsLineList* overflowLines = GetOverflowLines();
|
||||
return overflowLines ? nsFrameList(overflowLines->front()->mFirstChild,
|
||||
overflowLines->back()->LastChild())
|
||||
|
@ -2093,11 +2092,11 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
nsBlockFrame* nextInFlow = aState.mNextInFlow;
|
||||
line_iterator nifLine = nextInFlow->begin_lines();
|
||||
nsLineBox *toMove;
|
||||
PRBool collectOverflowFloats;
|
||||
PRBool toMoveIsOverflowLine;
|
||||
if (nifLine != nextInFlow->end_lines()) {
|
||||
toMove = nifLine;
|
||||
nextInFlow->mLines.erase(nifLine);
|
||||
collectOverflowFloats = PR_FALSE;
|
||||
toMoveIsOverflowLine = PR_FALSE;
|
||||
} else {
|
||||
// Grab an overflow line if there are any
|
||||
nsLineList* overflowLines = nextInFlow->GetOverflowLines();
|
||||
|
@ -2121,7 +2120,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
} else {
|
||||
delete overflowLines;
|
||||
}
|
||||
collectOverflowFloats = PR_TRUE;
|
||||
toMoveIsOverflowLine = PR_TRUE;
|
||||
}
|
||||
|
||||
if (0 == toMove->GetChildCount()) {
|
||||
|
@ -2141,20 +2140,37 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
lastFrame = frame;
|
||||
frame = frame->GetNextSibling();
|
||||
}
|
||||
lastFrame->SetNextSibling(nsnull);
|
||||
|
||||
// Reparent floats whose placeholders are in the line.
|
||||
ReparentFloats(toMove->mFirstChild, nextInFlow, collectOverflowFloats, PR_TRUE);
|
||||
NS_ASSERTION(lastFrame == toMove->LastChild(), "Unexpected lastFrame");
|
||||
|
||||
NS_ASSERTION(aState.mPrevChild || mLines.empty(), "should have a prevchild here");
|
||||
|
||||
// Add line to our line list, and set its last child as our new prev-child
|
||||
if (aState.mPrevChild) {
|
||||
aState.mPrevChild->SetNextSibling(toMove->mFirstChild);
|
||||
}
|
||||
aState.mPrevChild = toMove->LastChild();
|
||||
NS_ASSERTION(aState.mPrevChild == mFrames.LastChild(),
|
||||
"Incorrect aState.mPrevChild before inserting line at end");
|
||||
|
||||
// Shift toMove's frames into our mFrames list.
|
||||
if (toMoveIsOverflowLine) {
|
||||
// Pulling from an overflow list
|
||||
// XXXbz If we switch overflow lines to nsFrameList, we should
|
||||
// change this SetNextSibling call.
|
||||
lastFrame->SetNextSibling(nsnull);
|
||||
} else {
|
||||
// Pulling from nextInFlow->mFrames
|
||||
nsFrameList::FrameLinkEnumerator linkToBreak(nextInFlow->mFrames, lastFrame);
|
||||
nextInFlow->mFrames.ExtractHead(linkToBreak);
|
||||
}
|
||||
nsFrameList newFrames(toMove->mFirstChild, lastFrame);
|
||||
mFrames.AppendFrames(nsnull, newFrames);
|
||||
|
||||
// Add line to our line list, and set its last child as our new prev-child
|
||||
line = mLines.before_insert(end_lines(), toMove);
|
||||
aState.mPrevChild = lastFrame;
|
||||
|
||||
NS_ASSERTION(aState.mPrevChild == mFrames.LastChild(),
|
||||
"Incorrect aState.mPrevChild after inserting line at end");
|
||||
|
||||
// Reparent floats whose placeholders are in the line.
|
||||
ReparentFloats(toMove->mFirstChild, nextInFlow, toMoveIsOverflowLine, PR_TRUE);
|
||||
|
||||
DumpLine(aState, toMove, deltaY, 0);
|
||||
#ifdef DEBUG
|
||||
|
@ -2523,8 +2539,26 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
|
|||
"mPrevChild should be the LastChild of the line we are adding to");
|
||||
// The frame is being pulled from a next-in-flow; therefore we
|
||||
// need to add it to our sibling list.
|
||||
frame->SetNextSibling(nsnull);
|
||||
aState.mPrevChild->SetNextSibling(frame);
|
||||
if (fromLine == aFromContainer->mLines.begin()) {
|
||||
// Pulling from the next-in-flow's normal line list
|
||||
aFromContainer->mFrames.RemoveFrame(frame);
|
||||
} else {
|
||||
// Pulling from the next-in-flow's overflow list
|
||||
// XXXbz If we switch overflow lines to nsFrameList, we should
|
||||
// change this SetNextSibling call.
|
||||
frame->SetNextSibling(nsnull);
|
||||
}
|
||||
|
||||
// When pushing and pulling frames we need to check for whether any
|
||||
// views need to be reparented
|
||||
NS_ASSERTION(frame->GetParent() == aFromContainer, "unexpected parent frame");
|
||||
|
||||
ReparentFrame(frame, aFromContainer, this);
|
||||
mFrames.InsertFrame(nsnull, aState.mPrevChild, frame);
|
||||
|
||||
// The frame might have (or contain) floats that need to be
|
||||
// brought over too.
|
||||
ReparentFloats(frame, aFromContainer, aFromOverflowLine, PR_TRUE);
|
||||
}
|
||||
// when aFromContainer is 'this', then aLine->LastChild()'s next sibling
|
||||
// is already set correctly.
|
||||
|
@ -2564,19 +2598,6 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
|
|||
}
|
||||
}
|
||||
|
||||
// Change geometric parents
|
||||
if (aFromContainer != this) {
|
||||
// When pushing and pulling frames we need to check for whether any
|
||||
// views need to be reparented
|
||||
NS_ASSERTION(frame->GetParent() == aFromContainer, "unexpected parent frame");
|
||||
|
||||
ReparentFrame(frame, aFromContainer, this);
|
||||
|
||||
// The frame might have (or contain) floats that need to be
|
||||
// brought over too.
|
||||
ReparentFloats(frame, aFromContainer, aFromOverflowLine, PR_TRUE);
|
||||
}
|
||||
|
||||
// Stop pulling because we found a frame to pull
|
||||
aFrameResult = frame;
|
||||
#ifdef DEBUG
|
||||
|
@ -3172,8 +3193,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (parent != this)
|
||||
ReparentFrame(nextFrame, parent, this);
|
||||
nextFrame->SetNextSibling(frame->GetNextSibling());
|
||||
frame->SetNextSibling(nextFrame);
|
||||
mFrames.InsertFrame(nsnull, frame, nextFrame);
|
||||
madeContinuation = PR_TRUE; // needs to be added to mLines
|
||||
nextFrame->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
|
||||
frameReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
|
||||
|
@ -3241,8 +3261,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else if (madeContinuation) {
|
||||
frame->SetNextSibling(nextFrame->GetNextSibling());
|
||||
nextFrame->SetNextSibling(nsnull);
|
||||
mFrames.RemoveFrame(nextFrame, frame);
|
||||
}
|
||||
|
||||
// Put it in our overflow list
|
||||
|
@ -3861,9 +3880,7 @@ nsBlockFrame::CreateContinuationFor(nsBlockReflowState& aState,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsIFrame* sib = aFrame->GetNextSibling();
|
||||
aFrame->SetNextSibling(newFrame);
|
||||
newFrame->SetNextSibling(sib);
|
||||
mFrames.InsertFrame(nsnull, aFrame, newFrame);
|
||||
|
||||
if (aLine) {
|
||||
aLine->SetChildCount(aLine->GetChildCount() + 1);
|
||||
|
@ -4278,8 +4295,17 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
|
|||
overflowLines = new nsLineList();
|
||||
}
|
||||
if (overflowLines) {
|
||||
// First, remove the frames we're pushing from mFrames
|
||||
nsIFrame* oldLastChild = mFrames.LastChild();
|
||||
if (firstLine) {
|
||||
mFrames.Clear();
|
||||
} else {
|
||||
mFrames.RemoveFramesAfter(aLineBefore->LastChild());
|
||||
}
|
||||
if (!overflowLines->empty()) {
|
||||
mLines.back()->LastChild()->SetNextSibling(overflowLines->front()->mFirstChild);
|
||||
// XXXbz If we switch overflow lines to nsFrameList, we should
|
||||
// change this SetNextSibling call.
|
||||
oldLastChild->SetNextSibling(overflowLines->front()->mFirstChild);
|
||||
}
|
||||
overflowLines->splice(overflowLines->begin(), mLines, overBegin,
|
||||
end_lines());
|
||||
|
@ -4307,10 +4333,6 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
|
|||
}
|
||||
}
|
||||
|
||||
// Break frame sibling list
|
||||
if (!firstLine)
|
||||
aLineBefore->LastChild()->SetNextSibling(nsnull);
|
||||
|
||||
#ifdef DEBUG
|
||||
VerifyOverflowSituation();
|
||||
#endif
|
||||
|
@ -4379,15 +4401,18 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
|||
if (overflowLines) {
|
||||
if (!overflowLines->empty()) {
|
||||
// Join the line lists
|
||||
if (! mLines.empty())
|
||||
{
|
||||
if (!mLines.empty()) {
|
||||
// Remember to recompute the margins on the first line. This will
|
||||
// also recompute the correct deltaY if necessary.
|
||||
mLines.front()->MarkPreviousMarginDirty();
|
||||
// Join the sibling lists together
|
||||
nsIFrame* lastFrame = overflowLines->back()->LastChild();
|
||||
lastFrame->SetNextSibling(mLines.front()->mFirstChild);
|
||||
}
|
||||
}
|
||||
|
||||
// Join the sibling lists together
|
||||
nsIFrame* firstFrame = overflowLines->front()->mFirstChild;
|
||||
nsIFrame* lastFrame = overflowLines->back()->LastChild();
|
||||
nsFrameList framesToInsert(firstFrame, lastFrame);
|
||||
mFrames.InsertFrames(nsnull, nsnull, framesToInsert);
|
||||
|
||||
// Place overflow lines at the front of our line list
|
||||
mLines.splice(mLines.begin(), *overflowLines);
|
||||
NS_ASSERTION(overflowLines->empty(), "splice should empty list");
|
||||
|
@ -4396,10 +4421,11 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
|||
}
|
||||
if (ourOverflowLines) {
|
||||
if (!ourOverflowLines->empty()) {
|
||||
if (!mLines.empty()) {
|
||||
mLines.back()->LastChild()->
|
||||
SetNextSibling(ourOverflowLines->front()->mFirstChild);
|
||||
}
|
||||
nsIFrame* firstFrame = ourOverflowLines->front()->mFirstChild;
|
||||
nsIFrame* lastFrame = ourOverflowLines->back()->LastChild();
|
||||
nsFrameList framesToAppend(firstFrame, lastFrame);
|
||||
mFrames.AppendFrames(nsnull, framesToAppend);
|
||||
|
||||
// append the overflow to mLines
|
||||
mLines.splice(mLines.end(), *ourOverflowLines);
|
||||
}
|
||||
|
@ -4664,7 +4690,6 @@ nsBlockFrame::InsertFrames(nsIAtom* aListName,
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
aFrameList.Clear();
|
||||
#ifdef IBMBIDI
|
||||
if (aListName != nsGkAtoms::nextBidi)
|
||||
#endif // IBMBIDI
|
||||
|
@ -4687,8 +4712,7 @@ ShouldPutNextSiblingOnNewLine(nsIFrame* aLastFrame)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsBlockFrame::AddFrames(const nsFrameList& aFrameList,
|
||||
nsIFrame* aPrevSibling)
|
||||
nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling)
|
||||
{
|
||||
// Clear our line cursor, since our lines may change.
|
||||
ClearLineCursor();
|
||||
|
@ -4729,16 +4753,13 @@ nsBlockFrame::AddFrames(const nsFrameList& aFrameList,
|
|||
|
||||
// Find the frame following aPrevSibling so that we can join up the
|
||||
// two lists of frames.
|
||||
nsIFrame* prevSiblingNextFrame = nsnull;
|
||||
if (aPrevSibling) {
|
||||
prevSiblingNextFrame = aPrevSibling->GetNextSibling();
|
||||
|
||||
// Split line containing aPrevSibling in two if the insertion
|
||||
// point is somewhere in the middle of the line.
|
||||
PRInt32 rem = prevSibLine->GetChildCount() - prevSiblingIndex - 1;
|
||||
if (rem) {
|
||||
// Split the line in two where the frame(s) are being inserted.
|
||||
nsLineBox* line = NS_NewLineBox(presShell, prevSiblingNextFrame, rem, PR_FALSE);
|
||||
nsLineBox* line = NS_NewLineBox(presShell, aPrevSibling->GetNextSibling(), rem, PR_FALSE);
|
||||
if (!line) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -4753,20 +4774,20 @@ nsBlockFrame::AddFrames(const nsFrameList& aFrameList,
|
|||
line->MarkDirty();
|
||||
line->SetInvalidateTextRuns(PR_TRUE);
|
||||
}
|
||||
|
||||
// Now (partially) join the sibling lists together
|
||||
aPrevSibling->SetNextSibling(aFrameList.FirstChild());
|
||||
}
|
||||
else if (! mLines.empty()) {
|
||||
prevSiblingNextFrame = mLines.front()->mFirstChild;
|
||||
mLines.front()->MarkDirty();
|
||||
mLines.front()->SetInvalidateTextRuns(PR_TRUE);
|
||||
}
|
||||
const nsFrameList::Slice& newFrames =
|
||||
mFrames.InsertFrames(nsnull, aPrevSibling, aFrameList);
|
||||
|
||||
// Walk through the new frames being added and update the line data
|
||||
// structures to fit.
|
||||
nsIFrame* newFrame = aFrameList.FirstChild();
|
||||
while (newFrame) {
|
||||
for (nsFrameList::Enumerator e(newFrames); !e.AtEnd(); e.Next()) {
|
||||
nsIFrame* newFrame = e.get();
|
||||
NS_ASSERTION(!aPrevSibling || aPrevSibling->GetNextSibling() == newFrame,
|
||||
"Unexpected aPrevSibling");
|
||||
NS_ASSERTION(newFrame->GetType() != nsGkAtoms::placeholderFrame ||
|
||||
(!newFrame->GetStyleDisplay()->IsAbsolutelyPositioned() &&
|
||||
!newFrame->GetStyleDisplay()->IsFloating()),
|
||||
|
@ -4807,11 +4828,6 @@ nsBlockFrame::AddFrames(const nsFrameList& aFrameList,
|
|||
}
|
||||
|
||||
aPrevSibling = newFrame;
|
||||
newFrame = newFrame->GetNextSibling();
|
||||
}
|
||||
if (prevSiblingNextFrame) {
|
||||
// Connect the last new frame to the remainder of the sibling list
|
||||
aPrevSibling->SetNextSibling(prevSiblingNextFrame);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -5270,8 +5286,14 @@ found_frame:;
|
|||
// Take aDeletedFrame out of the sibling list. Note that
|
||||
// prevSibling will only be nsnull when we are deleting the very
|
||||
// first frame in the main or overflow list.
|
||||
if (prevSibling) {
|
||||
prevSibling->SetNextSibling(nextFrame);
|
||||
if (searchingOverflowList) {
|
||||
if (prevSibling) {
|
||||
// XXXbz If we switch overflow lines to nsFrameList, we should
|
||||
// change this SetNextSibling call.
|
||||
prevSibling->SetNextSibling(nextFrame);
|
||||
}
|
||||
} else {
|
||||
mFrames.RemoveFrame(aDeletedFrame, prevSibling);
|
||||
}
|
||||
|
||||
// Update the child count of the line to be accurate
|
||||
|
@ -5370,7 +5392,7 @@ found_frame:;
|
|||
// We switched to the overflow line list and we have a prev sibling
|
||||
// (in the main list), in this case we don't want to pick up any
|
||||
// sibling list from the deceased frames (bug 344557).
|
||||
prevSibling->SetNextSibling(nsnull);
|
||||
NS_ASSERTION(!prevSibling->GetNextSibling(), "Unexpected next sibling");
|
||||
prevSibling = nsnull;
|
||||
}
|
||||
#ifdef NOISY_REMOVE_FRAME
|
||||
|
@ -5435,11 +5457,18 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext,
|
|||
while (--n >= 0) {
|
||||
if (frame == aChild) {
|
||||
// Disconnect from sibling list
|
||||
if (prevSibling)
|
||||
prevSibling->SetNextSibling(frame->GetNextSibling());
|
||||
else
|
||||
if (frame == line->mFirstChild) {
|
||||
line->mFirstChild = frame->GetNextSibling();
|
||||
frame->SetNextSibling(nsnull);
|
||||
}
|
||||
if (searchingOverflowList) {
|
||||
// XXXbz If we switch overflow lines to nsFrameList, we should
|
||||
// change this SetNextSibling call.
|
||||
if (prevSibling)
|
||||
prevSibling->SetNextSibling(frame->GetNextSibling());
|
||||
frame->SetNextSibling(nsnull);
|
||||
} else {
|
||||
mFrames.RemoveFrame(frame, prevSibling);
|
||||
}
|
||||
|
||||
// Register removal with the line boxes
|
||||
PRInt32 count = line->GetChildCount();
|
||||
|
@ -5479,6 +5508,10 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext,
|
|||
}
|
||||
++line;
|
||||
TryAllLines(&line, &line_start, &line_end, &searchingOverflowList);
|
||||
if (prevSibling && !prevSibling->GetNextSibling()) {
|
||||
// We just switched to the overflow list. Null out prevSibling
|
||||
prevSibling = nsnull;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -6325,7 +6358,6 @@ nsBlockFrame::SetInitialChildList(nsIAtom* aListName,
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
aChildList.Clear();
|
||||
|
||||
// Create list bullet if this is a list-item. Note that this is done
|
||||
// here so that RenumberLists will work (it needs the bullets to
|
||||
|
@ -6366,7 +6398,8 @@ nsBlockFrame::SetInitialChildList(nsIAtom* aListName,
|
|||
// it to the flow now.
|
||||
if (NS_STYLE_LIST_STYLE_POSITION_INSIDE ==
|
||||
styleList->mListStylePosition) {
|
||||
AddFrames(nsFrameList(bullet, bullet), nsnull);
|
||||
nsFrameList bulletList(bullet, bullet);
|
||||
AddFrames(bulletList, nsnull);
|
||||
mState &= ~NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -400,9 +400,9 @@ protected:
|
|||
* knows nothing about lines at all. So we need to find the line that
|
||||
* contains aPrevSibling and add aFrameList after aPrevSibling on that line.
|
||||
* new lines are created as necessary to handle block data in aFrameList.
|
||||
* This function will clear aFrameList.
|
||||
*/
|
||||
virtual nsresult AddFrames(const nsFrameList& aFrameList,
|
||||
nsIFrame* aPrevSibling);
|
||||
virtual nsresult AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling);
|
||||
|
||||
#ifdef IBMBIDI
|
||||
/**
|
||||
|
|
|
@ -416,6 +416,11 @@ public:
|
|||
mPrev(aOther.mPrev)
|
||||
{}
|
||||
|
||||
/* This constructor needs to know about nsIFrame, and nsIFrame will need to
|
||||
know about nsFrameList methods, so in order to inline this put
|
||||
the implementation in nsIFrame.h */
|
||||
inline FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame);
|
||||
|
||||
void operator=(const FrameLinkEnumerator& aOther) {
|
||||
NS_PRECONDITION(&List() == &aOther.List(), "Different lists?");
|
||||
mFrame = aOther.mFrame;
|
||||
|
|
|
@ -2543,4 +2543,12 @@ nsFrameList::Enumerator::Next()
|
|||
mFrame = mFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
inline
|
||||
nsFrameList::FrameLinkEnumerator::
|
||||
FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
|
||||
: Enumerator(aList)
|
||||
{
|
||||
mPrev = aPrevFrame;
|
||||
mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
|
||||
}
|
||||
#endif /* nsIFrame_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче