Bug 411870. nsBidiPresUtils needs to track the current line across block continuation boundaries. r=smontagu

This commit is contained in:
roc+%cs.cmu.edu 2008-01-29 23:39:39 +00:00
Родитель 93766938aa
Коммит ddd44a8a49
8 изменённых файлов: 63 добавлений и 61 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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()
{

Просмотреть файл

@ -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; }
/**

Просмотреть файл

@ -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
{

Просмотреть файл

@ -153,6 +153,7 @@ public:
}
PRBool ContainsFrame(const nsIFrame* aFrame) const;
PRBool ContainsFrameBefore(const nsIFrame* aFrame, const nsIFrame* aEnd) const;
PRInt32 GetLength() const;

Просмотреть файл

@ -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
{

Просмотреть файл

@ -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;