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/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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 box_clipper.emplace(layout_table_section_, paint_info, | 102 box_clipper.emplace(layout_table_section_, paint_info, |
103 adjusted_paint_offset, kForceContentsClip); | 103 adjusted_paint_offset, kForceContentsClip); |
104 PaintObject(paint_info, adjusted_paint_offset); | 104 PaintObject(paint_info, adjusted_paint_offset); |
105 } | 105 } |
106 | 106 |
107 if (ShouldPaintSelfOutline(paint_info.phase)) | 107 if (ShouldPaintSelfOutline(paint_info.phase)) |
108 ObjectPainter(layout_table_section_) | 108 ObjectPainter(layout_table_section_) |
109 .PaintOutline(paint_info, adjusted_paint_offset); | 109 .PaintOutline(paint_info, adjusted_paint_offset); |
110 } | 110 } |
111 | 111 |
112 static inline bool CompareCellPositions(const LayoutTableCell* elem1, | |
113 const LayoutTableCell* elem2) { | |
114 return elem1->RowIndex() < elem2->RowIndex(); | |
115 } | |
116 | |
117 // This comparison is used only when we have overflowing cells as we have an | |
118 // unsorted array to sort. We thus need to sort both on rows and columns to | |
119 // paint in proper order. | |
120 static inline bool CompareCellPositionsWithOverflowingCells( | |
121 const LayoutTableCell* elem1, | |
122 const LayoutTableCell* elem2) { | |
123 if (elem1->RowIndex() != elem2->RowIndex()) | |
124 return elem1->RowIndex() < elem2->RowIndex(); | |
125 | |
126 return elem1->AbsoluteColumnIndex() < elem2->AbsoluteColumnIndex(); | |
127 } | |
128 | |
129 void TableSectionPainter::PaintCollapsedBorders( | 112 void TableSectionPainter::PaintCollapsedBorders( |
130 const PaintInfo& paint_info, | 113 const PaintInfo& paint_info, |
131 const LayoutPoint& paint_offset, | 114 const LayoutPoint& paint_offset, |
132 const CollapsedBorderValue& current_border_value) { | 115 const CollapsedBorderValue& current_border_value) { |
133 PaintCollapsedSectionBorders(paint_info, paint_offset, current_border_value); | 116 PaintCollapsedSectionBorders(paint_info, paint_offset, current_border_value); |
134 LayoutTable* table = layout_table_section_.Table(); | 117 LayoutTable* table = layout_table_section_.Table(); |
135 if (table->Header() == layout_table_section_) | 118 if (table->Header() == layout_table_section_) |
136 PaintRepeatingHeaderGroup(paint_info, paint_offset, current_border_value, | 119 PaintRepeatingHeaderGroup(paint_info, paint_offset, current_border_value, |
137 kPaintCollapsedBorders); | 120 kPaintCollapsedBorders); |
138 } | 121 } |
(...skipping 11 matching lines...) Expand all Loading... |
150 BoxClipper box_clipper(layout_table_section_, paint_info, | 133 BoxClipper box_clipper(layout_table_section_, paint_info, |
151 adjusted_paint_offset, kForceContentsClip); | 134 adjusted_paint_offset, kForceContentsClip); |
152 | 135 |
153 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); | 136 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); |
154 local_visual_rect.MoveBy(-adjusted_paint_offset); | 137 local_visual_rect.MoveBy(-adjusted_paint_offset); |
155 | 138 |
156 LayoutRect table_aligned_rect = | 139 LayoutRect table_aligned_rect = |
157 layout_table_section_.LogicalRectForWritingModeAndDirection( | 140 layout_table_section_.LogicalRectForWritingModeAndDirection( |
158 local_visual_rect); | 141 local_visual_rect); |
159 | 142 |
160 CellSpan dirtied_rows = layout_table_section_.DirtiedRows(table_aligned_rect); | 143 CellSpan dirtied_rows; |
161 CellSpan dirtied_columns = | 144 CellSpan dirtied_columns; |
162 layout_table_section_.DirtiedEffectiveColumns(table_aligned_rect); | 145 layout_table_section_.DirtiedRowsAndEffectiveColumns( |
| 146 table_aligned_rect, dirtied_rows, dirtied_columns); |
163 | 147 |
164 if (dirtied_columns.Start() >= dirtied_columns.end()) | 148 if (dirtied_columns.Start() >= dirtied_columns.End()) |
165 return; | 149 return; |
166 | 150 |
167 // Collapsed borders are painted from the bottom right to the top left so that | 151 // Collapsed borders are painted from the bottom right to the top left so that |
168 // precedence due to cell position is respected. | 152 // precedence due to cell position is respected. |
169 for (unsigned r = dirtied_rows.end(); r > dirtied_rows.Start(); r--) { | 153 for (unsigned r = dirtied_rows.End(); r > dirtied_rows.Start(); r--) { |
170 unsigned row = r - 1; | 154 unsigned row = r - 1; |
171 unsigned n_cols = layout_table_section_.NumCols(row); | 155 unsigned n_cols = layout_table_section_.NumCols(row); |
172 for (unsigned c = std::min(dirtied_columns.end(), n_cols); | 156 for (unsigned c = std::min(dirtied_columns.End(), n_cols); |
173 c > dirtied_columns.Start(); c--) { | 157 c > dirtied_columns.Start(); c--) { |
174 unsigned col = c - 1; | 158 unsigned col = c - 1; |
175 if (const LayoutTableCell* cell = | 159 if (const LayoutTableCell* cell = |
176 layout_table_section_.OriginatingCellAt(row, col)) { | 160 layout_table_section_.OriginatingCellAt(row, col)) { |
177 LayoutPoint cell_point = | 161 LayoutPoint cell_point = |
178 layout_table_section_.FlipForWritingModeForChild( | 162 layout_table_section_.FlipForWritingModeForChild( |
179 cell, adjusted_paint_offset); | 163 cell, adjusted_paint_offset); |
180 TableCellPainter(*cell).PaintCollapsedBorders(paint_info, cell_point, | 164 TableCellPainter(*cell).PaintCollapsedBorders(paint_info, cell_point, |
181 current_border_value); | 165 current_border_value); |
182 } | 166 } |
183 } | 167 } |
184 } | 168 } |
185 } | 169 } |
186 | 170 |
187 void TableSectionPainter::PaintObject(const PaintInfo& paint_info, | 171 void TableSectionPainter::PaintObject(const PaintInfo& paint_info, |
188 const LayoutPoint& paint_offset) { | 172 const LayoutPoint& paint_offset) { |
189 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); | 173 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); |
190 local_visual_rect.MoveBy(-paint_offset); | 174 local_visual_rect.MoveBy(-paint_offset); |
191 | 175 |
192 LayoutRect table_aligned_rect = | 176 LayoutRect table_aligned_rect = |
193 layout_table_section_.LogicalRectForWritingModeAndDirection( | 177 layout_table_section_.LogicalRectForWritingModeAndDirection( |
194 local_visual_rect); | 178 local_visual_rect); |
195 | 179 |
196 CellSpan dirtied_rows = layout_table_section_.DirtiedRows(table_aligned_rect); | 180 CellSpan dirtied_rows; |
197 CellSpan dirtied_columns = | 181 CellSpan dirtied_columns; |
198 layout_table_section_.DirtiedEffectiveColumns(table_aligned_rect); | 182 layout_table_section_.DirtiedRowsAndEffectiveColumns( |
| 183 table_aligned_rect, dirtied_rows, dirtied_columns); |
199 | 184 |
200 PaintInfo paint_info_for_descendants = paint_info.ForDescendants(); | 185 PaintInfo paint_info_for_descendants = paint_info.ForDescendants(); |
201 | 186 |
202 if (ShouldPaintSelfBlockBackground(paint_info.phase)) { | 187 if (ShouldPaintSelfBlockBackground(paint_info.phase)) { |
203 PaintBoxDecorationBackground(paint_info, paint_offset, dirtied_rows, | 188 PaintBoxDecorationBackground(paint_info, paint_offset, dirtied_rows, |
204 dirtied_columns); | 189 dirtied_columns); |
205 } | 190 } |
206 | 191 |
207 if (paint_info.phase == kPaintPhaseSelfBlockBackgroundOnly) | 192 if (paint_info.phase == kPaintPhaseSelfBlockBackgroundOnly) |
208 return; | 193 return; |
209 | 194 |
210 if (ShouldPaintDescendantBlockBackgrounds(paint_info.phase)) { | 195 if (ShouldPaintDescendantBlockBackgrounds(paint_info.phase)) { |
211 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 196 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
212 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); | 197 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); |
213 // If a row has a layer, we'll paint row background though | 198 // If a row has a layer, we'll paint row background though |
214 // TableRowPainter::paint(). | 199 // TableRowPainter::paint(). |
215 if (!row || row->HasSelfPaintingLayer()) | 200 if (!row || row->HasSelfPaintingLayer()) |
216 continue; | 201 continue; |
217 TableRowPainter(*row).PaintBoxDecorationBackground( | 202 TableRowPainter(*row).PaintBoxDecorationBackground( |
218 paint_info_for_descendants, paint_offset, dirtied_columns); | 203 paint_info_for_descendants, paint_offset, dirtied_columns); |
219 } | 204 } |
220 } | 205 } |
221 | 206 |
222 // This is tested after background painting because during background painting | 207 // This is tested after background painting because during background painting |
223 // we need to check validity of the previous background display item based on | 208 // we need to check validity of the previous background display item based on |
224 // dirtyRows and dirtyColumns. | 209 // dirtyRows and dirtyColumns. |
225 if (dirtied_rows.Start() >= dirtied_rows.end() || | 210 if (dirtied_rows.Start() >= dirtied_rows.End() || |
226 dirtied_columns.Start() >= dirtied_columns.end()) | 211 dirtied_columns.Start() >= dirtied_columns.End()) |
227 return; | 212 return; |
228 | 213 |
229 const auto& overflowing_cells = layout_table_section_.OverflowingCells(); | 214 const auto& overflowing_cells = layout_table_section_.OverflowingCells(); |
230 if (!layout_table_section_.HasMultipleCellLevels() && | 215 if (overflowing_cells.IsEmpty()) { |
231 overflowing_cells.IsEmpty()) { | |
232 // This path is for 2 cases: | 216 // This path is for 2 cases: |
233 // 1. Normal partial paint, without overflowing cells and multiple cell | 217 // 1. Normal partial paint, without overflowing cells; |
234 // levels; | |
235 // 2. Full paint, for small sections or big sections with many overflowing | 218 // 2. Full paint, for small sections or big sections with many overflowing |
236 // cells. | 219 // cells. |
237 // The difference between the normal partial paint and full paint is that | 220 // The difference between the normal partial paint and full paint is that |
238 // whether dirtied_rows and dirtied_columns cover the whole section. | 221 // whether dirtied_rows and dirtied_columns cover the whole section. |
239 DCHECK(!layout_table_section_.HasOverflowingCell() || | 222 DCHECK(!layout_table_section_.HasOverflowingCell() || |
240 (dirtied_rows == layout_table_section_.FullSectionRowSpan() && | 223 (dirtied_rows == layout_table_section_.FullSectionRowSpan() && |
241 dirtied_columns == | 224 dirtied_columns == |
242 layout_table_section_.FullTableEffectiveColumnSpan())); | 225 layout_table_section_.FullTableEffectiveColumnSpan())); |
243 | 226 |
244 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 227 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
245 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); | 228 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); |
246 // TODO(crbug.com/577282): This painting order is inconsistent with other | 229 // TODO(crbug.com/577282): This painting order is inconsistent with other |
247 // outlines. | 230 // outlines. |
248 if (row && !row->HasSelfPaintingLayer() && | 231 if (row && !row->HasSelfPaintingLayer() && |
249 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { | 232 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { |
250 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, | 233 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, |
251 paint_offset); | 234 paint_offset); |
252 } | 235 } |
253 for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.end(); | 236 for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.End(); |
254 c++) { | 237 c++) { |
255 if (const LayoutTableCell* cell = | 238 if (const LayoutTableCell* cell = |
256 layout_table_section_.OriginatingCellAt(r, c)) | 239 layout_table_section_.OriginatingCellAt(r, c)) |
257 PaintCell(*cell, paint_info_for_descendants, paint_offset); | 240 PaintCell(*cell, paint_info_for_descendants, paint_offset); |
258 } | 241 } |
259 } | 242 } |
260 } else { | 243 } else { |
261 // This path paints section with multiple cell levels or a reasonable number | 244 // This path paints section with a reasonable number of overflowing cells. |
262 // of overflowing cells. This is the "partial paint path" for overflowing | 245 // This is the "partial paint path" for overflowing cells referred in |
263 // cells referred in LayoutTableSection::ComputeOverflowFromDescendants(). | 246 // LayoutTableSection::ComputeOverflowFromDescendants(). |
264 Vector<const LayoutTableCell*> cells; | 247 Vector<const LayoutTableCell*> cells; |
265 CopyToVector(overflowing_cells, cells); | 248 CopyToVector(overflowing_cells, cells); |
266 | 249 |
267 HashSet<const LayoutTableCell*> spanning_cells; | 250 HashSet<const LayoutTableCell*> spanning_cells; |
268 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 251 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
269 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); | 252 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); |
270 // TODO(crbug.com/577282): This painting order is inconsistent with other | 253 // TODO(crbug.com/577282): This painting order is inconsistent with other |
271 // outlines. | 254 // outlines. |
272 if (row && !row->HasSelfPaintingLayer() && | 255 if (row && !row->HasSelfPaintingLayer() && |
273 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { | 256 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { |
274 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, | 257 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, |
275 paint_offset); | 258 paint_offset); |
276 } | 259 } |
277 unsigned n_cols = layout_table_section_.NumCols(r); | 260 unsigned n_cols = layout_table_section_.NumCols(r); |
278 for (unsigned c = dirtied_columns.Start(); | 261 for (unsigned c = dirtied_columns.Start(); |
279 c < n_cols && c < dirtied_columns.end(); c++) { | 262 c < n_cols && c < dirtied_columns.End(); c++) { |
280 for (const auto* cell : | 263 if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) { |
281 layout_table_section_.GridCellAt(r, c).Cells()) { | 264 if (!overflowing_cells.Contains(cell)) |
282 if (overflowing_cells.Contains(cell)) | 265 cells.push_back(cell); |
283 continue; | |
284 if (cell->RowSpan() > 1 || cell->ColSpan() > 1) { | |
285 if (!spanning_cells.insert(cell).is_new_entry) | |
286 continue; | |
287 } | |
288 cells.push_back(cell); | |
289 } | 266 } |
290 } | 267 } |
291 } | 268 } |
292 | 269 |
293 // Sort the dirty cells by paint order. | 270 // Sort the dirty cells by paint order. |
294 if (!overflowing_cells.size()) { | 271 std::sort(cells.begin(), cells.end(), LayoutTableCell::CompareInDOMOrder); |
295 std::stable_sort(cells.begin(), cells.end(), CompareCellPositions); | |
296 } else { | |
297 std::sort(cells.begin(), cells.end(), | |
298 CompareCellPositionsWithOverflowingCells); | |
299 } | |
300 | |
301 for (const auto* cell : cells) | 272 for (const auto* cell : cells) |
302 PaintCell(*cell, paint_info_for_descendants, paint_offset); | 273 PaintCell(*cell, paint_info_for_descendants, paint_offset); |
303 } | 274 } |
304 } | 275 } |
305 | 276 |
306 void TableSectionPainter::PaintBoxDecorationBackground( | 277 void TableSectionPainter::PaintBoxDecorationBackground( |
307 const PaintInfo& paint_info, | 278 const PaintInfo& paint_info, |
308 const LayoutPoint& paint_offset, | 279 const LayoutPoint& paint_offset, |
309 const CellSpan& dirtied_rows, | 280 const CellSpan& dirtied_rows, |
310 const CellSpan& dirtied_columns) { | 281 const CellSpan& dirtied_columns) { |
(...skipping 23 matching lines...) Expand all Loading... |
334 DisplayItem::kBoxDecorationBackground, bounds); | 305 DisplayItem::kBoxDecorationBackground, bounds); |
335 LayoutRect paint_rect(paint_offset, layout_table_section_.Size()); | 306 LayoutRect paint_rect(paint_offset, layout_table_section_.Size()); |
336 | 307 |
337 if (has_box_shadow) { | 308 if (has_box_shadow) { |
338 BoxPainter::PaintNormalBoxShadow(paint_info, paint_rect, | 309 BoxPainter::PaintNormalBoxShadow(paint_info, paint_rect, |
339 layout_table_section_.StyleRef()); | 310 layout_table_section_.StyleRef()); |
340 } | 311 } |
341 | 312 |
342 if (may_have_background) { | 313 if (may_have_background) { |
343 PaintInfo paint_info_for_cells = paint_info.ForDescendants(); | 314 PaintInfo paint_info_for_cells = paint_info.ForDescendants(); |
344 for (auto r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 315 for (auto r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
345 for (auto c = dirtied_columns.Start(); c < dirtied_columns.end(); c++) { | 316 for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) { |
346 if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) { | 317 if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) { |
347 PaintBackgroundsBehindCell(*cell, paint_info_for_cells, paint_offset); | 318 PaintBackgroundsBehindCell(*cell, paint_info_for_cells, paint_offset); |
348 } | 319 } |
349 } | 320 } |
350 } | 321 } |
351 } | 322 } |
352 | 323 |
353 if (has_box_shadow) { | 324 if (has_box_shadow) { |
354 // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting | 325 // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting |
355 // paintRect by half widths of collapsed borders. | 326 // paintRect by half widths of collapsed borders. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 const PaintInfo& paint_info_for_cells, | 373 const PaintInfo& paint_info_for_cells, |
403 const LayoutPoint& paint_offset) { | 374 const LayoutPoint& paint_offset) { |
404 if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer()) { | 375 if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer()) { |
405 LayoutPoint cell_point = | 376 LayoutPoint cell_point = |
406 layout_table_section_.FlipForWritingModeForChild(&cell, paint_offset); | 377 layout_table_section_.FlipForWritingModeForChild(&cell, paint_offset); |
407 cell.Paint(paint_info_for_cells, cell_point); | 378 cell.Paint(paint_info_for_cells, cell_point); |
408 } | 379 } |
409 } | 380 } |
410 | 381 |
411 } // namespace blink | 382 } // namespace blink |
OLD | NEW |