Bug 929484 - Create nsDisplayTableBackgroundImage to avoid display item collision when processing background image of table. r=mattwoodrow
MozReview-Commit-ID: LR3Lta3MHt5
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -3209,32 +3209,43 @@ nsDisplayBackgroundImage::AppendBackgrou
}
}
nsDisplayBackgroundImage* bgItem = nullptr;
{
// The clip is captured by the nsDisplayFixedPosition, so clear the
// clip for the nsDisplayBackgroundImage inside.
DisplayListClipState::AutoSaveRestore bgImageClip(aBuilder);
bgImageClip.Clear();
- bgItem = new (aBuilder) nsDisplayBackgroundImage(bgData);
+ if (aSecondaryReferenceFrame) {
+ bgItem = new (aBuilder) nsDisplayTableBackgroundImage(bgData,
+ aSecondaryReferenceFrame);
+ } else {
+ bgItem = new (aBuilder) nsDisplayBackgroundImage(bgData);
+ }
}
if (aSecondaryReferenceFrame) {
thisItemList.AppendNewToTop(
nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder,
aSecondaryReferenceFrame,
bgItem,
i,
aFrame));
} else {
thisItemList.AppendNewToTop(
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
}
} else {
- thisItemList.AppendNewToTop(new (aBuilder) nsDisplayBackgroundImage(bgData));
+ if (aSecondaryReferenceFrame) {
+ thisItemList.AppendNewToTop(
+ new (aBuilder) nsDisplayTableBackgroundImage(bgData,
+ aSecondaryReferenceFrame));
+ } else {
+ thisItemList.AppendNewToTop(new (aBuilder) nsDisplayBackgroundImage(bgData));
+ }
}
if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
DisplayListClipState::AutoSaveRestore blendClip(aBuilder);
blendClip.ClearUpToASR(asr);
// asr is scrolled. Even if we wrap a fixed background layer, that's
// fine, because the item will have a scrolled clip that limits the
// item with respect to asr.
@@ -3330,17 +3341,17 @@ nsDisplayBackgroundImage::GetImage()
nsDisplayBackgroundImage::ImageLayerization
nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager)
{
if (ForceActiveLayers()) {
return WHENEVER_POSSIBLE;
}
- nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(mFrame);
+ nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(StyleFrame());
if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder,
backgroundStyleFrame)) {
return WHENEVER_POSSIBLE;
}
if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
const nsStyleImage* image = &layer.mImage;
@@ -3439,31 +3450,31 @@ nsDisplayBackgroundImage::BuildLayer(nsD
ConfigureLayer(layer, aParameters);
return layer.forget();
}
bool
nsDisplayBackgroundImage::CanBuildWebRenderDisplayItems()
{
return mBackgroundStyle->mImage.mLayers[mLayer].mClip != StyleGeometryBox::Text &&
- nsCSSRendering::CanBuildWebRenderDisplayItemsForStyleImageLayer(*mFrame->PresContext(),
- mFrame,
+ nsCSSRendering::CanBuildWebRenderDisplayItemsForStyleImageLayer(*StyleFrame()->PresContext(),
+ StyleFrame(),
mBackgroundStyle,
mLayer);
}
void
nsDisplayBackgroundImage::CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
nsTArray<WebRenderParentCommand>& aParentCommands,
WebRenderDisplayItemLayer* aLayer)
{
nsCSSRendering::PaintBGParams params =
- nsCSSRendering::PaintBGParams::ForSingleLayer(*mFrame->PresContext(),
+ nsCSSRendering::PaintBGParams::ForSingleLayer(*StyleFrame()->PresContext(),
mVisibleRect, mBackgroundRect,
- mFrame, 0, mLayer,
+ StyleFrame(), 0, mLayer,
CompositionOp::OP_OVER);
params.bgClipRect = &mBounds;
image::DrawResult result =
nsCSSRendering::BuildWebRenderDisplayItemsForStyleImageLayer(params, aBuilder, aParentCommands, aLayer);
nsDisplayBackgroundGeometry::UpdateDrawResult(this, result);
}
@@ -3622,25 +3633,25 @@ nsDisplayBackgroundImage::PaintInternal(
nsRect* aClipRect) {
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
CheckForBorderItem(this, flags);
gfxContext* ctx = aCtx->ThebesContext();
StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
if (clip == StyleGeometryBox::Text) {
- if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
+ if (!GenerateAndPushTextMask(StyleFrame(), aCtx, mBackgroundRect, aBuilder)) {
return;
}
}
nsCSSRendering::PaintBGParams params =
- nsCSSRendering::PaintBGParams::ForSingleLayer(*mFrame->PresContext(),
+ nsCSSRendering::PaintBGParams::ForSingleLayer(*StyleFrame()->PresContext(),
aBounds, mBackgroundRect,
- mFrame, flags, mLayer,
+ StyleFrame(), flags, mLayer,
CompositionOp::OP_OVER);
params.bgClipRect = aClipRect;
image::DrawResult result =
nsCSSRendering::PaintStyleImageLayer(params, *aCtx);
if (clip == StyleGeometryBox::Text) {
ctx->PopGroupAndBlend();
}
@@ -3725,16 +3736,33 @@ nsDisplayBackgroundImage::GetBoundsInter
uint32_t
nsDisplayBackgroundImage::GetPerFrameKey()
{
return (mLayer << nsDisplayItem::TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
}
+nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(const InitData& aData,
+ nsIFrame* aCellFrame)
+ : nsDisplayBackgroundImage(aData)
+ , mStyleFrame(aData.frame)
+ , mTableType(GetTableTypeFromFrame(mStyleFrame))
+{
+ mFrame = aCellFrame;
+}
+
+bool
+nsDisplayTableBackgroundImage::IsInvalid(nsRect& aRect)
+{
+ bool result = mStyleFrame ? mStyleFrame->IsInvalid(aRect) : false;
+ aRect += ToReferenceFrame();
+ return result;
+}
+
nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsRect& aBackgroundRect)
: nsDisplayItem(aBuilder, aFrame)
, mBackgroundRect(aBackgroundRect)
{
MOZ_COUNT_CTOR(nsDisplayThemedBackground);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -3145,16 +3145,18 @@ protected:
bool CanBuildWebRenderDisplayItems();
bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
+ virtual nsIFrame* StyleFrame() { return mFrame; }
+
// Determine whether we want to be separated into our own layer, independent
// of whether this item can actually be layerized.
enum ImageLayerization {
WHENEVER_POSSIBLE,
ONLY_FOR_SCALING,
NO_LAYER_NEEDED
};
ImageLayerization ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
@@ -3191,16 +3193,46 @@ enum class TableTypeBits : uint8_t {
};
static_assert(
static_cast<uint8_t>(TableType::TABLE_TYPE_MAX) < (1 << (static_cast<uint8_t>(TableTypeBits::COUNT) + 1)),
"TableType cannot fit with TableTypeBits::COUNT");
TableType GetTableTypeFromFrame(nsIFrame* aFrame);
/**
+ * A display item to paint background image for table. For table parts, such
+ * as row, row group, col, col group, when drawing its background, we'll
+ * create separate background image display item for its containning cell.
+ * Those background image display items will reference to same DisplayItemData
+ * if we keep the mFrame point to cell's ancestor frame. We don't want to this
+ * happened bacause share same DisplatItemData will cause many bugs. So that
+ * we let mFrame point to cell frame and store the table type of the ancestor
+ * frame. And use mFrame and table type as key to generate DisplayItemData to
+ * avoid sharing DisplayItemData.
+ *
+ * Also store ancestor frame as mStyleFrame for all rendering informations.
+ */
+class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
+public:
+ nsDisplayTableBackgroundImage(const InitData& aInitData, nsIFrame* aCellFrame);
+
+ virtual uint32_t GetPerFrameKey() override {
+ return (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
+ nsDisplayItem::GetPerFrameKey();
+ }
+
+ virtual bool IsInvalid(nsRect& aRect) override;
+protected:
+ virtual nsIFrame* StyleFrame() override { return mStyleFrame; }
+
+ nsIFrame* mStyleFrame;
+ TableType mTableType;
+};
+
+/**
* A display item to paint the native theme background for a frame.
*/
class nsDisplayThemedBackground : public nsDisplayItem {
public:
nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect);
virtual ~nsDisplayThemedBackground();