| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/paint/TableSectionPainter.h" |
| 7 |
| 8 #include "core/paint/TableRowPainter.h" |
| 9 #include "core/rendering/GraphicsContextAnnotator.h" |
| 10 #include "core/rendering/PaintInfo.h" |
| 11 #include "core/rendering/RenderTable.h" |
| 12 #include "core/rendering/RenderTableCell.h" |
| 13 #include "core/rendering/RenderTableCol.h" |
| 14 #include "core/rendering/RenderTableRow.h" |
| 15 |
| 16 namespace blink { |
| 17 |
| 18 void TableSectionPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) |
| 19 { |
| 20 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderTableSection); |
| 21 |
| 22 ASSERT(!m_renderTableSection.needsLayout()); |
| 23 // avoid crashing on bugs that cause us to paint with dirty layout |
| 24 if (m_renderTableSection.needsLayout()) |
| 25 return; |
| 26 |
| 27 unsigned totalRows = m_renderTableSection.numRows(); |
| 28 unsigned totalCols = m_renderTableSection.table()->columns().size(); |
| 29 |
| 30 if (!totalRows || !totalCols) |
| 31 return; |
| 32 |
| 33 LayoutPoint adjustedPaintOffset = paintOffset + m_renderTableSection.locatio
n(); |
| 34 |
| 35 PaintPhase phase = paintInfo.phase; |
| 36 bool pushedClip = m_renderTableSection.pushContentsClip(paintInfo, adjustedP
aintOffset, ForceContentsClip); |
| 37 paintObject(paintInfo, adjustedPaintOffset); |
| 38 if (pushedClip) |
| 39 m_renderTableSection.popContentsClip(paintInfo, phase, adjustedPaintOffs
et); |
| 40 |
| 41 if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && m_rend
erTableSection.style()->visibility() == VISIBLE) |
| 42 m_renderTableSection.paintOutline(paintInfo, LayoutRect(adjustedPaintOff
set, m_renderTableSection.size())); |
| 43 } |
| 44 |
| 45 static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell*
elem2) |
| 46 { |
| 47 return elem1->rowIndex() < elem2->rowIndex(); |
| 48 } |
| 49 |
| 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. |
| 52 static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* ele
m1, RenderTableCell* elem2) |
| 53 { |
| 54 if (elem1->rowIndex() != elem2->rowIndex()) |
| 55 return elem1->rowIndex() < elem2->rowIndex(); |
| 56 |
| 57 return elem1->col() < elem2->col(); |
| 58 } |
| 59 |
| 60 void TableSectionPainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& p
aintOffset) |
| 61 { |
| 62 LayoutRect localPaintInvalidationRect = paintInfo.rect; |
| 63 localPaintInvalidationRect.moveBy(-paintOffset); |
| 64 |
| 65 LayoutRect tableAlignedRect = m_renderTableSection.logicalRectForWritingMode
AndDirection(localPaintInvalidationRect); |
| 66 |
| 67 CellSpan dirtiedRows = m_renderTableSection.dirtiedRows(tableAlignedRect); |
| 68 CellSpan dirtiedColumns = m_renderTableSection.dirtiedColumns(tableAlignedRe
ct); |
| 69 |
| 70 WillBeHeapHashSet<RawPtrWillBeMember<RenderTableCell> > overflowingCells = m
_renderTableSection.overflowingCells(); |
| 71 if (dirtiedColumns.start() < dirtiedColumns.end()) { |
| 72 if (!m_renderTableSection.hasMultipleCellLevels() && !overflowingCells.s
ize()) { |
| 73 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { |
| 74 // Collapsed borders are painted from the bottom right to the to
p left so that precedence |
| 75 // due to cell position is respected. |
| 76 for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r-
-) { |
| 77 unsigned row = r - 1; |
| 78 for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.s
tart(); c--) { |
| 79 unsigned col = c - 1; |
| 80 RenderTableSection::CellStruct& current = m_renderTableS
ection.cellAt(row, col); |
| 81 RenderTableCell* cell = current.primaryCell(); |
| 82 if (!cell || (row > dirtiedRows.start() && m_renderTable
Section.primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() &&
m_renderTableSection.primaryCellAt(row, col - 1) == cell)) |
| 83 continue; |
| 84 LayoutPoint cellPoint = m_renderTableSection.flipForWrit
ingModeForChild(cell, paintOffset); |
| 85 cell->paintCollapsedBorders(paintInfo, cellPoint); |
| 86 } |
| 87 } |
| 88 } else { |
| 89 // Draw the dirty cells in the order that they appear. |
| 90 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r+
+) { |
| 91 RenderTableRow* row = m_renderTableSection.rowRendererAt(r); |
| 92 if (row && !row->hasSelfPaintingLayer()) |
| 93 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintIn
fo, paintOffset); |
| 94 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns
.end(); c++) { |
| 95 RenderTableSection::CellStruct& current = m_renderTableS
ection.cellAt(r, c); |
| 96 RenderTableCell* cell = current.primaryCell(); |
| 97 if (!cell || (r > dirtiedRows.start() && m_renderTableSe
ction.primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_rende
rTableSection.primaryCellAt(r, c - 1) == cell)) |
| 98 continue; |
| 99 paintCell(cell, paintInfo, paintOffset); |
| 100 } |
| 101 } |
| 102 } |
| 103 } else { |
| 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_renderTableSection.numRows(); |
| 107 unsigned totalCols = m_renderTableSection.table()->columns().size(); |
| 108 ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowed
OverflowingCellRatioForFastPaintPath); |
| 109 #endif |
| 110 |
| 111 // To make sure we properly paint invalidate the section, we paint i
nvalidated all the overflowing cells that we collected. |
| 112 Vector<RenderTableCell*> cells; |
| 113 copyToVector(overflowingCells, cells); |
| 114 |
| 115 HashSet<RenderTableCell*> spanningCells; |
| 116 |
| 117 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
| 118 RenderTableRow* row = m_renderTableSection.rowRendererAt(r); |
| 119 if (row && !row->hasSelfPaintingLayer()) |
| 120 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo,
paintOffset); |
| 121 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end
(); c++) { |
| 122 RenderTableSection::CellStruct& current = m_renderTableSecti
on.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_renderTableSection.flipForWritingM
odeForChild(cells[i - 1], paintOffset); |
| 148 cells[i - 1]->paintCollapsedBorders(paintInfo, cellPoint); |
| 149 } |
| 150 } else { |
| 151 for (unsigned i = 0; i < cells.size(); ++i) |
| 152 paintCell(cells[i], paintInfo, paintOffset); |
| 153 } |
| 154 } |
| 155 } |
| 156 } |
| 157 |
| 158 void TableSectionPainter::paintCell(RenderTableCell* cell, PaintInfo& paintInfo,
const LayoutPoint& paintOffset) |
| 159 { |
| 160 LayoutPoint cellPoint = m_renderTableSection.flipForWritingModeForChild(cell
, paintOffset); |
| 161 PaintPhase paintPhase = paintInfo.phase; |
| 162 RenderTableRow* row = toRenderTableRow(cell->parent()); |
| 163 |
| 164 if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChild
BlockBackground) { |
| 165 // We need to handle painting a stack of backgrounds. This stack (from b
ottom to top) consists of |
| 166 // the column group, column, row group, row, and then the cell. |
| 167 RenderTableCol* column = m_renderTableSection.table()->colElement(cell->
col()); |
| 168 RenderTableCol* columnGroup = column ? column->enclosingColumnGroup() :
0; |
| 169 |
| 170 // Column groups and columns first. |
| 171 // FIXME: Columns and column groups do not currently support opacity, an
d they are being painted "too late" in |
| 172 // the stack, since we have already opened a transparency layer (potenti
ally) for the table row group. |
| 173 // Note that we deliberately ignore whether or not the cell has a layer,
since these backgrounds paint "behind" the |
| 174 // cell. |
| 175 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup); |
| 176 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, column); |
| 177 |
| 178 // Paint the row group next. |
| 179 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, &m_renderTableSec
tion); |
| 180 |
| 181 // Paint the row next, but only if it doesn't have a layer. If a row has
a layer, it will be responsible for |
| 182 // painting the row background for the cell. |
| 183 if (!row->hasSelfPaintingLayer()) |
| 184 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, row); |
| 185 } |
| 186 if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) |
| 187 cell->paint(paintInfo, cellPoint); |
| 188 } |
| 189 |
| 190 } // namespace blink |
| OLD | NEW |