Implement multiple background layers, implement fallback background color, and make -moz-background-inline-policy no longer be part of the background shorthand. (Bug 322475) r+sr=roc,bzbarsky

This commit is contained in:
L. David Baron 2009-02-19 21:29:21 -08:00
parent d8d09b1793
commit fa9a21c33d
56 changed files with 2090 additions and 638 deletions

View File

@ -526,8 +526,8 @@ nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor)
{
const nsStyleBackground *styleBackground = aFrame->GetStyleBackground();
if (!styleBackground->IsTransparent()) {
*aColor = styleBackground->mBackgroundColor;
if (NS_GET_A(styleBackground->mFallbackBackgroundColor) > 0) {
*aColor = styleBackground->mFallbackBackgroundColor;
return PR_TRUE;
}

View File

@ -1941,8 +1941,7 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
return;
nsPresContext* presContext = aData->mPresContext;
if (aData->mColorData->mBackImage.GetUnit() == eCSSUnit_Null &&
presContext->UseDocumentColors()) {
if (!aData->mColorData->mBackImage && presContext->UseDocumentColors()) {
// background
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::background);
if (value && value->Type() == nsAttrValue::eString) {
@ -1972,7 +1971,11 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
doc->NodePrincipal(), doc);
buffer->Release();
if (NS_LIKELY(img != 0)) {
aData->mColorData->mBackImage.SetImageValue(img);
// Use nsRuleDataColor's temporary mTempBackImage to
// make a value list.
aData->mColorData->mTempBackImage.mValue.SetImageValue(img);
aData->mColorData->mBackImage =
&aData->mColorData->mTempBackImage;
}
}
}
@ -1980,7 +1983,10 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
else if (presContext->CompatibilityMode() == eCompatibility_NavQuirks) {
// in NavQuirks mode, allow the empty string to set the
// background to empty
aData->mColorData->mBackImage.SetNoneValue();
// Use nsRuleDataColor's temporary mTempBackImage to make a value list.
aData->mColorData->mBackImage = nsnull;
aData->mColorData->mTempBackImage.mValue.SetNoneValue();
aData->mColorData->mBackImage = &aData->mColorData->mTempBackImage;
}
}
}
@ -1993,12 +1999,16 @@ nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)))
return;
if (aData->mColorData->mBackColor.GetUnit() == eCSSUnit_Null &&
if (aData->mColorData->mBackColor.mXValue.GetUnit() == eCSSUnit_Null &&
aData->mPresContext->UseDocumentColors()) {
NS_ASSERTION(aData->mColorData->mBackColor.mYValue.GetUnit() ==
eCSSUnit_Null,
"half a property?");
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
nscolor color;
if (value && value->GetColorValue(color)) {
aData->mColorData->mBackColor.SetColorValue(color);
aData->mColorData->mBackColor.mXValue.SetColorValue(color);
aData->mColorData->mBackColor.mYValue.SetColorValue(color);
}
}
}

View File

@ -377,10 +377,15 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
if (!value) {
value = aAttributes->GetAttr(nsGkAtoms::background);
}
if (value && aData->mColorData->mBackColor.GetUnit() == eCSSUnit_Null) {
if (value &&
aData->mColorData->mBackColor.mXValue.GetUnit() == eCSSUnit_Null) {
NS_ASSERTION(aData->mColorData->mBackColor.mYValue.GetUnit()
== eCSSUnit_Null,
"half a property?");
nscolor color;
if (value->GetColorValue(color)) {
aData->mColorData->mBackColor.SetColorValue(color);
aData->mColorData->mBackColor.mXValue.SetColorValue(color);
aData->mColorData->mBackColor.mYValue.SetColorValue(color);
}
}
}

View File

@ -676,6 +676,16 @@ public:
mContext->Save();
}
void Reset(gfxContext *aContext) {
// Do the equivalent of destroying and re-creating this object.
NS_PRECONDITION(aContext, "must provide a context");
if (mContext) {
mContext->Restore();
}
mContext = aContext;
mContext->Save();
}
private:
gfxContext *mContext;
};

View File

@ -262,6 +262,17 @@ protected:
};
/* Local functions */
static void PaintBackgroundLayer(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
const nsRect& aBGClipRect,
const nsStyleBackground& aBackground,
const nsStyleBackground::Layer& aLayer,
const nsStyleBorder& aBorder,
PRBool aUsePrintSettings);
static void DrawBorderImage(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
@ -800,35 +811,29 @@ nsCSSRendering::PaintFocus(nsPresContext* aPresContext,
* Points are returned relative to aOriginBounds.
*/
static void
ComputeBackgroundAnchorPoint(const nsStyleBackground& aColor,
ComputeBackgroundAnchorPoint(const nsStyleBackground::Layer& aLayer,
const nsSize& aOriginBounds,
const nsSize& aImageSize,
nsPoint* aTopLeft,
nsPoint* aAnchorPoint)
{
if (NS_STYLE_BG_X_POSITION_LENGTH & aColor.mBackgroundFlags) {
aTopLeft->x = aAnchorPoint->x = aColor.mBackgroundXPosition.mCoord;
if (!aLayer.mPosition.mXIsPercent) {
aTopLeft->x = aAnchorPoint->x = aLayer.mPosition.mXPosition.mCoord;
}
else if (NS_STYLE_BG_X_POSITION_PERCENT & aColor.mBackgroundFlags) {
double percent = aColor.mBackgroundXPosition.mFloat;
else {
double percent = aLayer.mPosition.mXPosition.mFloat;
aAnchorPoint->x = NSToCoordRound(percent*aOriginBounds.width);
aTopLeft->x = NSToCoordRound(percent*(aOriginBounds.width - aImageSize.width));
}
else {
aTopLeft->x = aAnchorPoint->x = 0;
}
if (NS_STYLE_BG_Y_POSITION_LENGTH & aColor.mBackgroundFlags) {
aTopLeft->y = aAnchorPoint->y = aColor.mBackgroundYPosition.mCoord;
if (!aLayer.mPosition.mYIsPercent) {
aTopLeft->y = aAnchorPoint->y = aLayer.mPosition.mYPosition.mCoord;
}
else if (NS_STYLE_BG_Y_POSITION_PERCENT & aColor.mBackgroundFlags) {
double percent = aColor.mBackgroundYPosition.mFloat;
else {
double percent = aLayer.mPosition.mYPosition.mFloat;
aAnchorPoint->y = NSToCoordRound(percent*aOriginBounds.height);
aTopLeft->y = NSToCoordRound(percent*(aOriginBounds.height - aImageSize.height));
}
else {
aTopLeft->y = aAnchorPoint->y = 0;
}
}
nsStyleContext*
@ -1342,6 +1347,103 @@ IsSolidBorder(const nsStyleBorder& aBorder)
return PR_TRUE;
}
static PRBool
UseImageRequestForBackground(imgIRequest *aRequest)
{
if (!aRequest)
return PR_FALSE;
PRUint32 status = imgIRequest::STATUS_ERROR;
aRequest->GetImageStatus(&status);
return (status & imgIRequest::STATUS_FRAME_COMPLETE) &&
(status & imgIRequest::STATUS_SIZE_AVAILABLE);
}
static inline void
SetupDirtyRects(const nsRect& aBGClipArea, const nsRect& aCallerDirtyRect,
nscoord aAppUnitsPerPixel,
/* OUT: */
nsRect* aDirtyRect, gfxRect* aDirtyRectGfx)
{
aDirtyRect->IntersectRect(aBGClipArea, aCallerDirtyRect);
// Compute the Thebes equivalent of the dirtyRect.
*aDirtyRectGfx = RectToGfxRect(*aDirtyRect, aAppUnitsPerPixel);
NS_WARN_IF_FALSE(aDirtyRect->IsEmpty() || !aDirtyRectGfx->IsEmpty(),
"converted dirty rect should not be empty");
NS_ABORT_IF_FALSE(!aDirtyRect->IsEmpty() || aDirtyRectGfx->IsEmpty(),
"second should be empty if first is");
}
static void
SetupBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
nsIFrame* aForFrame, const nsRect& aBorderArea,
const nsRect& aCallerDirtyRect, PRBool aHaveRoundedCorners,
const gfxCornerSizes& aBGRadii, nscoord aAppUnitsPerPixel,
gfxContextAutoSaveRestore* aAutoSR,
/* OUT: */
nsRect* aBGClipArea, nsRect* aDirtyRect,
gfxRect* aDirtyRectGfx)
{
*aBGClipArea = aBorderArea;
PRBool radiiAreOuter = PR_TRUE;
gfxCornerSizes clippedRadii = aBGRadii;
if (aBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
NS_ASSERTION(aBackgroundClip == NS_STYLE_BG_CLIP_PADDING,
"unexpected background-clip");
nsMargin border = aForFrame->GetUsedBorder();
aForFrame->ApplySkipSides(border);
aBGClipArea->Deflate(border);
if (aHaveRoundedCorners) {
gfxFloat borderSizes[4] = {
border.top / aAppUnitsPerPixel, border.right / aAppUnitsPerPixel,
border.bottom / aAppUnitsPerPixel, border.left / aAppUnitsPerPixel
};
nsCSSBorderRenderer::ComputeInnerRadii(aBGRadii, borderSizes,
&clippedRadii);
radiiAreOuter = PR_FALSE;
}
}
SetupDirtyRects(*aBGClipArea, aCallerDirtyRect, aAppUnitsPerPixel,
aDirtyRect, aDirtyRectGfx);
if (aDirtyRectGfx->IsEmpty()) {
// Our caller won't draw anything under this condition, so no need
// to set more up.
return;
}
// If we have rounded corners, clip all subsequent drawing to the
// rounded rectangle defined by bgArea and bgRadii (we don't know
// whether the rounded corners intrude on the dirtyRect or not).
// Do not do this if we have a caller-provided clip rect --
// as above with bgArea, arguably a bug, but table painting seems
// to depend on it.
if (aHaveRoundedCorners) {
gfxRect bgAreaGfx(RectToGfxRect(*aBGClipArea, aAppUnitsPerPixel));
bgAreaGfx.Round();
bgAreaGfx.Condition();
if (bgAreaGfx.IsEmpty()) {
// I think it's become possible to hit this since
// http://hg.mozilla.org/mozilla-central/rev/50e934e4979b landed.
NS_WARNING("converted background area should not be empty");
// Make our caller not do anything.
aDirtyRectGfx->size.SizeTo(0.0, 0.0);
return;
}
aAutoSR->Reset(aCtx);
aCtx->NewPath();
aCtx->RoundedRectangle(bgAreaGfx, clippedRadii, radiiAreOuter);
aCtx->Clip();
}
}
void
nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -1382,11 +1484,16 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
drawBackgroundColor = aPresContext->GetBackgroundColorDraw();
}
if ((aColor.mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) ||
!aColor.mBackgroundImage) {
NS_ASSERTION((aColor.mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) &&
!aColor.mBackgroundImage, "background flags/image mismatch");
drawBackgroundImage = PR_FALSE;
nsStyleBackground::Image bottomImage(aColor.BottomLayer().mImage);
PRBool useFallbackColor = PR_FALSE;
if (bottomImage.mSpecified) {
if (!drawBackgroundImage ||
!UseImageRequestForBackground(bottomImage.mRequest)) {
bottomImage.mRequest = nsnull;
}
useFallbackColor = bottomImage.mRequest == nsnull;
} else {
NS_ASSERTION(bottomImage.mRequest == nsnull, "malformed image struct");
}
// If GetBackgroundColorDraw() is false, we are still expected to
@ -1395,7 +1502,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// color was specified.
nscolor bgColor;
if (drawBackgroundColor) {
bgColor = aColor.mBackgroundColor;
bgColor = useFallbackColor ? aColor.mFallbackBackgroundColor
: aColor.mBackgroundColor;
if (NS_GET_A(bgColor) == 0)
drawBackgroundColor = PR_FALSE;
} else {
@ -1415,10 +1523,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
// Same coordinate space as aBorderArea & aBGClipRect
nsRect bgArea;
gfxCornerSizes bgRadii;
PRBool haveRoundedCorners;
PRBool radiiAreOuter = PR_TRUE;
{
nscoord radii[8];
haveRoundedCorners =
@ -1429,79 +1535,38 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
appUnitsPerPixel, &bgRadii);
}
// The background is rendered over the 'background-clip' area,
// which is normally equal to the border area but may be reduced
// to the padding area by CSS. Also, if the border is solid, we
// don't need to draw outside the padding area. In either case,
// if the borders are rounded, make sure we use the same inner
// radii as the border code will.
bgArea = aBorderArea;
if (aColor.mBackgroundClip != NS_STYLE_BG_CLIP_BORDER ||
IsSolidBorder(aBorder)) {
nsMargin border = aForFrame->GetUsedBorder();
aForFrame->ApplySkipSides(border);
bgArea.Deflate(border);
if (haveRoundedCorners) {
gfxCornerSizes outerRadii = bgRadii;
gfxFloat borderSizes[4] = {
border.top / appUnitsPerPixel, border.right / appUnitsPerPixel,
border.bottom / appUnitsPerPixel, border.left / appUnitsPerPixel
};
nsCSSBorderRenderer::ComputeInnerRadii(outerRadii, borderSizes,
&bgRadii);
radiiAreOuter = PR_FALSE;
}
}
// The 'bgClipArea' (used only by the image tiling logic, far below)
// is the caller-provided aBGClipRect if any, or else the bgArea
// computed above. (Arguably it should be the intersection, but
// that breaks the table painter -- in particular, honoring the
// bgArea when we have aBGClipRect breaks reftests/bugs/403429-1[ab].)
// The dirtyRect is the intersection of that rectangle with the
// caller-provided aDirtyRect. If the dirtyRect is empty there is
// nothing to draw.
nsRect bgClipArea;
if (aBGClipRect)
bgClipArea = *aBGClipRect;
else
bgClipArea = bgArea;
nsRect dirtyRect;
dirtyRect.IntersectRect(bgClipArea, aDirtyRect);
if (dirtyRect.IsEmpty())
return;
// Compute the Thebes equivalent of the dirtyRect.
gfxRect dirtyRectGfx(RectToGfxRect(dirtyRect, appUnitsPerPixel));
if (dirtyRectGfx.IsEmpty()) {
NS_WARNING("converted dirty rect should not be empty");
return;
}
// If we have rounded corners, clip all subsequent drawing to the
// rounded rectangle defined by bgArea and bgRadii (we don't know
// whether the rounded corners intrude on the dirtyRect or not).
// Do not do this if we have a caller-provided clip rect --
// as above with bgArea, arguably a bug, but table painting seems
// to depend on it.
// is the caller-provided aBGClipRect if any, or else the area
// determined by the value of 'background-clip' in
// SetupCurrentBackgroundClip. (Arguably it should be the
// intersection, but that breaks the table painter -- in particular,
// taking the intersection breaks reftests/bugs/403429-1[ab].)
nsRect bgClipArea, dirtyRect;
gfxRect dirtyRectGfx;
PRUint8 currentBackgroundClip;
PRBool isSolidBorder;
gfxContextAutoSaveRestore autoSR;
if (haveRoundedCorners && !aBGClipRect) {
gfxRect bgAreaGfx(RectToGfxRect(bgArea, appUnitsPerPixel));
bgAreaGfx.Round();
bgAreaGfx.Condition();
if (bgAreaGfx.IsEmpty()) {
NS_WARNING("converted background area should not be empty");
return;
}
autoSR.SetContext(ctx);
ctx->NewPath();
ctx->RoundedRectangle(bgAreaGfx, bgRadii, radiiAreOuter);
ctx->Clip();
if (aBGClipRect) {
bgClipArea = *aBGClipRect;
SetupDirtyRects(bgClipArea, aDirtyRect, appUnitsPerPixel,
&dirtyRect, &dirtyRectGfx);
} else {
// The background is rendered over the 'background-clip' area,
// which is normally equal to the border area but may be reduced
// to the padding area by CSS. Also, if the border is solid, we
// don't need to draw outside the padding area. In either case,
// if the borders are rounded, make sure we use the same inner
// radii as the border code will.
// The background-color is drawn based on the bottom
// background-clip.
currentBackgroundClip = aColor.BottomLayer().mClip;
isSolidBorder = IsSolidBorder(aBorder);
if (isSolidBorder)
currentBackgroundClip = NS_STYLE_BG_CLIP_PADDING;
SetupBackgroundClip(ctx, currentBackgroundClip, aForFrame,
aBorderArea, aDirtyRect, haveRoundedCorners,
bgRadii, appUnitsPerPixel, &autoSR,
&bgClipArea, &dirtyRect, &dirtyRectGfx);
}
// If we might be using a background color, go ahead and set it now.
@ -1512,9 +1577,11 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// neither a background image nor a color, we wouldn't have gotten
// this far.)
if (!drawBackgroundImage) {
ctx->NewPath();
ctx->Rectangle(dirtyRectGfx, PR_TRUE);
ctx->Fill();
if (!dirtyRectGfx.IsEmpty()) {
ctx->NewPath();
ctx->Rectangle(dirtyRectGfx, PR_TRUE);
ctx->Fill();
}
return;
}
@ -1523,21 +1590,83 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// association of the style data with the frame.
aPresContext->SetupBackgroundImageLoaders(aForFrame, &aColor);
imgIRequest *req = aColor.mBackgroundImage;
if (bottomImage.mRequest &&
aColor.BottomLayer().mRepeat == NS_STYLE_BG_REPEAT_XY &&
drawBackgroundColor) {
nsCOMPtr<imgIContainer> image;
bottomImage.mRequest->GetImage(getter_AddRefs(image));
// If the image is completely opaque, we may not need to paint
// the background color.
nsCOMPtr<gfxIImageFrame> gfxImgFrame;
image->GetCurrentFrame(getter_AddRefs(gfxImgFrame));
if (gfxImgFrame) {
gfxImgFrame->GetNeedsBackground(&drawBackgroundColor);
if (!drawBackgroundColor) {
// If the current frame is smaller than its container, we
// need to paint the background color even if the frame
// itself is opaque.
nsIntSize iSize;
image->GetWidth(&iSize.width);
image->GetHeight(&iSize.height);
nsIntRect iframeRect;
gfxImgFrame->GetRect(iframeRect);
if (iSize.width != iframeRect.width ||
iSize.height != iframeRect.height) {
drawBackgroundColor = PR_TRUE;
}
}
}
}
PRUint32 status = imgIRequest::STATUS_ERROR;
if (req)
req->GetImageStatus(&status);
// While waiting for the image, draw a color, if any.
if (!req ||
!(status & imgIRequest::STATUS_FRAME_COMPLETE) ||
!(status & imgIRequest::STATUS_SIZE_AVAILABLE)) {
if (drawBackgroundColor) {
// The background color is rendered over the entire dirty area,
// even if the image isn't.
if (drawBackgroundColor) {
if (!dirtyRectGfx.IsEmpty()) {
ctx->NewPath();
ctx->Rectangle(dirtyRectGfx, PR_TRUE);
ctx->Fill();
}
}
if (drawBackgroundImage) {
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, &aColor) {
const nsStyleBackground::Layer &layer = aColor.mLayers[i];
if (!aBGClipRect) {
PRUint8 newBackgroundClip =
isSolidBorder ? NS_STYLE_BG_CLIP_PADDING : layer.mClip;
if (currentBackgroundClip != newBackgroundClip) {
currentBackgroundClip = newBackgroundClip;
SetupBackgroundClip(ctx, currentBackgroundClip, aForFrame,
aBorderArea, aDirtyRect, haveRoundedCorners,
bgRadii, appUnitsPerPixel, &autoSR,
&bgClipArea, &dirtyRect, &dirtyRectGfx);
}
}
if (!dirtyRectGfx.IsEmpty()) {
PaintBackgroundLayer(aPresContext, aRenderingContext, aForFrame,
dirtyRect, aBorderArea, bgClipArea, aColor,
layer, aBorder, aUsePrintSettings);
}
}
}
}
static void
PaintBackgroundLayer(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect, // intersected with aBGClipRect
const nsRect& aBorderArea,
const nsRect& aBGClipRect,
const nsStyleBackground& aBackground,
const nsStyleBackground::Layer& aLayer,
const nsStyleBorder& aBorder,
PRBool aUsePrintSettings)
{
// Lookup the image
imgIRequest *req = aLayer.mImage.mRequest;
if (!UseImageRequestForBackground(req)) {
// There's no image or it's not ready to be painted.
return;
}
@ -1561,7 +1690,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nsIFrame* geometryFrame = aForFrame;
if (frameType == nsGkAtoms::inlineFrame ||
frameType == nsGkAtoms::positionedInlineFrame) {
switch (aColor.mBackgroundInlinePolicy) {
switch (aBackground.mBackgroundInlinePolicy) {
case NS_STYLE_BG_INLINE_POLICY_EACH_BOX:
bgOriginRect = nsRect(nsPoint(0,0), aBorderArea.Size());
break;
@ -1588,71 +1717,25 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// Background images are tiled over the 'background-clip' area
// but the origin of the tiling is based on the 'background-origin' area
if (aColor.mBackgroundOrigin != NS_STYLE_BG_ORIGIN_BORDER) {
if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_BORDER) {
nsMargin border = geometryFrame->GetUsedBorder();
geometryFrame->ApplySkipSides(border);
bgOriginRect.Deflate(border);
if (aColor.mBackgroundOrigin != NS_STYLE_BG_ORIGIN_PADDING) {
if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_PADDING) {
nsMargin padding = geometryFrame->GetUsedPadding();
geometryFrame->ApplySkipSides(padding);
bgOriginRect.Deflate(padding);
NS_ASSERTION(aColor.mBackgroundOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
"unknown background-origin value");
}
}
PRIntn repeat = aColor.mBackgroundRepeat;
switch (repeat) {
case NS_STYLE_BG_REPEAT_X:
break;
case NS_STYLE_BG_REPEAT_Y:
break;
case NS_STYLE_BG_REPEAT_XY:
if (drawBackgroundColor) {
// If the image is completely opaque, we may not need to paint
// the background color.
nsCOMPtr<gfxIImageFrame> gfxImgFrame;
image->GetCurrentFrame(getter_AddRefs(gfxImgFrame));
if (gfxImgFrame) {
gfxImgFrame->GetNeedsBackground(&drawBackgroundColor);
if (!drawBackgroundColor) {
// If the current frame is smaller than its container, we
// need to paint the background color even if the frame
// itself is opaque.
nsIntSize iSize;
image->GetWidth(&iSize.width);
image->GetHeight(&iSize.height);
nsIntRect iframeRect;
gfxImgFrame->GetRect(iframeRect);
if (iSize.width != iframeRect.width ||
iSize.height != iframeRect.height) {
drawBackgroundColor = PR_TRUE;
}
}
}
}
break;
case NS_STYLE_BG_REPEAT_OFF:
default:
NS_ASSERTION(repeat == NS_STYLE_BG_REPEAT_OFF,
"unknown background-repeat value");
break;
}
// The background color is rendered over the entire dirty area,
// even if the image isn't.
if (drawBackgroundColor) {
ctx->NewPath();
ctx->Rectangle(dirtyRectGfx, PR_TRUE);
ctx->Fill();
}
// Compute the anchor point.
//
// relative to aBorderArea.TopLeft() (which is where the top-left
// of aForFrame's border-box will be rendered)
nsPoint imageTopLeft, anchor;
if (NS_STYLE_BG_ATTACHMENT_FIXED == aColor.mBackgroundAttachment) {
if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment) {
// If it's a fixed background attachment, then the image is placed
// relative to the viewport, which is the area of the root frame
// in a screen context or the page content frame in a print context.
@ -1686,7 +1769,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
}
// Get the anchor point, relative to the viewport.
ComputeBackgroundAnchorPoint(aColor, viewportArea.Size(), imageSize,
ComputeBackgroundAnchorPoint(aLayer, viewportArea.Size(), imageSize,
&imageTopLeft, &anchor);
// Convert the anchor point from viewport coordinates to aForFrame
@ -1695,7 +1778,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
imageTopLeft += offset;
anchor += offset;
} else {
ComputeBackgroundAnchorPoint(aColor, bgOriginRect.Size(), imageSize,
ComputeBackgroundAnchorPoint(aLayer, bgOriginRect.Size(), imageSize,
&imageTopLeft, &anchor);
imageTopLeft += bgOriginRect.TopLeft();
anchor += bgOriginRect.TopLeft();
@ -1703,18 +1786,19 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nsRect destArea(imageTopLeft + aBorderArea.TopLeft(), imageSize);
nsRect fillArea = destArea;
PRIntn repeat = aLayer.mRepeat;
if (repeat & NS_STYLE_BG_REPEAT_X) {
fillArea.x = bgClipArea.x;
fillArea.width = bgClipArea.width;
fillArea.x = aBGClipRect.x;
fillArea.width = aBGClipRect.width;
}
if (repeat & NS_STYLE_BG_REPEAT_Y) {
fillArea.y = bgClipArea.y;
fillArea.height = bgClipArea.height;
fillArea.y = aBGClipRect.y;
fillArea.height = aBGClipRect.height;
}
fillArea.IntersectRect(fillArea, bgClipArea);
fillArea.IntersectRect(fillArea, aBGClipRect);
nsLayoutUtils::DrawImage(&aRenderingContext, image,
destArea, fillArea, anchor + aBorderArea.TopLeft(), dirtyRect);
destArea, fillArea, anchor + aBorderArea.TopLeft(), aDirtyRect);
}
static void

View File

@ -497,7 +497,8 @@ nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bg);
return (hasBG && NS_GET_A(bg->mBackgroundColor) == 255 &&
bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER &&
// bottom layer's clip is used for the color
bg->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER &&
!nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->
mBorderRadius));
}
@ -513,9 +514,10 @@ nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder) {
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bg);
if (!hasBG)
return PR_TRUE;
if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) &&
if (!bg->BottomLayer().mImage.mRequest &&
bg->mImageCount == 1 &&
!nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius) &&
bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER)
bg->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER)
return PR_TRUE;
return PR_FALSE;
}

View File

@ -3066,9 +3066,10 @@ nsLayoutUtils::GetFrameTransparency(nsIFrame* aFrame) {
const nsStyleBackground* bg;
if (!nsCSSRendering::FindBackground(aFrame->PresContext(), aFrame, &bg))
return eTransparencyTransparent;
if (NS_GET_A(bg->mBackgroundColor) < 255)
return eTransparencyTransparent;
if (bg->mBackgroundClip != NS_STYLE_BG_CLIP_BORDER)
if (NS_GET_A(bg->mBackgroundColor) < 255 ||
NS_GET_A(bg->mFallbackBackgroundColor) < 255 ||
// bottom layer's clip is used for the color
bg->BottomLayer().mClip != NS_STYLE_BG_CLIP_BORDER)
return eTransparencyTransparent;
return eTransparencyOpaque;
}

View File

@ -1252,10 +1252,12 @@ void
nsPresContext::SetupBackgroundImageLoaders(nsIFrame* aFrame,
const nsStyleBackground* aStyleBackground)
{
nsRefPtr<nsImageLoader> loader =
nsImageLoader::Create(aFrame, aStyleBackground->mBackgroundImage,
PR_FALSE, nsnull);
SetImageLoaders(aFrame, BACKGROUND_IMAGE, loader);
nsRefPtr<nsImageLoader> loaders;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, aStyleBackground) {
imgIRequest *image = aStyleBackground->mLayers[i].mImage.mRequest;
loaders = nsImageLoader::Create(aFrame, image, PR_FALSE, loaders);
}
SetImageLoaders(aFrame, BACKGROUND_IMAGE, loaders);
}
void

View File

@ -242,21 +242,16 @@
#define NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT -3
#define NS_COLOR_CURRENTCOLOR -4
// See nsStyleBackground
// 0x01 was background-color:transparent
#define NS_STYLE_BG_IMAGE_NONE 0x02
#define NS_STYLE_BG_X_POSITION_PERCENT 0x04
#define NS_STYLE_BG_X_POSITION_LENGTH 0x08
#define NS_STYLE_BG_Y_POSITION_PERCENT 0x10
#define NS_STYLE_BG_Y_POSITION_LENGTH 0x20
// See nsStyleBackground
#define NS_STYLE_BG_ATTACHMENT_SCROLL 0
#define NS_STYLE_BG_ATTACHMENT_FIXED 1
// See nsStyleBackground
// Code depends on these constants having the same values as BG_ORIGIN_*
#define NS_STYLE_BG_CLIP_BORDER 0
#define NS_STYLE_BG_CLIP_PADDING 1
// When we add NS_STYLE_BG_CLIP_CONTENT, we should add the PR_STATIC_ASSERTs
// to the places that assert equality for BORDER and PADDING.
// See nsStyleBackground
#define NS_STYLE_BG_INLINE_POLICY_EACH_BOX 0
@ -264,6 +259,7 @@
#define NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX 2
// See nsStyleBackground
// Code depends on these constants having the same values as BG_CLIP_*
#define NS_STYLE_BG_ORIGIN_BORDER 0
#define NS_STYLE_BG_ORIGIN_PADDING 1
#define NS_STYLE_BG_ORIGIN_CONTENT 2

View File

@ -547,14 +547,18 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
// to clear those notifiers unless we have to. (They'll be reset
// when we paint, although we could miss a notification in that
// interval.)
imgIRequest *oldBackgroundImage =
aOldStyleContext->GetStyleBackground()->mBackgroundImage;
if (oldBackgroundImage &&
!EqualImages(oldBackgroundImage,
GetStyleBackground()->mBackgroundImage)) {
// stop the image loading for the frame, the image has changed
PresContext()->SetImageLoaders(this,
nsPresContext::BACKGROUND_IMAGE, nsnull);
const nsStyleBackground *oldBG = aOldStyleContext->GetStyleBackground();
const nsStyleBackground *newBG = GetStyleBackground();
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, oldBG) {
imgIRequest *oldImage = oldBG->mLayers[i].mImage.mRequest;
imgIRequest *newImage =
(i < newBG->mImageCount) ? newBG->mLayers[i].mImage.mRequest : nsnull;
if (oldImage && !EqualImages(oldImage, newImage)) {
// stop the image loading for the frame, the image has changed
PresContext()->SetImageLoaders(this,
nsPresContext::BACKGROUND_IMAGE, nsnull);
break;
}
}
}
@ -4028,11 +4032,14 @@ nsIFrame::CheckInvalidateSizeChange(const nsRect& aOldRect,
// Invalidate the old frame background if the frame has a background
// whose position depends on the size of the frame
const nsStyleBackground* background = GetStyleBackground();
if (background->mBackgroundFlags &
(NS_STYLE_BG_X_POSITION_PERCENT | NS_STYLE_BG_Y_POSITION_PERCENT)) {
Invalidate(nsRect(0, 0, aOldRect.width, aOldRect.height));
return;
const nsStyleBackground *bg = GetStyleBackground();
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
const nsStyleBackground::Layer &layer = bg->mLayers[i];
if (layer.mImage.mRequest &&
(layer.mPosition.mXIsPercent || layer.mPosition.mYIsPercent)) {
Invalidate(nsRect(0, 0, aOldRect.width, aOldRect.height));
return;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color only applied when there is an image." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: lime red;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color only applied when there is an image." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background-color: lime red;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color not applied when background image loads successfully." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(transparent-32x32.png) lime red;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color applied when background image corrupted." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(malformed.png) red lime;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color applied when background image missing." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(404.png) red lime;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color is based on whether the *bottom-most* image is corrupted." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(transparent-32x32.png), url(malformed.png) red lime;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color is based on whether the *bottom-most* image is corrupted." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(malformed.png), url(transparent-32x32.png) lime red;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color is based on whether the *bottom-most* image is missing." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(transparent-32x32.png), url(404.png) red lime;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<meta name="assert" content="Fallback color is based on whether the *bottom-most* image is missing." />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(404.png), url(transparent-32x32.png) lime red;
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: fallback colors</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#background-color" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div {
width: 100px;
height: 100px;
background: url(lime-32x32.png);
}
]]></style>
</head>
<body>
<div></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

View File

@ -0,0 +1,35 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: number of background layers determined by background-image</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div {
position: relative; height: 100px; width: 100px;
}
]]></style>
</head>
<body>
<div>
<img style="position: absolute; left: 10px; top: 10px" src="aqua-32x32.png" />
</div>
<div>
<img style="position: absolute; left: 15px; top: 15px" src="fuchsia-32x32.png" />
<img style="position: absolute; left: 20px; top: 20px" src="blue-32x32.png" />
<img style="position: absolute; left: 5px; top: 5px" src="aqua-32x32.png" />
<img style="position: absolute; left: 10px; top: 10px" src="yellow-32x32.png" />
</div>
<div>
<img style="position: absolute; left: 20px; top: 20px" src="fuchsia-32x32.png" />
<img style="position: absolute; left: 5px; top: 5px" src="yellow-32x32.png" />
<img style="position: absolute; left: 10px; top: 10px" src="blue-32x32.png" />
</div>
</body>
</html>

View File

@ -0,0 +1,35 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: number of background layers determined by background-image</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div {
position: relative; height: 100px; width: 100px;
}
]]></style>
</head>
<body>
<div>
<img style="position: absolute; left: 10px; top: 10px" src="yellow-32x32.png" />
</div>
<div>
<img style="position: absolute; left: 15px; top: 15px" src="fuchsia-32x32.png" />
<img style="position: absolute; left: 20px; top: 20px" src="blue-32x32.png" />
<img style="position: absolute; left: 0px; top: 0px" src="aqua-32x32.png" />
<img style="position: absolute; left: 5px; top: 5px" src="yellow-32x32.png" />
</div>
<div>
<img style="position: absolute; left: 20px; top: 20px" src="blue-32x32.png" />
<img style="position: absolute; left: 5px; top: 5px" src="aqua-32x32.png" />
<img style="position: absolute; left: 10px; top: 10px" src="yellow-32x32.png" />
</div>
</body>
</html>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: number of background layers determined by background-image</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div {
position: relative; height: 100px; width: 100px;
background-repeat: no-repeat;
background-position: 10px 10px, 5px 5px, 20px 20px, 15px 15px;
background-image: url(aqua-32x32.png);
}
div.withclass {
background-image: url(yellow-32x32.png), url(aqua-32x32.png), url(blue-32x32.png), url(fuchsia-32x32.png), url(red-32x32.png);
}
div#withid {
background-image: url(blue-32x32.png), url(yellow-32x32.png), url(fuchsia-32x32.png);
}
]]></style>
</head>
<body>
<div></div>
<div class="withclass"></div>
<div class="withclass" id="withid"></div>
</body>
</html>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: number of background layers determined by background-image</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div {
position: relative; height: 100px; width: 100px;
background-repeat: no-repeat;
background-position: 10px 10px;
background-image: url(yellow-32x32.png), url(aqua-32x32.png), url(blue-32x32.png), url(fuchsia-32x32.png), url(red-32x32.png);
}
div.withclass {
background-position: 5px 5px, 0px 0px, 20px 20px, 15px 15px;
}
div#withid {
background-position: 10px 10px, 5px 5px, 20px 20px;
}
]]></style>
</head>
<body>
<div></div>
<div class="withclass"></div>
<div class="withclass" id="withid"></div>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: number of background layers determined by background-image</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
body > div {
position: relative; height: 300px; width: 100px;
background-repeat: no-repeat;
background-position: 10px 10px, 5px 5px, 20px 20px, 15px 15px;
background-image: url(aqua-32x32.png);
}
body > div > div {
position: absolute; height: 200px; width: 100px; top: 100px; left: 0;
background-repeat: no-repeat;
background-position: inherit;
background-image: url(yellow-32x32.png), url(aqua-32x32.png), url(blue-32x32.png), url(fuchsia-32x32.png), url(red-32x32.png);
}
body > div > div > div {
position: absolute; height: 100px; width: 100px; top: 100px; left: 0;
background: inherit;
background-image: url(blue-32x32.png), url(yellow-32x32.png), url(fuchsia-32x32.png);
}
]]></style>
</head>
<body>
<div><div><div></div></div></div>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: number of background layers determined by background-image</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
body > div {
position: relative; height: 300px; width: 100px;
background-repeat: no-repeat;
background-position: 10px 10px;
background-image: url(yellow-32x32.png), url(aqua-32x32.png), url(blue-32x32.png), url(fuchsia-32x32.png), url(red-32x32.png);
}
body > div > div {
position: absolute; height: 200px; width: 100px; top: 100px; left: 0;
background: inherit;
background-position: 5px 5px, 0px 0px, 20px 20px, 15px 15px;
}
body > div > div > div {
position: absolute; height: 100px; width: 100px; top: 100px; left: 0;
background-image: inherit;
background-repeat: inherit;
background-position: 10px 10px, 5px 5px, 20px 20px;
}
]]></style>
</head>
<body>
<div><div><div></div></div></div>
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: stacking order of layers</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div#test {
position: relative; height: 100px; width: 100px;
}
]]></style>
</head>
<body>
<div id="test">
<img src="aqua-32x32.png" style="position: absolute; left: 20px; top: 20px" />
<img src="fuchsia-32x32.png" style="position: absolute; left: 10px; top: 10px" />
<img src="yellow-32x32.png" style="position: absolute; left: 15px; top: 15px" />
<img src="blue-32x32.png" style="position: absolute; left: 5px; top: 5px" />
</div>
</body>
</html>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>css3-background: stacking order of layers</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://dev.w3.org/csswg/css3-background/#layering" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
div#test {
position: relative; height: 100px; width: 100px;
background: url(blue-32x32.png) 5px 5px no-repeat,
url(yellow-32x32.png) 15px 15px no-repeat,
url(fuchsia-32x32.png) 10px 10px no-repeat,
url(aqua-32x32.png) 20px 20px no-repeat;
}
]]></style>
</head>
<body>
<div id="test"></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

View File

@ -0,0 +1 @@
This is not a PNG file.

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

View File

@ -0,0 +1,15 @@
== fallback-color-1.xhtml fallback-color-ref.xhtml
== fallback-color-2.xhtml fallback-color-ref.xhtml
== fallback-color-3.xhtml fallback-color-ref.xhtml
== fallback-color-4.xhtml fallback-color-ref.xhtml
== fallback-color-5.xhtml fallback-color-ref.xhtml
== fallback-color-6.xhtml fallback-color-ref.xhtml
== fallback-color-7.xhtml fallback-color-ref.xhtml
== fallback-color-8.xhtml fallback-color-ref.xhtml
== fallback-color-9.xhtml fallback-color-ref.xhtml
!= fallback-color-ref.xhtml about:blank
== layers-stacking-order.xhtml layers-stacking-order-ref.xhtml
== layers-layer-count-cascade-1.xhtml layers-layer-count-1-ref.xhtml
== layers-layer-count-inheritance-1.xhtml layers-layer-count-1-ref.xhtml
== layers-layer-count-cascade-2.xhtml layers-layer-count-2-ref.xhtml
== layers-layer-count-inheritance-2.xhtml layers-layer-count-2-ref.xhtml

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

View File

@ -98,7 +98,7 @@
.parser { height: 3em; }
.parser { width: 200; }
.parser { border: 5em solid red ! error; }
.parser { background: red pink; }
.parser { background: red pink pink; }
/* line fourteen (last line of face): table */
ul { display: table; padding: 0; margin: -1em 7em 0; background: red; }

View File

@ -11,6 +11,9 @@ include reftest-sanity/reftest.list
# images (if libpr0n is busted, could result in weird failures in other tests)
include ../../modules/libpr0n/test/reftest/reftest.list
# backgrounds/
include backgrounds/reftest.list
# bidi/
include bidi/reftest.list

View File

@ -196,8 +196,7 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
if (target->GetUnit() == eCSSUnit_Null) {
const nsCSSValue *val = ValueAtCursor(cursor);
NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
if (iProp == eCSSProperty_background_image ||
iProp == eCSSProperty_list_style_image) {
if (iProp == eCSSProperty_list_style_image) {
if (val->GetUnit() == eCSSUnit_URL) {
val->StartImageLoad(
aRuleData->mPresContext->Document());
@ -217,8 +216,6 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
aRuleData->mFontData->mFamilyFromHTML = PR_FALSE;
}
else if (iProp == eCSSProperty_color ||
iProp == eCSSProperty_background_color ||
iProp == eCSSProperty_background_image ||
iProp == eCSSProperty_border_top_color ||
iProp == eCSSProperty_border_right_color_value ||
iProp == eCSSProperty_border_right_color_ltr_source ||
@ -230,32 +227,8 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
iProp == eCSSProperty__moz_column_rule_color ||
iProp == eCSSProperty_outline_color) {
if (ShouldIgnoreColors(aRuleData)) {
if (iProp == eCSSProperty_background_color) {
// Force non-'transparent' background
// colors to the user's default.
// We have the value in the form it was
// specified at this point, so we have to
// look for both the keyword 'transparent'
// and its equivalent in rgba notation.
nsCSSUnit u = target->GetUnit();
nsDependentString buf;
if ((u == eCSSUnit_Color &&
NS_GET_A(target->GetColorValue())
> 0) ||
(u == eCSSUnit_String &&
!nsGkAtoms::transparent->
Equals(target->GetStringValue(buf))) ||
(u == eCSSUnit_EnumColor)) {
target->SetColorValue(aRuleData->
mPresContext->
DefaultBackgroundColor());
}
} else {
// Ignore 'color', 'border-*-color', and
// 'background-image'
*target = nsCSSValue();
}
// Ignore 'color', 'border-*-color', etc.
*target = nsCSSValue();
}
}
}
@ -282,15 +255,50 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
val->mYValue.GetUnit() != eCSSUnit_Null, "oops");
nsCSSValuePair* target = static_cast<nsCSSValuePair*>(prop);
if (target->mXValue.GetUnit() == eCSSUnit_Null)
NS_ASSERTION((target->mXValue.GetUnit() == eCSSUnit_Null)
== (target->mYValue.GetUnit() == eCSSUnit_Null),
"half a property?");
if (target->mXValue.GetUnit() == eCSSUnit_Null) {
target->mXValue = val->mXValue;
if (target->mYValue.GetUnit() == eCSSUnit_Null)
target->mYValue = val->mYValue;
if (iProp == eCSSProperty_background_color &&
ShouldIgnoreColors(aRuleData)) {
// Force non-'transparent' background colors
// to the user's default. We have the value
// in the form it was specified at this
// point, so we have to look for both the
// keyword 'transparent' and its equivalent
// in rgba notation.
nsCSSValue &colorVal = target->mXValue;
nsCSSUnit u = colorVal.GetUnit();
nsDependentString buf;
if ((u == eCSSUnit_Color &&
NS_GET_A(colorVal.GetColorValue())
> 0) ||
(u == eCSSUnit_String &&
!nsGkAtoms::transparent->
Equals(colorVal.GetStringValue(buf))) ||
(u == eCSSUnit_EnumColor)) {
colorVal.SetColorValue(aRuleData->
mPresContext->
DefaultBackgroundColor());
}
// We could consider using the fallback
// background color for both values, but it
// might not make sense if the author didn't
// specify an image. But since we're
// dropping author images, we'll just use
// the non-fallback for both.
target->mYValue = target->mXValue;
}
}
cursor += CDBValuePairStorage_advance;
} break;
case eCSSType_ValueList:
if (iProp == eCSSProperty_content) {
if (iProp == eCSSProperty_background_image ||
iProp == eCSSProperty_content) {
for (nsCSSValueList* l = ValueListAtCursor(cursor);
l; l = l->mNext)
if (l->mValue.GetUnit() == eCSSUnit_URL)
@ -317,7 +325,8 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
NS_ASSERTION(val, "oops");
*target = val;
if (iProp == eCSSProperty_border_top_colors ||
if (iProp == eCSSProperty_background_image ||
iProp == eCSSProperty_border_top_colors ||
iProp == eCSSProperty_border_right_colors ||
iProp == eCSSProperty_border_bottom_colors ||
iProp == eCSSProperty_border_left_colors) {

View File

@ -209,12 +209,17 @@ PRBool nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty, nsAString&
NS_ASSERTION(item->mXValue.GetUnit() != eCSSUnit_Null,
"unexpected null unit");
AppendCSSValueToString(aProperty, item->mXValue, aResult);
if (item->mYValue.GetUnit() != eCSSUnit_Null) {
if (item->mXValue.GetUnit() != eCSSUnit_Inherit &&
item->mXValue.GetUnit() != eCSSUnit_Initial &&
item->mYValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
AppendCSSValueToString(aProperty, item->mYValue, aResult);
}
item = item->mNext;
if (item) {
if (nsCSSProps::PropHasFlags(aProperty,
CSS_PROPERTY_VALUE_LIST_USES_COMMAS))
aResult.Append(PRUnichar(','));
aResult.Append(PRUnichar(' '));
}
} while (item);
@ -761,50 +766,97 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty,
break;
}
case eCSSProperty_background: {
// The -moz-background-clip, -moz-background-origin, and
// -moz-background-inline-policy properties are reset by this
// shorthand property to their initial values, but can't be
// represented in its syntax.
const nsCSSValue *clipValue = static_cast<const nsCSSValue*>(
data->StorageFor(eCSSProperty__moz_background_clip));
const nsCSSValue *originValue = static_cast<const nsCSSValue*>(
data->StorageFor(eCSSProperty__moz_background_origin));
const nsCSSValue *inlinePolicyValue = static_cast<const nsCSSValue*>(
data->StorageFor(eCSSProperty__moz_background_inline_policy));
if (*clipValue !=
nsCSSValue(NS_STYLE_BG_CLIP_BORDER, eCSSUnit_Enumerated) ||
*originValue !=
nsCSSValue(NS_STYLE_BG_ORIGIN_PADDING, eCSSUnit_Enumerated) ||
*inlinePolicyValue !=
nsCSSValue(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS,
eCSSUnit_Enumerated)) {
return NS_OK;
}
PRBool appendedSomething = PR_FALSE;
if (AppendValueToString(eCSSProperty_background_color, aValue)) {
appendedSomething = PR_TRUE;
// We know from above that all subproperties were specified.
// However, we still can't represent that in the shorthand unless
// they're all lists of the same length. So if they're different
// lengths, we need to bail out.
// We also need to bail out if an item has background-clip and
// background-origin that are different and not the default
// values. (We omit them if they're both default.)
const nsCSSValueList *image =
* data->ValueListStorageFor(eCSSProperty_background_image);
const nsCSSValueList *repeat =
* data->ValueListStorageFor(eCSSProperty_background_repeat);
const nsCSSValueList *attachment =
* data->ValueListStorageFor(eCSSProperty_background_attachment);
const nsCSSValuePairList *position =
* data->ValuePairListStorageFor(eCSSProperty_background_position);
const nsCSSValueList *clip =
* data->ValueListStorageFor(eCSSProperty__moz_background_clip);
const nsCSSValueList *origin =
* data->ValueListStorageFor(eCSSProperty__moz_background_origin);
for (;;) {
AppendCSSValueToString(eCSSProperty_background_image,
image->mValue, aValue);
aValue.Append(PRUnichar(' '));
AppendCSSValueToString(eCSSProperty_background_repeat,
repeat->mValue, aValue);
aValue.Append(PRUnichar(' '));
AppendCSSValueToString(eCSSProperty_background_attachment,
attachment->mValue, aValue);
aValue.Append(PRUnichar(' '));
AppendCSSValueToString(eCSSProperty_background_position,
position->mXValue, aValue);
aValue.Append(PRUnichar(' '));
AppendCSSValueToString(eCSSProperty_background_position,
position->mYValue, aValue);
NS_ASSERTION(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
origin->mValue.GetUnit() == eCSSUnit_Enumerated,
"should not be inherit/initial within list and "
"should have returned early for real inherit/initial");
if (clip->mValue.GetIntValue() != NS_STYLE_BG_CLIP_BORDER ||
origin->mValue.GetIntValue() != NS_STYLE_BG_ORIGIN_PADDING) {
#if 0
// This is commented out for now until we change
// -moz-background-clip to background-clip, -moz-background-origin
// to background-origin, change their value names to *-box, and add
// support for content-box on background-clip.
PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_BORDER ==
NS_STYLE_BG_ORIGIN_BORDER);
PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_PADDING ==
NS_STYLE_BG_ORIGIN_PADDING);
// PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_CONTENT == /* does not exist */
// NS_STYLE_BG_ORIGIN_CONTENT);
if (clip->mValue != origin->mValue) {
aValue.Truncate();
return NS_OK;
}
aValue.Append(PRUnichar(' '));
AppendCSSValueToString(eCSSProperty__moz_background_clip,
clip->mValue, aValue);
#else
aValue.Truncate();
return NS_OK;
#endif
}
image = image->mNext;
repeat = repeat->mNext;
attachment = attachment->mNext;
position = position->mNext;
clip = clip->mNext;
origin = origin->mNext;
if (!image) {
if (repeat || attachment || position || clip || origin) {
// Uneven length lists, so can't be serialized as shorthand.
aValue.Truncate();
return NS_OK;
}
break;
}
if (!repeat || !attachment || !position || !clip || !origin) {
// Uneven length lists, so can't be serialized as shorthand.
aValue.Truncate();
return NS_OK;
}
aValue.Append(PRUnichar(','));
aValue.Append(PRUnichar(' '));
}
if (AppendValueToString(eCSSProperty_background_image, aValue)) {
aValue.Append(PRUnichar(' '));
appendedSomething = PR_TRUE;
}
if (AppendValueToString(eCSSProperty_background_repeat, aValue)) {
aValue.Append(PRUnichar(' '));
appendedSomething = PR_TRUE;
}
if (AppendValueToString(eCSSProperty_background_attachment, aValue)) {
aValue.Append(PRUnichar(' '));
appendedSomething = PR_TRUE;
}
if (!AppendValueToString(eCSSProperty_background_position, aValue) &&
appendedSomething) {
NS_ASSERTION(!aValue.IsEmpty() && aValue.Last() == PRUnichar(' '),
"We appended a space before!");
// We appended an extra space. Let's get rid of it
aValue.Truncate(aValue.Length() - 1);
}
aValue.Append(PRUnichar(' '));
AppendValueToString(eCSSProperty_background_color, aValue);
break;
}
case eCSSProperty_cue: {

View File

@ -84,6 +84,7 @@
#include "nsDOMError.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "prlog.h"
// Flags for ParseVariant method
#define VARIANT_KEYWORD 0x000001 // K
@ -390,9 +391,30 @@ protected:
// Property specific parsing routines
PRBool ParseAzimuth(nsCSSValue& aValue);
PRBool ParseBackground();
struct BackgroundItem;
friend struct BackgroundItem;
struct BackgroundItem {
nsCSSValue mImage;
nsCSSValue mRepeat;
nsCSSValue mAttachment;
nsCSSValuePair mPosition;
nsCSSValue mClip;
nsCSSValue mOrigin;
// The background-color is set as a side-effect, and if so, mLastItem
// is set to true.
PRBool mLastItem;
};
struct BackgroundItemSimpleValueInfo {
nsCSSValue BackgroundItem::*member;
nsCSSProperty propID;
};
PRBool ParseBackgroundItem(BackgroundItem& aItem, PRBool aFirstItem);
PRBool ParseBackgroundList(nsCSSProperty aPropID); // a single value prop-id
PRBool ParseBackgroundColor(PRBool aInShorthand);
PRBool ParseBackgroundPosition();
PRBool ParseBackgroundPositionValues();
PRBool ParseBoxPosition(nsCSSValuePair& aOut);
PRBool ParseBoxPositionValues(nsCSSValuePair& aOut);
PRBool ParseBorderColor();
PRBool ParseBorderColors(nsCSSValueList** aResult,
@ -4940,8 +4962,16 @@ CSSParserImpl::ParseProperty(nsCSSProperty aPropID)
switch (aPropID) { // handle shorthand or multiple properties
case eCSSProperty_background:
return ParseBackground();
case eCSSProperty_background_color:
return ParseBackgroundColor(PR_FALSE);
case eCSSProperty_background_position:
return ParseBackgroundPosition();
case eCSSProperty_background_attachment:
case eCSSProperty__moz_background_clip:
case eCSSProperty_background_image:
case eCSSProperty__moz_background_origin:
case eCSSProperty_background_repeat:
return ParseBackgroundList(aPropID);
case eCSSProperty_border:
return ParseBorderSide(kBorderTopIDs, PR_TRUE);
case eCSSProperty_border_color:
@ -5193,6 +5223,7 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
switch (aPropID) {
case eCSSProperty_UNKNOWN:
case eCSSProperty_background:
case eCSSProperty_background_color:
case eCSSProperty_background_position:
case eCSSProperty_border:
case eCSSProperty_border_color:
@ -5305,22 +5336,25 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
case eCSSProperty_azimuth:
return ParseAzimuth(aValue);
case eCSSProperty_background_attachment:
// Used only internally.
return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBackgroundAttachmentKTable);
case eCSSProperty__moz_background_clip:
// Used only internally.
return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBackgroundClipKTable);
case eCSSProperty_background_color:
return ParseVariant(aValue, VARIANT_HC, nsnull);
case eCSSProperty_background_image:
// Used only internally.
return ParseVariant(aValue, VARIANT_HUO, nsnull);
case eCSSProperty__moz_background_inline_policy:
return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBackgroundInlinePolicyKTable);
case eCSSProperty__moz_background_origin:
// Used only internally.
return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBackgroundOriginKTable);
case eCSSProperty_background_repeat:
// Used only internally.
return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBackgroundRepeatKTable);
case eCSSProperty_binding:
@ -5858,42 +5892,108 @@ CSSParserImpl::ParseBackground()
{
nsAutoParseCompoundProperty compound(this);
// These two are set through side-effects of ParseBackgroundItem.
mTempData.mColor.mBackColor.mXValue.SetColorValue(NS_RGBA(0, 0, 0, 0));
mTempData.mColor.mBackColor.mYValue.SetColorValue(NS_RGBA(0, 0, 0, 0));
BackgroundItem bgitem;
nsCSSValuePairList *positionHead = nsnull, **positionTail = &positionHead;
static const BackgroundItemSimpleValueInfo simpleValues[] = {
{ &BackgroundItem::mImage, eCSSProperty_background_image },
{ &BackgroundItem::mRepeat, eCSSProperty_background_repeat },
{ &BackgroundItem::mAttachment, eCSSProperty_background_attachment },
{ &BackgroundItem::mClip, eCSSProperty__moz_background_clip },
{ &BackgroundItem::mOrigin, eCSSProperty__moz_background_origin }
};
nsCSSValueList *simpleHeads[NS_ARRAY_LENGTH(simpleValues)];
nsCSSValueList **simpleTails[NS_ARRAY_LENGTH(simpleValues)];
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
simpleHeads[i] = nsnull;
simpleTails[i] = &simpleHeads[i];
}
for (;;) {
if (!ParseBackgroundItem(bgitem, !positionHead)) {
break;
}
nsCSSValuePairList *positionItem = new nsCSSValuePairList;
if (!positionItem) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
break;
}
positionItem->mXValue = bgitem.mPosition.mXValue;
positionItem->mYValue = bgitem.mPosition.mYValue;
*positionTail = positionItem;
positionTail = &positionItem->mNext;
PRBool fail = PR_FALSE;
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
nsCSSValueList *item = new nsCSSValueList;
if (!item) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
fail = PR_TRUE;
break;
}
item->mValue = bgitem.*(simpleValues[i].member);
*simpleTails[i] = item;
simpleTails[i] = &item->mNext;
}
if (fail) {
break;
}
if (!bgitem.mLastItem && ExpectSymbol(',', PR_TRUE)) {
continue;
}
if (!ExpectEndProperty()) {
break;
}
mTempData.mColor.mBackPosition = positionHead;
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
nsCSSValueList **source = static_cast<nsCSSValueList**>(
mTempData.PropertyAt(simpleValues[i].propID));
*source = simpleHeads[i];
}
mTempData.SetPropertyBit(eCSSProperty_background_color);
mTempData.SetPropertyBit(eCSSProperty_background_image);
mTempData.SetPropertyBit(eCSSProperty_background_repeat);
mTempData.SetPropertyBit(eCSSProperty_background_attachment);
mTempData.SetPropertyBit(eCSSProperty_background_position);
mTempData.SetPropertyBit(eCSSProperty__moz_background_clip);
mTempData.SetPropertyBit(eCSSProperty__moz_background_origin);
return PR_TRUE;
}
delete positionHead;
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
delete simpleHeads[i];
}
return PR_FALSE;
}
// Parse one item of the background shorthand property.
PRBool
CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem,
PRBool aFirstItem)
{
// Fill in the values that the shorthand will set if we don't find
// other values.
mTempData.mColor.mBackColor.SetColorValue(NS_RGBA(0, 0, 0, 0));
mTempData.SetPropertyBit(eCSSProperty_background_color);
mTempData.mColor.mBackImage.SetNoneValue();
mTempData.SetPropertyBit(eCSSProperty_background_image);
mTempData.mColor.mBackRepeat.SetIntValue(NS_STYLE_BG_REPEAT_XY,
eCSSUnit_Enumerated);
mTempData.SetPropertyBit(eCSSProperty_background_repeat);
mTempData.mColor.mBackAttachment.SetIntValue(NS_STYLE_BG_ATTACHMENT_SCROLL,
eCSSUnit_Enumerated);
mTempData.SetPropertyBit(eCSSProperty_background_attachment);
mTempData.mColor.mBackPosition.mXValue.SetPercentValue(0.0f);
mTempData.mColor.mBackPosition.mYValue.SetPercentValue(0.0f);
mTempData.SetPropertyBit(eCSSProperty_background_position);
// including the ones that we can't set from the shorthand.
mTempData.mColor.mBackClip.SetIntValue(NS_STYLE_BG_CLIP_BORDER,
eCSSUnit_Enumerated);
mTempData.SetPropertyBit(eCSSProperty__moz_background_clip);
mTempData.mColor.mBackOrigin.SetIntValue(NS_STYLE_BG_ORIGIN_PADDING,
eCSSUnit_Enumerated);
mTempData.SetPropertyBit(eCSSProperty__moz_background_origin);
mTempData.mColor.mBackInlinePolicy.SetIntValue(
NS_STYLE_BG_INLINE_POLICY_CONTINUOUS, eCSSUnit_Enumerated);
mTempData.SetPropertyBit(eCSSProperty__moz_background_inline_policy);
// XXX If ParseSingleValueProperty were table-driven (bug 376079) and
// automatically filled in the right field of mTempData, we could move
// ParseBackgroundPosition to it (as a special case) and switch back
// to using ParseChoice here.
aItem.mImage.SetNoneValue();
aItem.mRepeat.SetIntValue(NS_STYLE_BG_REPEAT_XY, eCSSUnit_Enumerated);
aItem.mAttachment.SetIntValue(NS_STYLE_BG_ATTACHMENT_SCROLL,
eCSSUnit_Enumerated);
aItem.mPosition.mXValue.SetPercentValue(0.0f);
aItem.mPosition.mYValue.SetPercentValue(0.0f);
aItem.mClip.SetIntValue(NS_STYLE_BG_CLIP_BORDER, eCSSUnit_Enumerated);
aItem.mOrigin.SetIntValue(NS_STYLE_BG_ORIGIN_PADDING, eCSSUnit_Enumerated);
aItem.mLastItem = PR_FALSE;
PRBool haveColor = PR_FALSE,
haveImage = PR_FALSE,
haveRepeat = PR_FALSE,
haveAttach = PR_FALSE,
havePosition = PR_FALSE;
havePosition = PR_FALSE,
haveSomething = PR_FALSE;
while (GetToken(PR_TRUE)) {
nsCSSTokenType tt = mToken.mType;
UngetToken(); // ...but we'll still cheat and use mToken
@ -5908,7 +6008,7 @@ CSSParserImpl::ParseBackground()
PRInt32 dummy;
if (keyword == eCSSKeyword_inherit ||
keyword == eCSSKeyword__moz_initial) {
if (haveColor || haveImage || haveRepeat || haveAttach || havePosition)
if (haveSomething || !aFirstItem)
return PR_FALSE;
haveColor = haveImage = haveRepeat = haveAttach = havePosition =
PR_TRUE;
@ -5919,24 +6019,21 @@ CSSParserImpl::ParseBackground()
} else {
val.SetInitialValue();
}
mTempData.mColor.mBackColor = val;
mTempData.mColor.mBackImage = val;
mTempData.mColor.mBackRepeat = val;
mTempData.mColor.mBackAttachment = val;
mTempData.mColor.mBackPosition.mXValue = val;
mTempData.mColor.mBackPosition.mYValue = val;
// Reset (for 'inherit') the 3 properties that can't be
// specified, although it's not entirely clear in the spec:
// http://lists.w3.org/Archives/Public/www-style/2007Mar/0110
mTempData.mColor.mBackClip = val;
mTempData.mColor.mBackOrigin = val;
mTempData.mColor.mBackInlinePolicy = val;
mTempData.mColor.mBackColor.SetBothValuesTo(val);
aItem.mImage = val;
aItem.mRepeat = val;
aItem.mAttachment = val;
aItem.mPosition.SetBothValuesTo(val);
aItem.mClip = val;
aItem.mOrigin = val;
aItem.mLastItem = PR_TRUE;
haveSomething = PR_TRUE;
break;
} else if (keyword == eCSSKeyword_none) {
if (haveImage)
return PR_FALSE;
haveImage = PR_TRUE;
if (!ParseSingleValueProperty(mTempData.mColor.mBackImage,
if (!ParseSingleValueProperty(aItem.mImage,
eCSSProperty_background_image)) {
NS_NOTREACHED("should be able to parse");
return PR_FALSE;
@ -5946,7 +6043,7 @@ CSSParserImpl::ParseBackground()
if (haveAttach)
return PR_FALSE;
haveAttach = PR_TRUE;
if (!ParseSingleValueProperty(mTempData.mColor.mBackAttachment,
if (!ParseSingleValueProperty(aItem.mAttachment,
eCSSProperty_background_attachment)) {
NS_NOTREACHED("should be able to parse");
return PR_FALSE;
@ -5956,7 +6053,7 @@ CSSParserImpl::ParseBackground()
if (haveRepeat)
return PR_FALSE;
haveRepeat = PR_TRUE;
if (!ParseSingleValueProperty(mTempData.mColor.mBackRepeat,
if (!ParseSingleValueProperty(aItem.mRepeat,
eCSSProperty_background_repeat)) {
NS_NOTREACHED("should be able to parse");
return PR_FALSE;
@ -5966,24 +6063,57 @@ CSSParserImpl::ParseBackground()
if (havePosition)
return PR_FALSE;
havePosition = PR_TRUE;
if (!ParseBackgroundPositionValues()) {
if (!ParseBoxPositionValues(aItem.mPosition)) {
return PR_FALSE;
}
#if 0
// This is commented out for now until we change
// -moz-background-clip to background-clip, -moz-background-origin
// to background-origin, change their value names to *-box, and add
// support for content-box on background-clip.
} else if (nsCSSProps::FindKeyword(keyword,
nsCSSProps::kBackgroundClipKTable, dummy)) {
// For now, we use the background-clip table, because we don't
// support 'content' on background-clip. But that's dangerous
// if we eventually support no-clip.
NS_ASSERTION(
nsCSSProps::kBackgroundClipKTable[0] == eCSSKeyword_border &&
nsCSSProps::kBackgroundClipKTable[2] == eCSSKeyword_padding &&
nsCSSProps::kBackgroundClipKTable[4] == eCSSKeyword_UNKNOWN,
"need to rewrite this code");
if (haveOrigin)
return PR_FALSE;
haveOrigin = PR_TRUE;
if (!ParseSingleValueProperty(aItem.mOrigin,
eCSSProperty__moz_background_origin)) {
NS_NOTREACHED("should be able to parse");
return PR_FALSE;
}
PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_BORDER ==
NS_STYLE_BG_ORIGIN_BORDER);
PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_PADDING ==
NS_STYLE_BG_ORIGIN_PADDING);
// PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_CONTENT == /* does not exist */
// NS_STYLE_BG_ORIGIN_CONTENT);
// When we support 'no-clip', this needs to be conditional on haveClip:
aItem.mClip = aItem.mOrigin;
// We'd support 'no-clip' as an additional |else| here.
#endif
} else {
if (haveColor)
return PR_FALSE;
haveColor = PR_TRUE;
if (!ParseSingleValueProperty(mTempData.mColor.mBackColor,
eCSSProperty_background_color)) {
if (!ParseBackgroundColor(PR_TRUE)) {
return PR_FALSE;
}
aItem.mLastItem = PR_TRUE;
}
} else if (eCSSToken_Function == tt &&
mToken.mIdent.LowerCaseEqualsLiteral("url")) {
if (haveImage)
return PR_FALSE;
haveImage = PR_TRUE;
if (!ParseSingleValueProperty(mTempData.mColor.mBackImage,
if (!ParseSingleValueProperty(aItem.mImage,
eCSSProperty_background_image)) {
return PR_FALSE;
}
@ -5991,37 +6121,131 @@ CSSParserImpl::ParseBackground()
if (havePosition)
return PR_FALSE;
havePosition = PR_TRUE;
if (!ParseBackgroundPositionValues()) {
if (!ParseBoxPositionValues(aItem.mPosition)) {
return PR_FALSE;
}
} else {
if (haveColor)
return PR_FALSE;
haveColor = PR_TRUE;
if (!ParseSingleValueProperty(mTempData.mColor.mBackColor,
eCSSProperty_background_color)) {
// Note: ParseBackgroundColor parses 'inherit' and 'initial', but
// we've already checked for them, so it's ok.
if (!ParseBackgroundColor(PR_TRUE)) {
return PR_FALSE;
}
aItem.mLastItem = PR_TRUE;
}
haveSomething = PR_TRUE;
}
return ExpectEndProperty() &&
(haveColor || haveImage || haveRepeat || haveAttach || havePosition);
return haveSomething;
}
// This function is very similar to ParseBackgroundPosition.
PRBool
CSSParserImpl::ParseBackgroundList(nsCSSProperty aPropID)
{
// aPropID is a single value prop-id
nsCSSValue value;
nsCSSValueList *head = nsnull, **tail = &head;
for (;;) {
if (!ParseSingleValueProperty(value, aPropID)) {
break;
}
PRBool inheritOrInitial = value.GetUnit() == eCSSUnit_Inherit ||
value.GetUnit() == eCSSUnit_Initial;
if (inheritOrInitial && head) {
// inherit and initial are only allowed on their own
break;
}
nsCSSValueList *item = new nsCSSValueList;
if (!item) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
break;
}
item->mValue = value;
*tail = item;
tail = &item->mNext;
if (!inheritOrInitial && ExpectSymbol(',', PR_TRUE)) {
continue;
}
if (!ExpectEndProperty()) {
break;
}
nsCSSValueList **source =
static_cast<nsCSSValueList**>(mTempData.PropertyAt(aPropID));
*source = head;
mTempData.SetPropertyBit(aPropID);
return PR_TRUE;
}
delete head;
return PR_FALSE;
}
PRBool
CSSParserImpl::ParseBackgroundColor(PRBool aInShorthand)
{
nsCSSValuePair &backColor = mTempData.mColor.mBackColor;
mTempData.SetPropertyBit(eCSSProperty_background_color);
if (!ParseVariant(backColor.mXValue,
aInShorthand ? VARIANT_COLOR : VARIANT_HC, nsnull)) {
return PR_FALSE;
}
backColor.mYValue = backColor.mXValue;
switch (backColor.mXValue.GetUnit()) {
case eCSSUnit_Inherit:
case eCSSUnit_Initial:
NS_ASSERTION(!aInShorthand,
"should not get inherit or initial in shorthand");
return ExpectEndProperty(); // we're done
default:
break;
}
// Ignore success, since the value is optional.
ParseVariant(backColor.mYValue, VARIANT_COLOR, nsnull);
return aInShorthand || ExpectEndProperty();
}
// This function is very similar to ParseBackgroundList.
PRBool
CSSParserImpl::ParseBackgroundPosition()
{
if (!ParseBoxPosition(mTempData.mColor.mBackPosition))
return PR_FALSE;
mTempData.SetPropertyBit(eCSSProperty_background_position);
return PR_TRUE;
}
PRBool
CSSParserImpl::ParseBackgroundPositionValues()
{
return ParseBoxPositionValues(mTempData.mColor.mBackPosition);
// aPropID is a single value prop-id
nsCSSValuePair valuePair;
nsCSSValuePairList *head = nsnull, **tail = &head;
for (;;) {
if (!ParseBoxPositionValues(valuePair)) {
break;
}
PRBool inheritOrInitial = valuePair.mXValue.GetUnit() == eCSSUnit_Inherit ||
valuePair.mXValue.GetUnit() == eCSSUnit_Initial;
if (inheritOrInitial && head) {
// inherit and initial are only allowed on their own
break;
}
nsCSSValuePairList *item = new nsCSSValuePairList;
if (!item) {
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
break;
}
item->mXValue = valuePair.mXValue;
item->mYValue = valuePair.mYValue;
*tail = item;
tail = &item->mNext;
if (!inheritOrInitial && ExpectSymbol(',', PR_TRUE)) {
continue;
}
if (!ExpectEndProperty()) {
break;
}
mTempData.mColor.mBackPosition = head;
mTempData.SetPropertyBit(eCSSProperty_background_position);
return PR_TRUE;
}
delete head;
return PR_FALSE;
}
/**
@ -6032,12 +6256,6 @@ CSSParserImpl::ParseBackgroundPositionValues()
* @param aOut The nsCSSValuePair where to place the result.
* @return Whether or not the operation succeeded.
*/
PRBool CSSParserImpl::ParseBoxPosition(nsCSSValuePair &aOut)
{
// Need to read the box positions and the end of the property.
return ParseBoxPositionValues(aOut) && ExpectEndProperty();
}
PRBool CSSParserImpl::ParseBoxPositionValues(nsCSSValuePair &aOut)
{
// First try a percentage or a length value
@ -7214,7 +7432,8 @@ PRBool CSSParserImpl::ParseMozTransform()
PRBool CSSParserImpl::ParseMozTransformOrigin()
{
/* Read in a box position, fail if we can't. */
if (!ParseBoxPosition(mTempData.mDisplay.mTransformOrigin))
if (!ParseBoxPositionValues(mTempData.mDisplay.mTransformOrigin) ||
!ExpectEndProperty())
return PR_FALSE;
/* Set the property bit and return. */

View File

@ -297,14 +297,14 @@ CSS_PROP_FONT(-x-system-font, _x_system_font, X, CSS_PROPERTY_APPLIES_TO_FIRST_L
#endif
CSS_PROP_BACKENDONLY(azimuth, azimuth, Azimuth, 0, Aural, mAzimuth, eCSSType_Value, kAzimuthKTable)
CSS_PROP_SHORTHAND(background, background, Background, 0)
CSS_PROP_BACKGROUND(background-attachment, background_attachment, BackgroundAttachment, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackAttachment, eCSSType_Value, kBackgroundAttachmentKTable)
CSS_PROP_BACKGROUND(-moz-background-clip, _moz_background_clip, MozBackgroundClip, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackClip, eCSSType_Value, kBackgroundClipKTable)
CSS_PROP_BACKGROUND(background-color, background_color, BackgroundColor, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackColor, eCSSType_Value, nsnull)
CSS_PROP_BACKGROUND(background-image, background_image, BackgroundImage, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackImage, eCSSType_Value, nsnull)
CSS_PROP_BACKGROUND(background-attachment, background_attachment, BackgroundAttachment, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Color, mBackAttachment, eCSSType_ValueList, kBackgroundAttachmentKTable)
CSS_PROP_BACKGROUND(-moz-background-clip, _moz_background_clip, MozBackgroundClip, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Color, mBackClip, eCSSType_ValueList, kBackgroundClipKTable)
CSS_PROP_BACKGROUND(background-color, background_color, BackgroundColor, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackColor, eCSSType_ValuePair, nsnull)
CSS_PROP_BACKGROUND(background-image, background_image, BackgroundImage, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Color, mBackImage, eCSSType_ValueList, nsnull)
CSS_PROP_BACKGROUND(-moz-background-inline-policy, _moz_background_inline_policy, MozBackgroundInlinePolicy, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackInlinePolicy, eCSSType_Value, kBackgroundInlinePolicyKTable)
CSS_PROP_BACKGROUND(-moz-background-origin, _moz_background_origin, MozBackgroundOrigin, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackOrigin, eCSSType_Value, kBackgroundOriginKTable)
CSS_PROP_BACKGROUND(background-position, background_position, BackgroundPosition, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackPosition, eCSSType_ValuePair, kBackgroundPositionKTable)
CSS_PROP_BACKGROUND(background-repeat, background_repeat, BackgroundRepeat, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE, Color, mBackRepeat, eCSSType_Value, kBackgroundRepeatKTable)
CSS_PROP_BACKGROUND(-moz-background-origin, _moz_background_origin, MozBackgroundOrigin, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Color, mBackOrigin, eCSSType_ValueList, kBackgroundOriginKTable)
CSS_PROP_BACKGROUND(background-position, background_position, BackgroundPosition, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Color, mBackPosition, eCSSType_ValuePairList, kBackgroundPositionKTable)
CSS_PROP_BACKGROUND(background-repeat, background_repeat, BackgroundRepeat, CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, Color, mBackRepeat, eCSSType_ValueList, kBackgroundRepeatKTable)
CSS_PROP_DISPLAY(-moz-binding, binding, MozBinding, 0, Display, mBinding, eCSSType_Value, nsnull) // XXX bug 3935
CSS_PROP_SHORTHAND(border, border, Border, 0)
CSS_PROP_SHORTHAND(border-bottom, border_bottom, BorderBottom, 0)

View File

@ -1489,9 +1489,8 @@ static const nsCSSProperty gBackgroundSubpropTable[] = {
eCSSProperty_background_repeat,
eCSSProperty_background_attachment,
eCSSProperty_background_position,
eCSSProperty__moz_background_clip, // XXX Added LDB.
eCSSProperty__moz_background_origin, // XXX Added LDB.
eCSSProperty__moz_background_inline_policy, // XXX Added LDB.
eCSSProperty__moz_background_clip,
eCSSProperty__moz_background_origin,
eCSSProperty_UNKNOWN
};

View File

@ -106,6 +106,12 @@ nsCSSValueList::Equal(nsCSSValueList* aList1, nsCSSValueList* aList2)
// --- nsCSSColor -----------------
nsCSSColor::nsCSSColor(void)
: mBackImage(nsnull)
, mBackRepeat(nsnull)
, mBackAttachment(nsnull)
, mBackPosition(nsnull)
, mBackClip(nsnull)
, mBackOrigin(nsnull)
{
MOZ_COUNT_CTOR(nsCSSColor);
}
@ -113,6 +119,13 @@ nsCSSColor::nsCSSColor(void)
nsCSSColor::~nsCSSColor(void)
{
MOZ_COUNT_DTOR(nsCSSColor);
delete mBackImage;
delete mBackRepeat;
delete mBackAttachment;
delete mBackPosition;
delete mBackClip;
delete mBackOrigin;
}
// --- nsCSSText -----------------

View File

@ -307,13 +307,13 @@ struct nsCSSColor : public nsCSSStruct {
~nsCSSColor(void);
nsCSSValue mColor;
nsCSSValue mBackColor;
nsCSSValue mBackImage;
nsCSSValue mBackRepeat;
nsCSSValue mBackAttachment;
nsCSSValuePair mBackPosition;
nsCSSValue mBackClip;
nsCSSValue mBackOrigin;
nsCSSValuePair mBackColor;
nsCSSValueList* mBackImage;
nsCSSValueList* mBackRepeat;
nsCSSValueList* mBackAttachment;
nsCSSValuePairList* mBackPosition;
nsCSSValueList* mBackClip;
nsCSSValueList* mBackOrigin;
nsCSSValue mBackInlinePolicy;
private:
nsCSSColor(const nsCSSColor& aOther); // NOT IMPLEMENTED
@ -321,6 +321,11 @@ private:
struct nsRuleDataColor : public nsCSSColor {
nsRuleDataColor() {}
// A little bit of a hack here: now that background-image is
// represented by a value list, attribute mapping code needs a place
// to store one item in a value list in order to map a simple value.
nsCSSValueList mTempBackImage;
private:
nsRuleDataColor(const nsRuleDataColor& aOther); // NOT IMPLEMENTED
};

View File

@ -1165,69 +1165,117 @@ nsComputedDOMStyle::GetFontVariant(nsIDOMCSSValue** aValue)
return CallQueryInterface(val, aValue);
}
nsresult
nsComputedDOMStyle::GetBackgroundList(PRUint8 nsStyleBackground::Layer::* aMember,
PRUint32 nsStyleBackground::* aCount,
const PRInt32 aTable[],
nsIDOMCSSValue** aResult)
{
const nsStyleBackground* bg = GetStyleBackground();
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE);
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
for (PRUint32 i = 0, i_end = bg->*aCount; i < i_end; ++i) {
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
if (!val || !valueList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
val->SetIdent(nsCSSProps::ValueToKeywordEnum(bg->mLayers[i].*aMember,
aTable));
}
return CallQueryInterface(valueList, aResult);
}
nsresult
nsComputedDOMStyle::GetBackgroundAttachment(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
const nsStyleBackground *background = GetStyleBackground();
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(background->mBackgroundAttachment,
nsCSSProps::kBackgroundAttachmentKTable));
return CallQueryInterface(val, aValue);
return GetBackgroundList(&nsStyleBackground::Layer::mAttachment,
&nsStyleBackground::mAttachmentCount,
nsCSSProps::kBackgroundAttachmentKTable,
aValue);
}
nsresult
nsComputedDOMStyle::GetBackgroundClip(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(GetStyleBackground()->mBackgroundClip,
nsCSSProps::kBackgroundClipKTable));
return CallQueryInterface(val, aValue);
return GetBackgroundList(&nsStyleBackground::Layer::mClip,
&nsStyleBackground::mClipCount,
nsCSSProps::kBackgroundClipKTable,
aValue);
}
nsresult
nsComputedDOMStyle::GetBackgroundColor(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
const nsStyleBackground* bg = GetStyleBackground();
nsresult rv;
const nsStyleBackground* color = GetStyleBackground();
nsresult rv = SetToRGBAColor(val, color->mBackgroundColor);
if (NS_FAILED(rv)) {
delete val;
return rv;
if (bg->mBackgroundColor == bg->mFallbackBackgroundColor) {
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
rv = SetToRGBAColor(val, bg->mBackgroundColor);
if (NS_FAILED(rv)) {
delete val;
return rv;
}
rv = CallQueryInterface(val, aValue);
} else {
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_FALSE);
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
for (PRUint32 i = 0; i < 2; ++i) {
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
if (!val || !valueList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
rv = SetToRGBAColor(val, (i == 0) ? bg->mBackgroundColor
: bg->mFallbackBackgroundColor);
if (NS_FAILED(rv)) {
delete valueList;
return rv;
}
}
rv = CallQueryInterface(valueList, aValue);
}
return CallQueryInterface(val, aValue);
return rv;
}
nsresult
nsComputedDOMStyle::GetBackgroundImage(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
const nsStyleBackground* bg = GetStyleBackground();
const nsStyleBackground* color = GetStyleBackground();
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE);
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
if (color->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) {
val->SetIdent(eCSSKeyword_none);
} else {
nsCOMPtr<nsIURI> uri;
if (color->mBackgroundImage) {
color->mBackgroundImage->GetURI(getter_AddRefs(uri));
for (PRUint32 i = 0, i_end = bg->mImageCount; i < i_end; ++i) {
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
if (!val || !valueList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
imgIRequest *image = bg->mLayers[i].mImage.mRequest;
if (!image) {
val->SetIdent(eCSSKeyword_none);
} else {
nsCOMPtr<nsIURI> uri;
image->GetURI(getter_AddRefs(uri));
val->SetURI(uri);
}
val->SetURI(uri);
}
return CallQueryInterface(val, aValue);
return CallQueryInterface(valueList, aValue);
}
nsresult
@ -1246,56 +1294,55 @@ nsComputedDOMStyle::GetBackgroundInlinePolicy(nsIDOMCSSValue** aValue)
nsresult
nsComputedDOMStyle::GetBackgroundOrigin(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(GetStyleBackground()->mBackgroundOrigin,
nsCSSProps::kBackgroundOriginKTable));
return CallQueryInterface(val, aValue);
return GetBackgroundList(&nsStyleBackground::Layer::mOrigin,
&nsStyleBackground::mOriginCount,
nsCSSProps::kBackgroundOriginKTable,
aValue);
}
nsresult
nsComputedDOMStyle::GetBackgroundPosition(nsIDOMCSSValue** aValue)
{
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_FALSE);
const nsStyleBackground* bg = GetStyleBackground();
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE);
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
nsROCSSPrimitiveValue *valX = GetROCSSPrimitiveValue();
if (!valX || !valueList->AppendCSSValue(valX)) {
delete valueList;
delete valX;
return NS_ERROR_OUT_OF_MEMORY;
}
for (PRUint32 i = 0, i_end = bg->mPositionCount; i < i_end; ++i) {
nsDOMCSSValueList *itemList = GetROCSSValueList(PR_FALSE);
if (!itemList || !valueList->AppendCSSValue(itemList)) {
delete valueList;
delete itemList;
return NS_ERROR_OUT_OF_MEMORY;
}
nsROCSSPrimitiveValue *valY = GetROCSSPrimitiveValue();
if (!valY || !valueList->AppendCSSValue(valY)) {
delete valueList;
delete valY;
return NS_ERROR_OUT_OF_MEMORY;
}
nsROCSSPrimitiveValue *valX = GetROCSSPrimitiveValue();
if (!valX || !itemList->AppendCSSValue(valX)) {
delete valueList;
delete valX;
return NS_ERROR_OUT_OF_MEMORY;
}
const nsStyleBackground *bg = GetStyleBackground();
nsROCSSPrimitiveValue *valY = GetROCSSPrimitiveValue();
if (!valY || !itemList->AppendCSSValue(valY)) {
delete valueList;
delete valY;
return NS_ERROR_OUT_OF_MEMORY;
}
if (NS_STYLE_BG_X_POSITION_LENGTH & bg->mBackgroundFlags) {
valX->SetAppUnits(bg->mBackgroundXPosition.mCoord);
}
else if (NS_STYLE_BG_X_POSITION_PERCENT & bg->mBackgroundFlags) {
valX->SetPercent(bg->mBackgroundXPosition.mFloat);
}
else {
valX->SetPercent(0.0f);
}
const nsStyleBackground::Position &pos = bg->mLayers[i].mPosition;
if (NS_STYLE_BG_Y_POSITION_LENGTH & bg->mBackgroundFlags) {
valY->SetAppUnits(bg->mBackgroundYPosition.mCoord);
}
else if (NS_STYLE_BG_Y_POSITION_PERCENT & bg->mBackgroundFlags) {
valY->SetPercent(bg->mBackgroundYPosition.mFloat);
}
else {
valY->SetPercent(0.0f);
if (pos.mXIsPercent) {
valX->SetPercent(pos.mXPosition.mFloat);
} else {
valX->SetAppUnits(pos.mXPosition.mCoord);
}
if (pos.mYIsPercent) {
valY->SetPercent(pos.mYPosition.mFloat);
} else {
valY->SetAppUnits(pos.mYPosition.mCoord);
}
}
return CallQueryInterface(valueList, aValue);
@ -1304,14 +1351,10 @@ nsComputedDOMStyle::GetBackgroundPosition(nsIDOMCSSValue** aValue)
nsresult
nsComputedDOMStyle::GetBackgroundRepeat(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(GetStyleBackground()->mBackgroundRepeat,
nsCSSProps::kBackgroundRepeatKTable));
return CallQueryInterface(val, aValue);
return GetBackgroundList(&nsStyleBackground::Layer::mRepeat,
&nsStyleBackground::mRepeatCount,
nsCSSProps::kBackgroundRepeatKTable,
aValue);
}
nsresult
@ -1831,7 +1874,7 @@ nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
for (nsCSSShadowItem *item = aArray->ShadowAt(0),
*item_end = item + aArray->Length();
*item_end = item + aArray->Length();
item < item_end; ++item) {
nsDOMCSSValueList *itemList = GetROCSSValueList(PR_FALSE);
if (!itemList || !valueList->AppendCSSValue(itemList)) {

View File

@ -55,6 +55,7 @@
#include "nsCOMPtr.h"
#include "nsWeakReference.h"
#include "nsAutoPtr.h"
#include "nsStyleStruct.h"
class nsComputedDOMStyle : public nsIComputedDOMStyle
{
@ -116,6 +117,11 @@ private:
PRBool aIsBoxShadow,
nsIDOMCSSValue** aValue);
nsresult GetBackgroundList(PRUint8 nsStyleBackground::Layer::* aMember,
PRUint32 nsStyleBackground::* aCount,
const PRInt32 aTable[],
nsIDOMCSSValue** aResult);
/* Properties Queryable as CSSValues */
nsresult GetAppearance(nsIDOMCSSValue** aValue);

View File

@ -1420,8 +1420,7 @@ nsRuleNode::GetUIResetData(nsStyleContext* aContext)
nsRuleData ruleData(NS_STYLE_INHERIT_BIT(UIReset), mPresContext, aContext);
ruleData.mUserInterfaceData = &uiData;
const void* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData);
return res;
return WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData);
}
const void*
@ -1455,7 +1454,17 @@ nsRuleNode::GetBackgroundData(nsStyleContext* aContext)
// null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
// and HasAuthorSpecifiedRules).
return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData);
const void *res = WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData);
// We are sharing with some style rule. It really owns the data.
colorData.mBackImage = nsnull;
colorData.mBackRepeat = nsnull;
colorData.mBackAttachment = nsnull;
colorData.mBackPosition = nsnull;
colorData.mBackClip = nsnull;
colorData.mBackOrigin = nsnull;
return res;
}
const void*
@ -3771,6 +3780,189 @@ nsRuleNode::ComputeColorData(void* aStartStruct,
COMPUTE_END_INHERITED(Color, color)
}
// information about how to compute values for background-* properties
template <class SpecifiedValueItem>
struct InitialInheritLocationFor {
};
NS_SPECIALIZE_TEMPLATE
struct InitialInheritLocationFor<nsCSSValueList> {
static nsCSSValue nsCSSValueList::* Location() {
return &nsCSSValueList::mValue;
}
};
NS_SPECIALIZE_TEMPLATE
struct InitialInheritLocationFor<nsCSSValuePairList> {
static nsCSSValue nsCSSValuePairList::* Location() {
return &nsCSSValuePairList::mXValue;
}
};
template <class SpecifiedValueItem, class ComputedValueItem>
struct BackgroundItemComputer {
};
NS_SPECIALIZE_TEMPLATE
struct BackgroundItemComputer<nsCSSValueList, PRUint8>
{
static void ComputeValue(nsStyleContext* aStyleContext,
const nsCSSValueList* aSpecifiedValue,
PRUint8& aComputedValue,
PRBool& aCanStoreInRuleTree)
{
SetDiscrete(aSpecifiedValue->mValue, aComputedValue, aCanStoreInRuleTree,
SETDSC_ENUMERATED, PRUint8(0), 0, 0, 0, 0, 0);
}
};
NS_SPECIALIZE_TEMPLATE
struct BackgroundItemComputer<nsCSSValueList, nsStyleBackground::Image>
{
static void ComputeValue(nsStyleContext* aStyleContext,
const nsCSSValueList* aSpecifiedValue,
nsStyleBackground::Image& aComputedValue,
PRBool& aCanStoreInRuleTree)
{
const nsCSSValue &value = aSpecifiedValue->mValue;
if (eCSSUnit_Image == value.GetUnit()) {
aComputedValue.mRequest = value.GetImageValue();
aComputedValue.mSpecified = PR_TRUE;
}
else {
NS_ASSERTION(eCSSUnit_None == value.GetUnit(), "unexpected unit");
aComputedValue.mRequest = nsnull;
aComputedValue.mSpecified = PR_FALSE;
}
}
};
struct BackgroundPositionAxis {
nsCSSValue nsCSSValuePairList::*specified;
nsStyleBackground::Position::PositionCoord
nsStyleBackground::Position::*result;
PRPackedBool nsStyleBackground::Position::*isPercent;
};
static const BackgroundPositionAxis gBGPosAxes[] = {
{ &nsCSSValuePairList::mXValue,
&nsStyleBackground::Position::mXPosition,
&nsStyleBackground::Position::mXIsPercent },
{ &nsCSSValuePairList::mYValue,
&nsStyleBackground::Position::mYPosition,
&nsStyleBackground::Position::mYIsPercent }
};
NS_SPECIALIZE_TEMPLATE
struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Position>
{
static void ComputeValue(nsStyleContext* aStyleContext,
const nsCSSValuePairList* aSpecifiedValue,
nsStyleBackground::Position& aComputedValue,
PRBool& aCanStoreInRuleTree)
{
nsStyleBackground::Position &position = aComputedValue;
for (const BackgroundPositionAxis *axis = gBGPosAxes,
*axis_end = gBGPosAxes + NS_ARRAY_LENGTH(gBGPosAxes);
axis != axis_end; ++axis) {
const nsCSSValue &specified = aSpecifiedValue->*(axis->specified);
if (eCSSUnit_Percent == specified.GetUnit()) {
(position.*(axis->result)).mFloat = specified.GetPercentValue();
position.*(axis->isPercent) = PR_TRUE;
}
else if (specified.IsLengthUnit()) {
(position.*(axis->result)).mCoord =
CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
aCanStoreInRuleTree);
position.*(axis->isPercent) = PR_FALSE;
}
else if (eCSSUnit_Enumerated == specified.GetUnit()) {
(position.*(axis->result)).mFloat =
GetFloatFromBoxPosition(specified.GetIntValue());
position.*(axis->isPercent) = PR_TRUE;
} else {
NS_NOTREACHED("unexpected unit");
}
}
}
};
template <class SpecifiedValueItem, class ComputedValueItem>
static void
SetBackgroundList(nsStyleContext* aStyleContext,
const SpecifiedValueItem* aValueList,
nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
const nsAutoTArray<nsStyleBackground::Layer, 1>
&aParentLayers,
ComputedValueItem nsStyleBackground::Layer::* aResultLocation,
ComputedValueItem aInitialValue,
PRUint32 aParentItemCount,
PRUint32& aItemCount,
PRUint32& aMaxItemCount,
PRBool& aRebuild,
PRBool& aCanStoreInRuleTree)
{
if (aValueList) {
aRebuild = PR_TRUE;
nsCSSValue SpecifiedValueItem::* initialInherit =
InitialInheritLocationFor<SpecifiedValueItem>::Location();
if (eCSSUnit_Inherit == (aValueList->*initialInherit).GetUnit()) {
NS_ASSERTION(!aValueList->mNext, "should have only one value");
aCanStoreInRuleTree = PR_FALSE;
if (!aLayers.EnsureLengthAtLeast(aParentItemCount)) {
NS_WARNING("out of memory");
aParentItemCount = aLayers.Length();
}
aItemCount = aParentItemCount;
for (PRUint32 i = 0; i < aParentItemCount; ++i) {
aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
}
} else if (eCSSUnit_Initial == (aValueList->*initialInherit).GetUnit()) {
NS_ASSERTION(!aValueList->mNext, "should have only one value");
aItemCount = 1;
aLayers[0].*aResultLocation = aInitialValue;
} else {
const SpecifiedValueItem *item = aValueList;
aItemCount = 0;
do {
NS_ASSERTION((item->*initialInherit).GetUnit() != eCSSUnit_Inherit &&
(item->*initialInherit).GetUnit() != eCSSUnit_Initial,
"unexpected unit");
++aItemCount;
if (!aLayers.EnsureLengthAtLeast(aItemCount)) {
NS_WARNING("out of memory");
--aItemCount;
break;
}
BackgroundItemComputer<SpecifiedValueItem, ComputedValueItem>
::ComputeValue(aStyleContext, item,
aLayers[aItemCount-1].*aResultLocation,
aCanStoreInRuleTree);
item = item->mNext;
} while (item);
}
}
if (aItemCount > aMaxItemCount)
aMaxItemCount = aItemCount;
}
template <class ComputedValueItem>
static void
FillBackgroundList(nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
ComputedValueItem nsStyleBackground::Layer::* aResultLocation,
PRUint32 aItemCount, PRUint32 aFillCount)
{
NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
for (PRUint32 sourceLayer = 0, destLayer = aItemCount;
destLayer < aFillCount;
++sourceLayer, ++destLayer) {
aLayers[destLayer].*aResultLocation =
aLayers[sourceLayer].*aResultLocation;
}
}
const void*
nsRuleNode::ComputeBackgroundData(void* aStartStruct,
const nsRuleDataStruct& aData,
@ -3781,52 +3973,55 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct,
{
COMPUTE_START_RESET(Background, (), bg, parentBG, Color, colorData)
// save parentFlags in case bg == parentBG and we clobber them later
PRUint8 parentFlags = parentBG->mBackgroundFlags;
// background-color: color, string, inherit
if (eCSSUnit_Initial == colorData.mBackColor.GetUnit()) {
// background-color: color, string, inherit [pair]
if (eCSSUnit_Initial == colorData.mBackColor.mXValue.GetUnit()) {
bg->mBackgroundColor = NS_RGBA(0, 0, 0, 0);
} else if (!SetColor(colorData.mBackColor, parentBG->mBackgroundColor,
mPresContext, aContext, bg->mBackgroundColor,
canStoreInRuleTree)) {
NS_ASSERTION(eCSSUnit_Null == colorData.mBackColor.GetUnit(),
} else if (!SetColor(colorData.mBackColor.mXValue,
parentBG->mBackgroundColor, mPresContext,
aContext, bg->mBackgroundColor, canStoreInRuleTree)) {
NS_ASSERTION(eCSSUnit_Null == colorData.mBackColor.mXValue.GetUnit(),
"unexpected color unit");
}
// background-image: url (stored as image), none, inherit
if (eCSSUnit_Image == colorData.mBackImage.GetUnit()) {
bg->mBackgroundImage = colorData.mBackImage.GetImageValue();
}
else if (eCSSUnit_None == colorData.mBackImage.GetUnit() ||
eCSSUnit_Initial == colorData.mBackImage.GetUnit()) {
bg->mBackgroundImage = nsnull;
}
else if (eCSSUnit_Inherit == colorData.mBackImage.GetUnit()) {
canStoreInRuleTree = PR_FALSE;
bg->mBackgroundImage = parentBG->mBackgroundImage;
if (eCSSUnit_Initial == colorData.mBackColor.mYValue.GetUnit()) {
bg->mFallbackBackgroundColor = NS_RGBA(0, 0, 0, 0);
} else if (!SetColor(colorData.mBackColor.mYValue,
parentBG->mFallbackBackgroundColor, mPresContext,
aContext, bg->mFallbackBackgroundColor,
canStoreInRuleTree)) {
NS_ASSERTION(eCSSUnit_Null == colorData.mBackColor.mYValue.GetUnit(),
"unexpected color unit");
}
if (bg->mBackgroundImage) {
bg->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE;
} else {
bg->mBackgroundFlags |= NS_STYLE_BG_IMAGE_NONE;
}
PRUint32 maxItemCount = 1;
PRBool rebuild = PR_FALSE;
// background-repeat: enum, inherit, initial
SetDiscrete(colorData.mBackRepeat, bg->mBackgroundRepeat, canStoreInRuleTree,
SETDSC_ENUMERATED, parentBG->mBackgroundRepeat,
NS_STYLE_BG_REPEAT_XY, 0, 0, 0, 0);
// background-image: url (stored as image), none, inherit [list]
SetBackgroundList(aContext, colorData.mBackImage, bg->mLayers,
parentBG->mLayers, &nsStyleBackground::Layer::mImage,
nsStyleBackground::Image(), parentBG->mImageCount,
bg->mImageCount, maxItemCount, rebuild, canStoreInRuleTree);
// background-attachment: enum, inherit, initial
SetDiscrete(colorData.mBackAttachment, bg->mBackgroundAttachment, canStoreInRuleTree,
SETDSC_ENUMERATED, parentBG->mBackgroundAttachment,
NS_STYLE_BG_ATTACHMENT_SCROLL, 0, 0, 0, 0);
// background-repeat: enum, inherit, initial [list]
SetBackgroundList(aContext, colorData.mBackRepeat, bg->mLayers,
parentBG->mLayers, &nsStyleBackground::Layer::mRepeat,
PRUint8(NS_STYLE_BG_REPEAT_XY), parentBG->mRepeatCount,
bg->mRepeatCount, maxItemCount, rebuild, canStoreInRuleTree);
// background-clip: enum, inherit, initial
SetDiscrete(colorData.mBackClip, bg->mBackgroundClip, canStoreInRuleTree,
SETDSC_ENUMERATED, parentBG->mBackgroundClip,
NS_STYLE_BG_CLIP_BORDER, 0, 0, 0, 0);
// background-attachment: enum, inherit, initial [list]
SetBackgroundList(aContext, colorData.mBackAttachment, bg->mLayers,
parentBG->mLayers,
&nsStyleBackground::Layer::mAttachment,
PRUint8(NS_STYLE_BG_ATTACHMENT_SCROLL),
parentBG->mAttachmentCount,
bg->mAttachmentCount, maxItemCount, rebuild,
canStoreInRuleTree);
// background-clip: enum, inherit, initial [list]
SetBackgroundList(aContext, colorData.mBackClip, bg->mLayers,
parentBG->mLayers, &nsStyleBackground::Layer::mClip,
PRUint8(NS_STYLE_BG_CLIP_BORDER), parentBG->mClipCount,
bg->mClipCount, maxItemCount, rebuild, canStoreInRuleTree);
// background-inline-policy: enum, inherit, initial
SetDiscrete(colorData.mBackInlinePolicy, bg->mBackgroundInlinePolicy,
@ -3834,66 +4029,40 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct,
parentBG->mBackgroundInlinePolicy,
NS_STYLE_BG_INLINE_POLICY_CONTINUOUS, 0, 0, 0, 0);
// background-origin: enum, inherit, initial
SetDiscrete(colorData.mBackOrigin, bg->mBackgroundOrigin, canStoreInRuleTree,
SETDSC_ENUMERATED, parentBG->mBackgroundOrigin,
NS_STYLE_BG_ORIGIN_PADDING, 0, 0, 0, 0);
// background-origin: enum, inherit, initial [list]
SetBackgroundList(aContext, colorData.mBackOrigin, bg->mLayers,
parentBG->mLayers, &nsStyleBackground::Layer::mOrigin,
PRUint8(NS_STYLE_BG_ORIGIN_PADDING), parentBG->mOriginCount,
bg->mOriginCount, maxItemCount, rebuild,
canStoreInRuleTree);
// background-position: enum, length, percent (flags), inherit
if (eCSSUnit_Percent == colorData.mBackPosition.mXValue.GetUnit()) {
bg->mBackgroundXPosition.mFloat = colorData.mBackPosition.mXValue.GetPercentValue();
bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT;
bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH;
}
else if (colorData.mBackPosition.mXValue.IsLengthUnit()) {
bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue,
aContext, mPresContext, canStoreInRuleTree);
bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_LENGTH;
bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_PERCENT;
}
else if (eCSSUnit_Enumerated == colorData.mBackPosition.mXValue.GetUnit()) {
bg->mBackgroundXPosition.mFloat =
GetFloatFromBoxPosition(colorData.mBackPosition.mXValue.GetIntValue());
// background-position: enum, length, percent (flags), inherit [pair list]
nsStyleBackground::Position initialPosition;
initialPosition.SetInitialValues();
SetBackgroundList(aContext, colorData.mBackPosition, bg->mLayers,
parentBG->mLayers, &nsStyleBackground::Layer::mPosition,
initialPosition, parentBG->mPositionCount,
bg->mPositionCount, maxItemCount, rebuild,
canStoreInRuleTree);
bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT;
bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH;
}
else if (eCSSUnit_Inherit == colorData.mBackPosition.mXValue.GetUnit()) {
canStoreInRuleTree = PR_FALSE;
bg->mBackgroundXPosition = parentBG->mBackgroundXPosition;
bg->mBackgroundFlags &= ~(NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT);
bg->mBackgroundFlags |= (parentFlags & (NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT));
}
else if (eCSSUnit_Initial == colorData.mBackPosition.mXValue.GetUnit()) {
bg->mBackgroundFlags &= ~(NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT);
}
if (rebuild) {
// Delete any extra items. We need to keep layers in which any
// property was specified.
bg->mLayers.TruncateLength(maxItemCount);
if (eCSSUnit_Percent == colorData.mBackPosition.mYValue.GetUnit()) {
bg->mBackgroundYPosition.mFloat = colorData.mBackPosition.mYValue.GetPercentValue();
bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT;
bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH;
}
else if (colorData.mBackPosition.mYValue.IsLengthUnit()) {
bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue,
aContext, mPresContext, canStoreInRuleTree);
bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_LENGTH;
bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_PERCENT;
}
else if (eCSSUnit_Enumerated == colorData.mBackPosition.mYValue.GetUnit()) {
bg->mBackgroundYPosition.mFloat =
GetFloatFromBoxPosition(colorData.mBackPosition.mYValue.GetIntValue());
bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT;
bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH;
}
else if (eCSSUnit_Inherit == colorData.mBackPosition.mYValue.GetUnit()) {
canStoreInRuleTree = PR_FALSE;
bg->mBackgroundYPosition = parentBG->mBackgroundYPosition;
bg->mBackgroundFlags &= ~(NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT);
bg->mBackgroundFlags |= (parentFlags & (NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT));
}
else if (eCSSUnit_Initial == colorData.mBackPosition.mYValue.GetUnit()) {
bg->mBackgroundFlags &= ~(NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT);
PRUint32 fillCount = bg->mImageCount;
FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mImage,
bg->mImageCount, fillCount);
FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mRepeat,
bg->mRepeatCount, fillCount);
FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mAttachment,
bg->mAttachmentCount, fillCount);
FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mClip,
bg->mClipCount, fillCount);
FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mOrigin,
bg->mOriginCount, fillCount);
FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mPosition,
bg->mPositionCount, fillCount);
}
COMPUTE_END_RESET(Background, bg)
@ -5499,6 +5668,7 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
{
nsRuleDataColor colorData;
nsRuleDataMargin marginData;
nsCSSValue firstBackgroundImage;
PRUint32 nValues = 0;
PRUint32 inheritBits = 0;
@ -5518,8 +5688,9 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
ruleData.mMarginData = &marginData;
nsCSSValue* backgroundValues[] = {
&colorData.mBackColor,
&colorData.mBackImage
&colorData.mBackColor.mXValue,
&colorData.mBackColor.mYValue,
&firstBackgroundImage
};
nsCSSValue* borderValues[] = {
@ -5583,11 +5754,25 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
if (rule) {
ruleData.mLevel = ruleNode->GetLevel();
ruleData.mIsImportantRule = ruleNode->IsImportantRule();
rule->MapRuleInfoInto(&ruleData);
if ((ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) &&
colorData.mBackImage &&
firstBackgroundImage.GetUnit() == eCSSUnit_Null) {
// Handle background-image being a value list
firstBackgroundImage = colorData.mBackImage->mValue;
}
// Do the same nulling out as in GetBorderData, GetBackgroundData
// or GetPaddingData.
// We are sharing with some style rule. It really owns the data.
marginData.mBoxShadow = nsnull;
colorData.mBackImage = nsnull;
colorData.mBackRepeat = nsnull;
colorData.mBackAttachment = nsnull;
colorData.mBackPosition = nsnull;
colorData.mBackClip = nsnull;
colorData.mBackOrigin = nsnull;
if (ruleData.mLevel == nsStyleSet::eAgentSheet ||
ruleData.mLevel == nsStyleSet::eUserSheet) {

View File

@ -1207,28 +1207,44 @@ nsChangeHint nsStyleColor::MaxDifference()
//
nsStyleBackground::nsStyleBackground()
: mBackgroundFlags(NS_STYLE_BG_IMAGE_NONE),
mBackgroundAttachment(NS_STYLE_BG_ATTACHMENT_SCROLL),
mBackgroundClip(NS_STYLE_BG_CLIP_BORDER),
mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS),
mBackgroundOrigin(NS_STYLE_BG_ORIGIN_PADDING),
mBackgroundRepeat(NS_STYLE_BG_REPEAT_XY),
mBackgroundColor(NS_RGBA(0, 0, 0, 0))
: mAttachmentCount(1)
, mClipCount(1)
, mOriginCount(1)
, mRepeatCount(1)
, mPositionCount(1)
, mImageCount(1)
, mBackgroundColor(NS_RGBA(0, 0, 0, 0))
, mFallbackBackgroundColor(NS_RGBA(0, 0, 0, 0))
, mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS)
{
Layer *onlyLayer = mLayers.AppendElement();
NS_ASSERTION(onlyLayer, "auto array must have room for 1 element");
onlyLayer->SetInitialValues();
}
nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
: mBackgroundFlags(aSource.mBackgroundFlags),
mBackgroundAttachment(aSource.mBackgroundAttachment),
mBackgroundClip(aSource.mBackgroundClip),
mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy),
mBackgroundOrigin(aSource.mBackgroundOrigin),
mBackgroundRepeat(aSource.mBackgroundRepeat),
mBackgroundXPosition(aSource.mBackgroundXPosition),
mBackgroundYPosition(aSource.mBackgroundYPosition),
mBackgroundColor(aSource.mBackgroundColor),
mBackgroundImage(aSource.mBackgroundImage)
: mAttachmentCount(aSource.mAttachmentCount)
, mClipCount(aSource.mClipCount)
, mOriginCount(aSource.mOriginCount)
, mRepeatCount(aSource.mRepeatCount)
, mPositionCount(aSource.mPositionCount)
, mImageCount(aSource.mImageCount)
, mLayers(aSource.mLayers) // deep copy
, mBackgroundColor(aSource.mBackgroundColor)
, mFallbackBackgroundColor(aSource.mFallbackBackgroundColor)
, mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy)
{
// If the deep copy of mLayers failed, truncate the counts.
PRUint32 count = mLayers.Length();
if (count != aSource.mLayers.Length()) {
NS_WARNING("truncating counts due to out-of-memory");
mAttachmentCount = PR_MAX(mAttachmentCount, count);
mClipCount = PR_MAX(mClipCount, count);
mOriginCount = PR_MAX(mOriginCount, count);
mRepeatCount = PR_MAX(mRepeatCount, count);
mPositionCount = PR_MAX(mPositionCount, count);
mImageCount = PR_MAX(mImageCount, count);
}
}
nsStyleBackground::~nsStyleBackground()
@ -1237,24 +1253,19 @@ nsStyleBackground::~nsStyleBackground()
nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
{
if ((mBackgroundAttachment == aOther.mBackgroundAttachment) &&
(mBackgroundFlags == aOther.mBackgroundFlags) &&
(mBackgroundRepeat == aOther.mBackgroundRepeat) &&
(mBackgroundColor == aOther.mBackgroundColor) &&
(mBackgroundClip == aOther.mBackgroundClip) &&
(mBackgroundInlinePolicy == aOther.mBackgroundInlinePolicy) &&
(mBackgroundOrigin == aOther.mBackgroundOrigin) &&
EqualImages(mBackgroundImage, aOther.mBackgroundImage) &&
((!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_PERCENT) ||
(mBackgroundXPosition.mFloat == aOther.mBackgroundXPosition.mFloat)) &&
(!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_LENGTH) ||
(mBackgroundXPosition.mCoord == aOther.mBackgroundXPosition.mCoord))) &&
((!(mBackgroundFlags & NS_STYLE_BG_Y_POSITION_PERCENT) ||
(mBackgroundYPosition.mFloat == aOther.mBackgroundYPosition.mFloat)) &&
(!(mBackgroundFlags & NS_STYLE_BG_Y_POSITION_LENGTH) ||
(mBackgroundYPosition.mCoord == aOther.mBackgroundYPosition.mCoord))))
return NS_STYLE_HINT_NONE;
return NS_STYLE_HINT_VISUAL;
if (mBackgroundColor != aOther.mBackgroundColor ||
mFallbackBackgroundColor != aOther.mFallbackBackgroundColor ||
mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy ||
mImageCount != aOther.mImageCount)
return NS_STYLE_HINT_VISUAL;
// We checked the image count above.
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
if (mLayers[i] != aOther.mLayers[i])
return NS_STYLE_HINT_VISUAL;
}
return NS_STYLE_HINT_NONE;
}
#ifdef DEBUG
@ -1267,8 +1278,80 @@ nsChangeHint nsStyleBackground::MaxDifference()
PRBool nsStyleBackground::HasFixedBackground() const
{
return mBackgroundAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
mBackgroundImage;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
const Layer &layer = mLayers[i];
if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
layer.mImage.mRequest) {
return PR_TRUE;
}
}
return PR_FALSE;
}
PRBool nsStyleBackground::IsTransparent() const
{
return !BottomLayer().mImage.mRequest && mImageCount == 1 &&
NS_GET_A(mBackgroundColor) == 0;
}
void
nsStyleBackground::Position::SetInitialValues()
{
mXPosition.mFloat = 0.0f;
mYPosition.mFloat = 0.0f;
mXIsPercent = PR_TRUE;
mYIsPercent = PR_TRUE;
}
// Initialize to initial values
nsStyleBackground::Image::Image()
{
SetInitialValues();
}
nsStyleBackground::Image::~Image()
{
}
void nsStyleBackground::Image::SetInitialValues()
{
mRequest = nsnull;
mSpecified = PR_FALSE;
}
PRBool nsStyleBackground::Image::operator==(const Image& aOther) const
{
return mSpecified == aOther.mSpecified &&
EqualImages(mRequest, aOther.mRequest);
}
nsStyleBackground::Layer::Layer()
{
}
nsStyleBackground::Layer::~Layer()
{
}
void
nsStyleBackground::Layer::SetInitialValues()
{
mAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL;
mClip = NS_STYLE_BG_CLIP_BORDER;
mOrigin = NS_STYLE_BG_ORIGIN_PADDING;
mRepeat = NS_STYLE_BG_REPEAT_XY;
mPosition.SetInitialValues();
mImage.SetInitialValues();
}
PRBool nsStyleBackground::Layer::operator==(const Layer& aOther) const
{
return mAttachment == aOther.mAttachment &&
mClip == aOther.mClip &&
mOrigin == aOther.mOrigin &&
mRepeat == aOther.mRepeat &&
mPosition == aOther.mPosition &&
mImage == aOther.mImage;
}
// --------------------

View File

@ -58,6 +58,7 @@
#include "nsIPresShell.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsIAtom.h"
#include "nsIURI.h"
#include "nsCSSValue.h"
@ -164,30 +165,122 @@ struct nsStyleBackground {
static nsChangeHint MaxDifference();
#endif
PRUint8 mBackgroundFlags; // [reset] See nsStyleConsts.h
PRUint8 mBackgroundAttachment; // [reset] See nsStyleConsts.h
PRUint8 mBackgroundClip; // [reset] See nsStyleConsts.h
PRUint8 mBackgroundInlinePolicy; // [reset] See nsStyleConsts.h
PRUint8 mBackgroundOrigin; // [reset] See nsStyleConsts.h
PRUint8 mBackgroundRepeat; // [reset] See nsStyleConsts.h
struct Position;
friend struct Position;
struct Position {
typedef union {
nscoord mCoord; // for lengths
float mFloat; // for percents
} PositionCoord;
PositionCoord mXPosition, mYPosition;
PRPackedBool mXIsPercent, mYIsPercent;
// Note: a member of this union is valid IFF the appropriate bit flag
// is set in mBackgroundFlags.
union {
nscoord mCoord;
float mFloat;
} mBackgroundXPosition, // [reset]
mBackgroundYPosition; // [reset]
// Initialize nothing
Position() {}
// Initialize to initial values
void SetInitialValues();
PRBool operator==(const Position& aOther) const {
return mXIsPercent == aOther.mXIsPercent &&
(mXIsPercent ? (mXPosition.mFloat == aOther.mXPosition.mFloat)
: (mXPosition.mCoord == aOther.mXPosition.mCoord)) &&
mYIsPercent == aOther.mYIsPercent &&
(mYIsPercent ? (mYPosition.mFloat == aOther.mYPosition.mFloat)
: (mYPosition.mCoord == aOther.mYPosition.mCoord));
}
PRBool operator!=(const Position& aOther) const {
return !(*this == aOther);
}
};
/**
* We represent images as as struct because we need to distinguish the
* case where the imgIRequest is null because the winning
* background-image declaration specified no image from the case where
* the imgIRequest is null because the image that was specified was
* blocked or missing (e.g., missing file).
*/
struct Image;
friend struct Image;
struct Image {
nsCOMPtr<imgIRequest> mRequest;
PRBool mSpecified; // if false, mRequest is guaranteed to be null
// These are not inline so that we can avoid #include "imgIRequest.h"
// Initialize to initial values
Image();
~Image();
void SetInitialValues();
// An equality operator that compares the images using URL-equality
// rather than pointer-equality.
PRBool operator==(const Image& aOther) const;
PRBool operator!=(const Image& aOther) const {
return !(*this == aOther);
}
};
struct Layer;
friend struct Layer;
struct Layer {
PRUint8 mAttachment; // [reset] See nsStyleConsts.h
PRUint8 mClip; // [reset] See nsStyleConsts.h
PRUint8 mOrigin; // [reset] See nsStyleConsts.h
PRUint8 mRepeat; // [reset] See nsStyleConsts.h
Position mPosition; // [reset]
Image mImage; // [reset]
// Initializes only mImage
Layer();
~Layer();
void SetInitialValues();
// An equality operator that compares the images using URL-equality
// rather than pointer-equality.
PRBool operator==(const Layer& aOther) const;
PRBool operator!=(const Layer& aOther) const {
return !(*this == aOther);
}
};
// The (positive) number of computed values of each property, since
// the lengths of the lists are independent.
PRUint32 mAttachmentCount,
mClipCount,
mOriginCount,
mRepeatCount,
mPositionCount,
mImageCount;
// Layers are stored in an array, matching the top-to-bottom order in
// which they are specified in CSS. The number of layers to be used
// should come from the background-image property. We create
// additional |Layer| objects for *any* property, not just
// background-image. This means that the bottommost layer that
// callers in layout care about (which is also the one whose
// background-clip applies to the background-color) may not be last
// layer. In layers below the bottom layer, properties will be
// unitialized unless their count, above, indicates that they are
// present.
nsAutoTArray<Layer, 1> mLayers;
const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
#define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(var_, stylebg_) \
for (PRUint32 var_ = (stylebg_)->mImageCount; var_-- != 0; )
nscolor mBackgroundColor; // [reset]
nsCOMPtr<imgIRequest> mBackgroundImage; // [reset]
nscolor mFallbackBackgroundColor; // [reset]
// FIXME: This (now background-break in css3-background) should
// probably move into a different struct so that everything in
// nsStyleBackground is set by the background shorthand.
PRUint8 mBackgroundInlinePolicy; // [reset] See nsStyleConsts.h
// True if this background is completely transparent.
PRBool IsTransparent() const
{
return (NS_GET_A(mBackgroundColor) == 0 &&
(mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE));
}
PRBool IsTransparent() const;
// We have to take slower codepaths for fixed background attachment,
// but we don't want to do that when there's no image.

View File

@ -72,12 +72,17 @@ var gCSSProperties = {
invalid_values: []
},
"-moz-background-clip": {
/*
* When we rename this to 'background-clip', we also
* need to rename the values to match the spec.
*/
domProp: "MozBackgroundClip",
inherited: false,
type: CSS_TYPE_LONGHAND,
/* XXX Need to add support for "content" -- important for symmetry when handling background shorthand */
initial_values: [ "border" ],
other_values: [ "padding" ],
invalid_values: [ "content", "margin" ]
other_values: [ "padding", "border, padding", "padding, padding, padding", "border, border" ],
invalid_values: [ "content", "margin", "border border" ]
},
"-moz-background-inline-policy": {
domProp: "MozBackgroundInlinePolicy",
@ -92,8 +97,8 @@ var gCSSProperties = {
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "padding" ],
other_values: [ "border", "content" ],
invalid_values: [ "margin" ]
other_values: [ "border", "content", "border, padding", "padding, padding, padding", "border, border" ],
invalid_values: [ "margin", "padding padding" ]
},
"-moz-binding": {
domProp: "MozBinding",
@ -608,14 +613,45 @@ var gCSSProperties = {
domProp: "background",
inherited: false,
type: CSS_TYPE_TRUE_SHORTHAND,
subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "-moz-background-clip", "-moz-background-inline-policy", "-moz-background-origin" ],
subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "-moz-background-clip", "-moz-background-origin" ],
initial_values: [ "transparent", "none", "repeat", "scroll", "0% 0%", "top left", "left top", "transparent none", "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "transparent none repeat scroll top left", "left top repeat none scroll transparent"],
other_values: [ "green", "none green repeat scroll left top", "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') transparent left top scroll", "repeat-x", "repeat-y", "no-repeat", "none repeat-y transparent scroll 0% 0%", "fixed", "0% top transparent fixed repeat none", "top", "left", "50% 50%", "center", "bottom right scroll none transparent repeat", "50% transparent", "transparent 50%", "50%" ],
other_values: [
/* without multiple backgrounds */
"green", "none green repeat scroll left top", "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') transparent left top scroll", "repeat-x", "repeat-y", "no-repeat", "none repeat-y transparent scroll 0% 0%", "fixed", "0% top transparent fixed repeat none", "top", "left", "50% 50%", "center", "bottom right scroll none transparent repeat", "50% transparent", "transparent 50%", "50%",
/* multiple backgrounds */
"url(404.png), url(404.png)",
"url(404.png), url(404.png) transparent",
"url(404.png), url(404.png) transparent red",
"repeat-x, fixed, none",
"0% top url(404.png), url(404.png) 0% top",
"fixed repeat-y top left url(404.png), repeat-x green",
/* test cases with clip+origin in the shorthand */
// This is commented out for now until we change
// -moz-background-clip to background-clip, -moz-background-origin
// to background-origin, change their value names to *-box, and add
// support for content-box on background-clip.
/*
"url(404.png) green padding-box",
"url(404.png) border-box transparent",
"content-box url(404.png) blue",
*/
],
invalid_values: [
/* mixes with keywords have to be in correct order */
"50% left", "top 50%",
/* bug 258080: don't accept background-position separated */
"left url(404.png) top", "top url(404.png) left"
"left url(404.png) top", "top url(404.png) left",
/* not allowed to have color in non-bottom layer */
"url(404.png) transparent, url(404.png)",
"url(404.png) red, url(404.png)",
"url(404.png) transparent, url(404.png) transparent",
"url(404.png) transparent red, url(404.png) transparent red",
"url(404.png) red, url(404.png) red",
"url(404.png) rgba(0, 0, 0, 0), url(404.png)",
"url(404.png) rgb(255, 0, 0), url(404.png)",
"url(404.png) rgba(0, 0, 0, 0), url(404.png) rgba(0, 0, 0, 0)",
"url(404.png) rgba(0, 0, 0, 0) rgb(255, 0, 0), url(404.png) rgba(0, 0, 0, 0) rgb(255, 0, 0)",
"url(404.png) rgb(255, 0, 0), url(404.png) rgb(255, 0, 0)",
]
},
"background-attachment": {
@ -623,15 +659,15 @@ var gCSSProperties = {
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "scroll" ],
other_values: [ "fixed" ],
other_values: [ "fixed", "scroll,scroll", "fixed, scroll", "scroll, fixed, scroll", "fixed, fixed" ],
invalid_values: []
},
"background-color": {
domProp: "backgroundColor",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "transparent", "rgba(255, 127, 15, 0)", "hsla(240, 97%, 50%, 0.0)", "rgba(0, 0, 0, 0)", "rgba(255,255,255,-3.7)" ],
other_values: [ "green", "rgb(255, 0, 128)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)" ],
initial_values: [ "transparent", "transparent transparent", "rgba(255, 127, 15, 0)", "hsla(240, 97%, 50%, 0.0)", "rgba(0, 0, 0, 0)", "rgba(255,255,255,-3.7)" ],
other_values: [ "green", "rgb(255, 0, 128)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)", "transparent green", "green transparent", "blue fuchsia", "rgb(3,4,5) hsl(240, 50%, 50%)" ],
invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "rgb(255.0,0.387,3489)" ]
},
"background-image": {
@ -639,15 +675,22 @@ var gCSSProperties = {
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==')", 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")', ],
other_values: [ "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==')", 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")',
"none, none",
"none, none, none, none, none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"none, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)"
],
invalid_values: []
},
"background-position": {
domProp: "backgroundPosition",
inherited: false,
type: CSS_TYPE_LONGHAND,
/* is "0px 0px" an initial value or not? */
initial_values: [ "top left", "left top", "0% 0%", "0% top", "left 0%" ],
other_values: [ "top", "left", "right", "bottom", "center", "center bottom", "bottom center", "center right", "right center", "center top", "top center", "center left", "left center", "right bottom", "bottom right", "50%" ],
other_values: [ "top", "left", "right", "bottom", "center", "center bottom", "bottom center", "center right", "right center", "center top", "top center", "center left", "left center", "right bottom", "bottom right", "50%", "top left, top left", "top left, top right", "top right, top left", "left top, 0% 0%", "10% 20%, 30%, 40%", "top left, bottom right", "right bottom, left top", "0%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top" ],
invalid_values: [ "50% left", "top 50%" ]
},
"background-repeat": {
@ -655,8 +698,13 @@ var gCSSProperties = {
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "repeat" ],
other_values: [ "repeat-x", "repeat-y", "no-repeat" ],
invalid_values: []
other_values: [ "repeat-x", "repeat-y", "no-repeat",
"repeat-x, repeat-x",
"repeat, no-repeat",
"repeat-y, no-repeat, repeat-y",
"repeat, repeat, repeat"
],
invalid_values: [ "repeat repeat" ]
},
"border": {
domProp: "border",

View File

@ -106,14 +106,24 @@ is(e.style.font, "", "should not have font shorthand");
e.setAttribute("style", "font: medium serif; font-stretch: condensed");
is(e.style.font, "", "should not have font shorthand");
// For background, we can only express the value as a shorthand if
// origin and clip are both their default, or if they're both the same.
// ... or at least we will once we support them in the shorthand.
e.setAttribute("style", "background: red");
isnot(e.style.background, "", "should have background shorthand");
e.setAttribute("style", "background: red; -moz-background-origin: border");
is(e.style.background, "", "should not have background shorthand");
is(e.style.background, "", "should not have background shorthand (origin:border)");
e.setAttribute("style", "background: red; -moz-background-clip: padding");
is(e.style.background, "", "should not have background shorthand");
is(e.style.background, "", "should not have background shorthand (clip:padding)");
e.setAttribute("style", "background: red; -moz-background-origin: content");
is(e.style.background, "", "should not have background shorthand (origin:content)");
// -moz-background-clip:content not yet supported
//e.setAttribute("style", "background: red; -moz-background-clip: content");
//is(e.style.background, "", "should not have background shorthand (clip:content)");
//e.setAttribute("style", "background: red; -moz-background-clip: content; -moz-background-origin: content;");
//isnot(e.style.background, "", "should have background shorthand (clip:content;origin:content)");
e.setAttribute("style", "background: red; -moz-background-inline-policy: each-box");
is(e.style.background, "", "should not have background shorthand");
isnot(e.style.background, "", "should have background shorthand (-moz-background-inline-policy not relevant)");
</script>
</pre>

View File

@ -197,7 +197,15 @@ inline PRBool
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
{
/* we only need accurate border data when positioning background images*/
return mBackground && !(mBackground->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE);
if (!mBackground) {
return PR_FALSE;
}
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, mBackground) {
if (mBackground->mLayers[i].mImage.mRequest)
return PR_TRUE;
}
return PR_FALSE;
}
nsresult

View File

@ -4114,7 +4114,9 @@ nsTreeBodyFrame::ScrollInternal(const ScrollParts& aParts, PRInt32 aRow)
// See if we have a transparent background or a background image.
// If we do, then we cannot blit.
const nsStyleBackground* background = GetStyleBackground();
if (background->mBackgroundImage || background->IsTransparent() ||
if (background->BottomLayer().mImage.mRequest ||
background->mImageCount > 1 ||
NS_GET_A(background->mBackgroundColor) < 255 ||
PR_ABS(delta)*mRowHeight >= mRect.height) {
Invalidate();
} else {
@ -4149,9 +4151,12 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, PRInt32 aPosition
PRInt32 delta = aPosition - mHorzPosition;
mHorzPosition = aPosition;
// See if we have a background image. If we do, then we cannot blit.
// See if we have a transparent background or a background image.
// If we do, then we cannot blit.
const nsStyleBackground* background = GetStyleBackground();
if (background->mBackgroundImage || background->IsTransparent() ||
if (background->BottomLayer().mImage.mRequest ||
background->mImageCount > 1 ||
NS_GET_A(background->mBackgroundColor) < 255 ||
PR_ABS(delta) >= mRect.width) {
Invalidate();
} else {

View File

@ -685,6 +685,20 @@ class nsTArray : public nsTArray_base {
RemoveElementsAt(newLen, oldLen - newLen);
}
// This method ensures that the array has length at least the given
// length. If the current length is shorter than the given length,
// then new elements will be constructed using elem_type's default
// constructor.
// @param minLen The desired minimum length of this array.
// @return True if the operation succeeded; false otherwise.
PRBool EnsureLengthAtLeast(size_type minLen) {
size_type oldLen = Length();
if (minLen > oldLen) {
return InsertElementsAt(oldLen, minLen - oldLen) != nsnull;
}
return PR_TRUE;
}
// This method inserts elements into the array, constructing
// them using elem_type's default constructor.
// @param index the place to insert the new elements. This must be no