| 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
 | 
| 
 |