зеркало из https://github.com/mozilla/pjs.git
Bug 476738. Implement 'inset' box-shadows. r+sr=roc,r=dbaron
This commit is contained in:
Родитель
4a08835d68
Коммит
7a2af3b188
|
@ -1050,37 +1050,38 @@ GetBorderRadiusTwips(const nsStyleCorners& aBorderRadius,
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1143,6 +1144,120 @@ nsCSSRendering::PaintBoxShadow(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -61,11 +61,17 @@ struct 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
|
||||
|
|
|
@ -647,21 +647,21 @@ nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -677,6 +677,14 @@ nsDisplayBoxShadow::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
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);
|
||||
|
|
|
@ -1037,16 +1037,16 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
|
@ -1054,7 +1054,26 @@ public:
|
|||
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")
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -100,6 +100,9 @@
|
|||
#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
|
||||
|
|
|
@ -91,6 +91,44 @@ nsButtonFrameRenderer::isDisabled()
|
|||
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)
|
||||
|
@ -164,6 +202,12 @@ 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);
|
||||
|
@ -226,6 +270,8 @@ nsButtonFrameRenderer::PaintBorderAndBackground(nsPresContext* aPresContext,
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -215,13 +215,15 @@ nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// 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);
|
||||
|
||||
|
@ -279,6 +281,9 @@ nsFieldSetFrame::PaintBorderBackground(nsIRenderingContext& aRenderingContext,
|
|||
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
|
||||
|
|
|
@ -557,7 +557,7 @@ nsFileControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// box-shadow
|
||||
if (GetStyleBorder()->mBoxShadow) {
|
||||
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayBoxShadow(this));
|
||||
nsDisplayBoxShadowOuter(this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -182,11 +182,7 @@ nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -915,9 +915,10 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -931,6 +932,12 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
|
|||
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));
|
||||
|
@ -3824,6 +3831,10 @@ ComputeOutlineAndEffectsRect(nsIFrame* aFrame, PRBool* aAnyOutlineOrEffects,
|
|||
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));
|
||||
|
|
|
@ -0,0 +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>
|
|
@ -0,0 +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>
|
|
@ -0,0 +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>
|
|
@ -0,0 +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>
|
|
@ -8,3 +8,5 @@
|
|||
== 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
|
||||
|
|
|
@ -433,7 +433,7 @@ protected:
|
|||
PRBool ParseSize();
|
||||
PRBool ParseTextDecoration(nsCSSValue& aValue);
|
||||
|
||||
nsCSSValueList* ParseCSSShadowList(PRBool aUsesSpread);
|
||||
nsCSSValueList* ParseCSSShadowList(PRBool aIsBoxShadow);
|
||||
PRBool ParseTextShadow();
|
||||
PRBool ParseBoxShadow();
|
||||
|
||||
|
@ -7686,7 +7686,7 @@ CSSParserImpl::ParseTextDecoration(nsCSSValue& aValue)
|
|||
}
|
||||
|
||||
nsCSSValueList*
|
||||
CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
|
||||
CSSParserImpl::ParseCSSShadowList(PRBool aIsBoxShadow)
|
||||
{
|
||||
nsAutoParseCompoundProperty compound(this);
|
||||
|
||||
|
@ -7700,7 +7700,8 @@ CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
|
|||
IndexY,
|
||||
IndexRadius,
|
||||
IndexSpread,
|
||||
IndexColor
|
||||
IndexColor,
|
||||
IndexInset
|
||||
};
|
||||
|
||||
nsCSSValueList *list = nsnull;
|
||||
|
@ -7710,9 +7711,18 @@ CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
|
|||
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;
|
||||
}
|
||||
|
@ -7720,7 +7730,7 @@ CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
|
|||
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;
|
||||
|
@ -7759,7 +7769,7 @@ CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
|
|||
break;
|
||||
}
|
||||
|
||||
if (aUsesSpread) {
|
||||
if (aIsBoxShadow) {
|
||||
// Optional spread (ignore errors)
|
||||
ParseVariant(val->Item(IndexSpread), VARIANT_LENGTH,
|
||||
nsnull);
|
||||
|
@ -7771,6 +7781,14 @@ CSSParserImpl::ParseCSSShadowList(PRBool aUsesSpread)
|
|||
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
|
||||
|
|
|
@ -390,7 +390,7 @@ CSS_PROP_BORDER(border-top-style, border_top_style, BorderTopStyle, CSS_PROPERTY
|
|||
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)
|
||||
|
|
|
@ -570,6 +570,11 @@ const PRInt32 nsCSSProps::kBoxPropSourceKTable[] = {
|
|||
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,
|
||||
|
|
|
@ -188,6 +188,7 @@ public:
|
|||
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[];
|
||||
|
|
|
@ -1795,7 +1795,7 @@ nsComputedDOMStyle::GetEllipseRadii(const nsStyleCorners& aRadius,
|
|||
nsresult
|
||||
nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
|
||||
const nscolor& aDefaultColor,
|
||||
PRBool aUsesSpread,
|
||||
PRBool aIsBoxShadow,
|
||||
nsIDOMCSSValue** aValue)
|
||||
{
|
||||
if (!aArray) {
|
||||
|
@ -1819,7 +1819,7 @@ nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
|
|||
|
||||
nscoord nsCSSShadowItem::* const * shadowValues;
|
||||
PRUint32 shadowValuesLength;
|
||||
if (aUsesSpread) {
|
||||
if (aIsBoxShadow) {
|
||||
shadowValues = shadowValuesWithSpread;
|
||||
shadowValuesLength = NS_ARRAY_LENGTH(shadowValuesWithSpread);
|
||||
} else {
|
||||
|
@ -1865,6 +1865,19 @@ nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
|
|||
}
|
||||
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);
|
||||
|
|
|
@ -113,7 +113,7 @@ private:
|
|||
|
||||
nsresult GetCSSShadowArray(nsCSSShadowArray* aArray,
|
||||
const nscolor& aDefaultColor,
|
||||
PRBool aUsesSpread,
|
||||
PRBool aIsBoxShadow,
|
||||
nsIDOMCSSValue** aValue);
|
||||
|
||||
/* Properties Queryable as CSSValues */
|
||||
|
|
|
@ -2937,7 +2937,7 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
|
|||
already_AddRefed<nsCSSShadowArray>
|
||||
nsRuleNode::GetShadowData(nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
PRBool aUsesSpread,
|
||||
PRBool aIsBoxShadow,
|
||||
PRBool& canStoreInRuleTree)
|
||||
{
|
||||
PRUint32 arrayLength = 0;
|
||||
|
@ -2981,7 +2981,7 @@ nsRuleNode::GetShadowData(nsCSSValueList* aList,
|
|||
}
|
||||
|
||||
// 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,
|
||||
canStoreInRuleTree);
|
||||
|
@ -2998,6 +2998,14 @@ nsRuleNode::GetShadowData(nsCSSValueList* aList,
|
|||
canStoreInRuleTree);
|
||||
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);
|
||||
|
|
|
@ -712,7 +712,7 @@ protected:
|
|||
NS_HIDDEN_(already_AddRefed<nsCSSShadowArray>)
|
||||
GetShadowData(nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
PRBool aUsesSpread,
|
||||
PRBool aIsBoxShadow,
|
||||
PRBool& inherited);
|
||||
|
||||
private:
|
||||
|
|
|
@ -307,6 +307,7 @@ struct nsCSSShadowItem {
|
|||
|
||||
nscolor mColor;
|
||||
PRPackedBool mHasColor; // Whether mColor should be used
|
||||
PRPackedBool mInset;
|
||||
|
||||
nsCSSShadowItem() : mHasColor(PR_FALSE) {
|
||||
MOZ_COUNT_CTOR(nsCSSShadowItem);
|
||||
|
@ -321,6 +322,7 @@ struct nsCSSShadowItem {
|
|||
mRadius == aOther.mRadius &&
|
||||
mHasColor == aOther.mHasColor &&
|
||||
mSpread == aOther.mSpread &&
|
||||
mInset == aOther.mInset &&
|
||||
(!mHasColor || mColor == aOther.mColor));
|
||||
}
|
||||
PRBool operator!=(const nsCSSShadowItem& aOther) {
|
||||
|
|
|
@ -333,8 +333,8 @@ var gCSSProperties = {
|
|||
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",
|
||||
|
|
|
@ -446,8 +446,10 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
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);
|
||||
}
|
||||
|
@ -465,6 +467,13 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
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) {
|
||||
|
|
|
@ -1373,10 +1373,11 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
|||
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);
|
||||
}
|
||||
|
@ -1391,6 +1392,13 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
|||
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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче