(Patch #2 to fix Bug 431260) Bug 455826 - Look into overflow-lists of inlines to find text when we're building textruns. Patch by Robert O'Callahan <robert@ocallahan.org> r=smontagu

git-svn-id: svn://10.0.0.236/trunk@256332 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dholbert%cs.stanford.edu
2009-02-26 20:20:31 +00:00
parent 2fa4de5805
commit f1bca53a79
4 changed files with 59 additions and 19 deletions

View File

@@ -747,10 +747,32 @@ TextContainsLineBreakerWhiteSpace(const void* aText, PRUint32 aLength,
}
struct FrameTextTraversal {
nsIFrame* mFrameToDescendInto;
PRPackedBool mDescendIntoFrameSiblings;
// These fields identify which frames should be recursively scanned
// The first normal frame to scan (or null, if no such frame should be scanned)
nsIFrame* mFrameToScan;
// The first overflow frame to scan (or null, if no such frame should be scanned)
nsIFrame* mOverflowFrameToScan;
// Whether to scan the siblings of mFrameToDescendInto/mOverflowFrameToDescendInto
PRPackedBool mScanSiblings;
// These identify the boundaries of the context required for
// line breaking or textrun construction
PRPackedBool mLineBreakerCanCrossFrameBoundary;
PRPackedBool mTextRunCanCrossFrameBoundary;
nsIFrame* NextFrameToScan() {
nsIFrame* f;
if (mFrameToScan) {
f = mFrameToScan;
mFrameToScan = mScanSiblings ? f->GetNextSibling() : nsnull;
} else if (mOverflowFrameToScan) {
f = mOverflowFrameToScan;
mOverflowFrameToScan = mScanSiblings ? f->GetNextSibling() : nsnull;
} else {
f = nsnull;
}
return f;
}
};
static FrameTextTraversal
@@ -765,28 +787,33 @@ CanTextCrossFrameBoundary(nsIFrame* aFrame, nsIAtom* aType)
// placeholders are "invisible", so a text run should be able to span
// across one. But don't descend into the out-of-flow.
result.mLineBreakerCanCrossFrameBoundary = PR_TRUE;
result.mOverflowFrameToScan = nsnull;
if (continuesTextRun) {
// ... Except for first-letter floats, which are really in-flow
// from the point of view of capitalization etc, so we'd better
// descend into them. But we actually need to break the textrun for
// first-letter floats since things look bad if, say, we try to make a
// ligature across the float boundary.
result.mFrameToDescendInto =
result.mFrameToScan =
(static_cast<nsPlaceholderFrame*>(aFrame))->GetOutOfFlowFrame();
result.mDescendIntoFrameSiblings = PR_FALSE;
result.mScanSiblings = PR_FALSE;
result.mTextRunCanCrossFrameBoundary = PR_FALSE;
} else {
result.mFrameToDescendInto = nsnull;
result.mFrameToScan = nsnull;
result.mTextRunCanCrossFrameBoundary = PR_TRUE;
}
} else {
if (continuesTextRun) {
result.mFrameToDescendInto = aFrame->GetFirstChild(nsnull);
result.mDescendIntoFrameSiblings = PR_TRUE;
result.mFrameToScan = aFrame->GetFirstChild(nsnull);
result.mOverflowFrameToScan = aFrame->GetFirstChild(nsGkAtoms::overflowList);
NS_WARN_IF_FALSE(!result.mOverflowFrameToScan,
"Scanning overflow inline frames is something we should avoid");
result.mScanSiblings = PR_TRUE;
result.mTextRunCanCrossFrameBoundary = PR_TRUE;
result.mLineBreakerCanCrossFrameBoundary = PR_TRUE;
} else {
result.mFrameToDescendInto = nsnull;
result.mFrameToScan = nsnull;
result.mOverflowFrameToScan = nsnull;
result.mTextRunCanCrossFrameBoundary = PR_FALSE;
result.mLineBreakerCanCrossFrameBoundary = PR_FALSE;
}
@@ -842,13 +869,11 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState
return FB_FOUND_VALID_TEXTRUN_BOUNDARY;
}
for (nsIFrame* f = traversal.mFrameToDescendInto; f;
f = f->GetNextSibling()) {
for (nsIFrame* f = traversal.NextFrameToScan(); f;
f = traversal.NextFrameToScan()) {
FindBoundaryResult result = FindBoundaries(f, aState);
if (result != FB_CONTINUE)
return result;
if (!traversal.mDescendIntoFrameSiblings)
break;
}
if (!traversal.mTextRunCanCrossFrameBoundary) {
@@ -1257,11 +1282,9 @@ void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
FlushFrames(PR_FALSE, PR_FALSE);
}
for (nsIFrame* f = traversal.mFrameToDescendInto; f;
f = f->GetNextSibling()) {
for (nsIFrame* f = traversal.NextFrameToScan(); f;
f = traversal.NextFrameToScan()) {
ScanFrame(f);
if (!traversal.mDescendIntoFrameSiblings)
break;
}
if (!traversal.mLineBreakerCanCrossFrameBoundary) {
@@ -3278,10 +3301,16 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
void
nsContinuingTextFrame::Destroy()
{
ClearTextRun();
if (mPrevContinuation || mNextContinuation) {
nsSplittableFrame::RemoveFromFlow(this);
// The text associated with this frame will become associated with our
// prev-continuation. If that means the text has changed style, then
// we need to wipe out the text run for the text.
// Note that mPrevContinuation can be null if we're destroying the whole
// frame chain from the start to the end.
if (!mPrevContinuation ||
mPrevContinuation->GetStyleContext() != GetStyleContext()) {
ClearTextRun();
}
nsSplittableFrame::RemoveFromFlow(this);
// Let the base class destroy the frame
nsFrame::Destroy();
}

View File

@@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body style="font-family: monospace; white-space:pre;">aa
aa
a<b>a a</b></body>
</html>

View File

@@ -0,0 +1,4 @@
<!DOCTYPE html>
<html>
<body style="font-family: monospace; width: 4.1ch;">aa aa a<b>a a</b></body>
</html>

View File

@@ -836,5 +836,6 @@ fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 424074-1-ref2.xul 424074-1-ref3.xul
== 440112.html 440112-ref.html
== 440149-1.html 440149-1-ref.html
== 445004-1.html 445004-1-ref.html
== 455826-1.html 455826-1-ref.html
== 459443-1.html 459443-1-ref.html
== 471594-1.xhtml 471594-1-ref.html