From 3e19b7fc4aaea0199fbdb4abd789db8f85339992 Mon Sep 17 00:00:00 2001 From: "roc+%cs.cmu.edu" Date: Tue, 19 Sep 2006 21:58:52 +0000 Subject: [PATCH] Bug 350148. Fix scrolling in IFRAMEs with borders or outlines, by having OptimizeVisibility take account of the fact that borders or outlines whose inner rectangle entirely encloses the visible area are not, in fact, visible. r+sr=dbaron git-svn-id: svn://10.0.0.236/trunk@212027 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsDisplayList.cpp | 56 +++++++++++++++++++++++---- mozilla/layout/base/nsDisplayList.h | 2 + 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/mozilla/layout/base/nsDisplayList.cpp b/mozilla/layout/base/nsDisplayList.cpp index 95dd4681039..dd89ebf0e08 100644 --- a/mozilla/layout/base/nsDisplayList.cpp +++ b/mozilla/layout/base/nsDisplayList.cpp @@ -486,15 +486,15 @@ NonZeroStyleCoord(const nsStyleCoord& aCoord) { } static PRBool -HasNonZeroBorderRadius(const nsStyleBorder* aBorder) { +HasNonZeroSide(const nsStyleSides& aSides) { nsStyleCoord coord; - aBorder->mBorderRadius.GetTop(coord); + aSides.GetTop(coord); if (NonZeroStyleCoord(coord)) return PR_TRUE; - aBorder->mBorderRadius.GetRight(coord); + aSides.GetRight(coord); if (NonZeroStyleCoord(coord)) return PR_TRUE; - aBorder->mBorderRadius.GetBottom(coord); + aSides.GetBottom(coord); if (NonZeroStyleCoord(coord)) return PR_TRUE; - aBorder->mBorderRadius.GetLeft(coord); + aSides.GetLeft(coord); if (NonZeroStyleCoord(coord)) return PR_TRUE; return PR_FALSE; @@ -512,7 +512,7 @@ nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) { nsCSSRendering::FindBackground(mFrame->GetPresContext(), mFrame, &bg, &isCanvas); if (!hasBG || (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) || bg->mBackgroundClip != NS_STYLE_BG_CLIP_BORDER || - HasNonZeroBorderRadius(mFrame->GetStyleBorder()) || + HasNonZeroSide(mFrame->GetStyleBorder()->mBorderRadius) || NS_GET_A(bg->mBackgroundColor) < 255) return PR_FALSE; return PR_TRUE; @@ -531,7 +531,7 @@ nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder) { if (!hasBG) return PR_TRUE; if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) && - !HasNonZeroBorderRadius(mFrame->GetStyleBorder()) && + !HasNonZeroSide(mFrame->GetStyleBorder()->mBorderRadius) && bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER) return PR_TRUE; return PR_FALSE; @@ -589,6 +589,28 @@ nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder, mFrame->GetStyleContext(), 0); } +PRBool +nsDisplayOutline::OptimizeVisibility(nsDisplayListBuilder* aBuilder, + nsRegion* aVisibleRegion) { + if (!nsDisplayItem::OptimizeVisibility(aBuilder, aVisibleRegion)) + return PR_FALSE; + + const nsStyleOutline* outline = mFrame->GetStyleOutline(); + nsPoint origin = aBuilder->ToReferenceFrame(mFrame); + if (nsRect(origin, mFrame->GetSize()).Contains(aVisibleRegion->GetBounds()) && + !HasNonZeroSide(outline->mOutlineRadius)) { + nscoord outlineOffset; + outline->GetOutlineOffset(outlineOffset); + if (outlineOffset >= 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 PR_FALSE; + } + } + + return PR_TRUE; +} + void nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect) { @@ -598,6 +620,26 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder, mFrame->GetStyleColor()->mColor); } +PRBool +nsDisplayBorder::OptimizeVisibility(nsDisplayListBuilder* aBuilder, + nsRegion* aVisibleRegion) { + if (!nsDisplayItem::OptimizeVisibility(aBuilder, aVisibleRegion)) + return PR_FALSE; + + const nsStyleBorder* border = mFrame->GetStyleBorder(); + nsRect contentRect = GetBounds(aBuilder); + contentRect.Deflate(border->GetBorder()); + if (contentRect.Contains(aVisibleRegion->GetBounds()) && + !HasNonZeroSide(border->mBorderRadius)) { + // the visible region is entirely inside the content rect, and no part + // of the border is rendered inside the content rect, so we are not + // visible + return PR_FALSE; + } + + return PR_TRUE; +} + void nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect) { diff --git a/mozilla/layout/base/nsDisplayList.h b/mozilla/layout/base/nsDisplayList.h index bb99a07604c..60a441043fb 100644 --- a/mozilla/layout/base/nsDisplayList.h +++ b/mozilla/layout/base/nsDisplayList.h @@ -935,6 +935,7 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect); + virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion); NS_DISPLAY_DECL_NAME("Border") }; @@ -980,6 +981,7 @@ public: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect); + virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion); NS_DISPLAY_DECL_NAME("Outline") };