diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 95ccce192a8..9555564c4fe 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -1247,30 +1247,16 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext, shadowContext->NewPath(); if (hasBorderRadius) { gfxCornerSizes clipRectRadii; - gfxFloat spreadDistance = -shadowItem->mSpread / twipsPerPixel; - gfxFloat borderSizes[4] = { 0, 0, 0, 0 }; + gfxFloat spreadDistance = shadowItem->mSpread / twipsPerPixel; - // We only give the spread radius to corners with a radius on them, otherwise we'll - // give a rounded shadow corner to a frame corner with 0 border radius, should - // the author use non-uniform border radii sizes (border-top-left-radius etc) - // (bug 514670) - if (borderRadii[C_TL].width > 0 || borderRadii[C_BL].width > 0) { - borderSizes[NS_SIDE_LEFT] = spreadDistance; - } + gfxFloat borderSizes[4]; - if (borderRadii[C_TL].height > 0 || borderRadii[C_TR].height > 0) { - borderSizes[NS_SIDE_TOP] = spreadDistance; - } + borderSizes[NS_SIDE_LEFT] = spreadDistance; + borderSizes[NS_SIDE_TOP] = spreadDistance; + borderSizes[NS_SIDE_RIGHT] = spreadDistance; + borderSizes[NS_SIDE_BOTTOM] = spreadDistance; - if (borderRadii[C_TR].width > 0 || borderRadii[C_BR].width > 0) { - borderSizes[NS_SIDE_RIGHT] = spreadDistance; - } - - if (borderRadii[C_BL].height > 0 || borderRadii[C_BR].height > 0) { - borderSizes[NS_SIDE_BOTTOM] = spreadDistance; - } - - nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes, + nsCSSBorderRenderer::ComputeOuterRadii(borderRadii, borderSizes, &clipRectRadii); shadowContext->RoundedRectangle(shadowGfxRect, clipRectRadii); } else { diff --git a/layout/base/nsCSSRenderingBorders.cpp b/layout/base/nsCSSRenderingBorders.cpp index 1470ef73c7b..b266b2b52dd 100644 --- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -221,6 +221,38 @@ nsCSSBorderRenderer::ComputeInnerRadii(const gfxCornerSizes& aRadii, iRadii[C_BL].height = NS_MAX(0.0, aRadii[C_BL].height - aBorderSizes[NS_SIDE_BOTTOM]); } +/* static */ void +nsCSSBorderRenderer::ComputeOuterRadii(const gfxCornerSizes& aRadii, + const gfxFloat *aBorderSizes, + gfxCornerSizes *aOuterRadiiRet) +{ + gfxCornerSizes& oRadii = *aOuterRadiiRet; + + // default all corners to sharp corners + oRadii = gfxCornerSizes(0.0); + + // round the edges that have radii > 0.0 to start with + if (aRadii[C_TL].width > 0.0 && aRadii[C_TL].height > 0.0) { + oRadii[C_TL].width = NS_MAX(0.0, aRadii[C_TL].width + aBorderSizes[NS_SIDE_LEFT]); + oRadii[C_TL].height = NS_MAX(0.0, aRadii[C_TL].height + aBorderSizes[NS_SIDE_TOP]); + } + + if (aRadii[C_TR].width > 0.0 && aRadii[C_TR].height > 0.0) { + oRadii[C_TR].width = NS_MAX(0.0, aRadii[C_TR].width + aBorderSizes[NS_SIDE_RIGHT]); + oRadii[C_TR].height = NS_MAX(0.0, aRadii[C_TR].height + aBorderSizes[NS_SIDE_TOP]); + } + + if (aRadii[C_BR].width > 0.0 && aRadii[C_BR].height > 0.0) { + oRadii[C_BR].width = NS_MAX(0.0, aRadii[C_BR].width + aBorderSizes[NS_SIDE_RIGHT]); + oRadii[C_BR].height = NS_MAX(0.0, aRadii[C_BR].height + aBorderSizes[NS_SIDE_BOTTOM]); + } + + if (aRadii[C_BL].width > 0.0 && aRadii[C_BL].height > 0.0) { + oRadii[C_BL].width = NS_MAX(0.0, aRadii[C_BL].width + aBorderSizes[NS_SIDE_LEFT]); + oRadii[C_BL].height = NS_MAX(0.0, aRadii[C_BL].height + aBorderSizes[NS_SIDE_BOTTOM]); + } +} + /*static*/ void ComputeBorderCornerDimensions(const gfxRect& aOuterRect, const gfxRect& aInnerRect, diff --git a/layout/base/nsCSSRenderingBorders.h b/layout/base/nsCSSRenderingBorders.h index 648a660dfcf..f35a3a7820e 100644 --- a/layout/base/nsCSSRenderingBorders.h +++ b/layout/base/nsCSSRenderingBorders.h @@ -236,6 +236,14 @@ struct nsCSSBorderRenderer { static void ComputeInnerRadii(const gfxCornerSizes& aRadii, const gfxFloat *aBorderSizes, gfxCornerSizes *aInnerRadiiRet); + + // Given aRadii as the border radii for a rectangle, compute the + // appropriate radii for another rectangle *outside* that rectangle + // by increasing the radii, except keeping sharp corners sharp. + // Used for spread box-shadows + static void ComputeOuterRadii(const gfxCornerSizes& aRadii, + const gfxFloat *aBorderSizes, + gfxCornerSizes *aOuterRadiiRet); }; #ifdef DEBUG_NEW_BORDERS diff --git a/layout/reftests/box-shadow/boxshadow-threecorners-ref.html b/layout/reftests/box-shadow/boxshadow-threecorners-ref.html new file mode 100644 index 00000000000..cd9f383e1f8 --- /dev/null +++ b/layout/reftests/box-shadow/boxshadow-threecorners-ref.html @@ -0,0 +1,3 @@ + +