From afabd727c05a85e8ab7890c02a100897388f9409 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 7 Sep 2010 15:20:34 -0700 Subject: [PATCH] Move skip-sides handling from nsCSSRendering::ComputePixelRadii to nsIFrame::ComputeBorderRadii. This fixes a bug (ignoring skip-sides) in nsDisplayBoxShadowOuter::ComputeVisibility, and improves the no-border-radius optimizations when skip-sides allow us to take them. (Bug 459144, patch 3) r=roc a2.0=blocking:beta6+ --- layout/base/nsCSSRendering.cpp | 61 ++++++++-------------------------- layout/base/nsDisplayList.cpp | 3 +- layout/generic/nsFrame.cpp | 43 +++++++++++++++++++++--- layout/generic/nsIFrame.h | 2 ++ 4 files changed, 55 insertions(+), 54 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 580176390158..8d8b3eb85a1c 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -471,48 +471,18 @@ RectToGfxRect(const nsRect& rect, nscoord twipsPerPixel) * Compute the float-pixel radii that should be used for drawing * this border/outline, given the various input bits. * - * If a side is skipped via skipSides, its corners are forced to 0. * All corner radii are then adjusted so they do not require more * space than outerRect, according to the algorithm in css3-background. */ static void ComputePixelRadii(const nscoord *aTwipsRadii, const nsRect& outerRect, - PRIntn skipSides, nscoord twipsPerPixel, gfxCornerSizes *oBorderRadii) { nscoord twipsRadii[8]; memcpy(twipsRadii, aTwipsRadii, sizeof twipsRadii); - if (skipSides & SIDE_BIT_TOP) { - twipsRadii[NS_CORNER_TOP_LEFT_X] = 0; - twipsRadii[NS_CORNER_TOP_LEFT_Y] = 0; - twipsRadii[NS_CORNER_TOP_RIGHT_X] = 0; - twipsRadii[NS_CORNER_TOP_RIGHT_Y] = 0; - } - - if (skipSides & SIDE_BIT_RIGHT) { - twipsRadii[NS_CORNER_TOP_RIGHT_X] = 0; - twipsRadii[NS_CORNER_TOP_RIGHT_Y] = 0; - twipsRadii[NS_CORNER_BOTTOM_RIGHT_X] = 0; - twipsRadii[NS_CORNER_BOTTOM_RIGHT_Y] = 0; - } - - if (skipSides & SIDE_BIT_BOTTOM) { - twipsRadii[NS_CORNER_BOTTOM_RIGHT_X] = 0; - twipsRadii[NS_CORNER_BOTTOM_RIGHT_Y] = 0; - twipsRadii[NS_CORNER_BOTTOM_LEFT_X] = 0; - twipsRadii[NS_CORNER_BOTTOM_LEFT_Y] = 0; - } - - if (skipSides & SIDE_BIT_LEFT) { - twipsRadii[NS_CORNER_BOTTOM_LEFT_X] = 0; - twipsRadii[NS_CORNER_BOTTOM_LEFT_Y] = 0; - twipsRadii[NS_CORNER_TOP_LEFT_X] = 0; - twipsRadii[NS_CORNER_TOP_LEFT_Y] = 0; - } - gfxFloat radii[8]; NS_FOR_CSS_HALF_CORNERS(corner) radii[corner] = twipsRadii[corner] / twipsPerPixel; @@ -629,7 +599,7 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext, } nsIFrame::ComputeBorderRadii(aStyleBorder.mBorderRadius, - aForFrame->GetSize(), twipsRadii); + aForFrame->GetSize(), aSkipSides, twipsRadii); // Turn off rendering for all of the zero sized sides if (aSkipSides & SIDE_BIT_TOP) border.top = 0; @@ -658,8 +628,7 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext, // convert the radii gfxCornerSizes borderRadii; - ComputePixelRadii(twipsRadii, outerRect, aSkipSides, twipsPerPixel, - &borderRadii); + ComputePixelRadii(twipsRadii, outerRect, twipsPerPixel, &borderRadii); PRUint8 borderStyles[4]; nscolor borderColors[4]; @@ -750,7 +719,7 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext, // get the radius for our outline nsIFrame::ComputeBorderRadii(ourOutline->mOutlineRadius, aBorderArea.Size(), - twipsRadii); + 0, twipsRadii); // When the outline property is set on :-moz-anonymous-block or // :-moz-anonyomus-positioned-block pseudo-elements, it inherited that @@ -806,8 +775,7 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext, // convert the radii nsMargin outlineMargin(width, width, width, width); gfxCornerSizes outlineRadii; - ComputePixelRadii(twipsRadii, outerRect, 0, twipsPerPixel, - &outlineRadii); + ComputePixelRadii(twipsRadii, outerRect, twipsPerPixel, &outlineRadii); PRUint8 outlineStyle = ourOutline->GetOutlineStyle(); PRUint8 outlineStyles[4] = { outlineStyle, @@ -865,7 +833,7 @@ nsCSSRendering::PaintFocus(nsPresContext* aPresContext, gfxCornerSizes focusRadii; { nscoord twipsRadii[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - ComputePixelRadii(twipsRadii, aFocusRect, 0, oneDevPixel, &focusRadii); + ComputePixelRadii(twipsRadii, aFocusRect, oneDevPixel, &focusRadii); } gfxFloat focusWidths[4] = { gfxFloat(oneCSSPixel / oneDevPixel), gfxFloat(oneCSSPixel / oneDevPixel), @@ -1167,11 +1135,10 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext, nativeTheme = PR_FALSE; nscoord twipsRadii[8]; hasBorderRadius = nsIFrame::ComputeBorderRadii(styleBorder->mBorderRadius, - aFrameArea.Size(), twipsRadii); + aFrameArea.Size(), aForFrame->GetSkipSides(), + twipsRadii); if (hasBorderRadius) { - PRIntn sidesToSkip = aForFrame->GetSkipSides(); - ComputePixelRadii(twipsRadii, aFrameArea, sidesToSkip, twipsPerPixel, - &borderRadii); + ComputePixelRadii(twipsRadii, aFrameArea, twipsPerPixel, &borderRadii); } } @@ -1348,7 +1315,7 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext, nscoord twipsRadii[8]; PRBool hasBorderRadius = nsIFrame::ComputeBorderRadii( styleBorder->mBorderRadius, aFrameArea.Size(), - twipsRadii); + aForFrame->GetSkipSides(), twipsRadii); nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1); nsRect paddingRect = aFrameArea; @@ -1359,10 +1326,8 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext, gfxCornerSizes innerRadii; if (hasBorderRadius) { gfxCornerSizes borderRadii; - PRIntn sidesToSkip = aForFrame->GetSkipSides(); - ComputePixelRadii(twipsRadii, aFrameArea, sidesToSkip, - twipsPerPixel, &borderRadii); + ComputePixelRadii(twipsRadii, aFrameArea, twipsPerPixel, &borderRadii); gfxFloat borderSizes[4] = { gfxFloat(border.top / twipsPerPixel), gfxFloat(border.right / twipsPerPixel), @@ -2240,10 +2205,10 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, { nscoord radii[8]; haveRoundedCorners = nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius, - aForFrame->GetSize(), radii); + aForFrame->GetSize(), aForFrame->GetSkipSides(), + radii); if (haveRoundedCorners) - ComputePixelRadii(radii, aBorderArea, aForFrame->GetSkipSides(), - appUnitsPerPixel, &bgRadii); + ComputePixelRadii(radii, aBorderArea, appUnitsPerPixel, &bgRadii); } // The 'bgClipArea' (used only by the image tiling logic, far below) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e6bb9cac304c..73e1758d7169 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1011,7 +1011,8 @@ nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder, nscoord twipsRadii[8]; PRBool hasBorderRadii = nsIFrame::ComputeBorderRadii( mFrame->GetStyleBorder()->mBorderRadius, - frameRect.Size(), twipsRadii); + frameRect.Size(), mFrame->GetSkipSides(), + twipsRadii); if (!hasBorderRadii) return PR_FALSE; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 93a8909c3e6a..ca7c128dabd6 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -739,10 +739,9 @@ nsIFrame::GetContentRect() const PRBool nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius, const nsSize& aFrameSize, + PRIntn aSkipSides, nscoord aRadii[8]) { - PRBool result = PR_FALSE; - // Percentages are relative to whichever side they're on. NS_FOR_CSS_HALF_CORNERS(i) { const nsStyleCoord c = aBorderRadius.Get(i); @@ -763,10 +762,44 @@ nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius, aRadii[i] = 0; break; } - - if (aRadii[i]) - result = PR_TRUE; } + + if (aSkipSides & (1 << NS_SIDE_TOP)) { + aRadii[NS_CORNER_TOP_LEFT_X] = 0; + aRadii[NS_CORNER_TOP_LEFT_Y] = 0; + aRadii[NS_CORNER_TOP_RIGHT_X] = 0; + aRadii[NS_CORNER_TOP_RIGHT_Y] = 0; + } + + if (aSkipSides & (1 << NS_SIDE_RIGHT)) { + aRadii[NS_CORNER_TOP_RIGHT_X] = 0; + aRadii[NS_CORNER_TOP_RIGHT_Y] = 0; + aRadii[NS_CORNER_BOTTOM_RIGHT_X] = 0; + aRadii[NS_CORNER_BOTTOM_RIGHT_Y] = 0; + } + + if (aSkipSides & (1 << NS_SIDE_BOTTOM)) { + aRadii[NS_CORNER_BOTTOM_RIGHT_X] = 0; + aRadii[NS_CORNER_BOTTOM_RIGHT_Y] = 0; + aRadii[NS_CORNER_BOTTOM_LEFT_X] = 0; + aRadii[NS_CORNER_BOTTOM_LEFT_Y] = 0; + } + + if (aSkipSides & (1 << NS_SIDE_LEFT)) { + aRadii[NS_CORNER_BOTTOM_LEFT_X] = 0; + aRadii[NS_CORNER_BOTTOM_LEFT_Y] = 0; + aRadii[NS_CORNER_TOP_LEFT_X] = 0; + aRadii[NS_CORNER_TOP_LEFT_Y] = 0; + } + + PRBool result = PR_FALSE; + NS_FOR_CSS_HALF_CORNERS(i) { + if (aRadii[i]) { + result = PR_TRUE; + break; + } + } + return result; } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index fb2dfef9ad4a..149fab9c80c7 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -922,9 +922,11 @@ public: * Get the size, in app units, of the border radii. It returns FALSE iff all * returned radii == 0 (so no border radii), TRUE otherwise. * For the aRadii indexes, use the NS_CORNER_* constants in nsStyleConsts.h + * If a side is skipped via aSkipSides, its corners are forced to 0. */ static PRBool ComputeBorderRadii(const nsStyleCorners& aBorderRadius, const nsSize& aFrameSize, + PRIntn aSkipSides, nscoord aRadii[8]); /**