diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index fdd57616de65..b090e7cb5f5e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3676,6 +3676,51 @@ nsLayoutUtils::ComputeHeightDependentValue( return 0; } +/* static */ void +nsLayoutUtils::MarkDescendantsDirty(nsIFrame *aSubtreeRoot) +{ + nsAutoTArray subtrees; + subtrees.AppendElement(aSubtreeRoot); + + // dirty descendants, iterating over subtrees that may include + // additional subtrees associated with placeholders + do { + nsIFrame *subtreeRoot = subtrees.ElementAt(subtrees.Length() - 1); + subtrees.RemoveElementAt(subtrees.Length() - 1); + + // Mark all descendants dirty (using an nsTArray stack rather than + // recursion). + // Note that nsHTMLReflowState::InitResizeFlags has some similar + // code; see comments there for how and why it differs. + nsAutoTArray stack; + stack.AppendElement(subtreeRoot); + + do { + nsIFrame *f = stack.ElementAt(stack.Length() - 1); + stack.RemoveElementAt(stack.Length() - 1); + + f->MarkIntrinsicWidthsDirty(); + + if (f->GetType() == nsGkAtoms::placeholderFrame) { + nsIFrame *oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f); + if (!nsLayoutUtils::IsProperAncestorFrame(subtreeRoot, oof)) { + // We have another distinct subtree we need to mark. + subtrees.AppendElement(oof); + } + } + + nsIFrame::ChildListIterator lists(f); + for (; !lists.IsDone(); lists.Next()) { + nsFrameList::Enumerator childFrames(lists.CurrentList()); + for (; !childFrames.AtEnd(); childFrames.Next()) { + nsIFrame* kid = childFrames.get(); + stack.AppendElement(kid); + } + } + } while (stack.Length() != 0); + } while (subtrees.Length() != 0); +} + #define MULDIV(a,b,c) (nscoord(int64_t(a) * int64_t(b) / int64_t(c))) /* static */ nsSize diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 77b6e9b5dea8..3f4a19582152 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1210,6 +1210,8 @@ public: nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) == 0); } + static void MarkDescendantsDirty(nsIFrame *aSubtreeRoot); + /* * Calculate the used values for 'width' and 'height' for a replaced element. * diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 59a4afb3022c..c2a72ec3bcf2 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -85,6 +85,7 @@ nsFirstLetterFrame::SetInitialChildList(ChildListID aListID, for (nsFrameList::Enumerator e(aChildList); !e.AtEnd(); e.Next()) { NS_ASSERTION(e.get()->GetParent() == this, "Unexpected parent"); restyleManager->ReparentStyleContext(e.get()); + nsLayoutUtils::MarkDescendantsDirty(e.get()); } mFrames.SetFrames(aChildList); diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index d344871c9326..526041e63646 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -286,6 +286,7 @@ ReparentChildListStyle(nsPresContext* aPresContext, for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) { NS_ASSERTION(e.get()->GetParent() == aParentFrame, "Bogus parentage"); restyleManager->ReparentStyleContext(e.get()); + nsLayoutUtils::MarkDescendantsDirty(e.get()); } } @@ -424,6 +425,7 @@ nsInlineFrame::DrainSelfOverflowListInternal(DrainFlags aFlags, f->SetParent(this); if (inFirstLine) { restyleManager->ReparentStyleContext(f); + nsLayoutUtils::MarkDescendantsDirty(f); } } } @@ -529,6 +531,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, child->SetParent(this); if (inFirstLine) { restyleManager->ReparentStyleContext(child); + nsLayoutUtils::MarkDescendantsDirty(child); } // We also need to do the same for |frame|'s next-in-flows that are in // the sibling list. Otherwise, if we reflow |frame| and it's complete @@ -563,6 +566,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, nextInFlow->SetParent(this); if (inFirstLine) { restyleManager->ReparentStyleContext(nextInFlow); + nsLayoutUtils::MarkDescendantsDirty(nextInFlow); } } else { @@ -1005,6 +1009,7 @@ nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowState& i // style-context that we just pulled. NS_ASSERTION(frame->GetParent() == this, "Incorrect parent?"); aPresContext->RestyleManager()->ReparentStyleContext(frame); + nsLayoutUtils::MarkDescendantsDirty(frame); } return frame; } diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index db056162c54d..e4b85009af8f 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4441,7 +4441,6 @@ nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) nsTextFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) { nsFrame::DidSetStyleContext(aOldStyleContext); - ClearTextRuns(); } class nsDisplayTextGeometry : public nsDisplayItemGenericGeometry diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 06c76093c0c3..a878b41ea1e5 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -3312,7 +3312,7 @@ SVGTextFrame::ScheduleReflowSVGNonDisplayText() MOZ_ASSERT(f, "should have found an ancestor frame to reflow"); PresContext()->PresShell()->FrameNeedsReflow( - f, nsIPresShell::eResize, NS_FRAME_HAS_DIRTY_CHILDREN); + f, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); } NS_IMPL_ISUPPORTS1(SVGTextFrame::MutationObserver, nsIMutationObserver)