summaryrefslogtreecommitdiffstats
path: root/layout/tables
diff options
context:
space:
mode:
Diffstat (limited to 'layout/tables')
-rw-r--r--layout/tables/nsTableCellFrame.cpp54
-rw-r--r--layout/tables/nsTableCellFrame.h1
-rw-r--r--layout/tables/nsTableColFrame.cpp9
-rw-r--r--layout/tables/nsTableColFrame.h1
-rw-r--r--layout/tables/nsTableColGroupFrame.cpp9
-rw-r--r--layout/tables/nsTableColGroupFrame.h1
-rw-r--r--layout/tables/nsTableFrame.cpp293
-rw-r--r--layout/tables/nsTableFrame.h130
-rw-r--r--layout/tables/nsTableRowFrame.cpp58
-rw-r--r--layout/tables/nsTableRowFrame.h6
-rw-r--r--layout/tables/nsTableRowGroupFrame.cpp52
-rw-r--r--layout/tables/nsTableRowGroupFrame.h1
-rw-r--r--layout/tables/nsTableWrapperFrame.cpp13
-rw-r--r--layout/tables/nsTableWrapperFrame.h2
14 files changed, 337 insertions, 293 deletions
diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp
index 8b811df1e..9c715d999 100644
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -450,7 +450,6 @@ nsTableCellFrame::ShouldPaintBackground(nsDisplayListBuilder* aBuilder)
void
nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
@@ -462,14 +461,14 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
}
+ nsRect bgRect = GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
+
// display background if we need to.
if (aBuilder->IsForEventDelivery() ||
!StyleBackground()->IsTransparent() ||
StyleDisplay()->mAppearance) {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
- this,
- GetRectRelativeToSelf(),
- aLists.BorderBackground());
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, this, bgRect, aLists.BorderBackground());
}
// display inset box-shadows if we need to.
@@ -488,16 +487,49 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
"TableCellSelection",
nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
}
+
+ // This can be null if display list building initiated in the middle
+ // of the table, which can happen with background-clip:text and
+ // -moz-element.
+ nsDisplayTableBackgroundSet* backgrounds =
+ aBuilder->GetTableBackgroundSet();
+ if (backgrounds) {
+ // Compute bgRect relative to reference frame, but using the
+ // normal (without position:relative offsets) positions for the
+ // cell, row and row group.
+ bgRect = GetRectRelativeToSelf() + GetNormalPosition();
+
+ nsTableRowFrame* row = GetTableRowFrame();
+ bgRect += row->GetNormalPosition();
+
+ nsTableRowGroupFrame* rowGroup = row->GetTableRowGroupFrame();
+ bgRect += rowGroup->GetNormalPosition();
+
+ bgRect += backgrounds->TableToReferenceFrame();
+
+ // Create backgrounds items as needed for the column and column
+ // group that this cell occupies.
+ nsTableColFrame* col = backgrounds->GetColForIndex(ColIndex());
+ nsTableColGroupFrame* colGroup = col->GetTableColGroupFrame();
+
+ Maybe<nsDisplayListBuilder::AutoBuildingDisplayList> buildingForColGroup;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, colGroup, bgRect, backgrounds->ColGroupBackgrounds(), false,
+ nullptr, colGroup->GetRect() + backgrounds->TableToReferenceFrame(),
+ this, &buildingForColGroup);
+
+ Maybe<nsDisplayListBuilder::AutoBuildingDisplayList> buildingForCol;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, col, bgRect, backgrounds->ColBackgrounds(), false, nullptr,
+ col->GetRect() + colGroup->GetPosition() +
+ backgrounds->TableToReferenceFrame(),
+ this, &buildingForCol);
+ }
}
// the 'empty-cells' property has no effect on 'outline'
DisplayOutline(aBuilder, aLists);
- // Push a null 'current table item' so that descendant tables can't
- // accidentally mess with our table
- nsAutoPushCurrentTableItem pushTableItem;
- pushTableItem.Push(aBuilder, nullptr);
-
nsIFrame* kid = mFrames.FirstChild();
NS_ASSERTION(kid && !kid->GetNextSibling(), "Table cells should have just one child");
// The child's background will go in our BorderBackground() list.
@@ -506,7 +538,7 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// because that/ would put the child's background in the Content() list
// which isn't right (e.g., would end up on top of our child floats for
// event handling).
- BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
+ BuildDisplayListForChild(aBuilder, kid, aLists);
}
nsIFrame::LogicalSides
diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h
index f626a45b0..a822e309d 100644
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -104,7 +104,6 @@ public:
virtual bool NeedsToObserve(const ReflowInput& aReflowInput) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
virtual nsresult ProcessBorders(nsTableFrame* aFrame,
diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp
index 54b03522b..6723f4701 100644
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -110,10 +110,15 @@ nsTableColFrame::Reflow(nsPresContext* aPresContext,
void
nsTableColFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
+ // Per https://drafts.csswg.org/css-tables-3/#global-style-overrides:
+ // "All css properties of table-column and table-column-group boxes are
+ // ignored, except when explicitly specified by this specification."
+ // CSS outlines and box-shadows fall into this category, so we skip them
+ // on these boxes.
+
+ MOZ_ASSERT_UNREACHABLE("Cols don't paint themselves");
}
int32_t nsTableColFrame::GetSpan()
diff --git a/layout/tables/nsTableColFrame.h b/layout/tables/nsTableColFrame.h
index fb989061f..ed6a843b6 100644
--- a/layout/tables/nsTableColFrame.h
+++ b/layout/tables/nsTableColFrame.h
@@ -60,7 +60,6 @@ public:
nsReflowStatus& aStatus) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
/**
diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp
index 6ee7f0b24..be5b71bb2 100644
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -385,10 +385,15 @@ nsTableColGroupFrame::Reflow(nsPresContext* aPresContext,
void
nsTableColGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
+ // Per https://drafts.csswg.org/css-tables-3/#global-style-overrides:
+ // "All css properties of table-column and table-column-group boxes are
+ // ignored, except when explicitly specified by this specification."
+ // CSS outlines and box-shadows fall into this category, so we skip them
+ // on these boxes.
+
+ MOZ_ASSERT_UNREACHABLE("Colgroups don't paint themselves");
}
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
diff --git a/layout/tables/nsTableColGroupFrame.h b/layout/tables/nsTableColGroupFrame.h
index b3dfb94e7..88ed67c2a 100644
--- a/layout/tables/nsTableColGroupFrame.h
+++ b/layout/tables/nsTableColGroupFrame.h
@@ -44,7 +44,6 @@ public:
}
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
/** A colgroup can be caused by three things:
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 4257c9c57..32fe38b05 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1161,242 +1161,127 @@ nsDisplayTableBorderCollapse::Paint(nsDisplayListBuilder* aBuilder,
static_cast<nsTableFrame*>(mFrame)->PaintBCBorders(*drawTarget, mVisibleRect - pt);
}
-/* static */ void
-nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsRect& aDirtyRect, const nsDisplayListSet& aLists)
-{
- // This is similar to what nsContainerFrame::BuildDisplayListForNonBlockChildren
- // does, except that we allow the children's background and borders to go
- // in our BorderBackground list. This doesn't really affect background
- // painting --- the children won't actually draw their own backgrounds
- // because the nsTableFrame already drew them, unless a child has its own
- // stacking context, in which case the child won't use its passed-in
- // BorderBackground list anyway. It does affect cell borders though; this
- // lets us get cell borders into the nsTableFrame's BorderBackground list.
- for (nsIFrame* kid : aFrame->GetChildList(kColGroupList)) {
- aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
+static inline bool FrameHasBorder(nsIFrame* f) {
+ if (!f->StyleVisibility()->IsVisible()) {
+ return false;
}
- for (nsIFrame* kid : aFrame->PrincipalChildList()) {
- aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
+ if (f->StyleBorder()->HasBorder()) {
+ return true;
}
-}
-
-static void
-PaintRowBackground(nsTableRowFrame* aRow,
- nsIFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists,
- const nsRect& aDirtyRect,
- const nsPoint& aOffset = nsPoint())
-{
- // Compute background rect by iterating over all cell frames.
- for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
- if (!cell->ShouldPaintBackground(aBuilder)) {
- continue;
- }
- auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
- if (!aDirtyRect.Intersects(cellRect)) {
- continue;
- }
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
- aLists.BorderBackground(),
- true, nullptr,
- aFrame->GetRectRelativeToSelf(),
- cell);
- }
+ return false;
}
-static void
-PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup,
- nsIFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists,
- const nsRect& aDirtyRect)
-{
- for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
- if (!aDirtyRect.Intersects(nsRect(row->GetNormalPosition(), row->GetSize()))) {
- continue;
- }
- PaintRowBackground(row, aFrame, aBuilder, aLists, aDirtyRect, row->GetNormalPosition());
+void nsTableFrame::CalcHasBCBorders() {
+ if (!IsBorderCollapse()) {
+ SetHasBCBorders(false);
+ return;
}
-}
-static void
-PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
- nsIFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists,
- const nsRect& aDirtyRect,
- const nsTArray<uint32_t>& aColIdx,
- const nsPoint& aOffset)
-{
- MOZ_DIAGNOSTIC_ASSERT(!aColIdx.IsEmpty(),
- "Must be painting backgrounds for something");
- for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
- auto rowPos = row->GetNormalPosition() + aOffset;
- if (!aDirtyRect.Intersects(nsRect(rowPos, row->GetSize()))) {
- continue;
- }
- for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
-
- uint32_t curColIdx = cell->ColIndex();
- if (!aColIdx.Contains(curColIdx)) {
- if (curColIdx > aColIdx.LastElement()) {
- // We can just stop looking at this row.
- break;
- }
- continue;
- }
-
- if (!cell->ShouldPaintBackground(aBuilder)) {
- continue;
- }
-
- auto cellPos = cell->GetNormalPosition() + rowPos;
- auto cellRect = nsRect(cellPos, cell->GetSize());
- if (!aDirtyRect.Intersects(cellRect)) {
- continue;
- }
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
- aLists.BorderBackground(),
- true, nullptr,
- aFrame->GetRectRelativeToSelf(),
- cell);
- }
+ if (FrameHasBorder(this)) {
+ SetHasBCBorders(true);
+ return;
}
-}
-/* static */ void
-nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
- nsFrame* aFrame,
- const nsRect& aDirtyRect,
- const nsDisplayListSet& aLists,
- DisplayGenericTablePartTraversal aTraversal)
-{
- bool isVisible = aFrame->IsVisibleForPainting(aBuilder);
- bool isTable = (aFrame->GetType() == nsGkAtoms::tableFrame);
-
- if (isVisible || !isTable) {
- nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
- // currentItem may be null, when none of the table parts have a
- // background or border
- if (currentItem) {
- currentItem->UpdateForFrameBackground(aFrame);
- }
- }
-
- if (isVisible) {
- // XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted
- // just because we're visible? Or should it depend on the cell visibility
- // when we're not the whole table?
-
- // Paint the outset box-shadows for the table frames
- if (aFrame->StyleEffects()->mBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
- }
- }
-
- // Background visibility for rows, rowgroups, columns, colgroups depends on
- // the visibility of the _cell_, not of the row/col(group).
- // See spec at https://drafts.csswg.org/css-tables-3/#drawing-cell-backgrounds
- if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
- nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
- PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists, aDirtyRect);
- } else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
- nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
- PaintRowBackground(row, aFrame, aBuilder, aLists, aDirtyRect);
- } else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
- // Compute background rect by iterating all cell frame.
- nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
- // Collecting column index.
- AutoTArray<uint32_t, 1> colIdx;
- for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
- MOZ_ASSERT(colIdx.IsEmpty() ||
- static_cast<uint32_t>(col->GetColIndex()) > colIdx.LastElement());
- colIdx.AppendElement(col->GetColIndex());
- }
-
- if (!colIdx.IsEmpty()) {
- // We have some actual cells that live inside this rowgroup.
- nsTableFrame* table = colGroup->GetTableFrame();
- RowGroupArray rowGroups;
- table->OrderRowGroups(rowGroups);
- for (nsTableRowGroupFrame* rowGroup : rowGroups) {
- auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
- if (!aDirtyRect.Intersects(nsRect(offset, rowGroup->GetSize()))) {
- continue;
- }
- PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, aDirtyRect, colIdx, offset);
- }
+ // Check col and col group has borders.
+ for (nsIFrame* f : this->GetChildList(kColGroupList)) {
+ if (FrameHasBorder(f)) {
+ SetHasBCBorders(true);
+ return;
}
- } else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
- // Compute background rect by iterating all cell frame.
- nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
- AutoTArray<uint32_t, 1> colIdx;
- colIdx.AppendElement(col->GetColIndex());
- nsTableFrame* table = col->GetTableFrame();
- RowGroupArray rowGroups;
- table->OrderRowGroups(rowGroups);
- for (nsTableRowGroupFrame* rowGroup : rowGroups) {
- auto offset = rowGroup->GetNormalPosition() -
- col->GetNormalPosition() -
- col->GetTableColGroupFrame()->GetNormalPosition();
- if (!aDirtyRect.Intersects(nsRect(offset, rowGroup->GetSize()))) {
- continue;
+ nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(f);
+ for (nsTableColFrame* col = colGroup->GetFirstColumn(); col;
+ col = col->GetNextCol()) {
+ if (FrameHasBorder(col)) {
+ SetHasBCBorders(true);
+ return;
}
- PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, aDirtyRect, colIdx, offset);
}
- } else if (isVisible) {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
- aFrame->GetRectRelativeToSelf(),
- aLists.BorderBackground());
}
- if (isVisible) {
- // XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted
- // just because we're visible? Or should it depend on the cell visibility
- // when we're not the whole table?
-
- // Paint the inset box-shadows for the table frames
- if (aFrame->StyleEffects()->mBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
+ // check row group, row and cell has borders.
+ RowGroupArray rowGroups;
+ OrderRowGroups(rowGroups);
+ for (nsTableRowGroupFrame* rowGroup : rowGroups) {
+ if (FrameHasBorder(rowGroup)) {
+ SetHasBCBorders(true);
+ return;
}
- }
- aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
+ for (nsTableRowFrame* row = rowGroup->GetFirstRow(); row;
+ row = row->GetNextRow()) {
+ if (FrameHasBorder(row)) {
+ SetHasBCBorders(true);
+ return;
+ }
- if (isVisible) {
- if (isTable) {
- nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
- // In the collapsed border model, overlay all collapsed borders.
- if (table->IsBorderCollapse()) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table));
- } else {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBorder(aBuilder, table));
+ for (nsTableCellFrame* cell = row->GetFirstCell(); cell;
+ cell = cell->GetNextCell()) {
+ if (FrameHasBorder(cell)) {
+ SetHasBCBorders(true);
+ return;
+ }
}
}
}
- aFrame->DisplayOutline(aBuilder, aLists);
+ SetHasBCBorders(false);
}
// table paint code is concerned primarily with borders and bg color
// SEC: TODO: adjust the rect for captions
void
nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
- DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
+ DisplayBorderBackgroundOutline(aBuilder, aLists);
+
+ nsDisplayTableBackgroundSet tableBGs(aBuilder, this);
+ nsDisplayListCollection lists(aBuilder);
+
+// This is similar to what
+ // nsContainerFrame::BuildDisplayListForNonBlockChildren does, except that we
+ // allow the children's background and borders to go in our BorderBackground
+ // list. This doesn't really affect background painting --- the children won't
+ // actually draw their own backgrounds because the nsTableFrame already drew
+ // them, unless a child has its own stacking context, in which case the child
+ // won't use its passed-in BorderBackground list anyway. It does affect cell
+ // borders though; this lets us get cell borders into the nsTableFrame's
+ // BorderBackground list.
+ for (nsIFrame* colGroup : FirstContinuation()->GetChildList(kColGroupList)) {
+ for (nsIFrame* col : colGroup->PrincipalChildList()) {
+ tableBGs.AddColumn((nsTableColFrame*)col);
+ }
+ }
+
+ for (nsIFrame* kid : PrincipalChildList()) {
+ BuildDisplayListForChild(aBuilder, kid, lists);
+ }
+
+ tableBGs.MoveTo(aLists);
+ lists.MoveTo(aLists);
+
+ if (IsVisibleForPainting(aBuilder)) {
+ // In the collapsed border model, overlay all collapsed borders.
+ if (IsBorderCollapse()) {
+ if (HasBCBorders()) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayTableBorderCollapse
+ (aBuilder, this));
+ }
+ } else {
+ const nsStyleBorder* borderStyle = StyleBorder();
+ if (borderStyle->HasBorder()) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBorder
+ (aBuilder, this));
+ }
+ }
+ }
}
nsMargin
@@ -4101,6 +3986,7 @@ nsTableFrame::AddBCDamageArea(const TableArea& aValue)
#endif
SetNeedToCalcBCBorders(true);
+ SetNeedToCalcHasBCBorders(true);
// Get the property
BCPropertyData* value = GetOrCreateBCProperty();
if (value) {
@@ -4141,6 +4027,7 @@ nsTableFrame::SetFullBCDamageArea()
NS_ASSERTION(IsBorderCollapse(), "invalid SetFullBCDamageArea call");
SetNeedToCalcBCBorders(true);
+ SetNeedToCalcHasBCBorders(true);
BCPropertyData* value = GetOrCreateBCProperty();
if (value) {
diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h
index a6b786402..7fcdcb9d8 100644
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -72,36 +72,59 @@ private:
bool mDrawsBackground;
};
-class nsAutoPushCurrentTableItem
-{
-public:
- nsAutoPushCurrentTableItem() : mBuilder(nullptr) {}
+class nsDisplayTableBackgroundSet {
+ public:
+ nsDisplayList* ColGroupBackgrounds() { return &mColGroupBackgrounds; }
+
+ nsDisplayList* ColBackgrounds() { return &mColBackgrounds; }
+
+ nsDisplayTableBackgroundSet(nsDisplayListBuilder* aBuilder, nsIFrame* aTable)
+ : mBuilder(aBuilder) {
+ mPrevTableBackgroundSet = mBuilder->SetTableBackgroundSet(this);
+ mozilla::DebugOnly<const nsIFrame*> reference =
+ mBuilder->FindReferenceFrameFor(aTable, &mToReferenceFrame);
+ MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(reference, aTable));
+ mDirtyRect = mBuilder->GetDirtyRect();
+ }
- void Push(nsDisplayListBuilder* aBuilder, nsDisplayTableItem* aPushItem)
- {
- mBuilder = aBuilder;
- mOldCurrentItem = aBuilder->GetCurrentTableItem();
- aBuilder->SetCurrentTableItem(aPushItem);
-#ifdef DEBUG
- mPushedItem = aPushItem;
-#endif
+ ~nsDisplayTableBackgroundSet() {
+ mozilla::DebugOnly<nsDisplayTableBackgroundSet*> result =
+ mBuilder->SetTableBackgroundSet(mPrevTableBackgroundSet);
+ MOZ_ASSERT(result == this);
}
- ~nsAutoPushCurrentTableItem() {
- if (!mBuilder)
- return;
-#ifdef DEBUG
- NS_ASSERTION(mBuilder->GetCurrentTableItem() == mPushedItem,
- "Someone messed with the current table item behind our back!");
-#endif
- mBuilder->SetCurrentTableItem(mOldCurrentItem);
+
+ /**
+ * Move all display items in our lists to top of the corresponding lists in
+ * the destination.
+ */
+ void MoveTo(const nsDisplayListSet& aDestination) {
+ aDestination.BorderBackground()->AppendToTop(ColGroupBackgrounds());
+ aDestination.BorderBackground()->AppendToTop(ColBackgrounds());
}
-private:
+ void AddColumn(nsTableColFrame* aFrame) { mColumns.AppendElement(aFrame); }
+
+ nsTableColFrame* GetColForIndex(int32_t aIndex) { return mColumns[aIndex]; }
+
+ const nsPoint& TableToReferenceFrame() { return mToReferenceFrame; }
+
+ const nsRect& GetDirtyRect() { return mDirtyRect; }
+
+ private:
+ // This class is only used on stack, so we don't have to worry about leaking
+ // it. Don't let us be heap-allocated!
+ void* operator new(size_t sz) CPP_THROW_NEW;
+
+ protected:
nsDisplayListBuilder* mBuilder;
- nsDisplayTableItem* mOldCurrentItem;
-#ifdef DEBUG
- nsDisplayTableItem* mPushedItem;
-#endif
+ nsDisplayTableBackgroundSet* mPrevTableBackgroundSet;
+
+ nsDisplayList mColGroupBackgrounds;
+ nsDisplayList mColBackgrounds;
+
+ nsTArray<nsTableColFrame*> mColumns;
+ nsPoint mToReferenceFrame;
+ nsRect mDirtyRect;
};
/* ============================================================================ */
@@ -229,29 +252,6 @@ public:
nsIFrame* aSourceFrame,
bool* aDidPassThrough);
- typedef void (* DisplayGenericTablePartTraversal)
- (nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsRect& aDirtyRect, const nsDisplayListSet& aLists);
- static void GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsRect& aDirtyRect, const nsDisplayListSet& aLists);
-
- /**
- * Helper method to handle display common to table frames, rowgroup frames
- * and row frames. It creates a background display item for handling events
- * if necessary, an outline display item if necessary, and displays
- * all the the frame's children.
- * @param aDisplayItem the display item created for this part, or null
- * if this part's border/background painting is delegated to an ancestor
- * @param aTraversal a function that gets called to traverse the table
- * part's child frames and add their display list items to a
- * display list set.
- */
- static void DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
- nsFrame* aFrame,
- const nsRect& aDirtyRect,
- const nsDisplayListSet& aLists,
- DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
-
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
// of type aChildType.
static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
@@ -268,7 +268,6 @@ public:
virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
/** Get the outer half (i.e., the part outside the height and width of
@@ -761,6 +760,13 @@ public:
bool NeedToCollapse() const;
void SetNeedToCollapse(bool aValue);
+ bool NeedToCalcHasBCBorders() const;
+ void SetNeedToCalcHasBCBorders(bool aValue);
+
+ void CalcHasBCBorders();
+ bool HasBCBorders();
+ void SetHasBCBorders(bool aValue);
+
/** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
* state bit, which implies that all descendants are dirty. The
* GeometryDirty still implies that all the parts of the table are
@@ -870,6 +876,8 @@ protected:
uint32_t mIStartContBCBorder:8;
uint32_t mNeedToCollapse:1; // rows, cols that have visibility:collapse need to be collapsed
uint32_t mResizedColumns:1; // have we resized columns since last reflow?
+ uint32_t mNeedToCalcHasBCBorders:1;
+ uint32_t mHasBCBorders:1;
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@@ -965,6 +973,30 @@ inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue)
mBits.mNeedToCalcBCBorders = (unsigned)aValue;
}
+inline bool nsTableFrame::NeedToCalcHasBCBorders() const
+{
+ return (bool)mBits.mNeedToCalcHasBCBorders;
+}
+
+inline void nsTableFrame::SetNeedToCalcHasBCBorders(bool aValue)
+{
+ mBits.mNeedToCalcHasBCBorders = (unsigned)aValue;
+}
+
+inline bool nsTableFrame::HasBCBorders()
+{
+ if (NeedToCalcHasBCBorders()) {
+ CalcHasBCBorders();
+ SetNeedToCalcHasBCBorders(false);
+ }
+ return (bool)mBits.mHasBCBorders;
+}
+
+inline void nsTableFrame::SetHasBCBorders(bool aValue)
+{
+ mBits.mHasBCBorders = (unsigned)aValue;
+}
+
inline nscoord
nsTableFrame::GetContinuousIStartBCBorderWidth() const
{
diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
index 02b85a141..18f11f876 100644
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -549,12 +549,66 @@ nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput)
return GetInitialBSize();
}
+void nsTableRowFrame::PaintCellBackgroundsForFrame(
+ nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists, const nsPoint& aOffset) {
+ // Compute background rect by iterating all cell frame.
+ const nsPoint toReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
+ for (nsTableCellFrame* cell = GetFirstCell(); cell;
+ cell = cell->GetNextCell()) {
+ if (!cell->ShouldPaintBackground(aBuilder)) {
+ continue;
+ }
+
+ auto cellRect =
+ cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
+ if (!aBuilder->GetDirtyRect().Intersects(cellRect)) {
+ continue;
+ }
+ cellRect += toReferenceFrame;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, aFrame, cellRect, aLists.BorderBackground(), true, nullptr,
+ aFrame->GetRectRelativeToSelf() + toReferenceFrame, cell);
+ }
+}
+
void
nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the outset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowOuter
+ (aBuilder, this));
+ }
+ }
+
+ PaintCellBackgroundsForFrame(this, aBuilder, aLists);
+
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the inset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowInner
+ (aBuilder, this));
+ }
+ }
+
+ DisplayOutline(aBuilder, aLists);
+
+ for (nsIFrame* kid : PrincipalChildList()) {
+ BuildDisplayListForChild(aBuilder, kid, aLists);
+ }
}
nsIFrame::LogicalSides
diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h
index c53c81ff1..4b6dd2628 100644
--- a/layout/tables/nsTableRowFrame.h
+++ b/layout/tables/nsTableRowFrame.h
@@ -79,9 +79,13 @@ public:
virtual nsMargin GetUsedPadding() const override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
+ void PaintCellBackgroundsForFrame(nsIFrame* aFrame,
+ nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists,
+ const nsPoint& aOffset = nsPoint());
+
// Implemented in nsTableCellFrame.h, because it needs to know about the
// nsTableCellFrame class, but we can't include nsTableCellFrame.h here.
inline nsTableCellFrame* GetFirstCell() const;
diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp
index 37f577f5c..56ca394de 100644
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -156,7 +156,7 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame
// Handle the child-traversal part of DisplayGenericTablePart
static void
DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsRect& aDirtyRect, const nsDisplayListSet& aLists)
+ const nsDisplayListSet& aLists)
{
nscoord overflowAbove;
nsTableRowGroupFrame* f = static_cast<nsTableRowGroupFrame*>(aFrame);
@@ -168,16 +168,16 @@ DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
// the rows in |f|, but that's exactly what we're trying to avoid, so we
// approximate it by checking it for |f|: if it's true for any row
// in |f| then it's true for |f| itself.
- nsIFrame* kid = aBuilder->ShouldDescendIntoFrame(f) ?
- nullptr : f->GetFirstRowContaining(aDirtyRect.y, &overflowAbove);
+ nsIFrame* kid = aBuilder->ShouldDescendIntoFrame(f, true) ?
+ nullptr : f->GetFirstRowContaining(aBuilder->GetVisibleRect().y, &overflowAbove);
if (kid) {
// If we have a cursor, use it
while (kid) {
- if (kid->GetRect().y - overflowAbove >= aDirtyRect.YMost()) {
+ if (kid->GetRect().y - overflowAbove >= aBuilder->GetDirtyRect().YMost()) {
break;
}
- f->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
+ f->BuildDisplayListForChild(aBuilder, kid, aLists);
kid = kid->GetNextSibling();
}
return;
@@ -187,7 +187,7 @@ DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
nsTableRowGroupFrame::FrameCursorData* cursor = f->SetupRowCursor();
kid = f->PrincipalChildList().FirstChild();
while (kid) {
- f->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
+ f->BuildDisplayListForChild(aBuilder, kid, aLists);
if (cursor) {
if (!cursor->AppendFrame(kid)) {
@@ -205,11 +205,45 @@ DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
void
nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect,
- aLists, DisplayRows);
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the outset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowOuter
+ (aBuilder, this));
+ }
+ }
+
+ for (nsTableRowFrame* row = GetFirstRow(); row; row = row->GetNextRow()) {
+ if (!aBuilder->GetDirtyRect().Intersects(row->GetVisualOverflowRect() + row->GetNormalPosition())) {
+ continue;
+ }
+ row->PaintCellBackgroundsForFrame(this, aBuilder, aLists,
+ row->GetNormalPosition());
+ }
+
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the inset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowInner
+ (aBuilder, this));
+ }
+ }
+
+ DisplayOutline(aBuilder, aLists);
+
+ DisplayRows(aBuilder, this, aLists);
}
nsIFrame::LogicalSides
diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h
index 721d91046..eb9f6205e 100644
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -75,7 +75,6 @@ public:
virtual nsMargin GetUsedPadding() const override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
/** calls Reflow for all of its child rows.
diff --git a/layout/tables/nsTableWrapperFrame.cpp b/layout/tables/nsTableWrapperFrame.cpp
index da71375d5..476024e96 100644
--- a/layout/tables/nsTableWrapperFrame.cpp
+++ b/layout/tables/nsTableWrapperFrame.cpp
@@ -168,7 +168,6 @@ nsTableWrapperFrame::RemoveFrame(ChildListID aListID,
void
nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// No border, background or outline are painted because they all belong
@@ -177,16 +176,15 @@ nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// If there's no caption, take a short cut to avoid having to create
// the special display list set and then sort it.
if (mCaptionFrames.IsEmpty()) {
- BuildDisplayListForInnerTable(aBuilder, aDirtyRect, aLists);
+ BuildDisplayListForInnerTable(aBuilder, aLists);
return;
}
- nsDisplayListCollection set;
- BuildDisplayListForInnerTable(aBuilder, aDirtyRect, set);
+ nsDisplayListCollection set(aBuilder);
+ BuildDisplayListForInnerTable(aBuilder, set);
nsDisplayListSet captionSet(set, set.BlockBorderBackgrounds());
- BuildDisplayListForChild(aBuilder, mCaptionFrames.FirstChild(),
- aDirtyRect, captionSet);
+ BuildDisplayListForChild(aBuilder, mCaptionFrames.FirstChild(), captionSet);
// Now we have to sort everything by content order, since the caption
// may be somewhere inside the table
@@ -200,7 +198,6 @@ nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
void
nsTableWrapperFrame::BuildDisplayListForInnerTable(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// Just paint the regular children, but the children's background is our
@@ -208,7 +205,7 @@ nsTableWrapperFrame::BuildDisplayListForInnerTable(nsDisplayListBuilder* aBuil
nsIFrame* kid = mFrames.FirstChild();
// The children should be in content order
while (kid) {
- BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
+ BuildDisplayListForChild(aBuilder, kid, aLists);
kid = kid->GetNextSibling();
}
}
diff --git a/layout/tables/nsTableWrapperFrame.h b/layout/tables/nsTableWrapperFrame.h
index 45d7c33e4..8095c7fc4 100644
--- a/layout/tables/nsTableWrapperFrame.h
+++ b/layout/tables/nsTableWrapperFrame.h
@@ -59,11 +59,9 @@ public:
#endif
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
void BuildDisplayListForInnerTable(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;