| 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 "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/TableSectionPainter.h" | 6 #include "core/paint/TableSectionPainter.h" |
| 7 | 7 |
| 8 #include "core/layout/LayoutTable.h" | 8 #include "core/layout/LayoutTable.h" |
| 9 #include "core/layout/LayoutTableCell.h" | 9 #include "core/layout/LayoutTableCell.h" |
| 10 #include "core/layout/LayoutTableCol.h" | 10 #include "core/layout/LayoutTableCol.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 // This comparison is used only when we have overflowing cells as we have an uns
orted array to sort. We thus need | 50 // 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. | 51 // to sort both on rows and columns to properly issue paint invalidations. |
| 52 static inline bool compareCellPositionsWithOverflowingCells(LayoutTableCell* ele
m1, LayoutTableCell* elem2) | 52 static inline bool compareCellPositionsWithOverflowingCells(LayoutTableCell* ele
m1, LayoutTableCell* elem2) |
| 53 { | 53 { |
| 54 if (elem1->rowIndex() != elem2->rowIndex()) | 54 if (elem1->rowIndex() != elem2->rowIndex()) |
| 55 return elem1->rowIndex() < elem2->rowIndex(); | 55 return elem1->rowIndex() < elem2->rowIndex(); |
| 56 | 56 |
| 57 return elem1->col() < elem2->col(); | 57 return elem1->col() < elem2->col(); |
| 58 } | 58 } |
| 59 | 59 |
| 60 void TableSectionPainter::paintCollapsedBorders(const PaintInfo& paintInfo, cons
t LayoutPoint& paintOffset, const CollapsedBorderValue& currentBorderValue) |
| 61 { |
| 62 if (!m_layoutTableSection.numRows() || !m_layoutTableSection.table()->column
s().size()) |
| 63 return; |
| 64 |
| 65 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableSection.locatio
n(); |
| 66 BoxClipper boxClipper(m_layoutTableSection, paintInfo, adjustedPaintOffset,
ForceContentsClip); |
| 67 |
| 68 LayoutRect localPaintInvalidationRect = LayoutRect(paintInfo.rect); |
| 69 localPaintInvalidationRect.moveBy(-adjustedPaintOffset); |
| 70 |
| 71 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode
AndDirection(localPaintInvalidationRect); |
| 72 |
| 73 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); |
| 74 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRe
ct); |
| 75 |
| 76 if (dirtiedColumns.start() >= dirtiedColumns.end()) |
| 77 return; |
| 78 |
| 79 // Collapsed borders are painted from the bottom right to the top left so th
at precedence |
| 80 // due to cell position is respected. |
| 81 for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r--) { |
| 82 unsigned row = r - 1; |
| 83 for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.start(); c--)
{ |
| 84 unsigned col = c - 1; |
| 85 const LayoutTableSection::CellStruct& current = m_layoutTableSection
.cellAt(row, col); |
| 86 const LayoutTableCell* cell = current.primaryCell(); |
| 87 if (!cell || (row > dirtiedRows.start() && m_layoutTableSection.prim
aryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() && m_layoutTab
leSection.primaryCellAt(row, col - 1) == cell)) |
| 88 continue; |
| 89 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForCh
ild(cell, adjustedPaintOffset); |
| 90 TableCellPainter(*cell).paintCollapsedBorders(paintInfo, cellPoint,
currentBorderValue); |
| 91 } |
| 92 } |
| 93 } |
| 94 |
| 60 void TableSectionPainter::paintObject(const PaintInfo& paintInfo, const LayoutPo
int& paintOffset) | 95 void TableSectionPainter::paintObject(const PaintInfo& paintInfo, const LayoutPo
int& paintOffset) |
| 61 { | 96 { |
| 62 LayoutRect localPaintInvalidationRect = LayoutRect(paintInfo.rect); | 97 LayoutRect localPaintInvalidationRect = LayoutRect(paintInfo.rect); |
| 63 localPaintInvalidationRect.moveBy(-paintOffset); | 98 localPaintInvalidationRect.moveBy(-paintOffset); |
| 64 | 99 |
| 65 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode
AndDirection(localPaintInvalidationRect); | 100 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingMode
AndDirection(localPaintInvalidationRect); |
| 66 | 101 |
| 67 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); | 102 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); |
| 68 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRe
ct); | 103 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRe
ct); |
| 69 | 104 |
| 105 if (dirtiedColumns.start() >= dirtiedColumns.end()) |
| 106 return; |
| 107 |
| 70 const HashSet<LayoutTableCell*>& overflowingCells = m_layoutTableSection.ove
rflowingCells(); | 108 const HashSet<LayoutTableCell*>& overflowingCells = m_layoutTableSection.ove
rflowingCells(); |
| 71 if (dirtiedColumns.start() < dirtiedColumns.end()) { | 109 if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.size(
)) { |
| 72 if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.s
ize()) { | 110 // Draw the dirty cells in the order that they appear. |
| 73 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { | 111 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
| 74 // Collapsed borders are painted from the bottom right to the to
p left so that precedence | 112 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r
); |
| 75 // due to cell position is respected. | 113 if (row && !row->hasSelfPaintingLayer()) |
| 76 for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r-
-) { | 114 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain
tOffset); |
| 77 unsigned row = r - 1; | 115 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
c++) { |
| 78 for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.s
tart(); c--) { | 116 const LayoutTableSection::CellStruct& current = m_layoutTableSec
tion.cellAt(r, c); |
| 79 unsigned col = c - 1; | 117 const LayoutTableCell* cell = current.primaryCell(); |
| 80 const LayoutTableSection::CellStruct& current = m_layout
TableSection.cellAt(row, col); | 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)) |
| 81 const LayoutTableCell* cell = current.primaryCell(); | 119 continue; |
| 82 if (!cell || (row > dirtiedRows.start() && m_layoutTable
Section.primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() &&
m_layoutTableSection.primaryCellAt(row, col - 1) == cell)) | 120 paintCell(*cell, paintInfo, paintOffset); |
| 121 } |
| 122 } |
| 123 } else { |
| 124 // The overflowing cells should be scarce to avoid adding a lot of cells
to the HashSet. |
| 125 #if ENABLE(ASSERT) |
| 126 unsigned totalRows = m_layoutTableSection.numRows(); |
| 127 unsigned totalCols = m_layoutTableSection.table()->columns().size(); |
| 128 ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowedOver
flowingCellRatioForFastPaintPath); |
| 129 #endif |
| 130 |
| 131 // To make sure we properly paint invalidate the section, we paint inval
idated all the overflowing cells that we collected. |
| 132 Vector<LayoutTableCell*> cells; |
| 133 copyToVector(overflowingCells, cells); |
| 134 |
| 135 HashSet<LayoutTableCell*> spanningCells; |
| 136 |
| 137 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
| 138 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r
); |
| 139 if (row && !row->hasSelfPaintingLayer()) |
| 140 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, pain
tOffset); |
| 141 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end();
c++) { |
| 142 const LayoutTableSection::CellStruct& current = m_layoutTableSec
tion.cellAt(r, c); |
| 143 if (!current.hasCells()) |
| 144 continue; |
| 145 for (unsigned i = 0; i < current.cells.size(); ++i) { |
| 146 if (overflowingCells.contains(current.cells[i])) |
| 147 continue; |
| 148 |
| 149 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->col
Span() > 1) { |
| 150 if (!spanningCells.add(current.cells[i]).isNewEntry) |
| 83 continue; | 151 continue; |
| 84 LayoutPoint cellPoint = m_layoutTableSection.flipForWrit
ingModeForChild(cell, paintOffset); | |
| 85 TableCellPainter(*cell).paintCollapsedBorders(paintInfo,
cellPoint); | |
| 86 } | 152 } |
| 87 } | 153 |
| 88 } else { | 154 cells.append(current.cells[i]); |
| 89 // Draw the dirty cells in the order that they appear. | |
| 90 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r+
+) { | |
| 91 const LayoutTableRow* row = m_layoutTableSection.rowLayoutOb
jectAt(r); | |
| 92 if (row && !row->hasSelfPaintingLayer()) | |
| 93 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintIn
fo, paintOffset); | |
| 94 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns
.end(); c++) { | |
| 95 const LayoutTableSection::CellStruct& current = m_layout
TableSection.cellAt(r, c); | |
| 96 const LayoutTableCell* cell = current.primaryCell(); | |
| 97 if (!cell || (r > dirtiedRows.start() && m_layoutTableSe
ction.primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_layou
tTableSection.primaryCellAt(r, c - 1) == cell)) | |
| 98 continue; | |
| 99 paintCell(*cell, paintInfo, paintOffset); | |
| 100 } | |
| 101 } | 155 } |
| 102 } | 156 } |
| 103 } else { | 157 } |
| 104 // The overflowing cells should be scarce to avoid adding a lot of c
ells to the HashSet. | |
| 105 #if ENABLE(ASSERT) | |
| 106 unsigned totalRows = m_layoutTableSection.numRows(); | |
| 107 unsigned totalCols = m_layoutTableSection.table()->columns().size(); | |
| 108 ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowed
OverflowingCellRatioForFastPaintPath); | |
| 109 #endif | |
| 110 | 158 |
| 111 // To make sure we properly paint invalidate the section, we paint i
nvalidated all the overflowing cells that we collected. | 159 // Sort the dirty cells by paint order. |
| 112 Vector<LayoutTableCell*> cells; | 160 if (!overflowingCells.size()) |
| 113 copyToVector(overflowingCells, cells); | 161 std::stable_sort(cells.begin(), cells.end(), compareCellPositions); |
| 162 else |
| 163 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverfl
owingCells); |
| 114 | 164 |
| 115 HashSet<LayoutTableCell*> spanningCells; | 165 for (unsigned i = 0; i < cells.size(); ++i) |
| 116 | 166 paintCell(*cells[i], paintInfo, paintOffset); |
| 117 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { | |
| 118 const LayoutTableRow* row = m_layoutTableSection.rowLayoutObject
At(r); | |
| 119 if (row && !row->hasSelfPaintingLayer()) | |
| 120 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo,
paintOffset); | |
| 121 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end
(); c++) { | |
| 122 const LayoutTableSection::CellStruct& current = m_layoutTabl
eSection.cellAt(r, c); | |
| 123 if (!current.hasCells()) | |
| 124 continue; | |
| 125 for (unsigned i = 0; i < current.cells.size(); ++i) { | |
| 126 if (overflowingCells.contains(current.cells[i])) | |
| 127 continue; | |
| 128 | |
| 129 if (current.cells[i]->rowSpan() > 1 || current.cells[i]-
>colSpan() > 1) { | |
| 130 if (!spanningCells.add(current.cells[i]).isNewEntry) | |
| 131 continue; | |
| 132 } | |
| 133 | |
| 134 cells.append(current.cells[i]); | |
| 135 } | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 // Sort the dirty cells by paint order. | |
| 140 if (!overflowingCells.size()) | |
| 141 std::stable_sort(cells.begin(), cells.end(), compareCellPosition
s); | |
| 142 else | |
| 143 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOv
erflowingCells); | |
| 144 | |
| 145 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { | |
| 146 for (unsigned i = cells.size(); i > 0; --i) { | |
| 147 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingM
odeForChild(cells[i - 1], paintOffset); | |
| 148 TableCellPainter(*cells[i - 1]).paintCollapsedBorders(paintI
nfo, cellPoint); | |
| 149 } | |
| 150 } else { | |
| 151 for (unsigned i = 0; i < cells.size(); ++i) | |
| 152 paintCell(*cells[i], paintInfo, paintOffset); | |
| 153 } | |
| 154 } | |
| 155 } | 167 } |
| 156 } | 168 } |
| 157 | 169 |
| 158 void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo
& paintInfo, const LayoutPoint& paintOffset) | 170 void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo
& paintInfo, const LayoutPoint& paintOffset) |
| 159 { | 171 { |
| 160 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cel
l, paintOffset); | 172 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cel
l, paintOffset); |
| 161 PaintPhase paintPhase = paintInfo.phase; | 173 PaintPhase paintPhase = paintInfo.phase; |
| 162 const LayoutTableRow* row = toLayoutTableRow(cell.parent()); | 174 const LayoutTableRow* row = toLayoutTableRow(cell.parent()); |
| 163 | 175 |
| 164 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChil
dBlockBackground) | 176 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChil
dBlockBackground) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 if (rowHasBackground && !row->hasSelfPaintingLayer()) | 208 if (rowHasBackground && !row->hasSelfPaintingLayer()) |
| 197 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellP
oint, row); | 209 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellP
oint, row); |
| 198 } | 210 } |
| 199 } | 211 } |
| 200 } | 212 } |
| 201 if ((!cell.hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) | 213 if ((!cell.hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) |
| 202 cell.paint(paintInfo, cellPoint); | 214 cell.paint(paintInfo, cellPoint); |
| 203 } | 215 } |
| 204 | 216 |
| 205 } // namespace blink | 217 } // namespace blink |
| OLD | NEW |