| OLD | NEW |
| 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/LayoutObjectDrawingRecorder.h" | 13 #include "core/paint/LayoutObjectDrawingRecorder.h" |
| 14 #include "core/paint/ObjectPainter.h" | 14 #include "core/paint/ObjectPainter.h" |
| 15 #include "core/paint/PaintInfo.h" | 15 #include "core/paint/PaintInfo.h" |
| 16 #include "core/paint/TableCellPainter.h" | 16 #include "core/paint/TableCellPainter.h" |
| 17 #include "core/paint/TableRowPainter.h" | 17 #include "core/paint/TableRowPainter.h" |
| 18 #include <algorithm> | 18 #include <algorithm> |
| 19 | 19 |
| 20 namespace blink { | 20 namespace blink { |
| 21 | 21 |
| 22 void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& p
aintOffset) | 22 void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& p
aintOffset) |
| 23 { | 23 { |
| 24 ASSERT(!m_layoutTableSection.needsLayout()); | 24 ASSERT(!m_layoutTableSection.needsLayout()); |
| 25 // avoid crashing on bugs that cause us to paint with dirty layout | 25 // avoid crashing on bugs that cause us to paint with dirty layout |
| 26 if (m_layoutTableSection.needsLayout()) | 26 if (m_layoutTableSection.needsLayout()) |
| 27 return; | 27 return; |
| 28 | 28 |
| 29 // Table sections don't paint self background. The cells paint table section
's background |
| 30 // behind them when needed during PaintPhaseBlockBackground or PaintPhaseDes
cendantBlockBackgroundOnly. |
| 31 if (paintInfo.phase == PaintPhaseSelfBlockBackgroundOnly) |
| 32 return; |
| 33 |
| 29 unsigned totalRows = m_layoutTableSection.numRows(); | 34 unsigned totalRows = m_layoutTableSection.numRows(); |
| 30 unsigned totalCols = m_layoutTableSection.table()->columns().size(); | 35 unsigned totalCols = m_layoutTableSection.table()->columns().size(); |
| 31 | 36 |
| 32 if (!totalRows || !totalCols) | 37 if (!totalRows || !totalCols) |
| 33 return; | 38 return; |
| 34 | 39 |
| 35 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableSection.locatio
n(); | 40 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableSection.locatio
n(); |
| 36 { | 41 |
| 42 if (paintInfo.phase != PaintPhaseSelfOutlineOnly) { |
| 37 BoxClipper boxClipper(m_layoutTableSection, paintInfo, adjustedPaintOffs
et, ForceContentsClip); | 43 BoxClipper boxClipper(m_layoutTableSection, paintInfo, adjustedPaintOffs
et, ForceContentsClip); |
| 38 paintObject(paintInfo, adjustedPaintOffset); | 44 paintObject(paintInfo, adjustedPaintOffset); |
| 39 } | 45 } |
| 40 | 46 |
| 41 if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSe
lfOutline) && m_layoutTableSection.style()->visibility() == VISIBLE) | 47 if (shouldPaintSelfOutline(paintInfo.phase)) |
| 42 ObjectPainter(m_layoutTableSection).paintOutline(paintInfo, adjustedPain
tOffset); | 48 ObjectPainter(m_layoutTableSection).paintOutline(paintInfo, adjustedPain
tOffset); |
| 43 } | 49 } |
| 44 | 50 |
| 45 static inline bool compareCellPositions(LayoutTableCell* elem1, LayoutTableCell*
elem2) | 51 static inline bool compareCellPositions(LayoutTableCell* elem1, LayoutTableCell*
elem2) |
| 46 { | 52 { |
| 47 return elem1->rowIndex() < elem2->rowIndex(); | 53 return elem1->rowIndex() < elem2->rowIndex(); |
| 48 } | 54 } |
| 49 | 55 |
| 50 // This comparison is used only when we have overflowing cells as we have an uns
orted array to sort. We thus need | 56 // This comparison is used only when we have overflowing cells as we have an uns
orted array to sort. We thus need |
| 51 // to sort both on rows and columns to properly issue paint invalidations. | 57 // to sort both on rows and columns to properly issue paint invalidations. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 localPaintInvalidationRect.moveBy(-paintOffset); | 104 localPaintInvalidationRect.moveBy(-paintOffset); |
| 99 | 105 |
| 100 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode
AndDirection(localPaintInvalidationRect); | 106 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode
AndDirection(localPaintInvalidationRect); |
| 101 | 107 |
| 102 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); | 108 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); |
| 103 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRe
ct); | 109 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRe
ct); |
| 104 | 110 |
| 105 if (dirtiedColumns.start() >= dirtiedColumns.end()) | 111 if (dirtiedColumns.start() >= dirtiedColumns.end()) |
| 106 return; | 112 return; |
| 107 | 113 |
| 114 PaintInfo paintInfoForCells = paintInfo.forDescendants(); |
| 108 const HashSet<LayoutTableCell*>& overflowingCells = m_layoutTableSection.ove
rflowingCells(); | 115 const HashSet<LayoutTableCell*>& overflowingCells = m_layoutTableSection.ove
rflowingCells(); |
| 109 if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.size(
)) { | 116 if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.size(
)) { |
| 110 // Draw the dirty cells in the order that they appear. | 117 // Draw the dirty cells in the order that they appear. |
| 111 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { | 118 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
| 112 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r
); | 119 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r
); |
| 120 // TODO(wangxianzhu): This painting order is inconsistent with other
outlines. crbug.com/577282. |
| 113 if (row && !row->hasSelfPaintingLayer()) | 121 if (row && !row->hasSelfPaintingLayer()) |
| 114 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain
tOffset); | 122 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain
tOffset); |
| 115 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
c++) { | 123 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
c++) { |
| 116 const LayoutTableSection::CellStruct& current = m_layoutTableSec
tion.cellAt(r, c); | 124 const LayoutTableSection::CellStruct& current = m_layoutTableSec
tion.cellAt(r, c); |
| 117 const LayoutTableCell* cell = current.primaryCell(); | 125 const LayoutTableCell* cell = current.primaryCell(); |
| 118 if (!cell || (r > dirtiedRows.start() && m_layoutTableSection.pr
imaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_layoutTableSe
ction.primaryCellAt(r, c - 1) == cell)) | 126 if (!cell || (r > dirtiedRows.start() && m_layoutTableSection.pr
imaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_layoutTableSe
ction.primaryCellAt(r, c - 1) == cell)) |
| 119 continue; | 127 continue; |
| 120 paintCell(*cell, paintInfo, paintOffset); | 128 paintCell(*cell, paintInfoForCells, paintOffset); |
| 121 } | 129 } |
| 122 } | 130 } |
| 123 } else { | 131 } else { |
| 124 // The overflowing cells should be scarce to avoid adding a lot of cells
to the HashSet. | 132 // The overflowing cells should be scarce to avoid adding a lot of cells
to the HashSet. |
| 125 #if ENABLE(ASSERT) | 133 #if ENABLE(ASSERT) |
| 126 unsigned totalRows = m_layoutTableSection.numRows(); | 134 unsigned totalRows = m_layoutTableSection.numRows(); |
| 127 unsigned totalCols = m_layoutTableSection.table()->columns().size(); | 135 unsigned totalCols = m_layoutTableSection.table()->columns().size(); |
| 128 ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowedOver
flowingCellRatioForFastPaintPath); | 136 ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowedOver
flowingCellRatioForFastPaintPath); |
| 129 #endif | 137 #endif |
| 130 | 138 |
| 131 // To make sure we properly paint invalidate the section, we paint inval
idated all the overflowing cells that we collected. | 139 // To make sure we properly paint invalidate the section, we paint inval
idated all the overflowing cells that we collected. |
| 132 Vector<LayoutTableCell*> cells; | 140 Vector<LayoutTableCell*> cells; |
| 133 copyToVector(overflowingCells, cells); | 141 copyToVector(overflowingCells, cells); |
| 134 | 142 |
| 135 HashSet<LayoutTableCell*> spanningCells; | 143 HashSet<LayoutTableCell*> spanningCells; |
| 136 | 144 |
| 137 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { | 145 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
| 138 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r
); | 146 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r
); |
| 147 // TODO(wangxianzhu): This painting order is inconsistent with other
outlines. crbug.com/577282. |
| 139 if (row && !row->hasSelfPaintingLayer()) | 148 if (row && !row->hasSelfPaintingLayer()) |
| 140 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain
tOffset); | 149 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain
tOffset); |
| 141 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
c++) { | 150 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
c++) { |
| 142 const LayoutTableSection::CellStruct& current = m_layoutTableSec
tion.cellAt(r, c); | 151 const LayoutTableSection::CellStruct& current = m_layoutTableSec
tion.cellAt(r, c); |
| 143 if (!current.hasCells()) | 152 if (!current.hasCells()) |
| 144 continue; | 153 continue; |
| 145 for (unsigned i = 0; i < current.cells.size(); ++i) { | 154 for (unsigned i = 0; i < current.cells.size(); ++i) { |
| 146 if (overflowingCells.contains(current.cells[i])) | 155 if (overflowingCells.contains(current.cells[i])) |
| 147 continue; | 156 continue; |
| 148 | 157 |
| 149 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->col
Span() > 1) { | 158 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->col
Span() > 1) { |
| 150 if (!spanningCells.add(current.cells[i]).isNewEntry) | 159 if (!spanningCells.add(current.cells[i]).isNewEntry) |
| 151 continue; | 160 continue; |
| 152 } | 161 } |
| 153 | 162 |
| 154 cells.append(current.cells[i]); | 163 cells.append(current.cells[i]); |
| 155 } | 164 } |
| 156 } | 165 } |
| 157 } | 166 } |
| 158 | 167 |
| 159 // Sort the dirty cells by paint order. | 168 // Sort the dirty cells by paint order. |
| 160 if (!overflowingCells.size()) | 169 if (!overflowingCells.size()) |
| 161 std::stable_sort(cells.begin(), cells.end(), compareCellPositions); | 170 std::stable_sort(cells.begin(), cells.end(), compareCellPositions); |
| 162 else | 171 else |
| 163 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverfl
owingCells); | 172 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverfl
owingCells); |
| 164 | 173 |
| 165 for (unsigned i = 0; i < cells.size(); ++i) | 174 for (unsigned i = 0; i < cells.size(); ++i) |
| 166 paintCell(*cells[i], paintInfo, paintOffset); | 175 paintCell(*cells[i], paintInfoForCells, paintOffset); |
| 167 } | 176 } |
| 168 } | 177 } |
| 169 | 178 |
| 170 void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo
& paintInfo, const LayoutPoint& paintOffset) | 179 void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo
& paintInfo, const LayoutPoint& paintOffset) |
| 171 { | 180 { |
| 172 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cel
l, paintOffset); | 181 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cel
l, paintOffset); |
| 173 PaintPhase paintPhase = paintInfo.phase; | 182 PaintPhase paintPhase = paintInfo.phase; |
| 174 const LayoutTableRow* row = toLayoutTableRow(cell.parent()); | 183 const LayoutTableRow* row = toLayoutTableRow(cell.parent()); |
| 175 | 184 |
| 176 if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhase
BlockBackground) | 185 if (shouldPaintSelfBlockBackground(paintPhase) |
| 177 && BlockPainter(cell).intersectsPaintRect(paintInfo, paintOffset)) { | 186 && BlockPainter(cell).intersectsPaintRect(paintInfo, paintOffset)) { |
| 178 // We need to handle painting a stack of backgrounds. This stack (from b
ottom to top) consists of | 187 // We need to handle painting a stack of backgrounds. This stack (from b
ottom to top) consists of |
| 179 // the column group, column, row group, row, and then the cell. | 188 // the column group, column, row group, row, and then the cell. |
| 180 | 189 |
| 181 LayoutTable::ColAndColGroup colAndColGroup = m_layoutTableSection.table(
)->colElement(cell.col()); | 190 LayoutTable::ColAndColGroup colAndColGroup = m_layoutTableSection.table(
)->colElement(cell.col()); |
| 182 LayoutTableCol* column = colAndColGroup.col; | 191 LayoutTableCol* column = colAndColGroup.col; |
| 183 LayoutTableCol* columnGroup = colAndColGroup.colgroup; | 192 LayoutTableCol* columnGroup = colAndColGroup.colgroup; |
| 184 TableCellPainter tableCellPainter(cell); | 193 TableCellPainter tableCellPainter(cell); |
| 185 | 194 |
| 186 // Column groups and columns first. | 195 // Column groups and columns first. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 200 // Paint the row next, but only if it doesn't have a layer. If a row has
a layer, it will be responsible for | 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 |
| 201 // painting the row background for the cell. | 210 // painting the row background for the cell. |
| 202 if (row->hasBackground() && !row->hasSelfPaintingLayer()) | 211 if (row->hasBackground() && !row->hasSelfPaintingLayer()) |
| 203 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, ro
w, DisplayItem::TableCellBackgroundFromRow); | 212 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, ro
w, DisplayItem::TableCellBackgroundFromRow); |
| 204 } | 213 } |
| 205 if ((!cell.hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) | 214 if ((!cell.hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) |
| 206 cell.paint(paintInfo, cellPoint); | 215 cell.paint(paintInfo, cellPoint); |
| 207 } | 216 } |
| 208 | 217 |
| 209 } // namespace blink | 218 } // namespace blink |
| OLD | NEW |