зеркало из https://github.com/mozilla/gecko-dev.git
Bug 385607. Ensure that whitespace is collapsed across text-run boundaries across incremental updates like adding/removing frames in the middle of the textrun. r+sr+a=dbaron
This commit is contained in:
Родитель
662617a914
Коммит
9a93a48ef0
|
@ -665,6 +665,7 @@ nsBlockFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
|||
}
|
||||
// XXX Bug NNNNNN Should probably handle percentage text-indent.
|
||||
|
||||
data.line = &line;
|
||||
nsIFrame *kid = line->mFirstChild;
|
||||
for (PRInt32 i = 0, i_end = line->GetChildCount(); i != i_end;
|
||||
++i, kid = kid->GetNextSibling()) {
|
||||
|
@ -736,6 +737,7 @@ nsBlockFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
|||
}
|
||||
// XXX Bug NNNNNN Should probably handle percentage text-indent.
|
||||
|
||||
data.line = &line;
|
||||
nsIFrame *kid = line->mFirstChild;
|
||||
for (PRInt32 i = 0, i_end = line->GetChildCount(); i != i_end;
|
||||
++i, kid = kid->GetNextSibling()) {
|
||||
|
@ -4798,12 +4800,19 @@ nsBlockFrame::AddFrames(nsIFrame* aFrameList,
|
|||
prevSibLine->SetChildCount(prevSibLine->GetChildCount() - rem);
|
||||
prevSibLine->MarkDirty();
|
||||
}
|
||||
// Force the lines next to where we're inserting content to regenerate
|
||||
// their textruns
|
||||
prevSibLine->SetInvalidateTextRuns(PR_TRUE);
|
||||
if (prevSibLine.next() != end_lines()) {
|
||||
prevSibLine.next()->SetInvalidateTextRuns(PR_TRUE);
|
||||
}
|
||||
|
||||
// Now (partially) join the sibling lists together
|
||||
aPrevSibling->SetNextSibling(aFrameList);
|
||||
}
|
||||
else if (! mLines.empty()) {
|
||||
prevSiblingNextFrame = mLines.front()->mFirstChild;
|
||||
mLines.front()->SetInvalidateTextRuns(PR_TRUE);
|
||||
}
|
||||
|
||||
// Walk through the new frames being added and update the line data
|
||||
|
@ -5212,6 +5221,10 @@ found_frame:;
|
|||
NS_ERROR("can't find deleted frame in lines");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (line != mLines.front()) {
|
||||
line.prev()->SetInvalidateTextRuns(PR_TRUE);
|
||||
}
|
||||
|
||||
if (prevSibling && !prevSibling->GetNextSibling()) {
|
||||
// We must have found the first frame in the overflow line list. So
|
||||
|
@ -5224,6 +5237,8 @@ found_frame:;
|
|||
NS_ASSERTION(this == aDeletedFrame->GetParent(), "messed up delete code");
|
||||
NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line");
|
||||
|
||||
line->SetInvalidateTextRuns(PR_TRUE);
|
||||
|
||||
// If the frame being deleted is the last one on the line then
|
||||
// optimize away the line->Contains(next-in-flow) call below.
|
||||
PRBool isLastFrameOnLine = (1 == line->GetChildCount() ||
|
||||
|
@ -5370,6 +5385,10 @@ found_frame:;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (line.next() != line_end) {
|
||||
line.next()->SetInvalidateTextRuns(PR_TRUE);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
VerifyLines(PR_TRUE);
|
||||
|
@ -6104,10 +6123,16 @@ nsBlockFrame::ChildIsDirty(nsIFrame* aChild)
|
|||
// otherwise we have an empty line list, and ReflowDirtyLines
|
||||
// will handle reflowing the bullet.
|
||||
} else {
|
||||
// Mark the line containing the child frame dirty.
|
||||
// Mark the line containing the child frame dirty. We would rather do this
|
||||
// in MarkIntrinsicWidthsDirty but that currently won't tell us which
|
||||
// child is being dirtied.
|
||||
line_iterator fline = FindLineFor(aChild);
|
||||
if (fline != end_lines())
|
||||
if (fline != end_lines()) {
|
||||
// An inline descendant might have been added or removed, so we should
|
||||
// reconstruct textruns.
|
||||
fline->SetInvalidateTextRuns(PR_TRUE);
|
||||
MarkLineDirty(fline);
|
||||
}
|
||||
}
|
||||
|
||||
nsBlockFrameSuper::ChildIsDirty(aChild);
|
||||
|
|
|
@ -92,6 +92,7 @@ class nsDisplayListSet;
|
|||
class nsDisplayList;
|
||||
class gfxSkipChars;
|
||||
class gfxSkipCharsIterator;
|
||||
class nsLineList_iterator;
|
||||
|
||||
struct nsPeekOffsetStruct;
|
||||
struct nsPoint;
|
||||
|
@ -1137,12 +1138,16 @@ public:
|
|||
*/
|
||||
struct InlineIntrinsicWidthData {
|
||||
InlineIntrinsicWidthData()
|
||||
: prevLines(0)
|
||||
: line(nsnull)
|
||||
, prevLines(0)
|
||||
, currentLine(0)
|
||||
, skipWhitespace(PR_TRUE)
|
||||
, trailingWhitespace(0)
|
||||
{}
|
||||
|
||||
// The line. This may be null if the inlines are not associated with a block.
|
||||
const nsLineList_iterator* line;
|
||||
|
||||
// The maximum intrinsic width for all previous lines.
|
||||
nscoord prevLines;
|
||||
|
||||
|
|
|
@ -305,6 +305,15 @@ public:
|
|||
return mFlags.mLineWrapped;
|
||||
}
|
||||
|
||||
// mInvalidateTextRuns bit
|
||||
void SetInvalidateTextRuns(PRBool aOn) {
|
||||
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
|
||||
mFlags.mInvalidateTextRuns = aOn;
|
||||
}
|
||||
PRBool GetInvalidateTextRuns() const {
|
||||
return mFlags.mInvalidateTextRuns;
|
||||
}
|
||||
|
||||
// mResizeReflowOptimizationDisabled bit
|
||||
void DisableResizeReflowOptimization() {
|
||||
mFlags.mResizeReflowOptimizationDisabled = PR_TRUE;
|
||||
|
@ -487,6 +496,7 @@ public:
|
|||
PRUint32 mBlock : 1;
|
||||
PRUint32 mImpactedByFloat : 1;
|
||||
PRUint32 mLineWrapped: 1;
|
||||
PRUint32 mInvalidateTextRuns : 1;
|
||||
PRUint32 mResizeReflowOptimizationDisabled: 1; // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
|
||||
PRUint32 mEmptyCacheValid: 1;
|
||||
PRUint32 mEmptyCacheState: 1;
|
||||
|
|
|
@ -1206,6 +1206,7 @@ BuildTextRuns(nsIRenderingContext* aRC, nsTextFrame* aForFrame,
|
|||
line = forwardIterator.GetLine();
|
||||
if (line->IsBlock())
|
||||
break;
|
||||
line->SetInvalidateTextRuns(PR_FALSE);
|
||||
scanner.SetAtStartOfLine();
|
||||
scanner.SetCommonAncestorWithLastFrame(nsnull);
|
||||
nsIFrame* child = line->mFirstChild;
|
||||
|
@ -1966,7 +1967,7 @@ nsTextFrame::EnsureTextRun(nsIRenderingContext* aRC, nsIFrame* aLineContainer,
|
|||
const nsLineList::iterator* aLine,
|
||||
PRUint32* aFlowEndInTextRun)
|
||||
{
|
||||
if (mTextRun) {
|
||||
if (mTextRun && (!aLine || !(*aLine)->GetInvalidateTextRuns())) {
|
||||
if (mTextRun->GetExpirationState()->IsTracked()) {
|
||||
gTextRuns->MarkUsed(mTextRun);
|
||||
}
|
||||
|
@ -5001,7 +5002,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
|
|||
{
|
||||
PRUint32 flowEndInTextRun;
|
||||
gfxSkipCharsIterator iter =
|
||||
EnsureTextRun(aRenderingContext, nsnull, nsnull, &flowEndInTextRun);
|
||||
EnsureTextRun(aRenderingContext, nsnull, aData->line, &flowEndInTextRun);
|
||||
if (!mTextRun)
|
||||
return;
|
||||
|
||||
|
@ -5099,7 +5100,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
|
|||
{
|
||||
PRUint32 flowEndInTextRun;
|
||||
gfxSkipCharsIterator iter =
|
||||
EnsureTextRun(aRenderingContext, nsnull, nsnull, &flowEndInTextRun);
|
||||
EnsureTextRun(aRenderingContext, nsnull, aData->line, &flowEndInTextRun);
|
||||
if (!mTextRun)
|
||||
return;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче