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 |