Index: third_party/WebKit/Source/core/paint/TableSectionPainter.cpp |
diff --git a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp |
index de40383390836b5c3a33ca986e192270964c068f..f2f9dc4605905fce8a8ae539ff1438e5bb0dd912 100644 |
--- a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp |
+++ b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp |
@@ -108,8 +108,8 @@ void TableSectionPainter::paintSection(const PaintInfo& paintInfo, |
.paintOutline(paintInfo, adjustedPaintOffset); |
} |
-static inline bool compareCellPositions(LayoutTableCell* elem1, |
- LayoutTableCell* elem2) { |
+static inline bool compareCellPositions(const LayoutTableCell* elem1, |
+ const LayoutTableCell* elem2) { |
return elem1->rowIndex() < elem2->rowIndex(); |
} |
@@ -117,8 +117,8 @@ static inline bool compareCellPositions(LayoutTableCell* elem1, |
// unsorted array to sort. We thus need to sort both on rows and columns to |
// properly issue paint invalidations. |
static inline bool compareCellPositionsWithOverflowingCells( |
- LayoutTableCell* elem1, |
- LayoutTableCell* elem2) { |
+ const LayoutTableCell* elem1, |
+ const LayoutTableCell* elem2) { |
if (elem1->rowIndex() != elem2->rowIndex()) |
return elem1->rowIndex() < elem2->rowIndex(); |
@@ -195,23 +195,11 @@ void TableSectionPainter::paintObject(const PaintInfo& paintInfo, |
CellSpan dirtiedColumns = |
m_layoutTableSection.dirtiedEffectiveColumns(tableAlignedRect); |
- if (dirtiedColumns.start() >= dirtiedColumns.end()) |
- return; |
- |
PaintInfo paintInfoForDescendants = paintInfo.forDescendants(); |
if (shouldPaintSelfBlockBackground(paintInfo.phase)) { |
- paintBoxShadow(paintInfo, paintOffset, Normal); |
- for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
- for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { |
- if (const LayoutTableCell* cell = |
- m_layoutTableSection.originatingCellAt(r, c)) { |
- paintBackgroundsBehindCell(*cell, paintInfoForDescendants, |
- paintOffset); |
- } |
- } |
- } |
- paintBoxShadow(paintInfo, paintOffset, Inset); |
+ paintBoxDecorationBackground(paintInfo, paintOffset, dirtiedRows, |
+ dirtiedColumns); |
} |
if (paintInfo.phase == PaintPhaseSelfBlockBackgroundOnly) |
@@ -220,28 +208,23 @@ void TableSectionPainter::paintObject(const PaintInfo& paintInfo, |
if (shouldPaintDescendantBlockBackgrounds(paintInfo.phase)) { |
for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); |
- // If a row has a layer, we'll paint row background in TableRowPainter. |
+ // If a row has a layer, we'll paint row background though |
+ // TableRowPainter::paint(). |
if (!row || row->hasSelfPaintingLayer()) |
continue; |
- |
- TableRowPainter rowPainter(*row); |
- rowPainter.paintBoxShadow(paintInfoForDescendants, paintOffset, Normal); |
- if (row->styleRef().hasBackground()) { |
- for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); |
- c++) { |
- if (const LayoutTableCell* cell = |
- m_layoutTableSection.originatingCellAt(r, c)) { |
- rowPainter.paintBackgroundBehindCell(*cell, paintInfoForDescendants, |
- paintOffset); |
- } |
- } |
- } |
- rowPainter.paintBoxShadow(paintInfoForDescendants, paintOffset, Inset); |
+ TableRowPainter(*row).paintBoxDecorationBackground( |
+ paintInfoForDescendants, paintOffset, dirtiedColumns); |
} |
} |
- const HashSet<LayoutTableCell*>& overflowingCells = |
- m_layoutTableSection.overflowingCells(); |
+ // This is tested after background painting because during background painting |
+ // we need to check validity of the previous background display item based on |
+ // dirtyRows and dirtyColumns. |
+ if (dirtiedRows.start() >= dirtiedRows.end() || |
+ dirtiedColumns.start() >= dirtiedColumns.end()) |
+ return; |
+ |
+ const auto& overflowingCells = m_layoutTableSection.overflowingCells(); |
if (!m_layoutTableSection.hasMultipleCellLevels() && |
overflowingCells.isEmpty()) { |
for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
@@ -249,9 +232,10 @@ void TableSectionPainter::paintObject(const PaintInfo& paintInfo, |
// TODO(crbug.com/577282): This painting order is inconsistent with other |
// outlines. |
if (row && !row->hasSelfPaintingLayer() && |
- shouldPaintSelfOutline(paintInfoForDescendants.phase)) |
+ shouldPaintSelfOutline(paintInfoForDescendants.phase)) { |
TableRowPainter(*row).paintOutline(paintInfoForDescendants, |
paintOffset); |
+ } |
for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { |
if (const LayoutTableCell* cell = |
m_layoutTableSection.originatingCellAt(r, c)) |
@@ -268,24 +252,24 @@ void TableSectionPainter::paintObject(const PaintInfo& paintInfo, |
// To make sure we properly paint the section, we paint all the overflowing |
// cells that we collected. |
- Vector<LayoutTableCell*> cells; |
+ Vector<const LayoutTableCell*> cells; |
copyToVector(overflowingCells, cells); |
- HashSet<LayoutTableCell*> spanningCells; |
+ HashSet<const LayoutTableCell*> spanningCells; |
for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); |
// TODO(crbug.com/577282): This painting order is inconsistent with other |
// outlines. |
if (row && !row->hasSelfPaintingLayer() && |
- shouldPaintSelfOutline(paintInfoForDescendants.phase)) |
+ shouldPaintSelfOutline(paintInfoForDescendants.phase)) { |
TableRowPainter(*row).paintOutline(paintInfoForDescendants, |
paintOffset); |
+ } |
unsigned nCols = m_layoutTableSection.numCols(r); |
for (unsigned c = dirtiedColumns.start(); |
c < nCols && c < dirtiedColumns.end(); c++) { |
- const LayoutTableSection::CellStruct& current = |
- m_layoutTableSection.cellAt(r, c); |
- for (LayoutTableCell* cell : current.cells) { |
+ const auto& cellStruct = m_layoutTableSection.cellAt(r, c); |
+ for (const auto* cell : cellStruct.cells) { |
if (overflowingCells.contains(cell)) |
continue; |
if (cell->rowSpan() > 1 || cell->colSpan() > 1) { |
@@ -298,17 +282,73 @@ void TableSectionPainter::paintObject(const PaintInfo& paintInfo, |
} |
// Sort the dirty cells by paint order. |
- if (!overflowingCells.size()) |
+ if (!overflowingCells.size()) { |
std::stable_sort(cells.begin(), cells.end(), compareCellPositions); |
- else |
+ } else { |
std::sort(cells.begin(), cells.end(), |
compareCellPositionsWithOverflowingCells); |
+ } |
- for (const LayoutTableCell* cell : cells) |
+ for (const auto* cell : cells) |
paintCell(*cell, paintInfoForDescendants, paintOffset); |
} |
} |
+void TableSectionPainter::paintBoxDecorationBackground( |
+ const PaintInfo& paintInfo, |
+ const LayoutPoint& paintOffset, |
+ const CellSpan& dirtiedRows, |
+ const CellSpan& dirtiedColumns) { |
+ bool mayHaveBackground = m_layoutTableSection.table()->hasColElements() || |
+ m_layoutTableSection.styleRef().hasBackground(); |
+ bool hasBoxShadow = m_layoutTableSection.styleRef().boxShadow(); |
+ if (!mayHaveBackground && !hasBoxShadow) |
+ return; |
+ |
+ PaintResult paintResult = |
+ dirtiedColumns == m_layoutTableSection.fullTableEffectiveColumnSpan() && |
+ dirtiedRows == m_layoutTableSection.fullSectionRowSpan() |
+ ? FullyPainted |
+ : MayBeClippedByPaintDirtyRect; |
+ m_layoutTableSection.getMutableForPainting().updatePaintResult( |
+ paintResult, paintInfo.cullRect()); |
+ |
+ if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible( |
+ paintInfo.context, m_layoutTableSection, |
+ DisplayItem::kBoxDecorationBackground)) |
+ return; |
+ |
+ LayoutRect bounds = BoxPainter(m_layoutTableSection) |
+ .boundsForDrawingRecorder(paintInfo, paintOffset); |
+ LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutTableSection, |
+ DisplayItem::kBoxDecorationBackground, |
+ bounds); |
+ LayoutRect paintRect(paintOffset, m_layoutTableSection.size()); |
+ |
+ if (hasBoxShadow) { |
+ BoxPainter::paintNormalBoxShadow(paintInfo, paintRect, |
+ m_layoutTableSection.styleRef()); |
+ } |
+ |
+ if (mayHaveBackground) { |
+ PaintInfo paintInfoForCells = paintInfo.forDescendants(); |
+ for (auto r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
+ for (auto c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { |
+ if (const auto* cell = m_layoutTableSection.originatingCellAt(r, c)) { |
+ paintBackgroundsBehindCell(*cell, paintInfoForCells, paintOffset); |
+ } |
+ } |
+ } |
+ } |
+ |
+ if (hasBoxShadow) { |
+ // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting |
+ // paintRect by half widths of collapsed borders. |
+ BoxPainter::paintInsetBoxShadow(paintInfo, paintRect, |
+ m_layoutTableSection.styleRef()); |
+ } |
+} |
+ |
void TableSectionPainter::paintBackgroundsBehindCell( |
const LayoutTableCell& cell, |
const PaintInfo& paintInfoForCells, |
@@ -333,20 +373,20 @@ void TableSectionPainter::paintBackgroundsBehindCell( |
// transparency layer (potentially) for the table row group. Note that we |
// deliberately ignore whether or not the cell has a layer, since these |
// backgrounds paint "behind" the cell. |
- if (columnGroup && columnGroup->styleRef().hasBackground()) |
+ if (columnGroup && columnGroup->styleRef().hasBackground()) { |
tableCellPainter.paintContainerBackgroundBehindCell( |
- paintInfoForCells, cellPoint, *columnGroup, |
- DisplayItem::kTableCellBackgroundFromColumnGroup); |
- if (column && column->styleRef().hasBackground()) |
- tableCellPainter.paintContainerBackgroundBehindCell( |
- paintInfoForCells, cellPoint, *column, |
- DisplayItem::kTableCellBackgroundFromColumn); |
+ paintInfoForCells, cellPoint, *columnGroup); |
+ } |
+ if (column && column->styleRef().hasBackground()) { |
+ tableCellPainter.paintContainerBackgroundBehindCell(paintInfoForCells, |
+ cellPoint, *column); |
+ } |
// Paint the row group next. |
- if (m_layoutTableSection.styleRef().hasBackground()) |
+ if (m_layoutTableSection.styleRef().hasBackground()) { |
tableCellPainter.paintContainerBackgroundBehindCell( |
- paintInfoForCells, cellPoint, m_layoutTableSection, |
- DisplayItem::kTableCellBackgroundFromSection); |
+ paintInfoForCells, cellPoint, m_layoutTableSection); |
+ } |
} |
void TableSectionPainter::paintCell(const LayoutTableCell& cell, |
@@ -359,34 +399,4 @@ void TableSectionPainter::paintCell(const LayoutTableCell& cell, |
} |
} |
-void TableSectionPainter::paintBoxShadow(const PaintInfo& paintInfo, |
- const LayoutPoint& paintOffset, |
- ShadowStyle shadowStyle) { |
- DCHECK(shouldPaintSelfBlockBackground(paintInfo.phase)); |
- if (!m_layoutTableSection.styleRef().boxShadow()) |
- return; |
- |
- DisplayItem::Type type = shadowStyle == Normal |
- ? DisplayItem::kTableSectionBoxShadowNormal |
- : DisplayItem::kTableSectionBoxShadowInset; |
- if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible( |
- paintInfo.context, m_layoutTableSection, type)) |
- return; |
- |
- LayoutRect bounds = BoxPainter(m_layoutTableSection) |
- .boundsForDrawingRecorder(paintInfo, paintOffset); |
- LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutTableSection, |
- type, bounds); |
- LayoutRect paintRect(paintOffset, m_layoutTableSection.size()); |
- if (shadowStyle == Normal) { |
- BoxPainter::paintNormalBoxShadow(paintInfo, paintRect, |
- m_layoutTableSection.styleRef()); |
- } else { |
- // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting |
- // paintRect by half widths of collapsed borders. |
- BoxPainter::paintInsetBoxShadow(paintInfo, paintRect, |
- m_layoutTableSection.styleRef()); |
- } |
-} |
- |
} // namespace blink |