diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 1fac1faebbad..2d1e91398a68 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1709,6 +1709,15 @@ nsDisplayItem::ZIndex() const return 0; } +bool +nsDisplayItem::ComputeVisibility(nsDisplayListBuilder* aBuilder, + nsRegion* aVisibleRegion, + const nsRect& aAllowVisibleRegionExpansion) +{ + return !mVisibleRect.IsEmpty() && + !IsInvisibleInRect(aVisibleRegion->GetBounds()); +} + bool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) { @@ -2646,26 +2655,20 @@ nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder, } bool -nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, - aAllowVisibleRegionExpansion)) { - return false; - } - +nsDisplayOutline::IsInvisibleInRect(const nsRect& aRect) +{ const nsStyleOutline* outline = mFrame->StyleOutline(); nsRect borderBox(ToReferenceFrame(), mFrame->GetSize()); - if (borderBox.Contains(aVisibleRegion->GetBounds()) && + if (borderBox.Contains(aRect) && !nsLayoutUtils::HasNonZeroCorner(outline->mOutlineRadius)) { if (outline->mOutlineOffset >= 0) { - // the visible region is entirely inside the border-rect, and the outline - // isn't rendered inside the border-rect, so the outline is not visible - return false; + // aRect is entirely inside the border-rect, and the outline isn't + // rendered inside the border-rect, so the outline is not visible. + return true; } } - return true; + return false; } void @@ -2725,30 +2728,24 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder, } bool -nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion) { - if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, - aAllowVisibleRegionExpansion)) { - return false; - } - +nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect) +{ nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() + ToReferenceFrame(); const nsStyleBorder *styleBorder; - if (paddingRect.Contains(aVisibleRegion->GetBounds()) && + if (paddingRect.Contains(aRect) && !(styleBorder = mFrame->StyleBorder())->IsBorderImageLoaded() && !nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) { - // the visible region is entirely inside the content rect, and no part + // aRect is entirely inside the content rect, and no part // of the border is rendered inside the content rect, so we are not // visible // Skip this if there's a border-image (which draws a background // too) or if there is a border-radius (which makes the border draw // further in). - return false; + return true; } - return true; + return false; } nsDisplayItemGeometry* @@ -2879,6 +2876,24 @@ nsDisplayBoxShadowOuter::GetBoundsInternal() { ToReferenceFrame(); } +bool +nsDisplayBoxShadowOuter::IsInvisibleInRect(const nsRect& aRect) +{ + nsPoint origin = ToReferenceFrame(); + nsRect frameRect(origin, mFrame->GetSize()); + if (!frameRect.Contains(aRect)) + return false; + + // the visible region is entirely inside the border-rect, and box shadows + // never render within the border-rect (unless there's a border radius). + nscoord twipsRadii[8]; + bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii); + if (!hasBorderRadii) + return true; + + return RoundedRectContainsRect(frameRect, twipsRadii, aRect); +} + bool nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, @@ -2890,21 +2905,7 @@ nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder, // Store the actual visible region mVisibleRegion.And(*aVisibleRegion, mVisibleRect); - - nsPoint origin = ToReferenceFrame(); - nsRect visibleBounds = aVisibleRegion->GetBounds(); - nsRect frameRect(origin, mFrame->GetSize()); - if (!frameRect.Contains(visibleBounds)) - return true; - - // the visible region is entirely inside the border-rect, and box shadows - // never render within the border-rect (unless there's a border radius). - nscoord twipsRadii[8]; - bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii); - if (!hasBorderRadii) - return false; - - return !RoundedRectContainsRect(frameRect, twipsRadii, visibleBounds); + return true; } void diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 994139cc8510..7a7b3931c76b 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -933,6 +933,14 @@ public: *aSnap = false; return nsRect(ToReferenceFrame(), Frame()->GetSize()); } + /** + * Returns true if nothing will be rendered inside aRect, false if uncertain. + * aRect is assumed to be contained in this item's bounds. + */ + virtual bool IsInvisibleInRect(const nsRect& aRect) + { + return false; + } /** * Returns the result of GetBounds intersected with the item's clip. * The intersection is approximate since rounded corners are not taking into @@ -1191,8 +1199,7 @@ public: */ virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion) - { return !mVisibleRect.IsEmpty(); } + const nsRect& aAllowVisibleRegionExpansion); /** * Try to merge with the other item (which is below us in the display @@ -2022,11 +2029,9 @@ public: } #endif + virtual bool IsInvisibleInRect(const nsRect& aRect) MOZ_OVERRIDE; virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER) virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; @@ -2344,6 +2349,7 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual bool IsInvisibleInRect(const nsRect& aRect) MOZ_OVERRIDE; virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; @@ -2430,11 +2436,9 @@ public: } #endif + virtual bool IsInvisibleInRect(const nsRect& aRect) MOZ_OVERRIDE; virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, - nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE) };