Bug 786502 - Separate background layers into separate items. r=roc

Separate out background layers into separate display-list items, so that
backgrounds that are a mix of fixed and non-fixed layers will be treated
individually.
This commit is contained in:
Chris Lord 2012-09-13 11:34:23 +01:00
parent 959da9d526
commit bb16d413e7
10 changed files with 154 additions and 54 deletions

View File

@ -1482,7 +1482,8 @@ nsCSSRendering::PaintBackground(nsPresContext* aPresContext,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsRect& aBorderArea, const nsRect& aBorderArea,
uint32_t aFlags, uint32_t aFlags,
nsRect* aBGClipRect) nsRect* aBGClipRect,
int32_t aLayer)
{ {
SAMPLE_LABEL("nsCSSRendering", "PaintBackground"); SAMPLE_LABEL("nsCSSRendering", "PaintBackground");
NS_PRECONDITION(aForFrame, NS_PRECONDITION(aForFrame,
@ -1510,7 +1511,7 @@ nsCSSRendering::PaintBackground(nsPresContext* aPresContext,
PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame, PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, sc, aDirtyRect, aBorderArea, sc,
*aForFrame->GetStyleBorder(), aFlags, *aForFrame->GetStyleBorder(), aFlags,
aBGClipRect); aBGClipRect, aLayer);
} }
static bool static bool
@ -2328,7 +2329,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nsStyleContext* aBackgroundSC, nsStyleContext* aBackgroundSC,
const nsStyleBorder& aBorder, const nsStyleBorder& aBorder,
uint32_t aFlags, uint32_t aFlags,
nsRect* aBGClipRect) nsRect* aBGClipRect,
int32_t aLayer)
{ {
NS_PRECONDITION(aForFrame, NS_PRECONDITION(aForFrame,
"Frame is expected to be provided to PaintBackground"); "Frame is expected to be provided to PaintBackground");
@ -2372,6 +2374,13 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
drawBackgroundImage, drawBackgroundImage,
drawBackgroundColor); drawBackgroundColor);
// If we're not drawing the back-most layer, we don't want to draw the
// background color.
const nsStyleBackground *bg = aBackgroundSC->GetStyleBackground();
if (drawBackgroundColor && aLayer >= 0 && aLayer != bg->mImageCount - 1) {
drawBackgroundColor = false;
}
// At this point, drawBackgroundImage and drawBackgroundColor are // At this point, drawBackgroundImage and drawBackgroundColor are
// true if and only if we are actually supposed to paint an image or // true if and only if we are actually supposed to paint an image or
// color into aDirtyRect, respectively. // color into aDirtyRect, respectively.
@ -2406,7 +2415,6 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// SetupCurrentBackgroundClip. (Arguably it should be the // SetupCurrentBackgroundClip. (Arguably it should be the
// intersection, but that breaks the table painter -- in particular, // intersection, but that breaks the table painter -- in particular,
// taking the intersection breaks reftests/bugs/403249-1[ab].) // taking the intersection breaks reftests/bugs/403249-1[ab].)
const nsStyleBackground *bg = aBackgroundSC->GetStyleBackground();
BackgroundClipState clipState; BackgroundClipState clipState;
uint8_t currentBackgroundClip; uint8_t currentBackgroundClip;
bool isSolidBorder; bool isSolidBorder;
@ -2456,13 +2464,27 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
return; return;
} }
if (bg->mImageCount < 1) {
// Return if there are no background layers, all work from this point
// onwards happens iteratively on these.
return;
}
// Validate the layer range before we start iterating.
int32_t startLayer = aLayer;
int32_t nLayers = 1;
if (startLayer < 0) {
startLayer = (int32_t)bg->mImageCount - 1;
nLayers = bg->mImageCount;
}
// Ensure we get invalidated for loads of the image. We need to do // Ensure we get invalidated for loads of the image. We need to do
// this here because this might be the only code that knows about the // this here because this might be the only code that knows about the
// association of the style data with the frame. // association of the style data with the frame.
if (aBackgroundSC != aForFrame->GetStyleContext()) { if (aBackgroundSC != aForFrame->GetStyleContext()) {
ImageLoader* loader = aPresContext->Document()->StyleImageLoader(); ImageLoader* loader = aPresContext->Document()->StyleImageLoader();
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) { NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, bg, startLayer, nLayers) {
if (bg->mLayers[i].mImage.GetType() == eStyleImageType_Image) { if (bg->mLayers[i].mImage.GetType() == eStyleImageType_Image) {
imgIRequest *image = bg->mLayers[i].mImage.GetImageData(); imgIRequest *image = bg->mLayers[i].mImage.GetImageData();
@ -2479,7 +2501,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
if (drawBackgroundImage) { if (drawBackgroundImage) {
bool clipSet = false; bool clipSet = false;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) { NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, bg, startLayer, nLayers) {
const nsStyleBackground::Layer &layer = bg->mLayers[i]; const nsStyleBackground::Layer &layer = bg->mLayers[i];
if (!aBGClipRect) { if (!aBGClipRect) {
uint8_t newBackgroundClip = layer.mClip; uint8_t newBackgroundClip = layer.mClip;

View File

@ -335,12 +335,17 @@ struct nsCSSRendering {
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsRect& aBorderArea, const nsRect& aBorderArea,
uint32_t aFlags, uint32_t aFlags,
nsRect* aBGClipRect = nullptr); nsRect* aBGClipRect = nullptr,
int32_t aLayer = -1);
/** /**
* Same as |PaintBackground|, except using the provided style structs. * Same as |PaintBackground|, except using the provided style structs.
* This short-circuits the code that ensures that the root element's * This short-circuits the code that ensures that the root element's
* background is drawn on the canvas. * background is drawn on the canvas.
* The aLayer parameter allows you to paint a single layer of the background.
* The default value for aLayer, -1, means that all layers will be painted.
* The background color will only be painted if the back-most layer is also
* being painted.
*/ */
static void PaintBackgroundWithSC(nsPresContext* aPresContext, static void PaintBackgroundWithSC(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext, nsRenderingContext& aRenderingContext,
@ -350,7 +355,8 @@ struct nsCSSRendering {
nsStyleContext *aStyleContext, nsStyleContext *aStyleContext,
const nsStyleBorder& aBorder, const nsStyleBorder& aBorder,
uint32_t aFlags, uint32_t aFlags,
nsRect* aBGClipRect = nullptr); nsRect* aBGClipRect = nullptr,
int32_t aLayer = -1);
/** /**
* Returns the rectangle covered by the given background layer image, taking * Returns the rectangle covered by the given background layer image, taking

View File

@ -1362,8 +1362,11 @@ RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
} }
nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame) nsIFrame* aFrame,
uint32_t aLayer)
: nsDisplayItem(aBuilder, aFrame) : nsDisplayItem(aBuilder, aFrame)
, mIsBottommostLayer(true)
, mLayer(aLayer)
{ {
MOZ_COUNT_CTOR(nsDisplayBackground); MOZ_COUNT_CTOR(nsDisplayBackground);
const nsStyleDisplay* disp = mFrame->GetStyleDisplay(); const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
@ -1383,8 +1386,17 @@ nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
nsPresContext* presContext = mFrame->PresContext(); nsPresContext* presContext = mFrame->PresContext();
nsStyleContext* bgSC; nsStyleContext* bgSC;
bool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC); bool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
if (hasBG && bgSC->GetStyleBackground()->HasFixedBackground()) { if (hasBG) {
aBuilder->SetHasFixedItems(); const nsStyleBackground* bg = bgSC->GetStyleBackground();
if (mLayer != bg->mImageCount - 1) {
mIsBottommostLayer = false;
}
// Check if this background layer is attachment-fixed
if (!bg->mLayers[mLayer].mImage.IsEmpty() &&
bg->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED) {
aBuilder->SetHasFixedItems();
}
} }
} }
} }
@ -1396,6 +1408,39 @@ nsDisplayBackground::~nsDisplayBackground()
#endif #endif
} }
/*static*/ nsresult
nsDisplayBackground::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsDisplayList* aList,
nsDisplayBackground** aBackground)
{
nsStyleContext* bgSC;
const nsStyleBackground* bg = nullptr;
nsPresContext* presContext = aFrame->PresContext();
if (!aFrame->IsThemed() &&
nsCSSRendering::FindBackground(presContext, aFrame, &bgSC)) {
bg = bgSC->GetStyleBackground();
}
// Passing bg == nullptr in this macro will result in one iteration with
// i = 0.
bool backgroundSet = !aBackground;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
nsDisplayBackground* bgItem =
new (aBuilder) nsDisplayBackground(aBuilder, aFrame, i);
nsresult rv = aList->AppendNewToTop(bgItem);
if (rv != NS_OK) {
return rv;
}
if (!backgroundSet) {
*aBackground = bgItem;
backgroundSet = true;
}
}
return NS_OK;
}
// Helper for RoundedRectIntersectsRect. // Helper for RoundedRectIntersectsRect.
static bool static bool
CheckCorner(nscoord aXOffset, nscoord aYOffset, CheckCorner(nscoord aXOffset, nscoord aYOffset,
@ -1574,16 +1619,11 @@ nsDisplayBackground::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
const nsStyleBackground *bg = bgSC->GetStyleBackground(); const nsStyleBackground *bg = bgSC->GetStyleBackground();
// We could pretty easily support multiple image layers, but for now we
// just punt here.
if (bg->mLayers.Length() != 1)
return false;
uint32_t flags = aBuilder->GetBackgroundPaintFlags(); uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsPoint offset = ToReferenceFrame(); nsPoint offset = ToReferenceFrame();
nsRect borderArea = nsRect(offset, mFrame->GetSize()); nsRect borderArea = nsRect(offset, mFrame->GetSize());
const nsStyleBackground::Layer &layer = bg->mLayers[0]; const nsStyleBackground::Layer &layer = bg->mLayers[mLayer];
nsBackgroundLayerState state = nsBackgroundLayerState state =
nsCSSRendering::PrepareBackgroundLayer(presContext, nsCSSRendering::PrepareBackgroundLayer(presContext,
@ -1784,7 +1824,7 @@ nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
*aSnap = true; *aSnap = true;
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize()); nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
if (NS_GET_A(bg->mBackgroundColor) == 255 && if (mIsBottommostLayer && NS_GET_A(bg->mBackgroundColor) == 255 &&
!nsCSSRendering::IsCanvasFrame(mFrame)) { !nsCSSRendering::IsCanvasFrame(mFrame)) {
result = GetInsideClipRegion(presContext, bottomLayer.mClip, borderBox, aSnap); result = GetInsideClipRegion(presContext, bottomLayer.mClip, borderBox, aSnap);
} }
@ -1796,13 +1836,11 @@ nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
// Of course, if there's only one frame in the flow, it doesn't matter. // Of course, if there's only one frame in the flow, it doesn't matter.
if (bg->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX || if (bg->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX ||
(!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) { (!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) { const nsStyleBackground::Layer& layer = bg->mLayers[mLayer];
const nsStyleBackground::Layer& layer = bg->mLayers[i]; if (layer.mImage.IsOpaque()) {
if (layer.mImage.IsOpaque()) { nsRect r = nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
nsRect r = nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame, borderBox, *bg, layer);
borderBox, *bg, layer); result.Or(result, GetInsideClipRegion(presContext, layer.mClip, r, aSnap));
result.Or(result, GetInsideClipRegion(presContext, layer.mClip, r, aSnap));
}
} }
} }
@ -1887,15 +1925,13 @@ nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
if (!bg->HasFixedBackground()) if (!bg->HasFixedBackground())
return false; return false;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) { const nsStyleBackground::Layer& layer = bg->mLayers[mLayer];
const nsStyleBackground::Layer& layer = bg->mLayers[i]; if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED &&
if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED && !layer.mImage.IsEmpty()) {
!layer.mImage.IsEmpty()) { return false;
return false;
}
if (layer.mClip != NS_STYLE_BG_CLIP_BORDER)
return false;
} }
if (layer.mClip != NS_STYLE_BG_CLIP_BORDER)
return false;
if (nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius)) if (nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius))
return false; return false;
@ -1925,7 +1961,7 @@ nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame, nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
mVisibleRect, mVisibleRect,
nsRect(offset, mFrame->GetSize()), nsRect(offset, mFrame->GetSize()),
flags); flags, nullptr, mLayer);
} }
nsRect nsRect
@ -1943,6 +1979,13 @@ nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
return r + ToReferenceFrame(); return r + ToReferenceFrame();
} }
uint32_t
nsDisplayBackground::GetPerFrameKey()
{
return (mLayer << nsDisplayItem::TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
}
nsRect nsRect
nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false; *aSnap = false;

View File

@ -1604,9 +1604,19 @@ private:
*/ */
class nsDisplayBackground : public nsDisplayItem { class nsDisplayBackground : public nsDisplayItem {
public: public:
nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame); // aLayer signifies which background layer this item represents
nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
uint32_t aLayer);
virtual ~nsDisplayBackground(); virtual ~nsDisplayBackground();
// This will create and append new items for all the layers of the
// background. If given, aBackground will be set with the address of the
// bottom-most background item.
static nsresult AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsDisplayList* aList,
nsDisplayBackground** aBackground = nullptr);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager, LayerManager* aManager,
const ContainerParameters& aParameters); const ContainerParameters& aParameters);
@ -1628,6 +1638,7 @@ public:
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder); virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx); virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual uint32_t GetPerFrameKey();
NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND) NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
// Returns the value of GetUnderlyingFrame()->IsThemed(), but cached // Returns the value of GetUnderlyingFrame()->IsThemed(), but cached
bool IsThemed() { return mIsThemed; } bool IsThemed() { return mIsThemed; }
@ -1645,11 +1656,14 @@ protected:
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */ /* Used to cache mFrame->IsThemed() since it isn't a cheap call */
bool mIsThemed; bool mIsThemed;
/* true if this item represents the bottom-most background layer */
bool mIsBottommostLayer;
nsITheme::Transparency mThemeTransparency; nsITheme::Transparency mThemeTransparency;
/* If this background can be a simple image layer, we store the format here. */ /* If this background can be a simple image layer, we store the format here. */
nsRefPtr<ImageContainer> mImageContainer; nsRefPtr<ImageContainer> mImageContainer;
gfxRect mDestRect; gfxRect mDestRect;
uint32_t mLayer;
}; };
/** /**

View File

@ -202,7 +202,7 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame); nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
nsPoint offset = ToReferenceFrame(); nsPoint offset = ToReferenceFrame();
nsRect bgClipRect = frame->CanvasArea() + offset; nsRect bgClipRect = frame->CanvasArea() + offset;
if (NS_GET_A(mExtraBackgroundColor) > 0) { if (mIsBottommostLayer && NS_GET_A(mExtraBackgroundColor) > 0) {
aCtx->SetColor(mExtraBackgroundColor); aCtx->SetColor(mExtraBackgroundColor);
aCtx->FillRect(bgClipRect); aCtx->FillRect(bgClipRect);
} }
@ -234,7 +234,7 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
surf ? bounds : mVisibleRect, surf ? bounds : mVisibleRect,
nsRect(offset, mFrame->GetSize()), nsRect(offset, mFrame->GetSize()),
aBuilder->GetBackgroundPaintFlags(), aBuilder->GetBackgroundPaintFlags(),
&bgClipRect); &bgClipRect, mLayer);
if (surf) { if (surf) {
BlitSurface(dest, mDestRect, surf); BlitSurface(dest, mDestRect, surf);
@ -295,10 +295,19 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// We don't have any border or outline, and our background draws over // We don't have any border or outline, and our background draws over
// the overflow area, so just add nsDisplayCanvasBackground instead of // the overflow area, so just add nsDisplayCanvasBackground instead of
// calling DisplayBorderBackgroundOutline. // calling DisplayBorderBackgroundOutline.
if (IsVisibleForPainting(aBuilder)) { if (IsVisibleForPainting(aBuilder)) {
rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder) nsStyleContext* bgSC;
nsDisplayCanvasBackground(aBuilder, this)); const nsStyleBackground* bg = nullptr;
NS_ENSURE_SUCCESS(rv, rv); if (!IsThemed() &&
nsCSSRendering::FindBackground(PresContext(), this, &bgSC)) {
bg = bgSC->GetStyleBackground();
}
// Create separate items for each background layer.
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
rv = aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayCanvasBackground(aBuilder, this, i));
NS_ENSURE_SUCCESS(rv, rv);
}
} }
nsIFrame* kid; nsIFrame* kid;

View File

@ -123,8 +123,8 @@ protected:
*/ */
class nsDisplayCanvasBackground : public nsDisplayBackground { class nsDisplayCanvasBackground : public nsDisplayBackground {
public: public:
nsDisplayCanvasBackground(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame) nsDisplayCanvasBackground(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, uint32_t aLayer)
: nsDisplayBackground(aBuilder, aFrame) : nsDisplayBackground(aBuilder, aFrame, aLayer)
{ {
mExtraBackgroundColor = NS_RGBA(0,0,0,0); mExtraBackgroundColor = NS_RGBA(0,0,0,0);
} }

View File

@ -1457,16 +1457,18 @@ nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
bool aForceBackground, bool aForceBackground,
nsDisplayBackground** aBackground) nsDisplayBackground** aBackground)
{ {
*aBackground = nullptr;
// Here we don't try to detect background propagation. Frames that might // Here we don't try to detect background propagation. Frames that might
// receive a propagated background should just set aForceBackground to // receive a propagated background should just set aForceBackground to
// true. // true.
if (aBuilder->IsForEventDelivery() || aForceBackground || if (aBuilder->IsForEventDelivery() || aForceBackground ||
!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) { !GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) {
nsDisplayBackground* bg = new (aBuilder) nsDisplayBackground(aBuilder, this); return nsDisplayBackground::AppendBackgroundItemsToTop(aBuilder, this,
*aBackground = bg; aLists.BorderBackground(),
return aLists.BorderBackground()->AppendNewToTop(bg); aBackground);
} }
*aBackground = nullptr;
return NS_OK; return NS_OK;
} }

View File

@ -498,14 +498,14 @@ public:
static void ShutdownLayerActivityTimer(); static void ShutdownLayerActivityTimer();
/** /**
* Adds display item for standard CSS background if necessary. * Adds display items for standard CSS background if necessary.
* Does not check IsVisibleForPainting. * Does not check IsVisibleForPainting.
* @param aForceBackground draw the background even if the frame * @param aForceBackground draw the background even if the frame
* background style appears to have no background --- this is useful * background style appears to have no background --- this is useful
* for frames that might receive a propagated background via * for frames that might receive a propagated background via
* nsCSSRendering::FindBackground * nsCSSRendering::FindBackground
* @param aBackground *aBackground is set to the new nsDisplayBackground item, * @param aBackground *aBackground is set to the bottom-most
* if one is created, otherwise null. * nsDisplayBackground item, if any are created, otherwise null.
*/ */
nsresult DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder, nsresult DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists, const nsDisplayListSet& aLists,

View File

@ -487,7 +487,11 @@ struct nsStyleBackground {
const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; } const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
#define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(var_, stylebg_) \ #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(var_, stylebg_) \
for (uint32_t var_ = (stylebg_)->mImageCount; var_-- != 0; ) for (uint32_t var_ = (stylebg_) ? (stylebg_)->mImageCount : 1; var_-- != 0; )
#define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, stylebg_, start_, count_) \
NS_ASSERTION((start_) >= 0 && (uint32_t)(start_) < ((stylebg_) ? (stylebg_)->mImageCount : 1), "Invalid layer start!"); \
NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
nscolor mBackgroundColor; // [reset] nscolor mBackgroundColor; // [reset]

View File

@ -1164,8 +1164,8 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
// handling events. // handling events.
// XXX how to handle collapsed borders? // XXX how to handle collapsed borders?
if (aBuilder->IsForEventDelivery()) { if (aBuilder->IsForEventDelivery()) {
nsresult rv = lists->BorderBackground()->AppendNewToTop( nsresult rv = nsDisplayBackground::AppendBackgroundItemsToTop(aBuilder, aFrame,
new (aBuilder) nsDisplayBackground(aBuilder, aFrame)); lists->BorderBackground());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }