From db98e3efff6087b690805358e6f4fda118ec9627 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 3 Nov 2019 15:12:34 +0100 Subject: Issue #146 - Part 3: Create nsDisplayTableFixedPosition to avoid display list collisions when processing the background image of a table. --- layout/base/nsDisplayList.cpp | 63 ++++++++++++++++++++++++++++++++++++++++--- layout/base/nsDisplayList.h | 45 +++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 5 deletions(-) (limited to 'layout/base') diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 744153831..6b792a779 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -80,6 +80,8 @@ #include "nsPluginFrame.h" #include "DisplayItemScrollClip.h" #include "nsSVGMaskFrame.h" +#include "nsTableCellFrame.h" +#include "nsTableColFrame.h" // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to // GetTickCount(). @@ -2632,7 +2634,8 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil nsDisplayList* aList, bool aAllowWillPaintBorderOptimization, nsStyleContext* aStyleContext, - const nsRect& aBackgroundOriginRect) + const nsRect& aBackgroundOriginRect, + nsIFrame* aSecondaryReferenceFrame) { nsStyleContext* bgSC = aStyleContext; const nsStyleBackground* bg = nullptr; @@ -2752,8 +2755,17 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg); if (bgItem->ShouldFixToViewport(aBuilder)) { - thisItemList.AppendNewToTop( - nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i)); + if (aSecondaryReferenceFrame) { + thisItemList.AppendNewToTop( + nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder, + aSecondaryReferenceFrame, + bgItem, + i, + aFrame)); + } else { + thisItemList.AppendNewToTop( + nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i)); + } } else { thisItemList.AppendNewToTop(bgItem); } @@ -5277,6 +5289,51 @@ bool nsDisplayFixedPosition::TryMerge(nsDisplayItem* aItem) { return true; } +TableType +GetTableTypeFromFrame(nsIFrame* aFrame) +{ + nsIAtom* type = aFrame->GetType(); + if (type == nsGkAtoms::tableFrame) { + return TableType::TABLE; + } else if (type == nsGkAtoms::tableColFrame) { + return TableType::TABLE_COL; + } else if (type == nsGkAtoms::tableColGroupFrame) { + return TableType::TABLE_COL_GROUP; + } else if (type == nsGkAtoms::tableRowFrame) { + return TableType::TABLE_ROW; + } else if (type == nsGkAtoms::tableRowGroupFrame) { + return TableType::TABLE_ROW_GROUP; + } else if (type == nsGkAtoms::tableCellFrame) { + return TableType::TABLE_CELL; + } else { + MOZ_ASSERT_UNREACHABLE("Invalid frame."); + return TableType::TABLE; + } +} + +nsDisplayTableFixedPosition::nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + nsDisplayList* aList, + uint32_t aIndex, + nsIFrame* aAncestorFrame) + : nsDisplayFixedPosition(aBuilder, aFrame, aList, aIndex) + , mTableType(GetTableTypeFromFrame(aAncestorFrame)) +{ +} + +/* static */ nsDisplayTableFixedPosition* +nsDisplayTableFixedPosition::CreateForFixedBackground(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + nsDisplayBackgroundImage* aImage, + uint32_t aIndex, + nsIFrame* aAncestorFrame) +{ + nsDisplayList temp; + temp.AppendToTop(aImage); + + return new (aBuilder) nsDisplayTableFixedPosition(aBuilder, aFrame, &temp, aIndex + 1, aAncestorFrame); +} + nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList) diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 9431e2cc0..69d13ded9 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2738,7 +2738,8 @@ public: nsDisplayList* aList, bool aAllowWillPaintBorderOptimization = true, nsStyleContext* aStyleContext = nullptr, - const nsRect& aBackgroundOriginRect = nsRect()); + const nsRect& aBackgroundOriginRect = nsRect(), + nsIFrame* aSecondaryReferenceFrame = nullptr); virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -2838,6 +2839,25 @@ protected: bool mShouldTreatAsFixed; }; +enum class TableType : uint8_t { + TABLE, + TABLE_COL, + TABLE_COL_GROUP, + TABLE_ROW, + TABLE_ROW_GROUP, + TABLE_CELL, + + TABLE_TYPE_MAX +}; + +enum class TableTypeBits : uint8_t { + COUNT = 3 +}; + +static_assert( + static_cast(TableType::TABLE_TYPE_MAX) < (1 << (static_cast(TableTypeBits::COUNT) + 1)), + "TableType cannot fit with TableTypeBits::COUNT"); +TableType GetTableTypeFromFrame(nsIFrame* aFrame); /** * A display item to paint the native theme background for a frame. @@ -3736,7 +3756,7 @@ public: return mAnimatedGeometryRootForScrollMetadata; } -private: +protected: // For background-attachment:fixed nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList, uint32_t aIndex); @@ -3747,6 +3767,27 @@ private: bool mIsFixedBackground; }; +class nsDisplayTableFixedPosition : public nsDisplayFixedPosition +{ +public: + static nsDisplayTableFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + nsDisplayBackgroundImage* aImage, + uint32_t aIndex, + nsIFrame* aAncestorFrame); + + virtual uint32_t GetPerFrameKey() override { + return (mIndex << (nsDisplayItem::TYPE_BITS + static_cast(TableTypeBits::COUNT))) | + (static_cast(mTableType) << nsDisplayItem::TYPE_BITS) | + nsDisplayItem::GetPerFrameKey(); + } +protected: + nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList, uint32_t aIndex, nsIFrame* aAncestorFrame); + + TableType mTableType; +}; + /** * This creates an empty scrollable layer. It has no child layers. * It is used to record the existence of a scrollable frame in the layer -- cgit v1.2.3