Backout bug 504524 due to test failure

This commit is contained in:
Robert O'Callahan 2009-08-05 17:33:51 +12:00
commit 9033246e16
10 changed files with 66 additions and 239 deletions

View File

@ -3816,6 +3816,16 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// Split line, but after the frame just reflowed // Split line, but after the frame just reflowed
rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus); rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (NS_INLINE_IS_BREAK_AFTER(frameReflowStatus) &&
!aLineLayout.GetLineEndsInBR()) {
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineList_iterator next = aLine.next();
if (next != end_lines() && !next->IsBlock()) {
next->MarkDirty();
}
}
} }
} }
} }
@ -3850,6 +3860,13 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
*aLineReflowStatus = LINE_REFLOW_STOP; *aLineReflowStatus = LINE_REFLOW_STOP;
rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus); rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Mark next line dirty in case SplitLine didn't end up
// pushing any frames.
nsLineList_iterator next = aLine.next();
if (next != end_lines() && !next->IsBlock()) {
next->MarkDirty();
}
} }
} }

View File

@ -177,7 +177,7 @@ public:
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval); NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval);
// Update offsets to account for new length. This may clear mTextRun. // Update offsets to account for new length. This may clear mTextRun.
void SetLength(PRInt32 aLength, nsLineLayout* aLineLayout); void SetLength(PRInt32 aLength);
NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const; NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const;

View File

@ -221,8 +221,8 @@ struct TextRunMappedFlow {
/** /**
* This is our user data for the textrun, when textRun->GetFlags() does not * This is our user data for the textrun, when textRun->GetFlags() does not
* have TEXT_IS_SIMPLE_FLOW set. When TEXT_IS_SIMPLE_FLOW is set, there is * have TEXT_SIMPLE_FLOW set. When TEXT_SIMPLE_FLOW is set, there is just one
* just one flow, the textrun's user data pointer is a pointer to mStartFrame * flow, the textrun's user data pointer is a pointer to mStartFrame
* for that flow, mDOMOffsetToBeforeTransformOffset is zero, and mContentLength * for that flow, mDOMOffsetToBeforeTransformOffset is zero, and mContentLength
* is the length of the text node. * is the length of the text node.
*/ */
@ -3779,73 +3779,53 @@ nsTextFrame::ClearTextRun()
} }
} }
static void
ClearTextRunsInFlowChain(nsTextFrame* aFrame)
{
nsTextFrame* f;
for (f = aFrame; f; f = static_cast<nsTextFrame*>(f->GetNextInFlow())) {
f->ClearTextRun();
}
}
NS_IMETHODIMP NS_IMETHODIMP
nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
{ {
// Find the first frame whose text has changed. Frames that are entirely ClearTextRunsInFlowChain(this);
// before the text change are completely unaffected.
nsTextFrame* next;
nsTextFrame* textFrame = this;
while (PR_TRUE) {
next = static_cast<nsTextFrame*>(textFrame->GetNextContinuation());
if (!next || next->GetContentOffset() > PRInt32(aInfo->mChangeStart))
break;
textFrame = next;
}
PRInt32 endOfChangedText = aInfo->mChangeStart + aInfo->mReplaceLength; nsTextFrame* targetTextFrame;
nsTextFrame* lastDirtiedFrame = nsnull; PRInt32 nodeLength = mContent->GetText()->GetLength();
nsIPresShell* shell = PresContext()->GetPresShell(); if (aInfo->mAppend) {
do { targetTextFrame = static_cast<nsTextFrame*>(GetLastContinuation());
// textFrame contained deleted text (or the insertion point, targetTextFrame->mState &= ~TEXT_WHITESPACE_FLAGS;
// if this was a pure insertion). } else {
textFrame->mState &= ~TEXT_WHITESPACE_FLAGS; // Mark all the continuation frames as dirty, and fix up content offsets to
textFrame->ClearTextRun(); // be valid.
if (!lastDirtiedFrame || // Don't set NS_FRAME_IS_DIRTY on |this|, since we call FrameNeedsReflow
lastDirtiedFrame->GetParent() != textFrame->GetParent()) { // below.
// Ask the parent frame to reflow me. nsTextFrame* textFrame = this;
shell->FrameNeedsReflow(textFrame, nsIPresShell::eStyleChange, PRInt32 newLength = nodeLength;
NS_FRAME_IS_DIRTY); do {
lastDirtiedFrame = textFrame; textFrame->mState &= ~TEXT_WHITESPACE_FLAGS;
} else { // If the text node has shrunk, clip the frame contentlength as necessary
// if the parent is a block, we're cheating here because we should if (textFrame->mContentOffset > newLength) {
// be marking our line dirty, but we're not. nsTextFrame::SetLength textFrame->mContentOffset = newLength;
// will do that when it gets called during reflow. }
textFrame->AddStateBits(NS_FRAME_IS_DIRTY);
}
// Below, frames that start after the deleted text will be adjusted so that
// their offsets move with the trailing unchanged text. If this change
// deletes more text than it inserts, those frame offsets will decrease.
// We need to maintain the invariant that mContentOffset is non-decreasing
// along the continuation chain. So we need to ensure that frames that
// started in the deleted text are all still starting before the
// unchanged text.
if (textFrame->mContentOffset > endOfChangedText) {
textFrame->mContentOffset = endOfChangedText;
}
textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation());
} while (textFrame && textFrame->GetContentOffset() < PRInt32(aInfo->mChangeEnd));
// This is how much the length of the string changed by --- i.e.,
// how much the trailing unchanged text moved.
PRInt32 sizeChange =
aInfo->mChangeStart + aInfo->mReplaceLength - aInfo->mChangeEnd;
if (sizeChange) {
// Fix the offsets of the text frames that start in the trailing
// unchanged text.
while (textFrame) {
textFrame->mContentOffset += sizeChange;
// XXX we could rescue some text runs by adjusting their user data
// to reflect the change in DOM offsets
textFrame->ClearTextRun();
textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation()); textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation());
} if (!textFrame) {
break;
}
textFrame->mState |= NS_FRAME_IS_DIRTY;
} while (1);
targetTextFrame = this;
} }
// Ask the parent frame to reflow me.
PresContext()->GetPresShell()->FrameNeedsReflow(targetTextFrame,
nsIPresShell::eStyleChange,
NS_FRAME_IS_DIRTY);
return NS_OK; return NS_OK;
} }
@ -5918,33 +5898,13 @@ HasSoftHyphenBefore(const nsTextFragment* aFrag, gfxTextRun* aTextRun,
} }
void void
nsTextFrame::SetLength(PRInt32 aLength, nsLineLayout* aLineLayout) nsTextFrame::SetLength(PRInt32 aLength)
{ {
mContentLengthHint = aLength; mContentLengthHint = aLength;
PRInt32 end = GetContentOffset() + aLength; PRInt32 end = GetContentOffset() + aLength;
nsTextFrame* f = static_cast<nsTextFrame*>(GetNextInFlow()); nsTextFrame* f = static_cast<nsTextFrame*>(GetNextInFlow());
if (!f) if (!f)
return; return;
// If our end offset is moving, then even if frames are not being pushed or
// pulled, content is moving to or from the next line and the next line
// must be reflowed.
// If the next-continuation is dirty, then we should dirty the next line now
// because we may have skipped doing it if we dirtied it in
// CharacterDataChanged. This is ugly but teaching FrameNeedsReflow
// and ChildIsDirty to handle a range of frames would be worse.
if (aLineLayout &&
(end != f->mContentOffset || (f->GetStateBits() & NS_FRAME_IS_DIRTY))) {
const nsLineList::iterator* line = aLineLayout->GetLine();
nsBlockFrame* block = do_QueryFrame(aLineLayout->GetLineContainerFrame());
if (line && block) {
nsLineList::iterator next = line->next();
if (next != block->end_lines() && !next->IsBlock()) {
next->MarkDirty();
}
}
}
if (end < f->mContentOffset) { if (end < f->mContentOffset) {
// Our frame is shrinking. Give the text to our next in flow. // Our frame is shrinking. Give the text to our next in flow.
f->mContentOffset = end; f->mContentOffset = end;
@ -5954,12 +5914,8 @@ nsTextFrame::SetLength(PRInt32 aLength, nsLineLayout* aLineLayout)
} }
return; return;
} }
// Our frame is growing. Take text from our in-flow(s).
// We can take text from frames in lines beyond just the next line.
// We don't dirty those lines. That's OK, because when we reflow
// our empty next-in-flow, it will take text from its next-in-flow and
// dirty that line.
while (f && f->mContentOffset < end) { while (f && f->mContentOffset < end) {
// Our frame is growing. Take text from our in-flow.
f->mContentOffset = end; f->mContentOffset = end;
if (f->GetTextRun() != mTextRun) { if (f->GetTextRun() != mTextRun) {
ClearTextRun(); ClearTextRun();
@ -5967,7 +5923,6 @@ nsTextFrame::SetLength(PRInt32 aLength, nsLineLayout* aLineLayout)
} }
f = static_cast<nsTextFrame*>(f->GetNextInFlow()); f = static_cast<nsTextFrame*>(f->GetNextInFlow());
} }
#ifdef DEBUG #ifdef DEBUG
f = this; f = this;
PRInt32 iterations = 0; PRInt32 iterations = 0;
@ -6091,7 +6046,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
// Layout dependent styles are a problem because we need to reconstruct // Layout dependent styles are a problem because we need to reconstruct
// the gfxTextRun based on our layout. // the gfxTextRun based on our layout.
if (lineLayout.GetInFirstLetter() || lineLayout.GetInFirstLine()) { if (lineLayout.GetInFirstLetter() || lineLayout.GetInFirstLine()) {
SetLength(maxContentLength, &lineLayout); SetLength(maxContentLength);
if (lineLayout.GetInFirstLetter()) { if (lineLayout.GetInFirstLetter()) {
// floating first-letter boundaries are significant in textrun // floating first-letter boundaries are significant in textrun
@ -6133,7 +6088,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
// Change this frame's length to the first-letter length right now // Change this frame's length to the first-letter length right now
// so that when we rebuild the textrun it will be built with the // so that when we rebuild the textrun it will be built with the
// right first-letter boundary // right first-letter boundary
SetLength(offset + length - GetContentOffset(), &lineLayout); SetLength(offset + length - GetContentOffset());
// Ensure that the textrun will be rebuilt // Ensure that the textrun will be rebuilt
ClearTextRun(); ClearTextRun();
} }
@ -6430,9 +6385,10 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
charsFit - numJustifiableCharacters); charsFit - numJustifiableCharacters);
} }
SetLength(contentLength, &lineLayout); SetLength(contentLength);
if (mContent->HasFlag(NS_TEXT_IN_SELECTION)) { if (mContent->HasFlag(NS_TEXT_IN_SELECTION)) {
// XXXroc Watch out, this could be slow!!! Speed up GetSelectionDetails?
SelectionDetails* details = GetSelectionDetails(); SelectionDetails* details = GetSelectionDetails();
if (details) { if (details) {
AddStateBits(NS_FRAME_SELECTED_CONTENT); AddStateBits(NS_FRAME_SELECTED_CONTENT);
@ -6863,7 +6819,7 @@ nsTextFrame::AdjustOffsetsForBidi(PRInt32 aStart, PRInt32 aEnd)
} }
mContentOffset = aStart; mContentOffset = aStart;
SetLength(aEnd - aStart, nsnull); SetLength(aEnd - aStart);
} }
/** /**

View File

@ -1,14 +0,0 @@
<!DOCTYPE HTML>
<html>
<body style="white-space:pre; margin:0;">
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
</body>
</html>

View File

@ -1,27 +0,0 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<head>
<script>
function doTest() {
var text = document.body.firstChild;
// Delete a line, then make a change after it
text.deleteData(8, 7);
text.replaceData(55, 1, "8");
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</head>
<body style="white-space:pre; margin:0;">
Line 1
Line 2
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line X
Line 9
</body>
</html>

View File

@ -1,25 +0,0 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<head>
<script>
function doTest() {
var text = document.body.firstChild;
// Insert a line, then make a change after it
text.insertData(8, "Line 2\n");
text.replaceData(55, 1, "8");
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</head>
<body style="white-space:pre; margin:0;">
Line 1
Line 3
Line 4
Line 5
Line 6
Line 7
Line X
Line 9
</body>
</html>

View File

@ -1,25 +0,0 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<head>
<script>
function doTest() {
var text = document.body.firstChild;
// Just make a change
text.replaceData(55, 1, "8");
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</head>
<body style="white-space:pre; margin:0;">
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line X
Line 9
</body>
</html>

View File

@ -1,26 +0,0 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<head>
<script>
function doTest() {
var text = document.body.firstChild;
// Replace three lines with two lines (but not at line boundaries)
text.replaceData(34, 21, "5\nLine 6\nLine ");
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</head>
<body style="white-space:pre; margin:0;">
Line 1
Line 2
Line 3
Line 4
Line X
Line X
Line X
Line 7
Line 8
Line 9
</body>
</html>

View File

@ -1,24 +0,0 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<head>
<script>
function doTest() {
var text = document.body.firstChild;
// Replace two lines with three lines (but not at line boundaries)
text.replaceData(34, 7, "5\nLine 6\nLine ");
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</head>
<body style="white-space:pre; margin:0;">
Line 1
Line 2
Line 3
Line 4
Line X
Line 7
Line 8
Line 9
</body>
</html>

View File

@ -12,11 +12,6 @@ random-if(MOZ_WIDGET_TOOLKIT!="cocoa") == font-size-adjust-02.html font-size-adj
== justification-1.html justification-1-ref.html == justification-1.html justification-1-ref.html
== justification-2a.html justification-2-ref.html == justification-2a.html justification-2-ref.html
== justification-2b.html justification-2-ref.html == justification-2b.html justification-2-ref.html
== line-editing-1a.html line-editing-1-ref.html
== line-editing-1b.html line-editing-1-ref.html
== line-editing-1c.html line-editing-1-ref.html
== line-editing-1d.html line-editing-1-ref.html
== line-editing-1e.html line-editing-1-ref.html
== long-1.html long-ref.html == long-1.html long-ref.html
== pre-line-1.html pre-line-1-ref.html == pre-line-1.html pre-line-1-ref.html
== pre-line-2.html pre-line-2-ref.html == pre-line-2.html pre-line-2-ref.html