diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index db2dd1f50d1..d4e0143d72a 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -90,5 +90,5 @@ load 405186-1.xhtml load 408292.html load 408299.html load 409461-1.xhtml -# load 411870-1.html +load 411870-1.html diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index 1649cc70c8a..794ce8c6aff 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -196,29 +196,38 @@ CreateBidiContinuation(nsIFrame* aFrame, } static PRBool +IsFrameInCurrentLine(nsBlockInFlowLineIterator* aLineIter, + nsIFrame* aPrevFrame, nsIFrame* aFrame) +{ + nsIFrame* endFrame = aLineIter->IsLastLineInList() ? nsnull : + aLineIter->GetLine().next()->mFirstChild; + nsIFrame* startFrame = aPrevFrame ? aPrevFrame : aLineIter->GetLine()->mFirstChild; + return nsFrameList(startFrame).ContainsFrameBefore(aFrame, endFrame); +} + +static void AdvanceLineIteratorToFrame(nsIFrame* aFrame, - nsIFrame* aBlockFrame, - nsBlockFrame::line_iterator& aLine, - nsIFrame*& aPrevFrame, - const nsBlockFrame::line_iterator& aEndLines) + nsBlockInFlowLineIterator* aLineIter, + nsIFrame*& aPrevFrame) { // Advance aLine to the line containing aFrame nsIFrame* child = aFrame; - nsIFrame* parent = child->GetParent(); - while (parent && parent != aBlockFrame) { - if (parent->GetStyleDisplay()->IsBlockOutside()) - return PR_FALSE; + nsFrameManager* frameManager = aFrame->PresContext()->FrameManager(); + nsIFrame* parent = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, child); + while (parent && !nsLayoutUtils::GetAsBlock(parent)) { child = parent; - parent = child->GetParent(); + parent = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, child); } NS_ASSERTION (parent, "aFrame is not a descendent of aBlockFrame"); - while (aLine != aEndLines && !aLine->ContainsAfter(aPrevFrame, child, aLine, aEndLines)) { - ++aLine; + while (!IsFrameInCurrentLine(aLineIter, aPrevFrame, child)) { +#ifdef DEBUG + PRBool hasNext = +#endif + aLineIter->Next(); + NS_ASSERTION(hasNext, "Can't find frame in lines!"); aPrevFrame = nsnull; } aPrevFrame = child; - NS_ASSERTION (aLine != aEndLines, "frame not found on any line"); - return PR_TRUE; } /* @@ -345,8 +354,11 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame, nsPropertyTable *propTable = presContext->PropertyTable(); - nsBlockFrame::line_iterator line = aBlockFrame->begin_lines(); - nsBlockFrame::line_iterator endLines = aBlockFrame->end_lines(); + nsBlockInFlowLineIterator lineIter(aBlockFrame, aBlockFrame->begin_lines(), PR_FALSE); + if (lineIter.GetLine() == aBlockFrame->end_lines()) { + // Advance to first valid line (might be in a next-continuation) + lineIter.Next(); + } nsIFrame* prevFrame = nsnull; PRBool lineNeedsUpdate = PR_FALSE; @@ -419,12 +431,10 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame, break; } if (lineNeedsUpdate) { - if (AdvanceLineIteratorToFrame(frame, aBlockFrame, line, - prevFrame, endLines)) { - lineNeedsUpdate = PR_FALSE; - } + AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame); + lineNeedsUpdate = PR_FALSE; } - line->MarkDirty(); + lineIter.GetLine()->MarkDirty(); frame = nextBidi; contentOffset += runLength; } // if (runLength < fragmentLength) @@ -434,12 +444,10 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame, if (newIndex > frameIndex) { RemoveBidiContinuation(frame, frameIndex, newIndex, temp); if (lineNeedsUpdate) { - if (AdvanceLineIteratorToFrame(frame, aBlockFrame, line, - prevFrame, endLines)) { - lineNeedsUpdate = PR_FALSE; - } + AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame); + lineNeedsUpdate = PR_FALSE; } - line->MarkDirty(); + lineIter.GetLine()->MarkDirty(); runLength -= temp; fragmentLength -= temp; lineOffset += temp; diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index bb6534b3d27..a928de2568d 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -5150,7 +5150,7 @@ nsBlockFrame::TryAllLines(nsLineList::iterator* aIterator, } nsBlockInFlowLineIterator::nsBlockInFlowLineIterator(nsBlockFrame* aFrame, - line_iterator& aLine, PRBool aInOverflow) + line_iterator aLine, PRBool aInOverflow) : mFrame(aFrame), mLine(aLine), mInOverflowLines(nsnull) { if (aInOverflow) { @@ -5159,6 +5159,13 @@ nsBlockInFlowLineIterator::nsBlockInFlowLineIterator(nsBlockFrame* aFrame, } } +PRBool +nsBlockInFlowLineIterator::IsLastLineInList() +{ + line_iterator end = mInOverflowLines ? mInOverflowLines->end() : mFrame->end_lines(); + return mLine != end && mLine.next() == end; +} + PRBool nsBlockInFlowLineIterator::Next() { diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 88e3e708655..7b6db0bb426 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -690,9 +690,10 @@ private: class nsBlockInFlowLineIterator { public: typedef nsBlockFrame::line_iterator line_iterator; - nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator& aLine, PRBool aInOverflow); - + nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator aLine, PRBool aInOverflow); + line_iterator GetLine() { return mLine; } + PRBool IsLastLineInList(); nsBlockFrame* GetContainer() { return mFrame; } PRBool GetInOverflow() { return mInOverflowLines != nsnull; } /** diff --git a/layout/generic/nsFrameList.cpp b/layout/generic/nsFrameList.cpp index 47f352e72ad..bbbbb8e5923 100644 --- a/layout/generic/nsFrameList.cpp +++ b/layout/generic/nsFrameList.cpp @@ -296,6 +296,23 @@ nsFrameList::ContainsFrame(const nsIFrame* aFrame) const return PR_FALSE; } +PRBool +nsFrameList::ContainsFrameBefore(const nsIFrame* aFrame, const nsIFrame* aEnd) const +{ + NS_PRECONDITION(nsnull != aFrame, "null ptr"); + nsIFrame* frame = mFirstChild; + while (frame) { + if (frame == aEnd) { + return PR_FALSE; + } + if (frame == aFrame) { + return PR_TRUE; + } + frame = frame->GetNextSibling(); + } + return PR_FALSE; +} + PRInt32 nsFrameList::GetLength() const { diff --git a/layout/generic/nsFrameList.h b/layout/generic/nsFrameList.h index 31036670cdb..24daf053a6b 100644 --- a/layout/generic/nsFrameList.h +++ b/layout/generic/nsFrameList.h @@ -153,6 +153,7 @@ public: } PRBool ContainsFrame(const nsIFrame* aFrame) const; + PRBool ContainsFrameBefore(const nsIFrame* aFrame, const nsIFrame* aEnd) const; PRInt32 GetLength() const; diff --git a/layout/generic/nsLineBox.cpp b/layout/generic/nsLineBox.cpp index b745ea81826..047598dcf3f 100644 --- a/layout/generic/nsLineBox.cpp +++ b/layout/generic/nsLineBox.cpp @@ -276,29 +276,6 @@ nsLineBox::IndexOf(nsIFrame* aFrame) const return -1; } -PRBool -nsLineBox::ContainsAfter(nsIFrame* aFrameInLine, - nsIFrame* aFrameToFind, - nsLineList::iterator aLineIter, - const nsLineList::iterator& aEndLines) const -{ - nsIFrame* firstFrameOnNextLine = nsnull; - ++aLineIter; - if (aLineIter != aEndLines) - firstFrameOnNextLine = aLineIter->mFirstChild; - - nsIFrame* frame = aFrameInLine; - if (!frame) - frame = mFirstChild; - - while (frame && frame != firstFrameOnNextLine) { - if (frame == aFrameToFind) - return PR_TRUE; - frame = frame->GetNextSibling(); - } - return PR_FALSE; -} - PRBool nsLineBox::IsEmpty() const { diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index bb032a4a0af..75d9b45533f 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -455,15 +455,6 @@ public: return IndexOf(aFrame) >= 0; } - // Search the line for aFrameToFind, going forward from aFrameInLine - // (or from the beginning of the line, if aFrameInLine is null). - // aLineIterator is a line iterator pointing to the line. - // aEndLine should point to the block's end_lines. - PRBool ContainsAfter(nsIFrame* aFrameInLine, - nsIFrame* aFrameToFind, - nsLineList_iterator aLineIter, - const nsLineList_iterator& aEndLines) const; - // whether the line box is "logically" empty (just like nsIFrame::IsEmpty) PRBool IsEmpty() const;