author | John Daggett <jdaggett@mozilla.com> |
Tue, 08 Apr 2014 14:13:28 +0900 | |
changeset 177427 | 353dde65b2421c1ef210733a4e18753614727505 |
parent 177426 | a28cd2a8b3970721f0cd2c93bc33cfbc968764e8 |
child 177428 | 9e1a8a3f1a6960e029902eddab0557889f179dfa |
push id | 26551 |
push user | cbook@mozilla.com |
push date | Tue, 08 Apr 2014 13:31:42 +0000 |
treeherder | mozilla-central@7de74f07e058 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dbaron |
bugs | 950526 |
milestone | 31.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3671,16 +3671,61 @@ nsLayoutUtils::ComputeHeightDependentVal } NS_ASSERTION(aCoord.GetUnit() == eStyleUnit_None || aCoord.GetUnit() == eStyleUnit_Auto, "unexpected height value"); return 0; } +/* static */ void +nsLayoutUtils::MarkDescendantsDirty(nsIFrame *aSubtreeRoot) +{ + nsAutoTArray<nsIFrame*, 4> 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<nsIFrame*, 32> 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 nsLayoutUtils::ComputeSizeWithIntrinsicDimensions( nsRenderingContext* aRenderingContext, nsIFrame* aFrame, const IntrinsicSize& aIntrinsicSize, nsSize aIntrinsicRatio, nsSize aCBSize, nsSize aMargin, nsSize aBorder, nsSize aPadding)
--- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1205,16 +1205,18 @@ public: aCoord.GetCoordValue() == 0) || (aCoord.GetUnit() == eStyleUnit_Percent && aCoord.GetPercentValue() == 0.0f) || (aCoord.IsCalcUnit() && nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) == 0 && nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) == 0); } + static void MarkDescendantsDirty(nsIFrame *aSubtreeRoot); + /* * Calculate the used values for 'width' and 'height' for a replaced element. * * http://www.w3.org/TR/CSS21/visudet.html#min-max-widths */ static nsSize ComputeSizeWithIntrinsicDimensions( nsRenderingContext* aRenderingContext, nsIFrame* aFrame, const mozilla::IntrinsicSize& aIntrinsicSize,
--- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -80,16 +80,17 @@ nsresult nsFirstLetterFrame::SetInitialChildList(ChildListID aListID, nsFrameList& aChildList) { RestyleManager* restyleManager = PresContext()->RestyleManager(); 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); return NS_OK; } nsresult nsFirstLetterFrame::GetChildFrameContainingOffset(int32_t inContentOffset,
--- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -281,16 +281,17 @@ ReparentChildListStyle(nsPresContext* aP const nsFrameList::Slice& aFrames, nsIFrame* aParentFrame) { RestyleManager* restyleManager = aPresContext->RestyleManager(); 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()); } } nsresult nsInlineFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) @@ -419,16 +420,17 @@ nsInlineFrame::DrainSelfOverflowListInte ReparentFloatsForInlineChild(aLineContainer, firstChild, true); } const bool inFirstLine = (aFlags & eInFirstLine); RestyleManager* restyleManager = PresContext()->RestyleManager(); for (nsIFrame* f = firstChild; f; f = f->GetNextSibling()) { f->SetParent(this); if (inFirstLine) { restyleManager->ReparentStyleContext(f); + nsLayoutUtils::MarkDescendantsDirty(f); } } } bool result = !overflowFrames->IsEmpty(); mFrames.AppendFrames(nullptr, *overflowFrames); return result; } return false; @@ -524,16 +526,17 @@ nsInlineFrame::ReflowFrames(nsPresContex // came from. If we really really have to optimize this we could // cache whether frame->GetParent() is under its containing blocks // overflowList or not. ReparentFloatsForInlineChild(irs.mLineContainer, child, false); } 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 // we'll crash when trying to delete its next-in-flow. // This scenario doesn't happen often, but it can happen. nsIFrame* nextSibling = child->GetNextSibling(); child = child->GetNextInFlow(); if (MOZ_UNLIKELY(child)) { @@ -558,16 +561,17 @@ nsInlineFrame::ReflowFrames(nsPresContex nsIFrame* nextInFlow = child->GetNextInFlow(); for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) { NS_ASSERTION(nextInFlow->GetType() == nsGkAtoms::textFrame, "unexpected frame type"); if (mFrames.ContainsFrame(nextInFlow)) { nextInFlow->SetParent(this); if (inFirstLine) { restyleManager->ReparentStyleContext(nextInFlow); + nsLayoutUtils::MarkDescendantsDirty(nextInFlow); } } else { #ifdef DEBUG // Once we find a next-in-flow that isn't ours none of the // remaining next-in-flows should be either. for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) { NS_ASSERTION(!mFrames.ContainsFrame(nextInFlow), @@ -1000,16 +1004,17 @@ nsFirstLineFrame::PullOneFrame(nsPresCon bool* aIsComplete) { nsIFrame* frame = nsInlineFrame::PullOneFrame(aPresContext, irs, aIsComplete); if (frame && !GetPrevInFlow()) { // We are a first-line frame. Fixup the child frames // style-context that we just pulled. NS_ASSERTION(frame->GetParent() == this, "Incorrect parent?"); aPresContext->RestyleManager()->ReparentStyleContext(frame); + nsLayoutUtils::MarkDescendantsDirty(frame); } return frame; } nsresult nsFirstLineFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState,
--- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4436,17 +4436,16 @@ nsTextFrame::CharacterDataChanged(Charac return NS_OK; } /* virtual */ void nsTextFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) { nsFrame::DidSetStyleContext(aOldStyleContext); - ClearTextRuns(); } class nsDisplayTextGeometry : public nsDisplayItemGenericGeometry { public: nsDisplayTextGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder) : nsDisplayItemGenericGeometry(aItem, aBuilder) {
--- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -3307,17 +3307,17 @@ SVGTextFrame::ScheduleReflowSVGNonDispla f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); } f = f->GetParent(); } 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) void SVGTextFrame::MutationObserver::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aFirstNewContent,