diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index c8497535e8b9..862da3e2aedd 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -228,7 +228,8 @@ static PRUint64 RegionArea(const nsRegion& aRegion) void nsDisplayListBuilder::SubtractFromVisibleRegion(nsRegion* aVisibleRegion, - const nsRegion& aRegion) + const nsRegion& aRegion, + PRBool aForceSubtract) { if (aRegion.IsEmpty()) return; @@ -239,7 +240,8 @@ nsDisplayListBuilder::SubtractFromVisibleRegion(nsRegion* aVisibleRegion, // to its bounds either, which can be very bad (see bug 516740). // Do let aVisibleRegion get more complex if by doing so we reduce its // area by at least half. - if (GetAccurateVisibleRegions() || tmp.GetNumRects() <= 15 || + if (aForceSubtract || GetAccurateVisibleRegions() || + tmp.GetNumRects() <= 15 || RegionArea(tmp) <= RegionArea(*aVisibleRegion)/2) { *aVisibleRegion = tmp; } @@ -369,7 +371,9 @@ nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) { nsRegion r; r.And(*aVisibleRegion, GetBounds(aBuilder)); - return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, r.GetBounds()); + PRBool notUsed; + return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, + r.GetBounds(), notUsed); } static nsRegion @@ -390,7 +394,8 @@ TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder, PRBool nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, - const nsRect& aListVisibleBounds) { + const nsRect& aListVisibleBounds, + PRBool& aContainsRootContentDocBG) { #ifdef DEBUG nsRegion r; r.And(*aVisibleRegion, GetBounds(aBuilder)); @@ -421,12 +426,18 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder, itemVisible.And(*aVisibleRegion, bounds); item->mVisibleRect = itemVisible.GetBounds(); - if (item->ComputeVisibility(aBuilder, aVisibleRegion)) { + PRBool containsRootContentDocBG = PR_FALSE; + if (item->ComputeVisibility(aBuilder, aVisibleRegion, + containsRootContentDocBG)) { + if (containsRootContentDocBG) { + aContainsRootContentDocBG = PR_TRUE; + } anyVisible = PR_TRUE; PRBool transparentBackground = PR_FALSE; nsRegion opaque = TreatAsOpaque(item, aBuilder, &transparentBackground); // Subtract opaque item from the visible region - aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque); + aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque, + containsRootContentDocBG); forceTransparentSurface = forceTransparentSurface || transparentBackground; } AppendToBottom(item); @@ -731,7 +742,8 @@ PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder, itemVisible.And(*aVisibleRegion, bounds); mVisibleRect = itemVisible.GetBounds(); - if (!ComputeVisibility(aBuilder, aVisibleRegion)) + PRBool notUsed; + if (!ComputeVisibility(aBuilder, aVisibleRegion, notUsed)) return PR_FALSE; PRBool forceTransparentBackground; @@ -746,6 +758,19 @@ void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder, aCtx->FillRect(mVisibleRect); } +PRBool +nsDisplaySolidColor::ComputeVisibility(nsDisplayListBuilder* aBuilder, + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) +{ + PRBool retval = nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG); + if (retval && IsRootContentDocBackground()) { + aContainsRootContentDocBG = PR_TRUE; + } + return retval; +} + static void RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) { @@ -895,10 +920,13 @@ nsDisplayBackground::HitTest(nsDisplayListBuilder* aBuilder, PRBool nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) + if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG)) { return PR_FALSE; + } // Return false if the background was propagated away from this // frame. We don't want this display item to show up and confuse @@ -1167,9 +1195,12 @@ nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder, PRBool nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { + if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG)) { return PR_FALSE; + } const nsStyleOutline* outline = mFrame->GetStyleOutline(); nsRect borderBox(ToReferenceFrame(), mFrame->GetSize()); @@ -1209,9 +1240,12 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder, PRBool nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { + if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG)) { return PR_FALSE; + } nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() + ToReferenceFrame(); @@ -1305,9 +1339,12 @@ nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) { PRBool nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { + if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG)) { return PR_FALSE; + } // Store the actual visible region mVisibleRegion.And(*aVisibleRegion, mVisibleRect); @@ -1348,9 +1385,12 @@ nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder, PRBool nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { + if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG)) { return PR_FALSE; + } // Store the actual visible region mVisibleRegion.And(*aVisibleRegion, mVisibleRect); @@ -1386,9 +1426,11 @@ nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder) { PRBool nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { return mList.ComputeVisibilityForSublist(aBuilder, aVisibleRegion, - mVisibleRect); + mVisibleRect, + aContainsRootContentDocBG); } nsRegion @@ -1573,7 +1615,8 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder, } PRBool nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { // Our children are translucent so we should not allow them to subtract // area from aVisibleRegion. We do need to find out what is visible under // our children in the temporary compositing buffer, because if our children @@ -1582,8 +1625,12 @@ PRBool nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRect bounds = GetBounds(aBuilder); nsRegion visibleUnderChildren; visibleUnderChildren.And(*aVisibleRegion, bounds); + // do not pass up the aContainsRootContentDocBG value because anything under + // us is not opaque + PRBool notUsed; return - nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren); + nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren, + notUsed); } PRBool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) { @@ -1658,7 +1705,8 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder, PRBool nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { nsPresContext* presContext = mFrame->PresContext(); nsIPresShell* presShell = presContext->GetPresShell(); @@ -1673,13 +1721,14 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRect boundedRect; boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder)); PRBool visible = mList.ComputeVisibilityForSublist( - aBuilder, &childVisibleRegion, boundedRect); + aBuilder, &childVisibleRegion, boundedRect, aContainsRootContentDocBG); mVisibleRect = boundedRect; return visible; } else { - return nsDisplayOwnLayer::ComputeVisibility(aBuilder, aVisibleRegion); + return nsDisplayOwnLayer::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG); } } @@ -1728,17 +1777,20 @@ void nsDisplayClip::Paint(nsDisplayListBuilder* aBuilder, } PRBool nsDisplayClip::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { nsRegion clipped; clipped.And(*aVisibleRegion, mClip); nsRegion finalClipped(clipped); PRBool anyVisible = - nsDisplayWrapList::ComputeVisibility(aBuilder, &finalClipped); + nsDisplayWrapList::ComputeVisibility(aBuilder, &finalClipped, + aContainsRootContentDocBG); nsRegion removed; removed.Sub(clipped, finalClipped); - aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed); + aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed, + aContainsRootContentDocBG); return anyVisible; } @@ -1825,12 +1877,14 @@ nsDisplayClipRoundedRect::WrapWithClone(nsDisplayListBuilder* aBuilder, PRBool nsDisplayClipRoundedRect::ComputeVisibility( nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { nsRegion clipped; clipped.And(*aVisibleRegion, mClip); - return nsDisplayWrapList::ComputeVisibility(aBuilder, &clipped); + PRBool notUsed; + return nsDisplayWrapList::ComputeVisibility(aBuilder, &clipped, notUsed); // FIXME: Remove a *conservative* opaque region from aVisibleRegion // (like in nsDisplayClip::ComputeVisibility). } @@ -1892,7 +1946,8 @@ void nsDisplayZoom::Paint(nsDisplayListBuilder* aBuilder, } PRBool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder, - nsRegion *aVisibleRegion) + nsRegion *aVisibleRegion, + PRBool& aContainsRootContentDocBG) { // Convert the passed in visible region to our appunits. nsRegion visibleRegion = @@ -1903,7 +1958,8 @@ PRBool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder, mVisibleRect.ConvertAppUnitsRoundOut(mParentAPD, mAPD); PRBool retval = mList.ComputeVisibilityForSublist(aBuilder, &visibleRegion, - transformedVisibleRect); + transformedVisibleRect, + aContainsRootContentDocBG); nsRegion removed; // removed = originalVisibleRegion - visibleRegion @@ -1912,7 +1968,8 @@ PRBool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder, removed = removed.ConvertAppUnitsRoundIn(mAPD, mParentAPD); // aVisibleRegion = aVisibleRegion - removed (modulo any simplifications // SubtractFromVisibleRegion does) - aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed); + aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed, + aContainsRootContentDocBG); return retval; } @@ -2098,7 +2155,8 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder, } PRBool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder, - nsRegion *aVisibleRegion) + nsRegion *aVisibleRegion, + PRBool& aContainsRootContentDocBG) { /* As we do this, we need to be sure to * untransform the visible rect, since we want everything that's painting to @@ -2379,7 +2437,8 @@ void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder, } PRBool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) { + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { nsPoint offset = aBuilder->ToReferenceFrame(mEffectsFrame); nsRect dirtyRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mEffectsFrame, @@ -2391,7 +2450,8 @@ PRBool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion childrenVisible(dirtyRect); nsRect r; r.IntersectRect(dirtyRect, mList.GetBounds(aBuilder)); - mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r); + PRBool notUsed; + mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r, notUsed); return PR_TRUE; } diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 315953f7a61d..3db58a21a78d 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -327,10 +327,12 @@ public: * Subtracts aRegion from *aVisibleRegion. We avoid letting * aVisibleRegion become overcomplex by simplifying it if necessary --- * unless mAccurateVisibleRegions is set, in which case we let it - * get arbitrarily complex. + * get arbitrarily complex. If aForceSubtract is true then we subtract + * aRegion even if it makes the visible region more complex. */ void SubtractFromVisibleRegion(nsRegion* aVisibleRegion, - const nsRegion& aRegion); + const nsRegion& aRegion, + PRBool aForceSubtract = PR_FALSE); /** * Mark the frames in aFrames to be displayed if they intersect aDirtyRect @@ -705,10 +707,12 @@ public: * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility. * * @return PR_TRUE if the item is visible, PR_FALSE if no part of the item - * is visible + * is visible. aContainsRootContentDocBG is set to true if this item contains + * the background for the root content document. */ virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { return !mVisibleRect.IsEmpty(); } /** @@ -982,11 +986,14 @@ public: * I.e., opaque contents of this list are subtracted from aVisibleRegion. * @param aListVisibleBounds must be equal to the bounds of the intersection * of aVisibleRegion and GetBounds() for this list. - * @return true if any item in the list is visible + * @return true if any item in the list is visible. aContainsRootContentDocBG + * is set to true if the list contains the background for a root content + * document. */ PRBool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, - const nsRect& aListVisibleBounds); + const nsRect& aListVisibleBounds, + PRBool& aContainsRootContentDocBG); /** * As ComputeVisibilityForSublist, but computes visibility for a root @@ -1391,7 +1398,8 @@ public: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER) protected: @@ -1412,8 +1420,10 @@ protected: class nsDisplaySolidColor : public nsDisplayItem { public: nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - const nsRect& aBounds, nscolor aColor) - : nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor) { + const nsRect& aBounds, nscolor aColor, + PRBool aIsRootContentDocBackground = PR_FALSE) + : nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor), + mIsRootContentDocBackground(aIsRootContentDocBackground) { NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!"); MOZ_COUNT_CTOR(nsDisplaySolidColor); } @@ -1445,12 +1455,20 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); + virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); + + PRBool IsRootContentDocBackground() { + return mIsRootContentDocBackground; + } + NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR) private: nsRect mBounds; nscolor mColor; - PRBool mTransparentBackground; + PRPackedBool mIsRootContentDocBackground; }; /** @@ -1468,7 +1486,8 @@ public: virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, HitTestState* aState, nsTArray *aOutFrames); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, PRBool* aForceTransparentSurface = nsnull); virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder, @@ -1506,7 +1525,8 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER) private: @@ -1530,7 +1550,8 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER) private: @@ -1555,7 +1576,8 @@ public: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE) }; @@ -1616,7 +1638,8 @@ public: nsIFrame* aFrame); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) { NS_WARNING("This list should already have been flattened!!!"); return PR_FALSE; @@ -1700,7 +1723,8 @@ public: virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY) }; @@ -1766,7 +1790,8 @@ public: LayerManager* aManager); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); private: nsIFrame* mViewportFrame; @@ -1796,7 +1821,8 @@ public: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); NS_DISPLAY_DECL_NAME("Clip", TYPE_CLIP) virtual PRUint32 GetPerFrameKey() { return 0; } @@ -1837,7 +1863,8 @@ public: virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, HitTestState* aState, nsTArray *aOutFrames); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); NS_DISPLAY_DECL_NAME("ClipRoundedRect", TYPE_CLIP_ROUNDED_RECT) @@ -1877,7 +1904,8 @@ public: virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, HitTestState* aState, nsTArray *aOutFrames); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM) // Get the app units per dev pixel ratio of the child document. @@ -1911,7 +1939,8 @@ public: } virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS) @@ -1974,7 +2003,8 @@ public: virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager); virtual PRBool ComputeVisibility(nsDisplayListBuilder *aBuilder, - nsRegion *aVisibleRegion); + nsRegion *aVisibleRegion, + PRBool& aContainsRootContentDocBG); virtual PRBool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem); /** diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 19857a33b3aa..f0e60568f66f 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -140,8 +140,8 @@ typedef struct CapturingContentInfo { { 0x95, 0x47, 0x85, 0x06, 0x5e, 0x02, 0xec, 0xb4 } } #define NS_IPRESSHELL_MOZILLA_2_0_BRANCH_IID \ - { 0x5e445910, 0xfbee, 0x11df, \ - { 0x8c, 0xff, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } } + { 0x4abb9970, 0xd7ce, 0x4c02, \ + { 0x8a, 0xdb, 0x42, 0xc6, 0xbd, 0xa8, 0x95, 0xb7 } } #define NS_IPRESSHELL_MOZILLA_2_0_BRANCH2_IID \ { 0x5ff6fd00, 0x1ba9, 0x11e0, \ @@ -180,6 +180,26 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPRESSHELL_MOZILLA_2_0_BRANCH_IID) virtual PRBool GetIsViewportOverridden() = 0; + + /** + * Add a solid color item to the bottom of aList with frame aFrame and bounds + * aBounds. Checks first if this needs to be done by checking if aFrame is a + * canvas frame (if the FORCE_DRAW flag is passed then this check is skipped). + * aBackstopColor is composed behind the background color of the canvas, it is + * transparent by default. The ROOT_CONTENT_DOC_BG flag indicates that this is + * the background for the root content document. + */ + enum { + FORCE_DRAW = 0x01, + ROOT_CONTENT_DOC_BG = 0x02 + }; + virtual nsresult AddCanvasBackgroundColorItem2(nsDisplayListBuilder& aBuilder, + nsDisplayList& aList, + nsIFrame* aFrame, + const nsRect& aBounds, + nscolor aBackstopColor = NS_RGBA(0,0,0,0), + PRUint32 aFlags = 0) = 0; + }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIPresShell_MOZILLA_2_0_BRANCH, diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 8b6ee87501d6..15eac91d02a6 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -954,6 +954,13 @@ public: virtual void UpdateCanvasBackground(); + virtual nsresult AddCanvasBackgroundColorItem2(nsDisplayListBuilder& aBuilder, + nsDisplayList& aList, + nsIFrame* aFrame, + const nsRect& aBounds, + nscolor aBackstopColor, + PRUint32 aFlags); + virtual nsresult AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder, nsDisplayList& aList, nsIFrame* aFrame, @@ -5850,6 +5857,18 @@ nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder, const nsRect& aBounds, nscolor aBackstopColor, PRBool aForceDraw) +{ + return AddCanvasBackgroundColorItem2(aBuilder, aList, aFrame, aBounds, + aBackstopColor, + aForceDraw ? nsIPresShell_MOZILLA_2_0_BRANCH::FORCE_DRAW : 0); +} + +nsresult PresShell::AddCanvasBackgroundColorItem2(nsDisplayListBuilder& aBuilder, + nsDisplayList& aList, + nsIFrame* aFrame, + const nsRect& aBounds, + nscolor aBackstopColor, + PRUint32 aFlags) { // We don't want to add an item for the canvas background color if the frame // (sub)tree we are painting doesn't include any canvas frames. There isn't @@ -5857,8 +5876,10 @@ nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder, // (sub)tree we are painting is a canvas frame that should cover us in all // cases (it will usually be a viewport frame when we have a canvas frame in // the (sub)tree). - if (!aForceDraw && !nsCSSRendering::IsCanvasFrame(aFrame)) + if (!(aFlags & nsIPresShell_MOZILLA_2_0_BRANCH::FORCE_DRAW) && + !nsCSSRendering::IsCanvasFrame(aFrame)) { return NS_OK; + } nscolor bgcolor = NS_ComposeColors(aBackstopColor, mCanvasBackgroundColor); if (NS_GET_A(bgcolor) == 0) @@ -5881,7 +5902,8 @@ nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder, } return aList.AppendNewToBottom( - new (&aBuilder) nsDisplaySolidColor(&aBuilder, aFrame, aBounds, bgcolor)); + new (&aBuilder) nsDisplaySolidColor(&aBuilder, aFrame, aBounds, bgcolor, + !!(aFlags & nsIPresShell_MOZILLA_2_0_BRANCH::ROOT_CONTENT_DOC_BG))); } static PRBool IsTransparentContainerElement(nsPresContext* aPresContext) diff --git a/layout/generic/nsCanvasFrame.h b/layout/generic/nsCanvasFrame.h index 9f5d7e77c0e0..b644cf30ebdc 100644 --- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -172,10 +172,16 @@ public: } virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { - return NS_GET_A(mExtraBackgroundColor) > 0 || - nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion); + PRBool retval = NS_GET_A(mExtraBackgroundColor) > 0 || + nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG); + if (retval && mFrame->PresContext()->IsRootContentDocument()) { + aContainsRootContentDocBG = PR_TRUE; + } + return retval; } virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, PRBool* aForceTransparentSurface = nsnull) diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 1afd53069f06..3e9d2027f0c8 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1284,10 +1284,12 @@ nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder, PRBool nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion) + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG) { mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder)); - return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion); + return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, + aContainsRootContentDocBG); } nsRegion diff --git a/layout/generic/nsObjectFrame.h b/layout/generic/nsObjectFrame.h index 2cf122ced835..05d579d54aaf 100644 --- a/layout/generic/nsObjectFrame.h +++ b/layout/generic/nsObjectFrame.h @@ -321,7 +321,8 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion); + nsRegion* aVisibleRegion, + PRBool& aContainsRootContentDocBG); NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN) diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index e5d8acd0f430..ab79c85444bc 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -411,9 +411,13 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // Add the canvas background color to the bottom of the list. This // happens after we've built the list so that AddCanvasBackgroundColorItem // can monkey with the contents if necessary. + PRUint32 flags = nsIPresShell_MOZILLA_2_0_BRANCH::FORCE_DRAW; + if (presContext->IsRootContentDocument()) { + flags |= nsIPresShell_MOZILLA_2_0_BRANCH::ROOT_CONTENT_DOC_BG; + } rv = presShell->AddCanvasBackgroundColorItem( *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this, - bounds, NS_RGBA(0,0,0,0), PR_TRUE); + bounds, NS_RGBA(0,0,0,0), flags); } }