diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index ede3cb92a0c4..8a978f6553e9 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -3092,6 +3092,9 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, nsIView* viewportView = nsnull; nsRect viewportArea; + // Remember that we've drawn position-varying content in this prescontext + aPresContext->SetRenderedPositionVaryingContent(); + nsIFrame* rootFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame(); NS_ASSERTION(rootFrame, "no root frame"); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 9c38c11d5c14..13ec7ae58a55 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -793,6 +793,9 @@ nsLayoutUtils::ComputeRepaintRegionForCopy(nsIFrame* aRootFrame, const nsRect& aCopyRect, nsRegion* aRepaintRegion) { + NS_ASSERTION(aRootFrame != aMovingFrame, + "The root frame shouldn't be the one that's moving, that makes no sense"); + // Build the 'after' display list over the whole area of interest. // Frames under aMovingFrame will not be allowed to affect (clip or cover) // non-moving frame display items ... then we can be sure the non-moving diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index c5a822219c7c..fe8aacaa95f5 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -386,6 +386,9 @@ public: * context. */ PRBool IsPaginated() const { return mPaginated; } + + PRBool GetRenderedPositionVaryingContent() const { return mRenderedPositionVaryingContent; } + void SetRenderedPositionVaryingContent() { mRenderedPositionVaryingContent = PR_TRUE; } /** * Sets whether the presentation context can scroll for a paginated @@ -762,6 +765,7 @@ protected: unsigned mPrefScrollbarSide : 2; unsigned mPendingSysColorChanged : 1; unsigned mPendingThemeChanged : 1; + unsigned mRenderedPositionVaryingContent : 1; #ifdef IBMBIDI unsigned mIsVisual : 1; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e55736bdd9ba..a39a6cebba63 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1155,8 +1155,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, if ((GetStateBits() & NS_FRAME_REPLACED_ELEMENT) && !IsVisibleForPainting(aBuilder)) return NS_OK; - if (GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE) - return NS_OK; nsRect absPosClip; const nsStyleDisplay* disp = GetStyleDisplay(); @@ -1337,19 +1335,29 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, dirty.IntersectRect(dirty, aChild->GetOverflowRect()); } - // If this child has a placeholder of interest then we must descend into - // it even if the child's descendant frames don't intersect the dirty - // area themselves. - // If the child is a scrollframe that we want to ignore, then we need - // to descend into it because its scrolled child may intersect the dirty - // area even if the scrollframe itself doesn't. - if (dirty.IsEmpty() && - !(aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) && - aChild != aBuilder->GetIgnoreScrollFrame()) - return NS_OK; + if (!(aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) { + // No need to descend into aChild to catch placeholders for visible + // positioned stuff. So see if we can short-circuit frame traversal here. + + // We can stop if aChild's intersection with the dirty area ended up empty. + // If the child is a scrollframe that we want to ignore, then we need + // to descend into it because its scrolled child may intersect the dirty + // area even if the scrollframe itself doesn't. + if (dirty.IsEmpty() && aChild != aBuilder->GetIgnoreScrollFrame()) + return NS_OK; + + // Note that aBuilder->GetRootMovingFrame() is non-null only if we're doing + // ComputeRepaintRegionForCopy. + if (aBuilder->GetRootMovingFrame() == this && + !GetPresContext()->GetRenderedPositionVaryingContent()) { + // No position-varying content has been rendered in this prescontext. + // Therefore there is no need to descend into analyzing the moving frame's + // descendants looking for such content, because any bitblit will + // not be copying position-varying graphics. + return NS_OK; + } + } - if (aChild->GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE) - return NS_OK; // XXX need to have inline-block and inline-table set pseudoStackingContext const nsStyleDisplay* ourDisp = GetStyleDisplay();