From ee663e2930650d181be1f7792952dfc32baf0bf0 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 3 Nov 2019 17:25:37 +0100 Subject: Issue #146 - Part 3: Create nsDisplayTableBackgroundImage to avoid display list collisions when processing the background image of a table. --- layout/base/nsDisplayList.cpp | 45 ++++++++++++++++++++++++++++++++++++------- layout/base/nsDisplayList.h | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) (limited to 'layout/base') diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 6b792a779..1579e6970 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2751,9 +2751,19 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil } nsDisplayList thisItemList; - nsDisplayBackgroundImage* bgItem = - new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg); - + nsDisplayBackgroundImage* bgItem; + if (aSecondaryReferenceFrame) { + bgItem = + new (aBuilder) nsDisplayTableBackgroundImage(aBuilder, + aFrame, + i, + bgOriginRect, + bg, + aSecondaryReferenceFrame); + } else { + bgItem = + new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg); + } if (bgItem->ShouldFixToViewport(aBuilder)) { if (aSecondaryReferenceFrame) { thisItemList.AppendNewToTop( @@ -2906,7 +2916,7 @@ nsDisplayBackgroundImage::ImageLayerization nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager) { - nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(mFrame); + nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(StyleFrame()); if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder, backgroundStyleFrame)) { return WHENEVER_POSSIBLE; @@ -3161,16 +3171,16 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder, 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(), *aCtx, aBounds, mBackgroundRect, - mFrame, flags, mLayer, + StyleFrame(), flags, mLayer, CompositionOp::OP_OVER); params.bgClipRect = aClipRect; image::DrawResult result = @@ -3272,6 +3282,27 @@ nsDisplayBackgroundImage::GetPerFrameKey() nsDisplayItem::GetPerFrameKey(); } +nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + uint32_t aLayer, + const nsRect& aBackgroundRect, + const nsStyleBackground* aBackgroundStyle, + nsIFrame* aCellFrame) + : nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aBackgroundRect, aBackgroundStyle) + , mStyleFrame(aFrame) + , 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) diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 69d13ded9..e9047b113 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2814,6 +2814,8 @@ protected: 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 { @@ -2859,6 +2861,41 @@ static_assert( "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(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + uint32_t aLayer, + const nsRect& aBackgroundRect, + const nsStyleBackground* aBackgroundStyle, + nsIFrame* aCellFrame); + + virtual uint32_t GetPerFrameKey() override { + return (static_cast(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. */ -- cgit v1.2.3