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

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

Issue 2786463004: Paint backgrounds of a table section/row in one display item (Closed)
Patch Set: - Created 3 years, 8 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/LayoutTableCell.h" 7 #include "core/layout/LayoutTableCell.h"
8 #include "core/layout/LayoutTableCol.h" 8 #include "core/layout/LayoutTableCol.h"
9 #include "core/layout/LayoutTableRow.h" 9 #include "core/layout/LayoutTableRow.h"
10 #include "core/paint/BoxClipper.h" 10 #include "core/paint/BoxClipper.h"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 boxClipper.emplace(m_layoutTableSection, paintInfo, adjustedPaintOffset, 101 boxClipper.emplace(m_layoutTableSection, paintInfo, adjustedPaintOffset,
102 ForceContentsClip); 102 ForceContentsClip);
103 paintObject(paintInfo, adjustedPaintOffset); 103 paintObject(paintInfo, adjustedPaintOffset);
104 } 104 }
105 105
106 if (shouldPaintSelfOutline(paintInfo.phase)) 106 if (shouldPaintSelfOutline(paintInfo.phase))
107 ObjectPainter(m_layoutTableSection) 107 ObjectPainter(m_layoutTableSection)
108 .paintOutline(paintInfo, adjustedPaintOffset); 108 .paintOutline(paintInfo, adjustedPaintOffset);
109 } 109 }
110 110
111 static inline bool compareCellPositions(LayoutTableCell* elem1, 111 static inline bool compareCellPositions(const LayoutTableCell* elem1,
112 LayoutTableCell* elem2) { 112 const LayoutTableCell* elem2) {
113 return elem1->rowIndex() < elem2->rowIndex(); 113 return elem1->rowIndex() < elem2->rowIndex();
114 } 114 }
115 115
116 // This comparison is used only when we have overflowing cells as we have an 116 // This comparison is used only when we have overflowing cells as we have an
117 // unsorted array to sort. We thus need to sort both on rows and columns to 117 // unsorted array to sort. We thus need to sort both on rows and columns to
118 // properly issue paint invalidations. 118 // properly issue paint invalidations.
119 static inline bool compareCellPositionsWithOverflowingCells( 119 static inline bool compareCellPositionsWithOverflowingCells(
120 LayoutTableCell* elem1, 120 const LayoutTableCell* elem1,
121 LayoutTableCell* elem2) { 121 const LayoutTableCell* elem2) {
122 if (elem1->rowIndex() != elem2->rowIndex()) 122 if (elem1->rowIndex() != elem2->rowIndex())
123 return elem1->rowIndex() < elem2->rowIndex(); 123 return elem1->rowIndex() < elem2->rowIndex();
124 124
125 return elem1->absoluteColumnIndex() < elem2->absoluteColumnIndex(); 125 return elem1->absoluteColumnIndex() < elem2->absoluteColumnIndex();
126 } 126 }
127 127
128 void TableSectionPainter::paintCollapsedBorders( 128 void TableSectionPainter::paintCollapsedBorders(
129 const PaintInfo& paintInfo, 129 const PaintInfo& paintInfo,
130 const LayoutPoint& paintOffset, 130 const LayoutPoint& paintOffset,
131 const CollapsedBorderValue& currentBorderValue) { 131 const CollapsedBorderValue& currentBorderValue) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 localVisualRect.moveBy(-paintOffset); 188 localVisualRect.moveBy(-paintOffset);
189 189
190 LayoutRect tableAlignedRect = 190 LayoutRect tableAlignedRect =
191 m_layoutTableSection.logicalRectForWritingModeAndDirection( 191 m_layoutTableSection.logicalRectForWritingModeAndDirection(
192 localVisualRect); 192 localVisualRect);
193 193
194 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); 194 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect);
195 CellSpan dirtiedColumns = 195 CellSpan dirtiedColumns =
196 m_layoutTableSection.dirtiedEffectiveColumns(tableAlignedRect); 196 m_layoutTableSection.dirtiedEffectiveColumns(tableAlignedRect);
197 197
198 if (dirtiedColumns.start() >= dirtiedColumns.end())
199 return;
200
201 PaintInfo paintInfoForDescendants = paintInfo.forDescendants(); 198 PaintInfo paintInfoForDescendants = paintInfo.forDescendants();
202 199
203 if (shouldPaintSelfBlockBackground(paintInfo.phase)) { 200 if (shouldPaintSelfBlockBackground(paintInfo.phase)) {
204 paintBoxShadow(paintInfo, paintOffset, Normal); 201 paintBoxDecorationBackground(paintInfo, paintOffset, dirtiedRows,
205 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { 202 dirtiedColumns);
206 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
207 if (const LayoutTableCell* cell =
208 m_layoutTableSection.originatingCellAt(r, c)) {
209 paintBackgroundsBehindCell(*cell, paintInfoForDescendants,
210 paintOffset);
211 }
212 }
213 }
214 paintBoxShadow(paintInfo, paintOffset, Inset);
215 } 203 }
216 204
217 if (paintInfo.phase == PaintPhaseSelfBlockBackgroundOnly) 205 if (paintInfo.phase == PaintPhaseSelfBlockBackgroundOnly)
218 return; 206 return;
219 207
220 if (shouldPaintDescendantBlockBackgrounds(paintInfo.phase)) { 208 if (shouldPaintDescendantBlockBackgrounds(paintInfo.phase)) {
221 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { 209 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
222 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); 210 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r);
223 // If a row has a layer, we'll paint row background in TableRowPainter. 211 // If a row has a layer, we'll paint row background though
212 // TableRowPainter::paint().
224 if (!row || row->hasSelfPaintingLayer()) 213 if (!row || row->hasSelfPaintingLayer())
225 continue; 214 continue;
226 215 TableRowPainter(*row).paintBoxDecorationBackground(
227 TableRowPainter rowPainter(*row); 216 paintInfoForDescendants, paintOffset, dirtiedColumns);
228 rowPainter.paintBoxShadow(paintInfoForDescendants, paintOffset, Normal);
229 if (row->styleRef().hasBackground()) {
230 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
231 c++) {
232 if (const LayoutTableCell* cell =
233 m_layoutTableSection.originatingCellAt(r, c)) {
234 rowPainter.paintBackgroundBehindCell(*cell, paintInfoForDescendants,
235 paintOffset);
236 }
237 }
238 }
239 rowPainter.paintBoxShadow(paintInfoForDescendants, paintOffset, Inset);
240 } 217 }
241 } 218 }
242 219
243 const HashSet<LayoutTableCell*>& overflowingCells = 220 // This is tested after background painting because during background painting
244 m_layoutTableSection.overflowingCells(); 221 // we need to check validity of the previous background display item based on
222 // dirtyRows and dirtyColumns.
223 if (dirtiedRows.start() >= dirtiedRows.end() ||
224 dirtiedColumns.start() >= dirtiedColumns.end())
225 return;
226
227 const auto& overflowingCells = m_layoutTableSection.overflowingCells();
245 if (!m_layoutTableSection.hasMultipleCellLevels() && 228 if (!m_layoutTableSection.hasMultipleCellLevels() &&
246 overflowingCells.isEmpty()) { 229 overflowingCells.isEmpty()) {
247 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { 230 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
248 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); 231 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r);
249 // TODO(crbug.com/577282): This painting order is inconsistent with other 232 // TODO(crbug.com/577282): This painting order is inconsistent with other
250 // outlines. 233 // outlines.
251 if (row && !row->hasSelfPaintingLayer() && 234 if (row && !row->hasSelfPaintingLayer() &&
252 shouldPaintSelfOutline(paintInfoForDescendants.phase)) 235 shouldPaintSelfOutline(paintInfoForDescendants.phase)) {
253 TableRowPainter(*row).paintOutline(paintInfoForDescendants, 236 TableRowPainter(*row).paintOutline(paintInfoForDescendants,
254 paintOffset); 237 paintOffset);
238 }
255 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { 239 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
256 if (const LayoutTableCell* cell = 240 if (const LayoutTableCell* cell =
257 m_layoutTableSection.originatingCellAt(r, c)) 241 m_layoutTableSection.originatingCellAt(r, c))
258 paintCell(*cell, paintInfoForDescendants, paintOffset); 242 paintCell(*cell, paintInfoForDescendants, paintOffset);
259 } 243 }
260 } 244 }
261 } else { 245 } else {
262 // The overflowing cells should be scarce to avoid adding a lot of cells to 246 // The overflowing cells should be scarce to avoid adding a lot of cells to
263 // the HashSet. 247 // the HashSet.
264 DCHECK(overflowingCells.size() < 248 DCHECK(overflowingCells.size() <
265 m_layoutTableSection.numRows() * 249 m_layoutTableSection.numRows() *
266 m_layoutTableSection.table()->effectiveColumns().size() * 250 m_layoutTableSection.table()->effectiveColumns().size() *
267 gMaxAllowedOverflowingCellRatioForFastPaintPath); 251 gMaxAllowedOverflowingCellRatioForFastPaintPath);
268 252
269 // To make sure we properly paint the section, we paint all the overflowing 253 // To make sure we properly paint the section, we paint all the overflowing
270 // cells that we collected. 254 // cells that we collected.
271 Vector<LayoutTableCell*> cells; 255 Vector<const LayoutTableCell*> cells;
272 copyToVector(overflowingCells, cells); 256 copyToVector(overflowingCells, cells);
273 257
274 HashSet<LayoutTableCell*> spanningCells; 258 HashSet<const LayoutTableCell*> spanningCells;
275 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { 259 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
276 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); 260 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r);
277 // TODO(crbug.com/577282): This painting order is inconsistent with other 261 // TODO(crbug.com/577282): This painting order is inconsistent with other
278 // outlines. 262 // outlines.
279 if (row && !row->hasSelfPaintingLayer() && 263 if (row && !row->hasSelfPaintingLayer() &&
280 shouldPaintSelfOutline(paintInfoForDescendants.phase)) 264 shouldPaintSelfOutline(paintInfoForDescendants.phase)) {
281 TableRowPainter(*row).paintOutline(paintInfoForDescendants, 265 TableRowPainter(*row).paintOutline(paintInfoForDescendants,
282 paintOffset); 266 paintOffset);
267 }
283 unsigned nCols = m_layoutTableSection.numCols(r); 268 unsigned nCols = m_layoutTableSection.numCols(r);
284 for (unsigned c = dirtiedColumns.start(); 269 for (unsigned c = dirtiedColumns.start();
285 c < nCols && c < dirtiedColumns.end(); c++) { 270 c < nCols && c < dirtiedColumns.end(); c++) {
286 const LayoutTableSection::CellStruct& current = 271 const auto& cellStruct = m_layoutTableSection.cellAt(r, c);
287 m_layoutTableSection.cellAt(r, c); 272 for (const auto* cell : cellStruct.cells) {
288 for (LayoutTableCell* cell : current.cells) {
289 if (overflowingCells.contains(cell)) 273 if (overflowingCells.contains(cell))
290 continue; 274 continue;
291 if (cell->rowSpan() > 1 || cell->colSpan() > 1) { 275 if (cell->rowSpan() > 1 || cell->colSpan() > 1) {
292 if (!spanningCells.insert(cell).isNewEntry) 276 if (!spanningCells.insert(cell).isNewEntry)
293 continue; 277 continue;
294 } 278 }
295 cells.push_back(cell); 279 cells.push_back(cell);
296 } 280 }
297 } 281 }
298 } 282 }
299 283
300 // Sort the dirty cells by paint order. 284 // Sort the dirty cells by paint order.
301 if (!overflowingCells.size()) 285 if (!overflowingCells.size()) {
302 std::stable_sort(cells.begin(), cells.end(), compareCellPositions); 286 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
303 else 287 } else {
304 std::sort(cells.begin(), cells.end(), 288 std::sort(cells.begin(), cells.end(),
305 compareCellPositionsWithOverflowingCells); 289 compareCellPositionsWithOverflowingCells);
290 }
306 291
307 for (const LayoutTableCell* cell : cells) 292 for (const auto* cell : cells)
308 paintCell(*cell, paintInfoForDescendants, paintOffset); 293 paintCell(*cell, paintInfoForDescendants, paintOffset);
309 } 294 }
310 } 295 }
311 296
297 void TableSectionPainter::paintBoxDecorationBackground(
298 const PaintInfo& paintInfo,
299 const LayoutPoint& paintOffset,
300 const CellSpan& dirtiedRows,
301 const CellSpan& dirtiedColumns) {
302 bool mayHaveBackground = m_layoutTableSection.table()->hasColElements() ||
303 m_layoutTableSection.styleRef().hasBackground();
304 bool hasBoxShadow = m_layoutTableSection.styleRef().boxShadow();
305 if (!mayHaveBackground && !hasBoxShadow)
306 return;
307
308 PaintResult paintResult =
309 dirtiedColumns == m_layoutTableSection.fullTableEffectiveColumnSpan() &&
310 dirtiedRows == m_layoutTableSection.fullSectionRowSpan()
311 ? FullyPainted
312 : MayBeClippedByPaintDirtyRect;
313 m_layoutTableSection.getMutableForPainting().updatePaintResult(
314 paintResult, paintInfo.cullRect());
315
316 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
317 paintInfo.context, m_layoutTableSection,
318 DisplayItem::kBoxDecorationBackground))
319 return;
320
321 LayoutRect bounds = BoxPainter(m_layoutTableSection)
322 .boundsForDrawingRecorder(paintInfo, paintOffset);
323 LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutTableSection,
324 DisplayItem::kBoxDecorationBackground,
325 bounds);
326 LayoutRect paintRect(paintOffset, m_layoutTableSection.size());
327
328 if (hasBoxShadow) {
329 BoxPainter::paintNormalBoxShadow(paintInfo, paintRect,
330 m_layoutTableSection.styleRef());
331 }
332
333 if (mayHaveBackground) {
334 PaintInfo paintInfoForCells = paintInfo.forDescendants();
335 for (auto r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
336 for (auto c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
337 if (const auto* cell = m_layoutTableSection.originatingCellAt(r, c)) {
338 paintBackgroundsBehindCell(*cell, paintInfoForCells, paintOffset);
339 }
340 }
341 }
342 }
343
344 if (hasBoxShadow) {
345 // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting
346 // paintRect by half widths of collapsed borders.
347 BoxPainter::paintInsetBoxShadow(paintInfo, paintRect,
348 m_layoutTableSection.styleRef());
349 }
350 }
351
312 void TableSectionPainter::paintBackgroundsBehindCell( 352 void TableSectionPainter::paintBackgroundsBehindCell(
313 const LayoutTableCell& cell, 353 const LayoutTableCell& cell,
314 const PaintInfo& paintInfoForCells, 354 const PaintInfo& paintInfoForCells,
315 const LayoutPoint& paintOffset) { 355 const LayoutPoint& paintOffset) {
316 LayoutPoint cellPoint = 356 LayoutPoint cellPoint =
317 m_layoutTableSection.flipForWritingModeForChild(&cell, paintOffset); 357 m_layoutTableSection.flipForWritingModeForChild(&cell, paintOffset);
318 358
319 // We need to handle painting a stack of backgrounds. This stack (from bottom 359 // We need to handle painting a stack of backgrounds. This stack (from bottom
320 // to top) consists of the column group, column, row group, row, and then the 360 // to top) consists of the column group, column, row group, row, and then the
321 // cell. 361 // cell.
322 362
323 LayoutTable::ColAndColGroup colAndColGroup = 363 LayoutTable::ColAndColGroup colAndColGroup =
324 m_layoutTableSection.table()->colElementAtAbsoluteColumn( 364 m_layoutTableSection.table()->colElementAtAbsoluteColumn(
325 cell.absoluteColumnIndex()); 365 cell.absoluteColumnIndex());
326 LayoutTableCol* column = colAndColGroup.col; 366 LayoutTableCol* column = colAndColGroup.col;
327 LayoutTableCol* columnGroup = colAndColGroup.colgroup; 367 LayoutTableCol* columnGroup = colAndColGroup.colgroup;
328 TableCellPainter tableCellPainter(cell); 368 TableCellPainter tableCellPainter(cell);
329 369
330 // Column groups and columns first. 370 // Column groups and columns first.
331 // FIXME: Columns and column groups do not currently support opacity, and they 371 // FIXME: Columns and column groups do not currently support opacity, and they
332 // are being painted "too late" in the stack, since we have already opened a 372 // are being painted "too late" in the stack, since we have already opened a
333 // transparency layer (potentially) for the table row group. Note that we 373 // transparency layer (potentially) for the table row group. Note that we
334 // deliberately ignore whether or not the cell has a layer, since these 374 // deliberately ignore whether or not the cell has a layer, since these
335 // backgrounds paint "behind" the cell. 375 // backgrounds paint "behind" the cell.
336 if (columnGroup && columnGroup->styleRef().hasBackground()) 376 if (columnGroup && columnGroup->styleRef().hasBackground()) {
337 tableCellPainter.paintContainerBackgroundBehindCell( 377 tableCellPainter.paintContainerBackgroundBehindCell(
338 paintInfoForCells, cellPoint, *columnGroup, 378 paintInfoForCells, cellPoint, *columnGroup);
339 DisplayItem::kTableCellBackgroundFromColumnGroup); 379 }
340 if (column && column->styleRef().hasBackground()) 380 if (column && column->styleRef().hasBackground()) {
341 tableCellPainter.paintContainerBackgroundBehindCell( 381 tableCellPainter.paintContainerBackgroundBehindCell(paintInfoForCells,
342 paintInfoForCells, cellPoint, *column, 382 cellPoint, *column);
343 DisplayItem::kTableCellBackgroundFromColumn); 383 }
344 384
345 // Paint the row group next. 385 // Paint the row group next.
346 if (m_layoutTableSection.styleRef().hasBackground()) 386 if (m_layoutTableSection.styleRef().hasBackground()) {
347 tableCellPainter.paintContainerBackgroundBehindCell( 387 tableCellPainter.paintContainerBackgroundBehindCell(
348 paintInfoForCells, cellPoint, m_layoutTableSection, 388 paintInfoForCells, cellPoint, m_layoutTableSection);
349 DisplayItem::kTableCellBackgroundFromSection); 389 }
350 } 390 }
351 391
352 void TableSectionPainter::paintCell(const LayoutTableCell& cell, 392 void TableSectionPainter::paintCell(const LayoutTableCell& cell,
353 const PaintInfo& paintInfoForCells, 393 const PaintInfo& paintInfoForCells,
354 const LayoutPoint& paintOffset) { 394 const LayoutPoint& paintOffset) {
355 if (!cell.hasSelfPaintingLayer() && !cell.row()->hasSelfPaintingLayer()) { 395 if (!cell.hasSelfPaintingLayer() && !cell.row()->hasSelfPaintingLayer()) {
356 LayoutPoint cellPoint = 396 LayoutPoint cellPoint =
357 m_layoutTableSection.flipForWritingModeForChild(&cell, paintOffset); 397 m_layoutTableSection.flipForWritingModeForChild(&cell, paintOffset);
358 cell.paint(paintInfoForCells, cellPoint); 398 cell.paint(paintInfoForCells, cellPoint);
359 } 399 }
360 } 400 }
361 401
362 void TableSectionPainter::paintBoxShadow(const PaintInfo& paintInfo,
363 const LayoutPoint& paintOffset,
364 ShadowStyle shadowStyle) {
365 DCHECK(shouldPaintSelfBlockBackground(paintInfo.phase));
366 if (!m_layoutTableSection.styleRef().boxShadow())
367 return;
368
369 DisplayItem::Type type = shadowStyle == Normal
370 ? DisplayItem::kTableSectionBoxShadowNormal
371 : DisplayItem::kTableSectionBoxShadowInset;
372 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
373 paintInfo.context, m_layoutTableSection, type))
374 return;
375
376 LayoutRect bounds = BoxPainter(m_layoutTableSection)
377 .boundsForDrawingRecorder(paintInfo, paintOffset);
378 LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutTableSection,
379 type, bounds);
380 LayoutRect paintRect(paintOffset, m_layoutTableSection.size());
381 if (shadowStyle == Normal) {
382 BoxPainter::paintNormalBoxShadow(paintInfo, paintRect,
383 m_layoutTableSection.styleRef());
384 } else {
385 // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting
386 // paintRect by half widths of collapsed borders.
387 BoxPainter::paintInsetBoxShadow(paintInfo, paintRect,
388 m_layoutTableSection.styleRef());
389 }
390 }
391
392 } // namespace blink 402 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698