Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / paint / TableSectionPainter.cpp
blobd638ab87aca0f886837555ace903f48e9d42295d
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.
5 #include "config.h"
6 #include "core/paint/TableSectionPainter.h"
8 #include "core/layout/LayoutTable.h"
9 #include "core/layout/LayoutTableCell.h"
10 #include "core/layout/LayoutTableCol.h"
11 #include "core/layout/LayoutTableRow.h"
12 #include "core/paint/BlockPainter.h"
13 #include "core/paint/BoxClipper.h"
14 #include "core/paint/LayoutObjectDrawingRecorder.h"
15 #include "core/paint/ObjectPainter.h"
16 #include "core/paint/PaintInfo.h"
17 #include "core/paint/TableCellPainter.h"
18 #include "core/paint/TableRowPainter.h"
20 namespace blink {
22 void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
24 ASSERT(!m_layoutTableSection.needsLayout());
25 // avoid crashing on bugs that cause us to paint with dirty layout
26 if (m_layoutTableSection.needsLayout())
27 return;
29 unsigned totalRows = m_layoutTableSection.numRows();
30 unsigned totalCols = m_layoutTableSection.table()->columns().size();
32 if (!totalRows || !totalCols)
33 return;
35 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableSection.location();
37 BoxClipper boxClipper(m_layoutTableSection, paintInfo, adjustedPaintOffset, ForceContentsClip);
38 paintObject(paintInfo, adjustedPaintOffset);
41 if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && m_layoutTableSection.style()->visibility() == VISIBLE)
42 ObjectPainter(m_layoutTableSection).paintOutline(paintInfo, adjustedPaintOffset);
45 static inline bool compareCellPositions(LayoutTableCell* elem1, LayoutTableCell* elem2)
47 return elem1->rowIndex() < elem2->rowIndex();
50 // This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
51 // to sort both on rows and columns to properly issue paint invalidations.
52 static inline bool compareCellPositionsWithOverflowingCells(LayoutTableCell* elem1, LayoutTableCell* elem2)
54 if (elem1->rowIndex() != elem2->rowIndex())
55 return elem1->rowIndex() < elem2->rowIndex();
57 return elem1->col() < elem2->col();
60 void TableSectionPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
62 LayoutRect localPaintInvalidationRect = LayoutRect(paintInfo.rect);
63 localPaintInvalidationRect.moveBy(-paintOffset);
65 LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingModeAndDirection(localPaintInvalidationRect);
67 CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect);
68 CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRect);
70 HashSet<LayoutTableCell*> overflowingCells = m_layoutTableSection.overflowingCells();
71 if (dirtiedColumns.start() < dirtiedColumns.end()) {
72 if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.size()) {
73 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
74 // Collapsed borders are painted from the bottom right to the top 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.start(); c--) {
79 unsigned col = c - 1;
80 LayoutTableSection::CellStruct& current = m_layoutTableSection.cellAt(row, col);
81 LayoutTableCell* cell = current.primaryCell();
82 if (!cell || (row > dirtiedRows.start() && m_layoutTableSection.primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() && m_layoutTableSection.primaryCellAt(row, col - 1) == cell))
83 continue;
84 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cell, paintOffset);
85 TableCellPainter(*cell).paintCollapsedBorders(paintInfo, cellPoint);
88 } else {
89 // Draw the dirty cells in the order that they appear.
90 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
91 LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r);
92 if (row && !row->hasSelfPaintingLayer())
93 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, paintOffset);
94 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
95 LayoutTableSection::CellStruct& current = m_layoutTableSection.cellAt(r, c);
96 LayoutTableCell* cell = current.primaryCell();
97 if (!cell || (r > dirtiedRows.start() && m_layoutTableSection.primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_layoutTableSection.primaryCellAt(r, c - 1) == cell))
98 continue;
99 paintCell(cell, paintInfo, paintOffset);
103 } else {
104 // The overflowing cells should be scarce to avoid adding a lot of cells 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 * gMaxAllowedOverflowingCellRatioForFastPaintPath);
109 #endif
111 // To make sure we properly paint invalidate the section, we paint invalidated all the overflowing cells that we collected.
112 Vector<LayoutTableCell*> cells;
113 copyToVector(overflowingCells, cells);
115 HashSet<LayoutTableCell*> spanningCells;
117 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
118 LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r);
119 if (row && !row->hasSelfPaintingLayer())
120 TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, paintOffset);
121 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
122 LayoutTableSection::CellStruct& current = m_layoutTableSection.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;
129 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
130 if (!spanningCells.add(current.cells[i]).isNewEntry)
131 continue;
134 cells.append(current.cells[i]);
139 // Sort the dirty cells by paint order.
140 if (!overflowingCells.size())
141 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
142 else
143 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells);
145 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
146 for (unsigned i = cells.size(); i > 0; --i) {
147 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cells[i - 1], paintOffset);
148 TableCellPainter(*cells[i - 1]).paintCollapsedBorders(paintInfo, cellPoint);
150 } else {
151 for (unsigned i = 0; i < cells.size(); ++i)
152 paintCell(cells[i], paintInfo, paintOffset);
158 void TableSectionPainter::paintCell(LayoutTableCell* cell, const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
160 LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cell, paintOffset);
161 PaintPhase paintPhase = paintInfo.phase;
162 LayoutTableRow* row = toLayoutTableRow(cell->parent());
164 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground)
165 && BlockPainter(*cell).intersectsPaintRect(paintInfo, paintOffset)) {
166 // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
167 // the column group, column, row group, row, and then the cell.
168 LayoutTableCol* column = m_layoutTableSection.table()->colElement(cell->col());
169 LayoutTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0;
171 bool columnHasBackground = column && column->hasBackground();
172 bool columnGroupHasBackground = columnGroup && columnGroup->hasBackground();
173 bool sectionHasBackground = m_layoutTableSection.hasBackground();
174 bool rowHasBackground = row->hasBackground();
176 if (columnHasBackground || columnGroupHasBackground || sectionHasBackground || rowHasBackground) {
177 TableCellPainter tableCellPainter(*cell);
178 if (!LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, *cell, DisplayItem::TableCellBackgroundFromContainers, paintOffset)) {
179 LayoutObjectDrawingRecorder recorder(*paintInfo.context, *cell, DisplayItem::TableCellBackgroundFromContainers, tableCellPainter.paintBounds(cellPoint, TableCellPainter::AddOffsetFromParent), paintOffset);
180 // Column groups and columns first.
181 // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
182 // the stack, since we have already opened a transparency layer (potentially) for the table row group.
183 // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
184 // cell.
185 if (columnGroupHasBackground)
186 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup);
187 if (columnHasBackground)
188 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, column);
190 // Paint the row group next.
191 if (sectionHasBackground)
192 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, &m_layoutTableSection);
194 // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
195 // painting the row background for the cell.
196 if (rowHasBackground && !row->hasSelfPaintingLayer())
197 tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, row);
201 if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()))
202 cell->paint(paintInfo, cellPoint);
205 } // namespace blink