From 1e843489e3b72d7ac06cac0fce9e4bb9c689ec7b Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Wed, 23 May 2012 17:27:15 +0200 Subject: [PATCH] Bug 756241. r=roc --- layout/generic/nsTextFrame.h | 4 ++- layout/generic/nsTextFrameThebes.cpp | 37 ++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 98e18bf308c..30180e889a0 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -385,7 +385,9 @@ public: void ClearTextRuns() { ClearTextRun(nsnull, nsTextFrame::eInflated); - ClearTextRun(nsnull, nsTextFrame::eNotInflated); + if (HasFontSizeInflation()) { + ClearTextRun(nsnull, nsTextFrame::eNotInflated); + } } // Get the DOM content range mapped by this frame after excluding diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index cc887b60351..24878e8f718 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -406,8 +406,9 @@ ClearAllTextRunReferences(nsTextFrame* aFrame, gfxTextRun* aTextRun, bool found = aStartContinuation == aFrame; while (aFrame) { NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame, "Bad frame"); - if (!aFrame->RemoveTextRun(aTextRun)) + if (!aFrame->RemoveTextRun(aTextRun)) { break; + } aFrame = static_cast(aFrame->GetNextContinuation()); } NS_POSTCONDITION(!found || aStartContinuation, "how did we find null?"); @@ -4211,13 +4212,16 @@ void nsTextFrame::ClearTextRun(nsTextFrame* aStartContinuation, TextRunType aWhichTextRun) { - // save textrun because ClearAllTextRunReferences may clear ours gfxTextRun* textRun = GetTextRun(aWhichTextRun); - - if (!textRun) + if (!textRun) { return; + } + DebugOnly checkmTextrun = textRun == mTextRun; UnhookTextRunFromFrames(textRun, aStartContinuation); + MOZ_ASSERT(checkmTextrun ? !mTextRun + : !Properties().Get(UninflatedTextRunProperty())); + // see comments in BuildTextRunForFrames... // if (textRun->GetFlags() & gfxFontGroup::TEXT_IS_PERSISTENT) { // NS_ERROR("Shouldn't reach here for now..."); @@ -6919,7 +6923,7 @@ HasSoftHyphenBefore(const nsTextFragment* aFrag, gfxTextRun* aTextRun, } static void -RemoveInFlows(nsIFrame* aFrame, nsIFrame* aFirstToNotRemove) +RemoveInFlows(nsTextFrame* aFrame, nsTextFrame* aFirstToNotRemove) { NS_PRECONDITION(aFrame != aFirstToNotRemove, "This will go very badly"); // We have to be careful here, because some RemoveFrame implementations @@ -6944,6 +6948,21 @@ RemoveInFlows(nsIFrame* aFrame, nsIFrame* aFirstToNotRemove) nsIFrame* prevContinuation = aFrame->GetPrevContinuation(); nsIFrame* lastRemoved = aFirstToNotRemove->GetPrevContinuation(); + nsIFrame* parent = aFrame->GetParent(); + nsBlockFrame* parentBlock = nsLayoutUtils::GetAsBlock(parent); + if (!parentBlock) { + // Clear the text run on the first frame we'll remove to make sure none of + // the frames we keep shares its text run. We need to do this now, before + // we unlink the frames to remove from the flow, because DestroyFrom calls + // ClearTextRuns() and that will start at the first frame with the text + // run and walk the continuations. We only need to care about the first + // and last frames we remove since text runs are contiguous. + aFrame->ClearTextRuns(); + if (aFrame != lastRemoved) { + // Clear the text run on the last frame we'll remove for the same reason. + static_cast(lastRemoved)->ClearTextRuns(); + } + } prevContinuation->SetNextInFlow(aFirstToNotRemove); aFirstToNotRemove->SetPrevInFlow(prevContinuation); @@ -6951,16 +6970,14 @@ RemoveInFlows(nsIFrame* aFrame, nsIFrame* aFirstToNotRemove) aFrame->SetPrevInFlow(nsnull); lastRemoved->SetNextInFlow(nsnull); - nsIFrame *parent = aFrame->GetParent(); - nsBlockFrame *parentBlock = nsLayoutUtils::GetAsBlock(parent); if (parentBlock) { // Manually call DoRemoveFrame so we can tell it that we're // removing empty frames; this will keep it from blowing away // text runs. parentBlock->DoRemoveFrame(aFrame, nsBlockFrame::FRAMES_ARE_EMPTY); } else { - // Just remove it normally; use the nextBidi list to avoid - // posting new reflows. + // Just remove it normally; use kNoReflowPrincipalList to avoid posting + // new reflows. parent->RemoveFrame(nsIFrame::kNoReflowPrincipalList, aFrame); } } @@ -7031,7 +7048,7 @@ nsTextFrame::SetLength(PRInt32 aLength, nsLineLayout* aLineLayout, // Note that in the process we may end up removing some frames from // the flow if they end up empty. - nsIFrame *framesToRemove = nsnull; + nsTextFrame* framesToRemove = nsnull; while (f && f->mContentOffset < end) { f->mContentOffset = end; if (f->GetTextRun(nsTextFrame::eInflated) != mTextRun) {