--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -1047,47 +1047,48 @@ GetBorderRadiusTwips(const nsStyleCorner
if (aTwipsRadii[i])
result = PR_TRUE;
}
return result;
}
void
-nsCSSRendering::PaintBoxShadow(nsPresContext* aPresContext,
- nsIRenderingContext& aRenderingContext,
- nsIFrame* aForFrame,
- const nsPoint& aForFramePt,
- const nsRect& aDirtyRect)
+nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ nsIFrame* aForFrame,
+ const nsRect& aFrameArea,
+ const nsRect& aDirtyRect)
{
const nsStyleBorder* styleBorder = aForFrame->GetStyleBorder();
if (!styleBorder->mBoxShadow)
return;
- nsMargin borderValues = styleBorder->GetActualBorder();
PRIntn sidesToSkip = aForFrame->GetSkipSides();
- nsRect frameRect = nsRect(aForFramePt, aForFrame->GetSize());
// Get any border radius, since box-shadow must also have rounded corners if the frame does
nscoord twipsRadii[8];
PRBool hasBorderRadius = GetBorderRadiusTwips(styleBorder->mBorderRadius,
- frameRect.width, twipsRadii);
+ aFrameArea.width, twipsRadii);
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
gfxCornerSizes borderRadii;
- ComputePixelRadii(twipsRadii, frameRect, sidesToSkip,
+ ComputePixelRadii(twipsRadii, aFrameArea, sidesToSkip,
twipsPerPixel, &borderRadii);
- gfxRect frameGfxRect = RectToGfxRect(frameRect, twipsPerPixel);
+ gfxRect frameGfxRect = RectToGfxRect(aFrameArea, twipsPerPixel);
frameGfxRect.Round();
gfxRect dirtyGfxRect = RectToGfxRect(aDirtyRect, twipsPerPixel);
for (PRUint32 i = styleBorder->mBoxShadow->Length(); i > 0; --i) {
nsCSSShadowItem* shadowItem = styleBorder->mBoxShadow->ShadowAt(i - 1);
- gfxRect shadowRect(frameRect.x, frameRect.y, frameRect.width, frameRect.height);
+ if (shadowItem->mInset)
+ continue;
+
+ gfxRect shadowRect(aFrameArea.x, aFrameArea.y, aFrameArea.width, aFrameArea.height);
shadowRect.MoveBy(gfxPoint(shadowItem->mXOffset, shadowItem->mYOffset));
shadowRect.Outset(shadowItem->mSpread);
gfxRect shadowRectPlusBlur = shadowRect;
shadowRect.ScaleInverse(twipsPerPixel);
shadowRect.Round();
// shadowRect won't include the blur, so make an extra rect here that includes the blur
@@ -1141,16 +1142,130 @@ nsCSSRendering::PaintBoxShadow(nsPresCon
shadowContext->Fill();
blurringArea.DoPaint();
renderContext->Restore();
}
}
void
+nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ nsIFrame* aForFrame,
+ const nsRect& aFrameArea,
+ const nsRect& aDirtyRect)
+{
+ const nsStyleBorder* styleBorder = aForFrame->GetStyleBorder();
+ if (!styleBorder->mBoxShadow)
+ return;
+
+ // Get any border radius, since box-shadow must also have rounded corners if the frame does
+ nscoord twipsRadii[8];
+ PRBool hasBorderRadius = GetBorderRadiusTwips(styleBorder->mBorderRadius,
+ aFrameArea.width, twipsRadii);
+ nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
+
+ nsRect paddingRect = aFrameArea;
+ nsMargin border = aForFrame->GetUsedBorder();
+ aForFrame->ApplySkipSides(border);
+ paddingRect.Deflate(border);
+
+ gfxCornerSizes innerRadii;
+ if (hasBorderRadius) {
+ gfxCornerSizes borderRadii;
+ PRIntn sidesToSkip = aForFrame->GetSkipSides();
+
+ ComputePixelRadii(twipsRadii, aFrameArea, sidesToSkip,
+ twipsPerPixel, &borderRadii);
+ gfxFloat borderSizes[4] = {
+ border.top / twipsPerPixel, border.right / twipsPerPixel,
+ border.bottom / twipsPerPixel, border.left / twipsPerPixel
+ };
+ nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes,
+ &innerRadii);
+ }
+
+ gfxRect frameGfxRect = RectToGfxRect(paddingRect, twipsPerPixel);
+ frameGfxRect.Round();
+ gfxRect dirtyGfxRect = RectToGfxRect(aDirtyRect, twipsPerPixel);
+
+ for (PRUint32 i = styleBorder->mBoxShadow->Length(); i > 0; --i) {
+ nsCSSShadowItem* shadowItem = styleBorder->mBoxShadow->ShadowAt(i - 1);
+ if (!shadowItem->mInset)
+ continue;
+
+ /*
+ * shadowRect: the frame's padding rect
+ * shadowPaintRect: the area to paint on the temp surface, larger than shadowRect
+ * so that blurs still happen properly near the edges
+ * shadowClipRect: the area on the temporary surface within shadowPaintRect
+ * that we will NOT paint in
+ */
+ nscoord blurRadius = shadowItem->mRadius;
+ gfxRect shadowRect(paddingRect.x, paddingRect.y, paddingRect.width, paddingRect.height);
+ gfxRect shadowPaintRect = shadowRect;
+ shadowPaintRect.Outset(blurRadius);
+
+ gfxRect shadowClipRect = shadowRect;
+ shadowClipRect.MoveBy(gfxPoint(shadowItem->mXOffset, shadowItem->mYOffset));
+ shadowClipRect.Inset(shadowItem->mSpread);
+
+ shadowRect.ScaleInverse(twipsPerPixel);
+ shadowRect.Round();
+ shadowPaintRect.ScaleInverse(twipsPerPixel);
+ shadowPaintRect.RoundOut();
+ shadowClipRect.ScaleInverse(twipsPerPixel);
+ shadowClipRect.Round();
+
+ gfxContext* renderContext = aRenderingContext.ThebesContext();
+ nsRefPtr<gfxContext> shadowContext;
+ nsContextBoxBlur blurringArea;
+
+ // shadowPaintRect is already in device pixels, pass 1 as the appunits/pixel value
+ blurRadius /= twipsPerPixel;
+ shadowContext = blurringArea.Init(shadowPaintRect, blurRadius, 1, renderContext, dirtyGfxRect);
+ if (!shadowContext)
+ continue;
+
+ // Set the shadow color; if not specified, use the foreground color
+ nscolor shadowColor;
+ if (shadowItem->mHasColor)
+ shadowColor = shadowItem->mColor;
+ else
+ shadowColor = aForFrame->GetStyleColor()->mColor;
+
+ renderContext->Save();
+ renderContext->SetColor(gfxRGBA(shadowColor));
+
+ // Clip the context to the area of the frame's padding rect, so no part of the
+ // shadow is painted outside
+ renderContext->NewPath();
+ if (hasBorderRadius)
+ renderContext->RoundedRectangle(shadowRect, innerRadii, PR_FALSE);
+ else
+ renderContext->Rectangle(shadowRect);
+ renderContext->Clip();
+
+ // Fill the temporary surface minus the area within the frame that we should
+ // not paint in, and blur and apply it
+ shadowContext->NewPath();
+ shadowContext->Rectangle(shadowPaintRect);
+ if (hasBorderRadius)
+ shadowContext->RoundedRectangle(shadowClipRect, innerRadii, PR_FALSE);
+ else
+ shadowContext->Rectangle(shadowClipRect);
+ shadowContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
+ shadowContext->Fill();
+
+ blurringArea.DoPaint();
+ renderContext->Restore();
+ }
+}
+
+void
nsCSSRendering::PaintBackground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
PRBool aUsePrintSettings,
nsRect* aBGClipRect)
{
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -56,21 +56,27 @@ struct nsCSSRendering {
*/
static nsresult Init();
/**
* Clean up any static variables used by nsCSSRendering.
*/
static void Shutdown();
- static void PaintBoxShadow(nsPresContext* aPresContext,
- nsIRenderingContext& aRenderingContext,
- nsIFrame* aForFrame,
- const nsPoint& aForFramePt,
- const nsRect& aDirtyRect);
+ static void PaintBoxShadowInner(nsPresContext* aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ nsIFrame* aForFrame,
+ const nsRect& aFrameArea,
+ const nsRect& aDirtyRect);
+
+ static void PaintBoxShadowOuter(nsPresContext* aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ nsIFrame* aForFrame,
+ const nsRect& aFrameArea,
+ const nsRect& aDirtyRect);
/**
* Render the border for an element using css rendering rules
* for borders. aSkipSides is a bitmask of the sides to skip
* when rendering. If 0 then no sides are skipped.
*
* Both aDirtyRect and aBorderArea are in the local coordinate space
* of aForFrame
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -638,46 +638,54 @@ nsDisplayBorder::Paint(nsDisplayListBuil
nsCSSRendering::PaintBorder(mFrame->PresContext(), *aCtx, mFrame,
aDirtyRect, nsRect(offset, mFrame->GetSize()),
*mFrame->GetStyleBorder(),
mFrame->GetStyleContext(),
mFrame->GetSkipSides());
}
void
-nsDisplayBoxShadow::Paint(nsDisplayListBuilder* aBuilder,
+nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
- nsCSSRendering::PaintBoxShadow(mFrame->PresContext(), *aCtx,
- mFrame, offset, aDirtyRect);
+ nsCSSRendering::PaintBoxShadowOuter(mFrame->PresContext(), *aCtx, mFrame,
+ nsRect(offset, mFrame->GetSize()), aDirtyRect);
}
nsRect
-nsDisplayBoxShadow::GetBounds(nsDisplayListBuilder* aBuilder) {
+nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
}
PRBool
-nsDisplayBoxShadow::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
- nsRegion* aVisibleRegion) {
+nsDisplayBoxShadowOuter::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
+ nsRegion* aVisibleRegion) {
if (!nsDisplayItem::OptimizeVisibility(aBuilder, aVisibleRegion))
return PR_FALSE;
const nsStyleBorder* border = mFrame->GetStyleBorder();
nsPoint origin = aBuilder->ToReferenceFrame(mFrame);
if (nsRect(origin, mFrame->GetSize()).Contains(aVisibleRegion->GetBounds()) &&
!nsLayoutUtils::HasNonZeroCorner(border->mBorderRadius)) {
// the visible region is entirely inside the border-rect, and box shadows
// never render within the border-rect (unless there's a border radius).
return PR_FALSE;
}
return PR_TRUE;
}
+void
+nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
+ nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
+ nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
+ nsCSSRendering::PaintBoxShadowInner(mFrame->PresContext(), *aCtx, mFrame,
+ nsRect(offset, mFrame->GetSize()), aDirtyRect);
+}
+
nsDisplayWrapList::nsDisplayWrapList(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayItem(aFrame) {
mList.AppendToTop(aList);
}
nsDisplayWrapList::nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem)
: nsDisplayItem(aFrame) {
mList.AppendToTop(aItem);
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1032,34 +1032,53 @@ public:
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Background")
private:
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
PRPackedBool mIsThemed;
};
/**
- * The standard display item to paint the CSS box-shadow of a frame.
+ * The standard display item to paint the outer CSS box-shadows of a frame.
*/
-class nsDisplayBoxShadow : public nsDisplayItem {
+class nsDisplayBoxShadowOuter : public nsDisplayItem {
public:
- nsDisplayBoxShadow(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
- MOZ_COUNT_CTOR(nsDisplayBoxShadow);
+ nsDisplayBoxShadowOuter(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
+ MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
}
#ifdef NS_BUILD_REFCNT_LOGGING
- virtual ~nsDisplayBoxShadow() {
- MOZ_COUNT_DTOR(nsDisplayBoxShadow);
+ virtual ~nsDisplayBoxShadowOuter() {
+ MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
}
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
- NS_DISPLAY_DECL_NAME("BoxShadow")
+ NS_DISPLAY_DECL_NAME("BoxShadowOuter")
+};
+
+/**
+ * The standard display item to paint the inner CSS box-shadows of a frame.
+ */
+class nsDisplayBoxShadowInner : public nsDisplayItem {
+public:
+ nsDisplayBoxShadowInner(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
+ MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
+ }
+#ifdef NS_BUILD_REFCNT_LOGGING
+ virtual ~nsDisplayBoxShadowInner() {
+ MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
+ }
+#endif
+
+ virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
+ const nsRect& aDirtyRect);
+ NS_DISPLAY_DECL_NAME("BoxShadowInner")
};
/**
* The standard display item to paint the CSS outline of a frame.
*/
class nsDisplayOutline : public nsDisplayItem {
public:
nsDisplayOutline(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -95,16 +95,19 @@
#define NS_BOXPROP_SOURCE_PHYSICAL 0
#define NS_BOXPROP_SOURCE_LOGICAL 1
// box-sizing
#define NS_STYLE_BOX_SIZING_CONTENT 0
#define NS_STYLE_BOX_SIZING_PADDING 1
#define NS_STYLE_BOX_SIZING_BORDER 2
+// box-shadow
+#define NS_STYLE_BOX_SHADOW_INSET 0
+
// float-edge
#define NS_STYLE_FLOAT_EDGE_CONTENT 0
#define NS_STYLE_FLOAT_EDGE_MARGIN 1
// key-equivalent
#define NS_STYLE_KEY_EQUIVALENT_NONE 0
// user-focus
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -86,16 +86,54 @@ nsButtonFrameRenderer::SetDisabled(PRBoo
PRBool
nsButtonFrameRenderer::isDisabled()
{
// get the content
return mFrame->GetContent()->HasAttr(kNameSpaceID_None,
nsGkAtoms::disabled);
}
+class nsDisplayButtonBoxShadowOuter : public nsDisplayItem {
+public:
+ nsDisplayButtonBoxShadowOuter(nsButtonFrameRenderer* aRenderer)
+ : nsDisplayItem(aRenderer->GetFrame()), mBFR(aRenderer) {
+ MOZ_COUNT_CTOR(nsDisplayButtonBoxShadowOuter);
+ }
+#ifdef NS_BUILD_REFCNT_LOGGING
+ virtual ~nsDisplayButtonBoxShadowOuter() {
+ MOZ_COUNT_DTOR(nsDisplayButtonBoxShadowOuter);
+ }
+#endif
+
+ virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
+ const nsRect& aDirtyRect);
+ virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
+ NS_DISPLAY_DECL_NAME("ButtonBoxShadowOuter")
+private:
+ nsButtonFrameRenderer* mBFR;
+};
+
+nsRect
+nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
+ return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
+}
+
+void
+nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
+ nsIRenderingContext* aCtx,
+ const nsRect& aDirtyRect) {
+ nsRect frameRect = nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
+
+ nsRect buttonRect;
+ mBFR->GetButtonRect(frameRect, buttonRect);
+
+ nsCSSRendering::PaintBoxShadowOuter(mFrame->PresContext(), *aCtx, mFrame,
+ buttonRect, aDirtyRect);
+}
+
class nsDisplayButtonBorderBackground : public nsDisplayItem {
public:
nsDisplayButtonBorderBackground(nsButtonFrameRenderer* aRenderer)
: nsDisplayItem(aRenderer->GetFrame()), mBFR(aRenderer) {
MOZ_COUNT_CTOR(nsDisplayButtonBorderBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayButtonBorderBackground() {
@@ -159,16 +197,22 @@ void nsDisplayButtonForeground::Paint(ns
}
}
nsresult
nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
nsDisplayList* aBackground,
nsDisplayList* aForeground)
{
+ if (mFrame->GetStyleBorder()->mBoxShadow) {
+ nsresult rv = aBackground->AppendNewToTop(new (aBuilder)
+ nsDisplayButtonBoxShadowOuter(this));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
nsresult rv = aBackground->AppendNewToTop(new (aBuilder)
nsDisplayButtonBorderBackground(this));
NS_ENSURE_SUCCESS(rv, rv);
return aForeground->AppendNewToTop(new (aBuilder)
nsDisplayButtonForeground(this));
}
@@ -221,16 +265,18 @@ nsButtonFrameRenderer::PaintBorderAndBac
GetButtonRect(aRect, buttonRect);
nsStyleContext* context = mFrame->GetStyleContext();
const nsStyleBorder* border = context->GetStyleBorder();
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
aDirtyRect, buttonRect, PR_FALSE);
+ nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext,
+ mFrame, buttonRect, aDirtyRect);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
aDirtyRect, buttonRect, *border, context);
}
void
nsButtonFrameRenderer::GetButtonOuterFocusRect(const nsRect& aRect, nsRect& focusRect)
{
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -210,23 +210,25 @@ NS_IMETHODIMP
nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
// Paint our background and border in a special way.
// REVIEW: We don't really need to check frame emptiness here; if it's empty,
// the background/border display item won't do anything, and if it isn't empty,
// we need to paint the outline
if (IsVisibleForPainting(aBuilder)) {
- nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
- nsDisplayBoxShadow(this));
- NS_ENSURE_SUCCESS(rv, rv);
+ if (GetStyleBorder()->mBoxShadow) {
+ nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
+ nsDisplayBoxShadowOuter(this));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
// don't bother checking to see if we really have a border or background.
// we usually will have a border.
- rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
+ nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayFieldSetBorderBackground(this));
NS_ENSURE_SUCCESS(rv, rv);
rv = DisplayOutlineUnconditional(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame");
}
@@ -274,16 +276,19 @@ nsFieldSetFrame::PaintBorderBackground(n
if (topBorder < mLegendRect.height)
yoff = (mLegendRect.height - topBorder)/2;
nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff);
nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
aDirtyRect, rect, PR_TRUE);
+ nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
+ this, rect, aDirtyRect);
+
if (mLegendFrame) {
// Use the rect of the legend frame, not mLegendRect, so we draw our
// border under the legend's left and right margins.
nsRect legendRect = mLegendFrame->GetRect() + aPt;
// we should probably use PaintBorderEdges to do this but for now just use clipping
// to achieve the same effect.
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -569,17 +569,17 @@ nsFileControlFrame::GetFormProperty(nsIA
NS_IMETHODIMP
nsFileControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// box-shadow
if (GetStyleBorder()->mBoxShadow) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
- nsDisplayBoxShadow(this));
+ nsDisplayBoxShadowOuter(this));
NS_ENSURE_SUCCESS(rv, rv);
}
// Our background is inherited to the text input, and we don't really want to
// paint it or out padding and borders (which we never have anyway, per
// styles in forms.css) -- doing it just makes us look ugly in some cases and
// has no effect in others.
nsDisplayListCollection tempList;
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -199,21 +199,17 @@ nsHTMLButtonControlFrame::HandleEvent(ns
NS_IMETHODIMP
nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsDisplayList onTop;
if (IsVisibleForPainting(aBuilder)) {
- nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
- nsDisplayBoxShadow(this));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
+ nsresult rv = mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
NS_ENSURE_SUCCESS(rv, rv);
}
nsDisplayListCollection set;
// Do not allow the child subtree to receive events.
if (!aBuilder->IsForEventDelivery()) {
nsresult rv =
BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), aDirtyRect, set,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -945,31 +945,38 @@ nsFrame::DisplayBorderBackgroundOutline(
PRBool aForceBackground)
{
// The visibility check belongs here since child elements have the
// opportunity to override the visibility property and display even if
// their parent is hidden.
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
- if (GetStyleBorder()->mBoxShadow) {
+ PRBool hasBoxShadow = !!(GetStyleBorder()->mBoxShadow);
+ if (hasBoxShadow) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
- nsDisplayBoxShadow(this));
+ nsDisplayBoxShadowOuter(this));
NS_ENSURE_SUCCESS(rv, rv);
}
// Here we don't try to detect background propagation. Frames that might
// receive a propagated background should just set aForceBackground to
// PR_TRUE.
if (aBuilder->IsForEventDelivery() || aForceBackground ||
!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBackground(this));
NS_ENSURE_SUCCESS(rv, rv);
}
+
+ if (hasBoxShadow) {
+ nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
+ nsDisplayBoxShadowInner(this));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
if (HasBorder()) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBorder(this));
NS_ENSURE_SUCCESS(rv, rv);
}
return DisplayOutlineUnconditional(aBuilder, aLists);
@@ -3851,16 +3858,20 @@ ComputeOutlineAndEffectsRect(nsIFrame* a
// box-shadow
nsCSSShadowArray* boxShadows = aFrame->GetStyleBorder()->mBoxShadow;
if (boxShadows) {
nsRect shadows;
for (PRUint32 i = 0; i < boxShadows->Length(); ++i) {
nsRect tmpRect = r;
nsCSSShadowItem* shadow = boxShadows->ShadowAt(i);
+
+ // inset shadows are never painted outside the frame
+ if (shadow->mInset)
+ continue;
nscoord outsetRadius = shadow->mRadius + shadow->mSpread;
tmpRect.MoveBy(nsPoint(shadow->mXOffset, shadow->mYOffset));
tmpRect.Inflate(outsetRadius, outsetRadius);
shadows.UnionRect(shadows, tmpRect);
}
r.UnionRect(r, shadows);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-shadow/boxshadow-inner-basic-ref.html
@@ -0,0 +1,1 @@
+<div style="background-color: grey; width: 300px; height: 300px; -moz-border-radius: 5px; position: absolute; top: 20px; left: 20px;">inset</div><div style="-moz-border-radius: 5px; width: 300px; height: 300px; background-color: white; position: absolute; top: 40px; left: 40px;"> </div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-shadow/boxshadow-inner-basic.html
@@ -0,0 +1,1 @@
+<div style="-moz-box-shadow: 20px 20px grey inset; width: 300px; height: 300px; -moz-border-radius: 5px; position: absolute; top: 20px; left: 20px;">inset</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-shadow/boxshadow-mixed-ref.html
@@ -0,0 +1,1 @@
+<div style="background-color: blue; border: 2px solid red; -moz-border-radius: 10px; width: 300px; height: 300px; position: absolute; top: 10px; left: 10px;">inset and outset</div><div style="-moz-border-radius: 10px; background-color: green; width: 304px; height: 304px; position: absolute; top: 10px; left: 360px;"> </div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-shadow/boxshadow-mixed.html
@@ -0,0 +1,1 @@
+<div style="border: 2px red solid; -moz-border-radius: 10px; width: 300px; height: 300px; -moz-box-shadow: 500px 500px 0px 20px blue inset, 350px 0px green; position: absolute; top: 10px; left: 10px;">inset and outset</div>
--- a/layout/reftests/box-shadow/reftest.list
+++ b/layout/reftests/box-shadow/reftest.list
@@ -3,8 +3,10 @@
== boxshadow-multiple.html boxshadow-multiple-ref.html
== boxshadow-spread.html boxshadow-spread-ref.html
== tableboxshadow-basic.html tableboxshadow-basic-ref.html
== tableboxshadow-trshadow.html tableboxshadow-trshadow-ref.html
== tableboxshadow-tdshadow.html tableboxshadow-tdshadow-ref.html
== boxshadow-rounding.html boxshadow-rounding-ref.html
== boxshadow-button.html boxshadow-button-ref.html
== boxshadow-fileupload.html boxshadow-fileupload-ref.html
+== boxshadow-inner-basic.html boxshadow-inner-basic-ref.html
+== boxshadow-mixed.html boxshadow-mixed-ref.html
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -429,17 +429,17 @@ protected:
PRBool ParseOutline();
PRBool ParseOverflow();
PRBool ParsePadding();
PRBool ParsePause();
PRBool ParseQuotes();
PRBool ParseSize();
PRBool ParseTextDecoration(nsCSSValue& aValue);
- nsCSSValueList* ParseCSSShadowList(PRBool aUsesSpread);
+ nsCSSValueList* ParseCSSShadowList(PRBool aIsBoxShadow);
PRBool ParseTextShadow();
PRBool ParseBoxShadow();
#ifdef MOZ_SVG
PRBool ParsePaint(nsCSSValuePair* aResult,
nsCSSProperty aPropID);
PRBool ParseDasharray();
PRBool ParseMarker();
@@ -7639,51 +7639,61 @@ CSSParserImpl::ParseTextDecoration(nsCSS
aValue.SetIntValue(intValue, eCSSUnit_Enumerated);
}
return PR_TRUE;
}
return PR_FALSE;
}
nsCSSValueList*
-CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
+CSSParserImpl::ParseCSSShadowList(PRBool aIsBoxShadow)
{
nsAutoParseCompoundProperty compound(this);
// Parses x, y, radius, color (in two possible orders)
// This parses the input into a list. Either it contains just a "none" or
// "inherit" value, or a list of arrays.
// The resulting arrays will always contain the above order, with color and
// radius as null values as needed
enum {
IndexX,
IndexY,
IndexRadius,
IndexSpread,
- IndexColor
+ IndexColor,
+ IndexInset
};
nsCSSValueList *list = nsnull;
for (nsCSSValueList **curp = &list, *cur; ; curp = &cur->mNext) {
cur = *curp = new nsCSSValueList();
if (!cur) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
break;
}
+
+ nsCSSValue isInset;
+ if (aIsBoxShadow) {
+ // Optional inset keyword (ignore errors)
+ ParseVariant(isInset, VARIANT_KEYWORD,
+ nsCSSProps::kBoxShadowTypeKTable);
+ }
+
+ PRBool isFirstToken = (cur == list && isInset.GetUnit() == eCSSUnit_Null);
if (!ParseVariant(cur->mValue,
- (cur == list) ? VARIANT_HC | VARIANT_LENGTH | VARIANT_NONE
- : VARIANT_COLOR | VARIANT_LENGTH,
+ isFirstToken ? VARIANT_HC | VARIANT_LENGTH | VARIANT_NONE
+ : VARIANT_COLOR | VARIANT_LENGTH,
nsnull)) {
break;
}
nsCSSUnit unit = cur->mValue.GetUnit();
if (unit != eCSSUnit_None && unit != eCSSUnit_Inherit &&
unit != eCSSUnit_Initial) {
- nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(5);
+ nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(6);
if (!val) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
break;
}
PRBool haveColor = PR_FALSE;
if (cur->mValue.IsLengthUnit()) {
val->Item(IndexX) = cur->mValue;
} else {
@@ -7712,28 +7722,36 @@ CSSParserImpl::ParseCSSShadowList(PRBool
// value which we must reject. If we use ParsePositiveVariant we can't
// tell the difference between an unspecified radius and a negative
// radius, so that's why we don't use it.
if (ParseVariant(val->Item(IndexRadius), VARIANT_LENGTH, nsnull) &&
val->Item(IndexRadius).GetFloatValue() < 0) {
break;
}
- if (aUsesSpread) {
+ if (aIsBoxShadow) {
// Optional spread (ignore errors)
ParseVariant(val->Item(IndexSpread), VARIANT_LENGTH,
nsnull);
}
if (!haveColor) {
// Optional color (ignore errors)
ParseVariant(val->Item(IndexColor), VARIANT_COLOR,
nsnull);
}
+ if (aIsBoxShadow && isInset.GetUnit() == eCSSUnit_Null) {
+ // Optional inset keyword (ignore errors)
+ ParseVariant(val->Item(IndexInset), VARIANT_KEYWORD,
+ nsCSSProps::kBoxShadowTypeKTable);
+ } else if (isInset.GetUnit() == eCSSUnit_Enumerated) {
+ val->Item(IndexInset) = isInset;
+ }
+
// Might be at a comma now
if (ExpectSymbol(',', PR_TRUE)) {
// Go to next value
continue;
}
}
if (!ExpectEndProperty()) {
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -385,17 +385,17 @@ CSS_PROP_BORDER(border-start-width-value
CSS_PROP_SHORTHAND(border-style, border_style, BorderStyle, 0) // on/off will need reflow
CSS_PROP_SHORTHAND(border-top, border_top, BorderTop, 0)
CSS_PROP_BORDER(border-top-color, border_top_color, BorderTopColor, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER, Margin, mBorderColor.mTop, eCSSType_Value, kBorderColorKTable)
CSS_PROP_BORDER(-moz-border-top-colors, border_top_colors, MozBorderTopColors, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER, Margin, mBorderColors.mTop, eCSSType_ValueList, nsnull)
CSS_PROP_BORDER(border-top-style, border_top_style, BorderTopStyle, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER, Margin, mBorderStyle.mTop, eCSSType_Value, kBorderStyleKTable) // on/off will need reflow
CSS_PROP_BORDER(border-top-width, border_top_width, BorderTopWidth, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER, Margin, mBorderWidth.mTop, eCSSType_Value, kBorderWidthKTable)
CSS_PROP_SHORTHAND(border-width, border_width, BorderWidth, 0)
CSS_PROP_POSITION(bottom, bottom, Bottom, 0, Position, mOffset.mBottom, eCSSType_Value, nsnull)
-CSS_PROP_BORDER(-moz-box-shadow, box_shadow, MozBoxShadow, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Margin, mBoxShadow, eCSSType_ValueList, nsnull)
+CSS_PROP_BORDER(-moz-box-shadow, box_shadow, MozBoxShadow, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Margin, mBoxShadow, eCSSType_ValueList, kBoxShadowTypeKTable)
CSS_PROP_POSITION(-moz-box-sizing, box_sizing, MozBoxSizing, 0, Position, mBoxSizing, eCSSType_Value, kBoxSizingKTable) // XXX bug 3935
CSS_PROP_TABLEBORDER(caption-side, caption_side, CaptionSide, 0, Table, mCaptionSide, eCSSType_Value, kCaptionSideKTable)
CSS_PROP_DISPLAY(clear, clear, Clear, 0, Display, mClear, eCSSType_Value, kClearKTable)
CSS_PROP_DISPLAY(clip, clip, Clip, 0, Display, mClip, eCSSType_Rect, nsnull)
CSS_PROP_COLOR(color, color, Color, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mColor, eCSSType_Value, nsnull)
CSS_PROP_COLUMN(-moz-column-count, _moz_column_count, MozColumnCount, 0, Column, mColumnCount, eCSSType_Value, nsnull)
CSS_PROP_COLUMN(-moz-column-width, _moz_column_width, MozColumnWidth, 0, Column, mColumnWidth, eCSSType_Value, nsnull)
CSS_PROP_COLUMN(-moz-column-gap, _moz_column_gap, MozColumnGap, 0, Column, mColumnGap, eCSSType_Value, nsnull)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -432,16 +432,21 @@ const PRInt32 nsCSSProps::kBorderWidthKT
};
const PRInt32 nsCSSProps::kBoxPropSourceKTable[] = {
eCSSKeyword_physical, NS_BOXPROP_SOURCE_PHYSICAL,
eCSSKeyword_logical, NS_BOXPROP_SOURCE_LOGICAL,
eCSSKeyword_UNKNOWN,-1
};
+const PRInt32 nsCSSProps::kBoxShadowTypeKTable[] = {
+ eCSSKeyword_inset, NS_STYLE_BOX_SHADOW_INSET,
+ eCSSKeyword_UNKNOWN,-1
+};
+
const PRInt32 nsCSSProps::kBoxSizingKTable[] = {
eCSSKeyword_content_box, NS_STYLE_BOX_SIZING_CONTENT,
eCSSKeyword_border_box, NS_STYLE_BOX_SIZING_BORDER,
eCSSKeyword_padding_box, NS_STYLE_BOX_SIZING_PADDING,
eCSSKeyword_UNKNOWN,-1
};
const PRInt32 nsCSSProps::kCaptionSideKTable[] = {
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -157,16 +157,17 @@ public:
static const PRInt32 kShapeRenderingKTable[];
static const PRInt32 kStrokeLinecapKTable[];
static const PRInt32 kStrokeLinejoinKTable[];
static const PRInt32 kTextAnchorKTable[];
static const PRInt32 kTextRenderingKTable[];
static const PRInt32 kColorInterpolationKTable[];
#endif
static const PRInt32 kBoxPropSourceKTable[];
+ static const PRInt32 kBoxShadowTypeKTable[];
static const PRInt32 kBoxSizingKTable[];
static const PRInt32 kCaptionSideKTable[];
static const PRInt32 kClearKTable[];
static const PRInt32 kColorKTable[];
static const PRInt32 kContentKTable[];
static const PRInt32 kCursorKTable[];
static const PRInt32 kDirectionKTable[];
static const PRInt32 kDisplayKTable[];
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1783,17 +1783,17 @@ nsComputedDOMStyle::GetEllipseRadii(cons
return CallQueryInterface(valueList, aValue);
}
}
nsresult
nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
const nscolor& aDefaultColor,
- PRBool aUsesSpread,
+ PRBool aIsBoxShadow,
nsIDOMCSSValue** aValue)
{
if (!aArray) {
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
val->SetIdent(nsGkAtoms::none);
return CallQueryInterface(val, aValue);
}
@@ -1807,17 +1807,17 @@ nsComputedDOMStyle::GetCSSShadowArray(ns
&nsCSSShadowItem::mXOffset,
&nsCSSShadowItem::mYOffset,
&nsCSSShadowItem::mRadius,
&nsCSSShadowItem::mSpread
};
nscoord nsCSSShadowItem::* const * shadowValues;
PRUint32 shadowValuesLength;
- if (aUsesSpread) {
+ if (aIsBoxShadow) {
shadowValues = shadowValuesWithSpread;
shadowValuesLength = NS_ARRAY_LENGTH(shadowValuesWithSpread);
} else {
shadowValues = shadowValuesNoSpread;
shadowValuesLength = NS_ARRAY_LENGTH(shadowValuesNoSpread);
}
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE);
@@ -1853,16 +1853,29 @@ nsComputedDOMStyle::GetCSSShadowArray(ns
val = GetROCSSPrimitiveValue();
if (!val || !itemList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
val->SetAppUnits(item->*(shadowValues[i]));
}
+
+ if (item->mInset && aIsBoxShadow) {
+ // This is an inset box-shadow
+ val = GetROCSSPrimitiveValue();
+ if (!val || !itemList->AppendCSSValue(val)) {
+ delete val;
+ delete valueList;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ val->SetIdent(
+ nsCSSProps::ValueToKeywordEnum(NS_STYLE_BOX_SHADOW_INSET,
+ nsCSSProps::kBoxShadowTypeKTable));
+ }
}
return CallQueryInterface(valueList, aValue);
}
nsresult
nsComputedDOMStyle::GetBoxShadow(nsIDOMCSSValue** aValue)
{
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -111,17 +111,17 @@ private:
nsresult GetBorderColorFor(PRUint8 aSide, nsIDOMCSSValue** aValue);
nsresult GetMarginWidthFor(PRUint8 aSide, nsIDOMCSSValue** aValue);
PRBool GetLineHeightCoord(nscoord& aCoord);
nsresult GetCSSShadowArray(nsCSSShadowArray* aArray,
const nscolor& aDefaultColor,
- PRBool aUsesSpread,
+ PRBool aIsBoxShadow,
nsIDOMCSSValue** aValue);
/* Properties Queryable as CSSValues */
nsresult GetAppearance(nsIDOMCSSValue** aValue);
/* Box properties */
nsresult GetBoxAlign(nsIDOMCSSValue** aValue);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2848,17 +2848,17 @@ nsRuleNode::ComputeFontData(void* aStart
}
COMPUTE_END_INHERITED(Font, font)
}
already_AddRefed<nsCSSShadowArray>
nsRuleNode::GetShadowData(nsCSSValueList* aList,
nsStyleContext* aContext,
- PRBool aUsesSpread,
+ PRBool aIsBoxShadow,
PRBool& inherited)
{
PRUint32 arrayLength = 0;
for (nsCSSValueList *list2 = aList; list2; list2 = list2->mNext)
++arrayLength;
NS_ASSERTION(arrayLength > 0, "Non-null text-shadow list, yet we counted 0 items.");
nsCSSShadowArray* shadowList = new(arrayLength) nsCSSShadowArray(arrayLength);
@@ -2889,32 +2889,40 @@ nsRuleNode::GetShadowData(nsCSSValueList
SETCOORD_LENGTH, aContext, mPresContext, inherited);
NS_ASSERTION(unitOK, "unexpected unit");
item->mRadius = tempCoord.GetCoordValue();
} else {
item->mRadius = 0;
}
// Find the spread radius
- if (aUsesSpread && arr->Item(3).GetUnit() != eCSSUnit_Null) {
+ if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
SETCOORD_LENGTH, aContext, mPresContext, inherited);
NS_ASSERTION(unitOK, "unexpected unit");
item->mSpread = tempCoord.GetCoordValue();
} else {
item->mSpread = 0;
}
if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
item->mHasColor = PR_TRUE;
// 2nd argument can be bogus since inherit is not a valid color
unitOK = SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor,
inherited);
NS_ASSERTION(unitOK, "unexpected unit");
}
+
+ if (aIsBoxShadow && arr->Item(5).GetUnit() == eCSSUnit_Enumerated) {
+ NS_ASSERTION(arr->Item(5).GetIntValue() == NS_STYLE_BOX_SHADOW_INSET,
+ "invalid keyword type for box shadow");
+ item->mInset = PR_TRUE;
+ } else {
+ item->mInset = PR_FALSE;
+ }
}
NS_ADDREF(shadowList);
return shadowList;
}
const void*
nsRuleNode::ComputeTextData(void* aStartStruct,
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -682,17 +682,17 @@ protected:
#ifdef MOZ_SVG
NS_HIDDEN_(const void*) GetSVGData(nsStyleContext* aContext);
NS_HIDDEN_(const void*) GetSVGResetData(nsStyleContext* aContext);
#endif
NS_HIDDEN_(already_AddRefed<nsCSSShadowArray>)
GetShadowData(nsCSSValueList* aList,
nsStyleContext* aContext,
- PRBool aUsesSpread,
+ PRBool aIsBoxShadow,
PRBool& inherited);
private:
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
nsIStyleRule* aRule, PRUint8 aLevel, PRBool aIsImportant)
NS_HIDDEN;
~nsRuleNode() NS_HIDDEN;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -303,30 +303,32 @@ private:
struct nsCSSShadowItem {
nscoord mXOffset;
nscoord mYOffset;
nscoord mRadius;
nscoord mSpread;
nscolor mColor;
PRPackedBool mHasColor; // Whether mColor should be used
+ PRPackedBool mInset;
nsCSSShadowItem() : mHasColor(PR_FALSE) {
MOZ_COUNT_CTOR(nsCSSShadowItem);
}
~nsCSSShadowItem() {
MOZ_COUNT_DTOR(nsCSSShadowItem);
}
PRBool operator==(const nsCSSShadowItem& aOther) {
return (mXOffset == aOther.mXOffset &&
mYOffset == aOther.mYOffset &&
mRadius == aOther.mRadius &&
mHasColor == aOther.mHasColor &&
mSpread == aOther.mSpread &&
+ mInset == aOther.mInset &&
(!mHasColor || mColor == aOther.mColor));
}
PRBool operator!=(const nsCSSShadowItem& aOther) {
return !(*this == aOther);
}
};
class nsCSSShadowArray {
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -328,18 +328,18 @@ var gCSSProperties = {
invalid_values: []
},
"-moz-box-shadow": {
domProp: "MozBoxShadow",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
prerequisites: { "color": "blue" },
- other_values: [ "2px 2px", "2px 2px 1px", "2px 2px 2px 2px", "blue 3px 2px", "2px 2px 1px 5px green", "2px 2px red", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px, 1px 2px 3px 2px orange", "3px 0 0 0" ],
- invalid_values: [ "3% 3%", "1px 1px 1px 1px 1px", "2px 2px, none", "red 2px 2px blue", "inherit, 2px 2px", "2px 2px, inherit", "2px 2px -5px" ]
+ other_values: [ "2px 2px", "2px 2px 1px", "2px 2px 2px 2px", "blue 3px 2px", "2px 2px 1px 5px green", "2px 2px red", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px, 1px 2px 3px 2px orange", "3px 0 0 0", "inset 2px 2px 3px 4px black", "2px -2px green inset, 4px 4px 3px blue, inset 2px 2px" ],
+ invalid_values: [ "3% 3%", "1px 1px 1px 1px 1px", "2px 2px, none", "red 2px 2px blue", "inherit, 2px 2px", "2px 2px, inherit", "2px 2px -5px", "inset 4px 4px black inset", "inset inherit", "inset none" ]
},
"-moz-box-sizing": {
domProp: "MozBoxSizing",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "content-box" ],
other_values: [ "border-box", "padding-box" ],
invalid_values: [ "margin-box", "content", "padding", "border", "margin" ]
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -441,34 +441,43 @@ nsTableCellFrame::BuildDisplayList(nsDis
PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
if (!isRoot) {
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
NS_ASSERTION(currentItem, "No current table item???");
currentItem->UpdateForFrameBackground(this);
}
- if (GetStyleBorder()->mBoxShadow) {
- nsDisplayItem* item = new (aBuilder) nsDisplayBoxShadow(this);
+ // display outset box-shadows if we need to.
+ PRBool hasBoxShadow = !!(GetStyleBorder()->mBoxShadow);
+ if (hasBoxShadow) {
+ nsDisplayItem* item = new (aBuilder) nsDisplayBoxShadowOuter(this);
nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
NS_ENSURE_SUCCESS(rv, rv);
}
// display background if we need to.
if (aBuilder->IsForEventDelivery() ||
(((!tableFrame->IsBorderCollapse() || isRoot) &&
(!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance)))) {
// The cell background was not painted by the nsTablePainter,
// so we need to do it. We have special background processing here
// so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline
nsDisplayTableItem* item = new (aBuilder) nsDisplayTableCellBackground(this);
nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
NS_ENSURE_SUCCESS(rv, rv);
item->UpdateForFrameBackground(this);
}
+
+ // display inset box-shadows if we need to.
+ if (hasBoxShadow) {
+ nsDisplayItem* item = new (aBuilder) nsDisplayBoxShadowInner(this);
+ nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
// display borders if we need to
if (!tableFrame->IsBorderCollapse() && HasBorder() &&
emptyCellStyle == NS_STYLE_TABLE_EMPTY_CELLS_SHOW) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBorder(this));
NS_ENSURE_SUCCESS(rv, rv);
}
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1375,34 +1375,42 @@ nsTableFrame::DisplayGenericTablePart(ns
nsAutoPushCurrentTableItem pushTableItem;
if (aDisplayItem) {
pushTableItem.Push(aBuilder, aDisplayItem);
}
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
NS_ASSERTION(currentItem, "No current table item!");
currentItem->UpdateForFrameBackground(aFrame);
- // Paint the box-shadow for the table frames
- if (aFrame->IsVisibleForPainting(aBuilder) &&
- aFrame->GetStyleBorder()->mBoxShadow) {
- nsDisplayItem* item = new (aBuilder) nsDisplayBoxShadow(aFrame);
+ // Paint the outset box-shadows for the table frames
+ PRBool hasBoxShadow = aFrame->IsVisibleForPainting(aBuilder) &&
+ aFrame->GetStyleBorder()->mBoxShadow;
+ if (hasBoxShadow) {
+ nsDisplayItem* item = new (aBuilder) nsDisplayBoxShadowOuter(aFrame);
nsresult rv = lists->BorderBackground()->AppendNewToTop(item);
NS_ENSURE_SUCCESS(rv, rv);
}
// Create dedicated background display items per-frame when we're
// handling events.
// XXX how to handle collapsed borders?
if (aBuilder->IsForEventDelivery() &&
aFrame->IsVisibleForPainting(aBuilder)) {
nsresult rv = lists->BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBackground(aFrame));
NS_ENSURE_SUCCESS(rv, rv);
}
+ // Paint the inset box-shadows for the table frames
+ if (hasBoxShadow) {
+ nsDisplayItem* item = new (aBuilder) nsDisplayBoxShadowInner(aFrame);
+ nsresult rv = lists->BorderBackground()->AppendNewToTop(item);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
nsresult rv = aTraversal(aBuilder, aFrame, aDirtyRect, *lists);
NS_ENSURE_SUCCESS(rv, rv);
if (sortEventBackgrounds) {
// Ensure that the table frame event background goes before the
// table rowgroups event backgrounds, before the table row event backgrounds,
// before everything else (cells and their blocks)
separatedCollection.BorderBackground()->Sort(aBuilder, CompareByTablePartRank, nsnull);