| 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 |