Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutTableSection.cpp

Issue 2783953002: Fix spanning cell painting background from wrong row (Closed)
Patch Set: Remove non-const version and use faster implementation Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 * (C) 1997 Torben Weis (weis@kde.org) 3 * (C) 1997 Torben Weis (weis@kde.org)
4 * (C) 1998 Waldo Bastian (bastian@kde.org) 4 * (C) 1998 Waldo Bastian (bastian@kde.org)
5 * (C) 1999 Lars Knoll (knoll@kde.org) 5 * (C) 1999 Lars Knoll (knoll@kde.org)
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) 6 * (C) 1999 Antti Koivisto (koivisto@kde.org)
7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. 7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc.
8 * All rights reserved. 8 * All rights reserved.
9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
10 * 10 *
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 LayoutTableSection::LayoutTableSection(Element* element) 99 LayoutTableSection::LayoutTableSection(Element* element)
100 : LayoutTableBoxComponent(element), 100 : LayoutTableBoxComponent(element),
101 m_cCol(0), 101 m_cCol(0),
102 m_cRow(0), 102 m_cRow(0),
103 m_outerBorderStart(0), 103 m_outerBorderStart(0),
104 m_outerBorderEnd(0), 104 m_outerBorderEnd(0),
105 m_outerBorderBefore(0), 105 m_outerBorderBefore(0),
106 m_outerBorderAfter(0), 106 m_outerBorderAfter(0),
107 m_needsCellRecalc(false), 107 m_needsCellRecalc(false),
108 m_forceSlowPaintPathWithOverflowingCell(false), 108 m_forceSlowPaintPathWithOverflowingCell(false),
109 m_hasMultipleCellLevels(false) { 109 m_hasMultipleCellLevels(false),
110 m_hasSpanningCells(false) {
110 // init LayoutObject attributes 111 // init LayoutObject attributes
111 setInline(false); // our object is not Inline 112 setInline(false); // our object is not Inline
112 } 113 }
113 114
114 LayoutTableSection::~LayoutTableSection() {} 115 LayoutTableSection::~LayoutTableSection() {}
115 116
116 void LayoutTableSection::styleDidChange(StyleDifference diff, 117 void LayoutTableSection::styleDidChange(StyleDifference diff,
117 const ComputedStyle* oldStyle) { 118 const ComputedStyle* oldStyle) {
118 DCHECK(style()->display() == EDisplay::kTableFooterGroup || 119 DCHECK(style()->display() == EDisplay::kTableFooterGroup ||
119 style()->display() == EDisplay::kTableRowGroup || 120 style()->display() == EDisplay::kTableRowGroup ||
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 void LayoutTableSection::addCell(LayoutTableCell* cell, LayoutTableRow* row) { 241 void LayoutTableSection::addCell(LayoutTableCell* cell, LayoutTableRow* row) {
241 // We don't insert the cell if we need cell recalc as our internal columns' 242 // We don't insert the cell if we need cell recalc as our internal columns'
242 // representation will have drifted from the table's representation. Also 243 // representation will have drifted from the table's representation. Also
243 // recalcCells will call addCell at a later time after sync'ing our columns' 244 // recalcCells will call addCell at a later time after sync'ing our columns'
244 // with the table's. 245 // with the table's.
245 if (needsCellRecalc()) 246 if (needsCellRecalc())
246 return; 247 return;
247 248
248 unsigned rSpan = cell->rowSpan(); 249 unsigned rSpan = cell->rowSpan();
249 unsigned cSpan = cell->colSpan(); 250 unsigned cSpan = cell->colSpan();
251 if (rSpan > 1 || cSpan > 1)
252 m_hasSpanningCells = true;
253
250 const Vector<LayoutTable::ColumnStruct>& columns = 254 const Vector<LayoutTable::ColumnStruct>& columns =
251 table()->effectiveColumns(); 255 table()->effectiveColumns();
252 unsigned insertionRow = row->rowIndex(); 256 unsigned insertionRow = row->rowIndex();
253 257
254 // ### mozilla still seems to do the old HTML way, even for strict DTD 258 // ### mozilla still seems to do the old HTML way, even for strict DTD
255 // (see the annotation on table cell layouting in the CSS specs and the 259 // (see the annotation on table cell layouting in the CSS specs and the
256 // testcase below: 260 // testcase below:
257 // <TABLE border> 261 // <TABLE border>
258 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4 262 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
259 // <TR><TD colspan="2">5 263 // <TR><TD colspan="2">5
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 if (coveredRows.start() == m_rowPos.size() - 1 && 1543 if (coveredRows.start() == m_rowPos.size() - 1 &&
1540 m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= 1544 m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >=
1541 damageRect.y()) 1545 damageRect.y())
1542 coveredRows.decreaseStart(); 1546 coveredRows.decreaseStart();
1543 1547
1544 if (!coveredRows.end() && 1548 if (!coveredRows.end() &&
1545 m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY()) 1549 m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY())
1546 coveredRows.increaseEnd(); 1550 coveredRows.increaseEnd();
1547 1551
1548 coveredRows.ensureConsistency(m_grid.size()); 1552 coveredRows.ensureConsistency(m_grid.size());
1553 if (!m_hasSpanningCells || !coveredRows.start() ||
1554 coveredRows.start() >= m_grid.size())
1555 return coveredRows;
1549 1556
1550 return coveredRows; 1557 // If there are any cells spanning into the first row, expand coveredRows
1558 // to cover the primary cells.
1559 unsigned nCols = numCols(coveredRows.start());
1560 unsigned smallestRow = coveredRows.start();
1561 CellSpan coveredColumns = spannedEffectiveColumns(damageRect);
1562 for (unsigned c = coveredColumns.start();
1563 c < std::min(coveredColumns.end(), nCols); ++c) {
1564 if (const auto* cell = primaryCellAt(coveredRows.start(), c)) {
1565 smallestRow = std::min(smallestRow, cell->rowIndex());
1566 if (!smallestRow)
1567 break;
1568 }
1569 }
1570 return CellSpan(smallestRow, coveredRows.end());
1551 } 1571 }
1552 1572
1553 CellSpan LayoutTableSection::dirtiedEffectiveColumns( 1573 CellSpan LayoutTableSection::dirtiedEffectiveColumns(
1554 const LayoutRect& damageRect) const { 1574 const LayoutRect& damageRect) const {
1555 if (m_forceSlowPaintPathWithOverflowingCell) 1575 if (m_forceSlowPaintPathWithOverflowingCell)
1556 return fullTableEffectiveColumnSpan(); 1576 return fullTableEffectiveColumnSpan();
1557 1577
1558 CHECK(table()->numEffectiveColumns()); 1578 CHECK(table()->numEffectiveColumns());
1559 CellSpan coveredColumns = spannedEffectiveColumns(damageRect); 1579 CellSpan coveredColumns = spannedEffectiveColumns(damageRect);
1560 1580
1561 const Vector<int>& columnPos = table()->effectiveColumnPositions(); 1581 const Vector<int>& columnPos = table()->effectiveColumnPositions();
1562 // To issue paint invalidations for the border we might need to paint 1582 // To issue paint invalidations for the border we might need to paint
1563 // invalidate the first or last column even if they are not spanned 1583 // invalidate the first or last column even if they are not spanned
1564 // themselves. 1584 // themselves.
1565 CHECK_LT(coveredColumns.start(), columnPos.size()); 1585 CHECK_LT(coveredColumns.start(), columnPos.size());
1566 if (coveredColumns.start() == columnPos.size() - 1 && 1586 if (coveredColumns.start() == columnPos.size() - 1 &&
1567 columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= 1587 columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >=
1568 damageRect.x()) 1588 damageRect.x())
1569 coveredColumns.decreaseStart(); 1589 coveredColumns.decreaseStart();
1570 1590
1571 if (!coveredColumns.end() && 1591 if (!coveredColumns.end() &&
1572 columnPos[0] - table()->outerBorderStart() <= damageRect.maxX()) 1592 columnPos[0] - table()->outerBorderStart() <= damageRect.maxX())
1573 coveredColumns.increaseEnd(); 1593 coveredColumns.increaseEnd();
1574 1594
1575 coveredColumns.ensureConsistency(table()->numEffectiveColumns()); 1595 coveredColumns.ensureConsistency(table()->numEffectiveColumns());
1596 if (!m_hasSpanningCells || !coveredColumns.start())
1597 return coveredColumns;
1576 1598
1577 return coveredColumns; 1599 // If there are any cells spanning into the first column, expand
1600 // coveredRows to cover the primary cells.
1601 unsigned smallestColumn = coveredColumns.start();
1602 CellSpan coveredRows = spannedRows(damageRect);
1603 for (unsigned r = coveredRows.start(); r < coveredRows.end(); ++r) {
1604 const auto& row = m_grid[r].row;
1605 if (coveredColumns.start() < row.size()) {
1606 unsigned c = coveredColumns.start();
1607 while (c && row[c].inColSpan)
1608 --c;
1609 smallestColumn = std::min(c, smallestColumn);
1610 if (!smallestColumn)
1611 break;
1612 }
1613 }
1614 return CellSpan(smallestColumn, coveredColumns.end());
1578 } 1615 }
1579 1616
1580 CellSpan LayoutTableSection::spannedRows(const LayoutRect& flippedRect) const { 1617 CellSpan LayoutTableSection::spannedRows(const LayoutRect& flippedRect) const {
1581 // Find the first row that starts after rect top. 1618 // Find the first row that starts after rect top.
1582 unsigned nextRow = 1619 unsigned nextRow =
1583 std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - 1620 std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) -
1584 m_rowPos.begin(); 1621 m_rowPos.begin();
1585 1622
1586 // After all rows. 1623 // After all rows.
1587 if (nextRow == m_rowPos.size()) 1624 if (nextRow == m_rowPos.size())
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1724 return primaryCellAt(0, adjoiningStartCellColumnIndex); 1761 return primaryCellAt(0, adjoiningStartCellColumnIndex);
1725 } 1762 }
1726 1763
1727 const LayoutTableCell* LayoutTableSection::firstRowCellAdjoiningTableEnd() 1764 const LayoutTableCell* LayoutTableSection::firstRowCellAdjoiningTableEnd()
1728 const { 1765 const {
1729 unsigned adjoiningEndCellColumnIndex = 1766 unsigned adjoiningEndCellColumnIndex =
1730 hasSameDirectionAs(table()) ? table()->lastEffectiveColumnIndex() : 0; 1767 hasSameDirectionAs(table()) ? table()->lastEffectiveColumnIndex() : 0;
1731 return primaryCellAt(0, adjoiningEndCellColumnIndex); 1768 return primaryCellAt(0, adjoiningEndCellColumnIndex);
1732 } 1769 }
1733 1770
1771 const LayoutTableCell* LayoutTableSection::originatingCellAt(
1772 unsigned row,
1773 unsigned effectiveColumn) const {
1774 const auto& rowVector = m_grid[row].row;
1775 if (effectiveColumn >= rowVector.size())
1776 return nullptr;
1777 const auto& cellStruct = rowVector[effectiveColumn];
1778 if (cellStruct.inColSpan)
1779 return nullptr;
1780 if (const auto* cell = cellStruct.primaryCell()) {
1781 if (cell->rowIndex() == row)
1782 return cell;
1783 }
1784 return nullptr;
1785 }
1786
1734 void LayoutTableSection::appendEffectiveColumn(unsigned pos) { 1787 void LayoutTableSection::appendEffectiveColumn(unsigned pos) {
1735 ASSERT(!m_needsCellRecalc); 1788 ASSERT(!m_needsCellRecalc);
1736 1789
1737 for (unsigned row = 0; row < m_grid.size(); ++row) 1790 for (unsigned row = 0; row < m_grid.size(); ++row)
1738 m_grid[row].row.resize(pos + 1); 1791 m_grid[row].row.resize(pos + 1);
1739 } 1792 }
1740 1793
1741 void LayoutTableSection::splitEffectiveColumn(unsigned pos, unsigned first) { 1794 void LayoutTableSection::splitEffectiveColumn(unsigned pos, unsigned first) {
1742 ASSERT(!m_needsCellRecalc); 1795 ASSERT(!m_needsCellRecalc);
1743 1796
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 transformState.flatten(); 2132 transformState.flatten();
2080 FloatRect rect = transformState.lastPlanarQuad().boundingBox(); 2133 FloatRect rect = transformState.lastPlanarQuad().boundingBox();
2081 rect.setHeight(table()->logicalHeight()); 2134 rect.setHeight(table()->logicalHeight());
2082 transformState.setQuad(FloatQuad(rect)); 2135 transformState.setQuad(FloatQuad(rect));
2083 } 2136 }
2084 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpaceInternal( 2137 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpaceInternal(
2085 ancestor, transformState, flags); 2138 ancestor, transformState, flags);
2086 } 2139 }
2087 2140
2088 } // namespace blink 2141 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698