diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index badae074f7d..782dc123618 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -5607,66 +5607,12 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, uint32_t aFlags) return RemoveBlockChild(aDeletedFrame, !(aFlags & REMOVE_FIXED_CONTINUATIONS)); } -static bool -FindBlockLineFor(nsIFrame* aChild, - nsLineList::iterator aBegin, - nsLineList::iterator aEnd, - nsLineList::iterator* aResult) -{ - MOZ_ASSERT(aChild->IsBlockOutside()); - for (nsLineList::iterator line = aBegin; line != aEnd; ++line) { - MOZ_ASSERT(line->GetChildCount() > 0); - if (line->IsBlock() && line->mFirstChild == aChild) { - MOZ_ASSERT(line->GetChildCount() == 1); - *aResult = line; - return true; - } - } - return false; -} - -static bool -FindInlineLineFor(nsIFrame* aChild, - const nsFrameList& aFrameList, - nsLineList::iterator aBegin, - nsLineList::iterator aEnd, - nsLineList::iterator* aResult) -{ - MOZ_ASSERT(!aChild->IsBlockOutside()); - for (nsLineList::iterator line = aBegin; line != aEnd; ++line) { - MOZ_ASSERT(line->GetChildCount() > 0); - if (!line->IsBlock()) { - // Optimize by comparing the line's last child first. - nsLineList::iterator next = line.next(); - if (aChild == (next == aEnd ? aFrameList.LastChild() - : next->mFirstChild->GetPrevSibling()) || - line->Contains(aChild)) { - *aResult = line; - return true; - } - } - } - return false; -} - -static bool -FindLineFor(nsIFrame* aChild, - const nsFrameList& aFrameList, - nsLineList::iterator aBegin, - nsLineList::iterator aEnd, - nsLineList::iterator* aResult) -{ - return aChild->IsBlockOutside() ? - FindBlockLineFor(aChild, aBegin, aEnd, aResult) : - FindInlineLineFor(aChild, aFrameList, aBegin, aEnd, aResult); -} - nsresult nsBlockFrame::StealFrame(nsPresContext* aPresContext, nsIFrame* aChild, bool aForceNormal) { - MOZ_ASSERT(aChild->GetParent() == this); + NS_PRECONDITION(aPresContext && aChild, "null pointer"); if ((aChild->GetStateBits() & NS_FRAME_OUT_OF_FLOW) && aChild->IsFloating()) { @@ -5675,52 +5621,81 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext, } if ((aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) - && !aForceNormal) { + && !aForceNormal) return nsContainerFrame::StealFrame(aPresContext, aChild); - } - MOZ_ASSERT(!(aChild->GetStateBits() & NS_FRAME_OUT_OF_FLOW)); + // Find the line and the previous sibling that contains + // aChild; we also find the pointer to the line. + nsLineList::iterator line = mLines.begin(), + line_start = line, + line_end = mLines.end(); + bool searchingOverflowList = false; + FrameLines* overflowLines = nullptr; + nsIFrame* prevSibling = nullptr; + // Make sure we look in the overflow lines even if the normal line + // list is empty + TryAllLines(&line, &line_start, &line_end, &searchingOverflowList, + &overflowLines); + while (line != line_end) { + nsIFrame* frame = line->mFirstChild; + int32_t n = line->GetChildCount(); + while (--n >= 0) { + if (frame == aChild) { + if (frame == line->mFirstChild) { + line->mFirstChild = frame->GetNextSibling(); + } + if (searchingOverflowList) { + overflowLines->mFrames.RemoveFrame(frame); + } else { + mFrames.RemoveFrame(frame); + } - nsLineList::iterator line; - if (FindLineFor(aChild, mFrames, mLines.begin(), mLines.end(), &line)) { - RemoveFrameFromLine(aChild, line, mFrames, mLines); - } else { - FrameLines* overflowLines = GetOverflowLines(); - DebugOnly found; - found = FindLineFor(aChild, overflowLines->mFrames, - overflowLines->mLines.begin(), - overflowLines->mLines.end(), &line); - MOZ_ASSERT(found); - RemoveFrameFromLine(aChild, line, overflowLines->mFrames, - overflowLines->mLines); - if (overflowLines->mLines.empty()) { - DestroyOverflowLines(); + // Register removal with the line boxes + line->NoteFrameRemoved(frame); + if (line->GetChildCount() > 0) { + line->MarkDirty(); + } else { + // Remove the line box + nsLineBox* lineBox = line; + if (searchingOverflowList) { + // Erase the line, destroy the property if it was the last one. + line = overflowLines->mLines.erase(line); + if (overflowLines->mLines.empty()) { + DestroyOverflowLines(); + overflowLines = nullptr; + // We just invalidated our iterators. Since we were in + // the overflow lines list, which is now empty, set them + // so we're at the end of the regular line list. + line_start = mLines.begin(); + line_end = mLines.end(); + line = line_end; + } + } else { + line = mLines.erase(line); + } + FreeLineBox(lineBox); + if (line != line_end) { + // Line disappeared, so tell next line it may have to change position + line->MarkPreviousMarginDirty(); + } + } + + // Ok, we're done + return NS_OK; + } + prevSibling = frame; + frame = frame->GetNextSibling(); + } + ++line; + TryAllLines(&line, &line_start, &line_end, &searchingOverflowList, + &overflowLines); + if (prevSibling && !prevSibling->GetNextSibling()) { + // We just switched to the overflow list. Null out prevSibling + prevSibling = nullptr; } } - - return NS_OK; -} - -void -nsBlockFrame::RemoveFrameFromLine(nsIFrame* aChild, nsLineList::iterator aLine, - nsFrameList& aFrameList, nsLineList& aLineList) -{ - aFrameList.RemoveFrame(aChild); - if (aChild == aLine->mFirstChild) { - aLine->mFirstChild = aChild->GetNextSibling(); - } - aLine->NoteFrameRemoved(aChild); - if (aLine->GetChildCount() > 0) { - aLine->MarkDirty(); - } else { - // The line became empty - destroy it. - nsLineBox* lineBox = aLine; - aLine = aLineList.erase(aLine); - if (aLine != aLineList.end()) { - aLine->MarkPreviousMarginDirty(); - } - FreeLineBox(lineBox); - } + MOZ_ASSERT(false, "StealFrame failed to remove the frame"); + return NS_ERROR_UNEXPECTED; } void diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 4f26ad1d456..8e8714c3086 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -384,11 +384,6 @@ protected: } aLine->Destroy(PresContext()->PresShell()); } - /** - * Helper method for StealFrame. - */ - void RemoveFrameFromLine(nsIFrame* aChild, nsLineList::iterator aLine, - nsFrameList& aFrameList, nsLineList& aLineList); void TryAllLines(nsLineList::iterator* aIterator, nsLineList::iterator* aStartIterator, diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 5408b7ba731..3c6059fff22 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -747,9 +747,7 @@ nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild, nsIntPoint* aCellIndex) { // reflow the child - nsHTMLReflowState reflowState(aPresContext, aReflowState, aChild, aSize); - reflowState.SetComputedWidth(std::max(0, aSize.width - reflowState.mComputedBorderPadding.LeftRight())); - reflowState.SetComputedHeight(std::max(0, aSize.height - reflowState.mComputedBorderPadding.TopBottom())); + nsHTMLReflowState reflowState(aPresContext, aReflowState, aChild, aSize); nsHTMLReflowMetrics metrics; metrics.width = aSize.width; metrics.height= aSize.height; diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index f801755f3e8..70e60bba066 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -677,19 +677,28 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext, NS_ASSERTION(mContent->GetPrimaryFrame() == this, "Shouldn't happen"); - // XUL