Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: third_party/WebKit/Source/core/paint/TableSectionPainter.cpp

Issue 1983853003: Refactor background painting behind table cells (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/paint/TableSectionPainter.h" 5 #include "core/paint/TableSectionPainter.h"
6 6
7 #include "core/layout/LayoutTable.h" 7 #include "core/layout/LayoutTable.h"
8 #include "core/layout/LayoutTableCell.h" 8 #include "core/layout/LayoutTableCell.h"
9 #include "core/layout/LayoutTableCol.h" 9 #include "core/layout/LayoutTableCol.h"
10 #include "core/layout/LayoutTableRow.h" 10 #include "core/layout/LayoutTableRow.h"
11 #include "core/paint/BlockPainter.h" 11 #include "core/paint/BlockPainter.h"
12 #include "core/paint/BoxClipper.h" 12 #include "core/paint/BoxClipper.h"
13 #include "core/paint/BoxPainter.h"
13 #include "core/paint/LayoutObjectDrawingRecorder.h" 14 #include "core/paint/LayoutObjectDrawingRecorder.h"
14 #include "core/paint/ObjectPainter.h" 15 #include "core/paint/ObjectPainter.h"
15 #include "core/paint/PaintInfo.h" 16 #include "core/paint/PaintInfo.h"
16 #include "core/paint/TableCellPainter.h" 17 #include "core/paint/TableCellPainter.h"
17 #include "core/paint/TableRowPainter.h" 18 #include "core/paint/TableRowPainter.h"
18 #include <algorithm> 19 #include <algorithm>
19 20
20 namespace blink { 21 namespace blink {
21 22
23 inline const LayoutTableCell* TableSectionPainter::primaryCellToPaint(unsigned r ow, unsigned column, const CellSpan& dirtiedRows, const CellSpan& dirtiedColumns ) const
24 {
25 DCHECK(row >= dirtiedRows.start() && row < dirtiedRows.end());
26 DCHECK(column >= dirtiedColumns.start() && column < dirtiedColumns.end());
27
28 const LayoutTableCell* cell = m_layoutTableSection.primaryCellAt(row, column );
29 if (!cell)
30 return nullptr;
31 // We have painted (row, column) when painting (row - 1, column).
32 if (row > dirtiedRows.start() && m_layoutTableSection.primaryCellAt(row - 1, column) == cell)
33 return nullptr;
34 // We have painted (row, column) when painting (row, column -1).
35 if (column > dirtiedColumns.start() && m_layoutTableSection.primaryCellAt(ro w, column - 1) == cell)
36 return nullptr;
37 return cell;
38 }
39
22 void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& p aintOffset) 40 void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& p aintOffset)
23 { 41 {
24 ASSERT(!m_layoutTableSection.needsLayout()); 42 DCHECK(!m_layoutTableSection.needsLayout());
25 // avoid crashing on bugs that cause us to paint with dirty layout 43 // avoid crashing on bugs that cause us to paint with dirty layout
26 if (m_layoutTableSection.needsLayout()) 44 if (m_layoutTableSection.needsLayout())
27 return; 45 return;
28 46
29 unsigned totalRows = m_layoutTableSection.numRows(); 47 unsigned totalRows = m_layoutTableSection.numRows();
30 unsigned totalCols = m_layoutTableSection.table()->numEffectiveColumns(); 48 unsigned totalCols = m_layoutTableSection.table()->numEffectiveColumns();
31 49
32 if (!totalRows || !totalCols) 50 if (!totalRows || !totalCols)
33 return; 51 return;
34 52
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 localPaintInvalidationRect.moveBy(-paintOffset); 119 localPaintInvalidationRect.moveBy(-paintOffset);
102 120
103 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode AndDirection(localPaintInvalidationRect); 121 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode AndDirection(localPaintInvalidationRect);
104 122
105 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); 123 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect);
106 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedEffectiveColumns(table AlignedRect); 124 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedEffectiveColumns(table AlignedRect);
107 125
108 if (dirtiedColumns.start() >= dirtiedColumns.end()) 126 if (dirtiedColumns.start() >= dirtiedColumns.end())
109 return; 127 return;
110 128
111 PaintInfo paintInfoForCells = paintInfo.forDescendants(); 129 PaintInfo paintInfoForDescendants = paintInfo.forDescendants();
112 const HashSet<LayoutTableCell*>& overflowingCells = m_layoutTableSection.ove rflowingCells(); 130
113 if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.size( )) { 131 if (shouldPaintSelfBlockBackground(paintInfo.phase)) {
114 // Draw the dirty cells in the order that they appear. 132 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
133 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
134 if (const LayoutTableCell* cell = primaryCellToPaint(r, c, dirti edRows, dirtiedColumns))
135 paintBackgroundsBehindCell(*cell, paintInfoForDescendants, p aintOffset);
136 }
137 }
138 }
139
140 if (paintInfo.phase == PaintPhaseSelfBlockBackgroundOnly)
141 return;
142
143 if (shouldPaintDescendantBlockBackgrounds(paintInfo.phase)) {
115 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { 144 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
116 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r ); 145 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r );
117 // TODO(wangxianzhu): This painting order is inconsistent with other outlines. crbug.com/577282. 146 // If a row has a layer, we'll paint row background in TableRowPaint er.
118 if (row && !row->hasSelfPaintingLayer()) 147 if (!row || row->hasSelfPaintingLayer() || !row->hasBackground())
119 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain tOffset); 148 continue;
149
150 TableRowPainter rowPainter(*row);
120 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { 151 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
121 const LayoutTableSection::CellStruct& current = m_layoutTableSec tion.cellAt(r, c); 152 if (const LayoutTableCell* cell = primaryCellToPaint(r, c, dirti edRows, dirtiedColumns))
122 const LayoutTableCell* cell = current.primaryCell(); 153 rowPainter.paintBackgroundBehindCell(*cell, paintInfoForDesc endants, paintOffset);
123 if (!cell || (r > dirtiedRows.start() && m_layoutTableSection.pr imaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_layoutTableSe ction.primaryCellAt(r, c - 1) == cell)) 154 }
124 continue; 155 }
125 paintCell(*cell, paintInfo.phase, paintInfoForCells, paintOffset ); 156 }
157
158 const HashSet<LayoutTableCell*>& overflowingCells = m_layoutTableSection.ove rflowingCells();
159 if (!m_layoutTableSection.hasMultipleCellLevels() && overflowingCells.isEmpt y()) {
160 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
161 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r );
162 // TODO(crbug.com/577282): This painting order is inconsistent with other outlines.
163 if (row && !row->hasSelfPaintingLayer() && shouldPaintSelfOutline(pa intInfoForDescendants.phase))
164 TableRowPainter(*row).paintOutline(paintInfoForDescendants, pain tOffset);
165 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
166 if (const LayoutTableCell * cell = primaryCellToPaint(r, c, dirt iedRows, dirtiedColumns))
167 paintCell(*cell, paintInfoForDescendants, paintOffset);
126 } 168 }
127 } 169 }
128 } else { 170 } else {
129 // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet. 171 // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
130 #if ENABLE(ASSERT) 172 DCHECK(overflowingCells.size() < m_layoutTableSection.numRows() * m_layo utTableSection.table()->effectiveColumns().size() * gMaxAllowedOverflowingCellRa tioForFastPaintPath);
131 unsigned totalRows = m_layoutTableSection.numRows();
132 unsigned totalCols = m_layoutTableSection.table()->effectiveColumns().si ze();
133 ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowedOver flowingCellRatioForFastPaintPath);
134 #endif
135 173
136 // To make sure we properly paint invalidate the section, we paint inval idated all the overflowing cells that we collected. 174 // To make sure we properly paint the section, we paint all the overflow ing cells that we collected.
137 Vector<LayoutTableCell*> cells; 175 Vector<LayoutTableCell*> cells;
138 copyToVector(overflowingCells, cells); 176 copyToVector(overflowingCells, cells);
139 177
140 HashSet<LayoutTableCell*> spanningCells; 178 HashSet<LayoutTableCell*> spanningCells;
141
142 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { 179 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
143 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r ); 180 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r );
144 // TODO(wangxianzhu): This painting order is inconsistent with other outlines. crbug.com/577282. 181 // TODO(crbug.com/577282): This painting order is inconsistent with other outlines.
145 if (row && !row->hasSelfPaintingLayer()) 182 if (row && !row->hasSelfPaintingLayer() && shouldPaintSelfOutline(pa intInfoForDescendants.phase))
146 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain tOffset); 183 TableRowPainter(*row).paintOutline(paintInfoForDescendants, pain tOffset);
147 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { 184 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
148 const LayoutTableSection::CellStruct& current = m_layoutTableSec tion.cellAt(r, c); 185 const LayoutTableSection::CellStruct& current = m_layoutTableSec tion.cellAt(r, c);
149 if (!current.hasCells()) 186 for (LayoutTableCell* cell : current.cells) {
150 continue; 187 if (overflowingCells.contains(cell))
151 for (unsigned i = 0; i < current.cells.size(); ++i) {
152 if (overflowingCells.contains(current.cells[i]))
153 continue; 188 continue;
154 189 if (cell->rowSpan() > 1 || cell->colSpan() > 1) {
155 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->col Span() > 1) { 190 if (!spanningCells.add(cell).isNewEntry)
156 if (!spanningCells.add(current.cells[i]).isNewEntry)
157 continue; 191 continue;
158 } 192 }
159 193 cells.append(cell);
160 cells.append(current.cells[i]);
161 } 194 }
162 } 195 }
163 } 196 }
164 197
165 // Sort the dirty cells by paint order. 198 // Sort the dirty cells by paint order.
166 if (!overflowingCells.size()) 199 if (!overflowingCells.size())
167 std::stable_sort(cells.begin(), cells.end(), compareCellPositions); 200 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
168 else 201 else
169 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverfl owingCells); 202 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverfl owingCells);
170 203
171 for (unsigned i = 0; i < cells.size(); ++i) 204 for (const LayoutTableCell* cell : cells)
172 paintCell(*cells[i], paintInfo.phase, paintInfoForCells, paintOffset ); 205 paintCell(*cell, paintInfoForDescendants, paintOffset);
173 } 206 }
174 } 207 }
175 208
176 void TableSectionPainter::paintCell(const LayoutTableCell& cell, PaintPhase orig inalPaintPhase, const PaintInfo& paintInfoForCells, const LayoutPoint& paintOffs et) 209 void TableSectionPainter::paintBackgroundsBehindCell(const LayoutTableCell& cell , const PaintInfo& paintInfoForCells, const LayoutPoint& paintOffset)
177 { 210 {
178 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cel l, paintOffset); 211 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cel l, paintOffset);
179 const LayoutTableRow* row = toLayoutTableRow(cell.parent());
180 212
181 if (!BlockPainter(cell).intersectsPaintRect(paintInfoForCells, paintOffset + cell.location())) 213 // We need to handle painting a stack of backgrounds. This stack (from botto m to top) consists of
182 return; 214 // the column group, column, row group, row, and then the cell.
Xianzhu 2016/05/16 21:47:53 The caller of paintCell() has ensured this. Removi
chrishtr 2016/05/17 21:22:19 Can you show me where? I can't see it yet.
Xianzhu 2016/05/17 21:49:57 See new line 121-127, which calculates dirtiedRows
183 215
184 if (shouldPaintSelfBlockBackground(originalPaintPhase)) { 216 LayoutTable::ColAndColGroup colAndColGroup = m_layoutTableSection.table()->c olElementAtAbsoluteColumn(cell.absoluteColumnIndex());
185 // We need to handle painting a stack of backgrounds. This stack (from b ottom to top) consists of 217 LayoutTableCol* column = colAndColGroup.col;
186 // the column group, column, row group, row, and then the cell. 218 LayoutTableCol* columnGroup = colAndColGroup.colgroup;
219 TableCellPainter tableCellPainter(cell);
187 220
188 LayoutTable::ColAndColGroup colAndColGroup = m_layoutTableSection.table( )->colElementAtAbsoluteColumn(cell.absoluteColumnIndex()); 221 // Column groups and columns first.
189 LayoutTableCol* column = colAndColGroup.col; 222 // FIXME: Columns and column groups do not currently support opacity, and th ey are being painted "too late" in
190 LayoutTableCol* columnGroup = colAndColGroup.colgroup; 223 // the stack, since we have already opened a transparency layer (potentially ) for the table row group.
191 TableCellPainter tableCellPainter(cell); 224 // Note that we deliberately ignore whether or not the cell has a layer, sin ce these backgrounds paint "behind" the
225 // cell.
226 if (columnGroup && columnGroup->hasBackground())
227 tableCellPainter.paintContainerBackgroundBehindCell(paintInfoForCells, c ellPoint, *columnGroup, DisplayItem::TableCellBackgroundFromColumnGroup);
228 if (column && column->hasBackground())
229 tableCellPainter.paintContainerBackgroundBehindCell(paintInfoForCells, c ellPoint, *column, DisplayItem::TableCellBackgroundFromColumn);
192 230
193 // Column groups and columns first. 231 // Paint the row group next.
194 // FIXME: Columns and column groups do not currently support opacity, an d they are being painted "too late" in 232 if (m_layoutTableSection.hasBackground())
195 // the stack, since we have already opened a transparency layer (potenti ally) for the table row group. 233 tableCellPainter.paintContainerBackgroundBehindCell(paintInfoForCells, c ellPoint, m_layoutTableSection, DisplayItem::TableCellBackgroundFromSection);
196 // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the 234 }
197 // cell.
198 if (columnGroup && columnGroup->hasBackground())
199 tableCellPainter.paintBackgroundsBehindCell(paintInfoForCells, cellP oint, columnGroup, DisplayItem::TableCellBackgroundFromColumnGroup);
200 if (column && column->hasBackground())
201 tableCellPainter.paintBackgroundsBehindCell(paintInfoForCells, cellP oint, column, DisplayItem::TableCellBackgroundFromColumn);
202 235
203 // Paint the row group next. 236 void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo & paintInfoForCells, const LayoutPoint& paintOffset)
204 if (m_layoutTableSection.hasBackground()) 237 {
205 tableCellPainter.paintBackgroundsBehindCell(paintInfoForCells, cellP oint, &m_layoutTableSection, DisplayItem::TableCellBackgroundFromSection); 238 if (!cell.hasSelfPaintingLayer() && !cell.row()->hasSelfPaintingLayer()) {
239 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild( &cell, paintOffset);
240 cell.paint(paintInfoForCells, cellPoint);
206 } 241 }
207
208 if (shouldPaintDescendantBlockBackgrounds(originalPaintPhase)) {
209 // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
210 // painting the row background for the cell.
211 if (row->hasBackground() && !row->hasSelfPaintingLayer())
212 TableCellPainter(cell).paintBackgroundsBehindCell(paintInfoForCells, cellPoint, row, DisplayItem::TableCellBackgroundFromRow);
213 }
214
215 if (originalPaintPhase != PaintPhaseSelfBlockBackgroundOnly && !cell.hasSelf PaintingLayer() && !row->hasSelfPaintingLayer())
216 cell.paint(paintInfoForCells, cellPoint);
217 } 242 }
218 243
219 } // namespace blink 244 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698