Chromium Code Reviews| 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 { | |
|
Xianzhu
2015/10/02 18:22:25
Note: this is extracted from TableSectionPainter::
| |
| 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( )) { |
|
Xianzhu
2015/10/02 18:22:25
Note: Actually the amount of change here is much s
| |
| 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 |