Issue #146 - Part 3: Create nsDisplayTableFixedPosition to avoid display

list collisions when processing the background image of a table.
This commit is contained in:
wolfbeast 2019-11-03 15:12:34 +01:00 • committed by Roy Tam
commit c8aaad0428
3 changed files with 108 additions and 8 deletions

View file

@ -80,6 +80,8 @@
#include "nsPluginFrame.h" #include "nsPluginFrame.h"
#include "DisplayItemScrollClip.h" #include "DisplayItemScrollClip.h"
#include "nsSVGMaskFrame.h" #include "nsSVGMaskFrame.h"
#include "nsTableCellFrame.h"
#include "nsTableColFrame.h"
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
// GetTickCount(). // GetTickCount().
@ -2632,7 +2634,8 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
nsDisplayList* aList, nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization, bool aAllowWillPaintBorderOptimization,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
const nsRect& aBackgroundOriginRect) const nsRect& aBackgroundOriginRect,
nsIFrame* aSecondaryReferenceFrame)
{ {
nsStyleContext* bgSC = aStyleContext; nsStyleContext* bgSC = aStyleContext;
const nsStyleBackground* bg = nullptr; const nsStyleBackground* bg = nullptr;
@ -2752,8 +2755,17 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg); new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg);
if (bgItem->ShouldFixToViewport(aBuilder)) { if (bgItem->ShouldFixToViewport(aBuilder)) {
thisItemList.AppendNewToTop( if (aSecondaryReferenceFrame) {
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i)); thisItemList.AppendNewToTop(
nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder,
aSecondaryReferenceFrame,
bgItem,
i,
aFrame));
} else {
thisItemList.AppendNewToTop(
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
}
} else { } else {
thisItemList.AppendNewToTop(bgItem); thisItemList.AppendNewToTop(bgItem);
} }
@ -5277,6 +5289,51 @@ bool nsDisplayFixedPosition::TryMerge(nsDisplayItem* aItem) {
return true; 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, nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsIFrame* aFrame,
nsDisplayList* aList) nsDisplayList* aList)

View file

@ -2738,7 +2738,8 @@ public:
nsDisplayList* aList, nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization = true, bool aAllowWillPaintBorderOptimization = true,
nsStyleContext* aStyleContext = nullptr, nsStyleContext* aStyleContext = nullptr,
const nsRect& aBackgroundOriginRect = nsRect()); const nsRect& aBackgroundOriginRect = nsRect(),
nsIFrame* aSecondaryReferenceFrame = nullptr);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager, LayerManager* aManager,
@ -2838,6 +2839,25 @@ protected:
bool mShouldTreatAsFixed; 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<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 the native theme background for a frame. * A display item to paint the native theme background for a frame.
@ -3736,7 +3756,7 @@ public:
return mAnimatedGeometryRootForScrollMetadata; return mAnimatedGeometryRootForScrollMetadata;
} }
private: protected:
// For background-attachment:fixed // For background-attachment:fixed
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint32_t aIndex); nsDisplayList* aList, uint32_t aIndex);
@ -3747,6 +3767,27 @@ private:
bool mIsFixedBackground; 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<uint8_t>(TableTypeBits::COUNT))) |
(static_cast<uint8_t>(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. * 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 * It is used to record the existence of a scrollable frame in the layer

View file

@ -1194,13 +1194,14 @@ PaintRowBackground(nsTableRowFrame* aRow,
const nsDisplayListSet& aLists, const nsDisplayListSet& aLists,
const nsPoint& aOffset = nsPoint()) const nsPoint& aOffset = nsPoint())
{ {
// Compute background rect by iterating all cell frame. // Compute background rect by iterating over all cell frames.
for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) { for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset; auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect, nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
aLists.BorderBackground(), aLists.BorderBackground(),
true, nullptr, true, nullptr,
aFrame->GetRectRelativeToSelf()); aFrame->GetRectRelativeToSelf(),
cell);
} }
} }
@ -1232,7 +1233,8 @@ PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect, nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
aLists.BorderBackground(), aLists.BorderBackground(),
true, nullptr, true, nullptr,
aFrame->GetRectRelativeToSelf()); aFrame->GetRectRelativeToSelf(),
cell);
} }
} }
} }