mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
Bug 411870. Make bidi resolution track lines across block continuation boundaries. r=smontagu
This commit is contained in:
parent
3f16295798
commit
fbf20e6e5d
@ -196,29 +196,37 @@ 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;
|
||||
while (parent && parent->IsFrameOfType(nsIFrame::eLineParticipant)) {
|
||||
child = parent;
|
||||
parent = child->GetParent();
|
||||
}
|
||||
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 +353,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 +430,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 +443,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;
|
||||
|
@ -5128,7 +5128,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) {
|
||||
@ -5137,6 +5137,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()
|
||||
{
|
||||
|
@ -674,9 +674,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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user