Bug 1395312 part 2. Table backgrounds should be drawn or not based on the visibility of the relevant cell, not of the column/row/colgroup/rowgroup they come from. r=heycam

MozReview-Commit-ID: B863KFWjLLW
This commit is contained in:
Boris Zbarsky 2017-08-31 09:12:35 -04:00
Родитель 8216808d0e
Коммит 7f0ccc9510
8 изменённых файлов: 141 добавлений и 68 удалений

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<table style="width: 200px; height: 200px; empty-cells: hide; color: white">
<colgroup style="background: red">
<col style="background: red">
</colgroup>
<tbody style="background: red">
<tr style="background: red">
<td></td>
<td style="visibility: hidden">X</td>
</tr>
</tbody>
</table>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<table style="width: 200px; height: 200px; empty-cells: show; color: white">
<colgroup style="background: red">
<col style="background: red">
</colgroup>
<tbody style="background: red">
<tr style="background: red">
<td style="background: white"></td>
<td style="visibility: hidden"></td>
</tr>
</tbody>
</table>

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<table style="width: 200px; height: 200px; empty-cells: show; border-collapse: collapse">
<colgroup style="background: red">
<col style="background: red">
</colgroup>
<tbody style="background: red">
<tr style="background: red">
<td style="background: green">
</td>
<td style="background: white">
</td>
</tr>
</tbody>
</table>

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<table style="width: 200px; height: 200px; empty-cells: hide; border-collapse: collapse">
<colgroup style="background: red">
<col style="background: red">
</colgroup>
<tbody style="background: red">
<tr style="background: green; visibility: hidden">
<td style="visibility: visible">
</td>
<td>
</td>
</tr>
</tbody>
</table>

Просмотреть файл

@ -60,3 +60,7 @@ fuzzy-if(d2d||skiaContent,1,95000) == border-separate-opacity-table.html border-
== empty-cells-default-2.html empty-cells-default-2-ref.html
fuzzy-if(OSX,1,113) fuzzy-if(winWidget,1,12) fuzzy-if(winWidget&&!layersGPUAccelerated,82,116) fuzzy-if(skiaContent,84,5500) fuzzy-if(Android,2,5957) == table-row-opacity-dynamic-1.html table-row-opacity-dynamic-1-ref.html
== table-row-opacity-dynamic-2.html table-row-opacity-dynamic-2-ref.html
== hidden-cells-1.html about:blank
== hidden-cells-2.html about:blank
== hidden-cells-3.html hidden-cells-3-ref.html

Просмотреть файл

@ -491,6 +491,12 @@ nsTableCellFrame::ShouldPaintBordersAndBackgrounds() const
return StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
}
bool
nsTableCellFrame::ShouldPaintBackground(nsDisplayListBuilder* aBuilder)
{
return ShouldPaintBordersAndBackgrounds() && IsVisibleInSelection(aBuilder);
}
void
nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)

Просмотреть файл

@ -226,6 +226,8 @@ public:
bool ShouldPaintBordersAndBackgrounds() const;
bool ShouldPaintBackground(nsDisplayListBuilder* aBuilder);
protected:
nsTableCellFrame(nsStyleContext* aContext, nsTableFrame* aTableFrame,
ClassID aID);

Просмотреть файл

@ -1377,6 +1377,10 @@ PaintRowBackground(nsTableRowFrame* aRow,
{
// Compute background rect by iterating all cell frame.
for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
if (!cell->ShouldPaintBackground(aBuilder)) {
continue;
}
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
if (!aBuilder->GetDirtyRect().Intersects(cellRect)) {
continue;
@ -1418,6 +1422,10 @@ PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
continue;
}
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
if (!cell->ShouldPaintBackground(aBuilder)) {
continue;
}
int32_t curColIdx;
cell->GetColIndex(curColIdx);
if (aColIdx.Contains(curColIdx)) {
@ -1511,89 +1519,90 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
DisplayGenericTablePartTraversal aTraversal)
{
bool isVisible = aFrame->IsVisibleForPainting(aBuilder);
bool isColumn = aFrame->IsTableColFrame();
// If we have an anonymous column in the AppendAnonymousColFrames sense, it
// might think it's visible for painting (due to not inheriting its colgroup's
// styles) while the colgroup as a whole is actually not visible for painting
// because it has hidden visibility. In that situation we should also treat
// the column as not visible, because otherwise hit-testing can get a bit
// confused.
//
// XXXbz It's not clear whether anonymous columns and column groups should
// ever affect hit-testing at all. See
// https://github.com/w3c/csswg-drafts/issues/1763 which might result in them
// not existing conceptually and hence not affecting hit-testing.
if (isVisible && isColumn &&
aFrame->StyleContext()->GetPseudo() == nsCSSAnonBoxes::tableCol &&
!aFrame->GetParent()->StyleVisibility()->IsVisible()) {
isVisible = false;
}
if (isVisible) {
bool isTable = aFrame->IsTableFrame();
// Note that we UpdateForFrameBackground() even if we're not visible, unless
// we're a table frame, because our backgrounds may paint anyway if the _cell_
// is visible.
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) {
// 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
bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
if (hasBoxShadow) {
if (aFrame->StyleEffects()->mBoxShadow) {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
}
}
if (aFrame->IsTableRowGroupFrame()) {
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
} else if (aFrame->IsTableRowFrame()) {
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
PaintRowBackground(row, aFrame, aBuilder, aLists);
} else if (aFrame->IsTableColGroupFrame()) {
// 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();
if (!aBuilder->GetDirtyRect().Intersects(nsRect(offset, rowGroup->GetSize()))) {
continue;
}
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
}
} else if (isColumn) {
// 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).
if (aFrame->IsTableRowGroupFrame()) {
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
} else if (aFrame->IsTableRowFrame()) {
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
PaintRowBackground(row, aFrame, aBuilder, aLists);
} else if (aFrame->IsTableColGroupFrame()) {
// 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();
if (!aBuilder->GetDirtyRect().Intersects(nsRect(offset, rowGroup->GetSize()))) {
continue;
}
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();
if (!aBuilder->GetDirtyRect().Intersects(nsRect(offset, rowGroup->GetSize()))) {
continue;
}
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
}
} else if (aFrame->IsTableColFrame()) {
// 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();
if (!aBuilder->GetDirtyRect().Intersects(nsRect(offset, rowGroup->GetSize()))) {
continue;
}
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
}
} else if (isVisible) {
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
aFrame->GetRectRelativeToSelf(),
aLists.BorderBackground());
}
if (isVisible) {
// 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 (hasBoxShadow) {
if (aFrame->StyleEffects()->mBoxShadow) {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
}
@ -1602,7 +1611,7 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
aTraversal(aBuilder, aFrame, aLists);
if (isVisible) {
if (aFrame->IsTableFrame()) {
if (isTable) {
nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
// In the collapsed border model, overlay all collapsed borders.
if (table->IsBorderCollapse()) {