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 "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 void TableSectionPainter::PaintCollapsedBorders( | 112 void TableSectionPainter::PaintCollapsedBorders( |
| 118 const PaintInfo& paint_info, | 113 const PaintInfo& paint_info, |
| 119 const LayoutPoint& paint_offset, | 114 const LayoutPoint& paint_offset, |
| 120 const CollapsedBorderValue& current_border_value) { | 115 const CollapsedBorderValue& current_border_value) { |
| 121 PaintCollapsedSectionBorders(paint_info, paint_offset, current_border_value); | 116 PaintCollapsedSectionBorders(paint_info, paint_offset, current_border_value); |
| 122 LayoutTable* table = layout_table_section_.Table(); | 117 LayoutTable* table = layout_table_section_.Table(); |
| 123 if (table->Header() == layout_table_section_) | 118 if (table->Header() == layout_table_section_) |
| 124 PaintRepeatingHeaderGroup(paint_info, paint_offset, current_border_value, | 119 PaintRepeatingHeaderGroup(paint_info, paint_offset, current_border_value, |
| 125 kPaintCollapsedBorders); | 120 kPaintCollapsedBorders); |
| 126 } | 121 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 138 BoxClipper box_clipper(layout_table_section_, paint_info, | 133 BoxClipper box_clipper(layout_table_section_, paint_info, |
| 139 adjusted_paint_offset, kForceContentsClip); | 134 adjusted_paint_offset, kForceContentsClip); |
| 140 | 135 |
| 141 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); | 136 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); |
| 142 local_visual_rect.MoveBy(-adjusted_paint_offset); | 137 local_visual_rect.MoveBy(-adjusted_paint_offset); |
| 143 | 138 |
| 144 LayoutRect table_aligned_rect = | 139 LayoutRect table_aligned_rect = |
| 145 layout_table_section_.LogicalRectForWritingModeAndDirection( | 140 layout_table_section_.LogicalRectForWritingModeAndDirection( |
| 146 local_visual_rect); | 141 local_visual_rect); |
| 147 | 142 |
| 148 CellSpan dirtied_rows = layout_table_section_.DirtiedRows(table_aligned_rect); | 143 CellSpan dirtied_rows; |
| 149 CellSpan dirtied_columns = | 144 CellSpan dirtied_columns; |
| 150 layout_table_section_.DirtiedEffectiveColumns(table_aligned_rect); | 145 layout_table_section_.DirtiedRowsAndEffectiveColumns( |
| 146 table_aligned_rect, dirtied_rows, dirtied_columns); | |
| 151 | 147 |
| 152 if (dirtied_columns.Start() >= dirtied_columns.end()) | 148 if (dirtied_columns.Start() >= dirtied_columns.End()) |
| 153 return; | 149 return; |
| 154 | 150 |
| 155 // 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 |
| 156 // precedence due to cell position is respected. | 152 // precedence due to cell position is respected. |
| 157 for (unsigned r = dirtied_rows.end(); r > dirtied_rows.Start(); r--) { | 153 for (unsigned r = dirtied_rows.End(); r > dirtied_rows.Start(); r--) { |
| 158 unsigned row = r - 1; | 154 unsigned row = r - 1; |
| 159 unsigned n_cols = layout_table_section_.NumEffectiveColumns(row); | 155 unsigned n_cols = layout_table_section_.NumEffectiveColumns(row); |
| 160 for (unsigned c = std::min(dirtied_columns.end(), n_cols); | 156 for (unsigned c = std::min(dirtied_columns.End(), n_cols); |
| 161 c > dirtied_columns.Start(); c--) { | 157 c > dirtied_columns.Start(); c--) { |
| 162 unsigned col = c - 1; | 158 unsigned col = c - 1; |
| 163 if (const LayoutTableCell* cell = | 159 if (const LayoutTableCell* cell = |
| 164 layout_table_section_.OriginatingCellAt(row, col)) { | 160 layout_table_section_.OriginatingCellAt(row, col)) { |
| 165 LayoutPoint cell_point = | 161 LayoutPoint cell_point = |
| 166 layout_table_section_.FlipForWritingModeForChild( | 162 layout_table_section_.FlipForWritingModeForChild( |
| 167 cell, adjusted_paint_offset); | 163 cell, adjusted_paint_offset); |
| 168 TableCellPainter(*cell).PaintCollapsedBorders(paint_info, cell_point, | 164 TableCellPainter(*cell).PaintCollapsedBorders(paint_info, cell_point, |
| 169 current_border_value); | 165 current_border_value); |
| 170 } | 166 } |
| 171 } | 167 } |
| 172 } | 168 } |
| 173 } | 169 } |
| 174 | 170 |
| 175 void TableSectionPainter::PaintObject(const PaintInfo& paint_info, | 171 void TableSectionPainter::PaintObject(const PaintInfo& paint_info, |
| 176 const LayoutPoint& paint_offset) { | 172 const LayoutPoint& paint_offset) { |
| 177 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); | 173 LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_); |
| 178 local_visual_rect.MoveBy(-paint_offset); | 174 local_visual_rect.MoveBy(-paint_offset); |
| 179 | 175 |
| 180 LayoutRect table_aligned_rect = | 176 LayoutRect table_aligned_rect = |
| 181 layout_table_section_.LogicalRectForWritingModeAndDirection( | 177 layout_table_section_.LogicalRectForWritingModeAndDirection( |
| 182 local_visual_rect); | 178 local_visual_rect); |
| 183 | 179 |
| 184 CellSpan dirtied_rows = layout_table_section_.DirtiedRows(table_aligned_rect); | 180 CellSpan dirtied_rows; |
| 185 CellSpan dirtied_columns = | 181 CellSpan dirtied_columns; |
| 186 layout_table_section_.DirtiedEffectiveColumns(table_aligned_rect); | 182 layout_table_section_.DirtiedRowsAndEffectiveColumns( |
| 183 table_aligned_rect, dirtied_rows, dirtied_columns); | |
| 187 | 184 |
| 188 PaintInfo paint_info_for_descendants = paint_info.ForDescendants(); | 185 PaintInfo paint_info_for_descendants = paint_info.ForDescendants(); |
| 189 | 186 |
| 190 if (ShouldPaintSelfBlockBackground(paint_info.phase)) { | 187 if (ShouldPaintSelfBlockBackground(paint_info.phase)) { |
| 191 PaintBoxDecorationBackground(paint_info, paint_offset, dirtied_rows, | 188 PaintBoxDecorationBackground(paint_info, paint_offset, dirtied_rows, |
| 192 dirtied_columns); | 189 dirtied_columns); |
| 193 } | 190 } |
| 194 | 191 |
| 195 if (paint_info.phase == kPaintPhaseSelfBlockBackgroundOnly) | 192 if (paint_info.phase == kPaintPhaseSelfBlockBackgroundOnly) |
| 196 return; | 193 return; |
| 197 | 194 |
| 198 if (ShouldPaintDescendantBlockBackgrounds(paint_info.phase)) { | 195 if (ShouldPaintDescendantBlockBackgrounds(paint_info.phase)) { |
| 199 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 196 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
| 200 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); | 197 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); |
| 201 // 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 |
| 202 // TableRowPainter::paint(). | 199 // TableRowPainter::paint(). |
| 203 if (!row || row->HasSelfPaintingLayer()) | 200 if (!row || row->HasSelfPaintingLayer()) |
| 204 continue; | 201 continue; |
| 205 TableRowPainter(*row).PaintBoxDecorationBackground( | 202 TableRowPainter(*row).PaintBoxDecorationBackground( |
| 206 paint_info_for_descendants, paint_offset, dirtied_columns); | 203 paint_info_for_descendants, paint_offset, dirtied_columns); |
| 207 } | 204 } |
| 208 } | 205 } |
| 209 | 206 |
| 210 // This is tested after background painting because during background painting | 207 // This is tested after background painting because during background painting |
| 211 // 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 |
| 212 // dirtyRows and dirtyColumns. | 209 // dirtyRows and dirtyColumns. |
| 213 if (dirtied_rows.Start() >= dirtied_rows.end() || | 210 if (dirtied_rows.Start() >= dirtied_rows.End() || |
| 214 dirtied_columns.Start() >= dirtied_columns.end()) | 211 dirtied_columns.Start() >= dirtied_columns.End()) |
| 215 return; | 212 return; |
| 216 | 213 |
| 217 const auto& overflowing_cells = layout_table_section_.OverflowingCells(); | 214 const auto& overflowing_cells = layout_table_section_.OverflowingCells(); |
| 218 if (!layout_table_section_.HasMultipleCellLevels() && | 215 if (overflowing_cells.IsEmpty()) { |
| 219 overflowing_cells.IsEmpty()) { | |
| 220 // This path is for 2 cases: | 216 // This path is for 2 cases: |
| 221 // 1. Normal partial paint, without overflowing cells and multiple cell | 217 // 1. Normal partial paint, without overflowing cells; |
| 222 // levels; | |
| 223 // 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 |
| 224 // cells. | 219 // cells. |
| 225 // 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 |
| 226 // whether dirtied_rows and dirtied_columns cover the whole section. | 221 // whether dirtied_rows and dirtied_columns cover the whole section. |
| 227 DCHECK(!layout_table_section_.HasOverflowingCell() || | 222 DCHECK(!layout_table_section_.HasOverflowingCell() || |
| 228 (dirtied_rows == layout_table_section_.FullSectionRowSpan() && | 223 (dirtied_rows == layout_table_section_.FullSectionRowSpan() && |
| 229 dirtied_columns == | 224 dirtied_columns == |
| 230 layout_table_section_.FullTableEffectiveColumnSpan())); | 225 layout_table_section_.FullTableEffectiveColumnSpan())); |
| 231 | 226 |
| 232 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 227 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
| 233 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); | 228 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); |
| 234 // TODO(crbug.com/577282): This painting order is inconsistent with other | 229 // TODO(crbug.com/577282): This painting order is inconsistent with other |
| 235 // outlines. | 230 // outlines. |
| 236 if (row && !row->HasSelfPaintingLayer() && | 231 if (row && !row->HasSelfPaintingLayer() && |
| 237 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { | 232 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { |
| 238 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, | 233 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, |
| 239 paint_offset); | 234 paint_offset); |
| 240 } | 235 } |
| 241 for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.end(); | 236 for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.End(); |
| 242 c++) { | 237 c++) { |
| 243 if (const LayoutTableCell* cell = | 238 if (const LayoutTableCell* cell = |
| 244 layout_table_section_.OriginatingCellAt(r, c)) | 239 layout_table_section_.OriginatingCellAt(r, c)) |
| 245 PaintCell(*cell, paint_info_for_descendants, paint_offset); | 240 PaintCell(*cell, paint_info_for_descendants, paint_offset); |
| 246 } | 241 } |
| 247 } | 242 } |
| 248 } else { | 243 } else { |
| 249 // This path paints section with multiple cell levels or a reasonable number | 244 // This path paints section with a reasonable number of overflowing cells. |
| 250 // of overflowing cells. This is the "partial paint path" for overflowing | 245 // This is the "partial paint path" for overflowing cells referred in |
| 251 // cells referred in LayoutTableSection::ComputeOverflowFromDescendants(). | 246 // LayoutTableSection::ComputeOverflowFromDescendants(). |
| 252 Vector<const LayoutTableCell*> cells; | 247 Vector<const LayoutTableCell*> cells; |
| 253 CopyToVector(overflowing_cells, cells); | 248 CopyToVector(overflowing_cells, cells); |
| 254 | 249 |
| 255 HashSet<const LayoutTableCell*> spanning_cells; | 250 HashSet<const LayoutTableCell*> spanning_cells; |
| 256 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 251 for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
| 257 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); | 252 const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r); |
| 258 // TODO(crbug.com/577282): This painting order is inconsistent with other | 253 // TODO(crbug.com/577282): This painting order is inconsistent with other |
| 259 // outlines. | 254 // outlines. |
| 260 if (row && !row->HasSelfPaintingLayer() && | 255 if (row && !row->HasSelfPaintingLayer() && |
| 261 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { | 256 ShouldPaintSelfOutline(paint_info_for_descendants.phase)) { |
| 262 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, | 257 TableRowPainter(*row).PaintOutline(paint_info_for_descendants, |
| 263 paint_offset); | 258 paint_offset); |
| 264 } | 259 } |
| 265 unsigned n_cols = layout_table_section_.NumEffectiveColumns(r); | 260 unsigned n_cols = layout_table_section_.NumEffectiveColumns(r); |
| 266 for (unsigned c = dirtied_columns.Start(); | 261 for (unsigned c = dirtied_columns.Start(); |
| 267 c < n_cols && c < dirtied_columns.end(); c++) { | 262 c < n_cols && c < dirtied_columns.End(); c++) { |
| 268 for (const auto* cell : | 263 if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) { |
| 269 layout_table_section_.GridCellAt(r, c).Cells()) { | 264 if (!overflowing_cells.Contains(cell)) |
| 270 if (overflowing_cells.Contains(cell)) | 265 cells.push_back(cell); |
|
Xianzhu
2017/05/16 17:18:13
This is simplified because dirtied_columns and dir
| |
| 271 continue; | |
| 272 if (cell->RowSpan() > 1 || cell->ColSpan() > 1) { | |
| 273 if (!spanning_cells.insert(cell).is_new_entry) | |
| 274 continue; | |
| 275 } | |
| 276 cells.push_back(cell); | |
| 277 } | 266 } |
| 278 } | 267 } |
| 279 } | 268 } |
| 280 | 269 |
| 281 // Sort the dirty cells by paint order. | 270 // Sort the dirty cells by paint order. |
| 282 if (!overflowing_cells.size()) { | 271 std::sort(cells.begin(), cells.end(), LayoutTableCell::CompareInDOMOrder); |
|
Xianzhu
2017/05/16 17:18:13
Now only one sort method left because we enter thi
| |
| 283 std::stable_sort(cells.begin(), cells.end(), CompareCellPositions); | |
| 284 } else { | |
| 285 // This comparison is used only when we have overflowing cells as we have | |
| 286 // an unsorted array to sort. We thus need to sort both on rows and | |
| 287 // columns to paint in proper order. | |
| 288 std::sort(cells.begin(), cells.end(), LayoutTableCell::CompareInDOMOrder); | |
| 289 } | |
| 290 | |
| 291 for (const auto* cell : cells) | 272 for (const auto* cell : cells) |
| 292 PaintCell(*cell, paint_info_for_descendants, paint_offset); | 273 PaintCell(*cell, paint_info_for_descendants, paint_offset); |
| 293 } | 274 } |
| 294 } | 275 } |
| 295 | 276 |
| 296 void TableSectionPainter::PaintBoxDecorationBackground( | 277 void TableSectionPainter::PaintBoxDecorationBackground( |
| 297 const PaintInfo& paint_info, | 278 const PaintInfo& paint_info, |
| 298 const LayoutPoint& paint_offset, | 279 const LayoutPoint& paint_offset, |
| 299 const CellSpan& dirtied_rows, | 280 const CellSpan& dirtied_rows, |
| 300 const CellSpan& dirtied_columns) { | 281 const CellSpan& dirtied_columns) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 324 DisplayItem::kBoxDecorationBackground, bounds); | 305 DisplayItem::kBoxDecorationBackground, bounds); |
| 325 LayoutRect paint_rect(paint_offset, layout_table_section_.Size()); | 306 LayoutRect paint_rect(paint_offset, layout_table_section_.Size()); |
| 326 | 307 |
| 327 if (has_box_shadow) { | 308 if (has_box_shadow) { |
| 328 BoxPainter::PaintNormalBoxShadow(paint_info, paint_rect, | 309 BoxPainter::PaintNormalBoxShadow(paint_info, paint_rect, |
| 329 layout_table_section_.StyleRef()); | 310 layout_table_section_.StyleRef()); |
| 330 } | 311 } |
| 331 | 312 |
| 332 if (may_have_background) { | 313 if (may_have_background) { |
| 333 PaintInfo paint_info_for_cells = paint_info.ForDescendants(); | 314 PaintInfo paint_info_for_cells = paint_info.ForDescendants(); |
| 334 for (auto r = dirtied_rows.Start(); r < dirtied_rows.end(); r++) { | 315 for (auto r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) { |
| 335 for (auto c = dirtied_columns.Start(); c < dirtied_columns.end(); c++) { | 316 for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) { |
| 336 if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) { | 317 if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) { |
| 337 PaintBackgroundsBehindCell(*cell, paint_info_for_cells, paint_offset); | 318 PaintBackgroundsBehindCell(*cell, paint_info_for_cells, paint_offset); |
| 338 } | 319 } |
| 339 } | 320 } |
| 340 } | 321 } |
| 341 } | 322 } |
| 342 | 323 |
| 343 if (has_box_shadow) { | 324 if (has_box_shadow) { |
| 344 // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting | 325 // TODO(wangxianzhu): Calculate the inset shadow bounds by insetting |
| 345 // paintRect by half widths of collapsed borders. | 326 // paintRect by half widths of collapsed borders. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 const PaintInfo& paint_info_for_cells, | 371 const PaintInfo& paint_info_for_cells, |
| 391 const LayoutPoint& paint_offset) { | 372 const LayoutPoint& paint_offset) { |
| 392 if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer()) { | 373 if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer()) { |
| 393 LayoutPoint cell_point = | 374 LayoutPoint cell_point = |
| 394 layout_table_section_.FlipForWritingModeForChild(&cell, paint_offset); | 375 layout_table_section_.FlipForWritingModeForChild(&cell, paint_offset); |
| 395 cell.Paint(paint_info_for_cells, cell_point); | 376 cell.Paint(paint_info_for_cells, cell_point); |
| 396 } | 377 } |
| 397 } | 378 } |
| 398 | 379 |
| 399 } // namespace blink | 380 } // namespace blink |
| OLD | NEW |