summaryrefslogtreecommitdiffstats
path: root/layout
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2020-02-02 02:16:41 +0100
committerwolfbeast <mcwerewolf@wolfbeast.com>2020-04-14 12:22:44 +0200
commitfddc35e4384c20b1ad5d0c9818f490be29b1ece5 (patch)
tree46d948b46e1057a21f382152c9ac4215eb5703fa /layout
parent7e4efa4e1f9d1569edcaed7440fbbfe831236c8d (diff)
downloadUXP-fddc35e4384c20b1ad5d0c9818f490be29b1ece5.tar
UXP-fddc35e4384c20b1ad5d0c9818f490be29b1ece5.tar.gz
UXP-fddc35e4384c20b1ad5d0c9818f490be29b1ece5.tar.lz
UXP-fddc35e4384c20b1ad5d0c9818f490be29b1ece5.tar.xz
UXP-fddc35e4384c20b1ad5d0c9818f490be29b1ece5.zip
Issue #1378 - Align the drawing of table cell backgrounds with the spec.
Diffstat (limited to 'layout')
-rw-r--r--layout/tables/nsTableCellFrame.cpp37
-rw-r--r--layout/tables/nsTableCellFrame.h8
-rw-r--r--layout/tables/nsTableFrame.cpp115
3 files changed, 105 insertions, 55 deletions
diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp
index 043509fc4..2862bb201 100644
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -450,19 +450,40 @@ PaintTableCellSelection(nsIFrame* aFrame, DrawTarget* aDrawTarget,
aPt);
}
+bool
+nsTableCellFrame::ShouldPaintBordersAndBackgrounds() const
+{
+ // If we're not visible, we don't paint.
+ if (!StyleVisibility()->IsVisible()) {
+ return false;
+ }
+
+ // Consider 'empty-cells', but only in separated borders mode.
+ if (!GetContentEmpty()) {
+ return true;
+ }
+
+ nsTableFrame* tableFrame = GetTableFrame();
+ if (tableFrame->IsBorderCollapse()) {
+ return true;
+ }
+
+ return StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
+}
+
+bool
+nsTableCellFrame::ShouldPaintBackground(nsDisplayListBuilder* aBuilder)
+{
+ return ShouldPaintBordersAndBackgrounds() && IsVisibleInSelection(aBuilder);
+}
+
void
nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
- nsTableFrame* tableFrame = GetTableFrame();
- int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
- StyleTableBorder()->mEmptyCells
- : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
- // take account of 'empty-cells'
- if (StyleVisibility()->IsVisible() &&
- (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
+ if (ShouldPaintBordersAndBackgrounds()) {
// display outset box-shadows if we need to.
bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
if (hasBoxShadow) {
@@ -487,7 +508,7 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
// display borders if we need to
- ProcessBorders(tableFrame, aBuilder, aLists);
+ ProcessBorders(GetTableFrame(), aBuilder, aLists);
// and display the selection border if we need to
if (IsSelected()) {
diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h
index d8debe993..e8dad5c20 100644
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -209,7 +209,7 @@ public:
/** set the desired size returned by this frame during its last reflow */
inline void SetDesiredSize(const ReflowOutput & aDesiredSize);
- bool GetContentEmpty();
+ bool GetContentEmpty() const;
void SetContentEmpty(bool aContentEmpty);
bool HasPctOverBSize();
@@ -246,6 +246,10 @@ public:
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
+
+ bool ShouldPaintBordersAndBackgrounds() const;
+
+ bool ShouldPaintBackground(nsDisplayListBuilder* aBuilder);
protected:
virtual LogicalSides
@@ -283,7 +287,7 @@ inline void nsTableCellFrame::SetDesiredSize(const ReflowOutput & aDesiredSize)
mDesiredSize = aDesiredSize.Size(wm).ConvertTo(GetWritingMode(), wm);
}
-inline bool nsTableCellFrame::GetContentEmpty()
+inline bool nsTableCellFrame::GetContentEmpty() const
{
return HasAnyStateBits(NS_TABLE_CELL_CONTENT_EMPTY);
}
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 890d050fd..891d7e7cd 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1196,6 +1196,10 @@ PaintRowBackground(nsTableRowFrame* aRow,
{
// 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;
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
aLists.BorderBackground(),
@@ -1226,6 +1230,10 @@ PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
{
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
+ if (!cell->ShouldPaintBackground(aBuilder)) {
+ continue;
+ }
+
int32_t curColIdx;
cell->GetColIndex(curColIdx);
if (aColIdx.Contains(curColIdx)) {
@@ -1247,66 +1255,83 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists,
DisplayGenericTablePartTraversal aTraversal)
{
- if (aFrame->IsVisibleForPainting(aBuilder)) {
+ 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
- bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
- if (hasBoxShadow) {
+ if (aFrame->StyleEffects()->mBoxShadow) {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
}
+ }
- if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
- nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
- PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
- } else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
- nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
- PaintRowBackground(row, aFrame, aBuilder, aLists);
- } else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
- // Compute background rect by iterating all cell frame.
- nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
- // Collecting column index.
- AutoTArray<int32_t, 1> colIdx;
- for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
- colIdx.AppendElement(col->GetColIndex());
- }
-
- nsTableFrame* table = colGroup->GetTableFrame();
- RowGroupArray rowGroups;
- table->OrderRowGroups(rowGroups);
- for (nsTableRowGroupFrame* rowGroup : rowGroups) {
- auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
- PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
- }
- } else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
- // Compute background rect by iterating all cell frame.
- nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
- AutoTArray<int32_t, 1> colIdx;
+ // 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);
+ } else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
+ nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
+ PaintRowBackground(row, aFrame, aBuilder, aLists);
+ } else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
+ // Compute background rect by iterating all cell frame.
+ nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
+ // Collecting column index.
+ AutoTArray<int32_t, 1> colIdx;
+ for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
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();
- PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
- }
- } else {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
- aFrame->GetRectRelativeToSelf(),
- aLists.BorderBackground());
+ nsTableFrame* table = colGroup->GetTableFrame();
+ RowGroupArray rowGroups;
+ table->OrderRowGroups(rowGroups);
+ for (nsTableRowGroupFrame* rowGroup : rowGroups) {
+ auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
+ PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
+ }
+ } else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
+ // Compute background rect by iterating all cell frame.
+ nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
+ AutoTArray<int32_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();
+ PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
}
+ } else {
+ 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 (hasBoxShadow) {
+ if (aFrame->StyleEffects()->mBoxShadow) {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
}
@@ -1314,8 +1339,8 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
- if (aFrame->IsVisibleForPainting(aBuilder)) {
- if (aFrame->GetType() == nsGkAtoms::tableFrame) {
+ if (isVisible) {
+ if (isTable) {
nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
// In the collapsed border model, overlay all collapsed borders.
if (table->IsBorderCollapse()) {