OLD | NEW |
---|---|
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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 table()->effectiveColumns(); | 251 table()->effectiveColumns(); |
252 unsigned insertionRow = row->rowIndex(); | 252 unsigned insertionRow = row->rowIndex(); |
253 | 253 |
254 // ### mozilla still seems to do the old HTML way, even for strict DTD | 254 // ### 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 | 255 // (see the annotation on table cell layouting in the CSS specs and the |
256 // testcase below: | 256 // testcase below: |
257 // <TABLE border> | 257 // <TABLE border> |
258 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4 | 258 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4 |
259 // <TR><TD colspan="2">5 | 259 // <TR><TD colspan="2">5 |
260 // </TABLE> | 260 // </TABLE> |
261 while (m_cCol < numCols(insertionRow) && | 261 unsigned nCols = numCols(insertionRow); |
262 (cellAt(insertionRow, m_cCol).hasCells() || | 262 while (m_cCol < nCols && (cellAt(insertionRow, m_cCol).hasCells() || |
263 cellAt(insertionRow, m_cCol).inColSpan)) | 263 cellAt(insertionRow, m_cCol).inColSpan)) |
264 m_cCol++; | 264 m_cCol++; |
265 | 265 |
266 updateLogicalHeightForCell(m_grid[insertionRow], cell); | 266 updateLogicalHeightForCell(m_grid[insertionRow], cell); |
267 | 267 |
268 ensureRows(insertionRow + rSpan); | 268 ensureRows(insertionRow + rSpan); |
269 | 269 |
270 m_grid[insertionRow].rowLayoutObject = row; | 270 m_grid[insertionRow].rowLayoutObject = row; |
271 | 271 |
272 unsigned col = m_cCol; | 272 unsigned col = m_cCol; |
273 // tell the cell where it is | 273 // tell the cell where it is |
274 bool inColSpan = false; | 274 bool inColSpan = false; |
275 unsigned colSize = columns.size(); | |
275 while (cSpan) { | 276 while (cSpan) { |
276 unsigned currentSpan; | 277 unsigned currentSpan; |
277 if (m_cCol >= columns.size()) { | 278 if (m_cCol >= colSize) { |
278 table()->appendEffectiveColumn(cSpan); | 279 table()->appendEffectiveColumn(cSpan); |
279 currentSpan = cSpan; | 280 currentSpan = cSpan; |
280 } else { | 281 } else { |
281 if (cSpan < columns[m_cCol].span) | 282 if (cSpan < columns[m_cCol].span) |
282 table()->splitEffectiveColumn(m_cCol, cSpan); | 283 table()->splitEffectiveColumn(m_cCol, cSpan); |
283 currentSpan = columns[m_cCol].span; | 284 currentSpan = columns[m_cCol].span; |
284 } | 285 } |
285 for (unsigned r = 0; r < rSpan; r++) { | 286 for (unsigned r = 0; r < rSpan; r++) { |
286 ensureCols(insertionRow + r, m_cCol + 1); | 287 ensureCols(insertionRow + r, m_cCol + 1); |
287 CellStruct& c = cellAt(insertionRow + r, m_cCol); | 288 CellStruct& c = cellAt(insertionRow + r, m_cCol); |
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1145 } | 1146 } |
1146 rowLayoutObject->setLogicalHeight(rowLogicalHeight); | 1147 rowLayoutObject->setLogicalHeight(rowLogicalHeight); |
1147 rowLayoutObject->updateLayerTransformAfterLayout(); | 1148 rowLayoutObject->updateLayerTransformAfterLayout(); |
1148 } | 1149 } |
1149 } | 1150 } |
1150 | 1151 |
1151 // Vertically align and flex the cells in each row. | 1152 // Vertically align and flex the cells in each row. |
1152 for (unsigned r = 0; r < totalRows; r++) { | 1153 for (unsigned r = 0; r < totalRows; r++) { |
1153 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; | 1154 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; |
1154 | 1155 |
1155 for (unsigned c = 0; c < numCols(r); c++) { | 1156 unsigned nCols = numCols(r); |
mstensho (USE GERRIT)
2017/01/20 10:02:04
These are good. I was meaning to point it out in t
| |
1157 for (unsigned c = 0; c < nCols; c++) { | |
1156 CellStruct& cs = cellAt(r, c); | 1158 CellStruct& cs = cellAt(r, c); |
1157 LayoutTableCell* cell = cs.primaryCell(); | 1159 LayoutTableCell* cell = cs.primaryCell(); |
1158 | 1160 |
1159 if (!cell || cs.inColSpan) | 1161 if (!cell || cs.inColSpan) |
1160 continue; | 1162 continue; |
1161 | 1163 |
1162 if (cell->rowIndex() != r) | 1164 if (cell->rowIndex() != r) |
1163 continue; // Rowspanned cells are handled in the first row they occur. | 1165 continue; // Rowspanned cells are handled in the first row they occur. |
1164 | 1166 |
1165 int rHeight; | 1167 int rHeight; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1265 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount; | 1267 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount; |
1266 | 1268 |
1267 m_overflow.reset(); | 1269 m_overflow.reset(); |
1268 m_overflowingCells.clear(); | 1270 m_overflowingCells.clear(); |
1269 m_forceSlowPaintPathWithOverflowingCell = false; | 1271 m_forceSlowPaintPathWithOverflowingCell = false; |
1270 #if ENABLE(ASSERT) | 1272 #if ENABLE(ASSERT) |
1271 bool hasOverflowingCell = false; | 1273 bool hasOverflowingCell = false; |
1272 #endif | 1274 #endif |
1273 // Now that our height has been determined, add in overflow from cells. | 1275 // Now that our height has been determined, add in overflow from cells. |
1274 for (unsigned r = 0; r < totalRows; r++) { | 1276 for (unsigned r = 0; r < totalRows; r++) { |
1275 for (unsigned c = 0; c < numCols(r); c++) { | 1277 unsigned nCols = numCols(r); |
1278 unsigned nextRowCells = r < totalRows - 1 ? numCols(r + 1) : 0; | |
1279 for (unsigned c = 0; c < nCols; c++) { | |
1276 CellStruct& cs = cellAt(r, c); | 1280 CellStruct& cs = cellAt(r, c); |
1277 LayoutTableCell* cell = cs.primaryCell(); | 1281 LayoutTableCell* cell = cs.primaryCell(); |
1278 if (!cell || cs.inColSpan) | 1282 if (!cell || cs.inColSpan) |
1279 continue; | 1283 continue; |
1280 if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c)) | 1284 if (r < totalRows - 1 && c < nextRowCells && |
1285 cell == primaryCellAt(r + 1, c)) | |
1281 continue; | 1286 continue; |
1282 addOverflowFromChild(cell); | 1287 addOverflowFromChild(cell); |
1283 #if ENABLE(ASSERT) | 1288 #if ENABLE(ASSERT) |
1284 hasOverflowingCell |= cell->hasVisualOverflow(); | 1289 hasOverflowingCell |= cell->hasVisualOverflow(); |
1285 #endif | 1290 #endif |
1286 if (cell->hasVisualOverflow() && | 1291 if (cell->hasVisualOverflow() && |
1287 !m_forceSlowPaintPathWithOverflowingCell) { | 1292 !m_forceSlowPaintPathWithOverflowingCell) { |
1288 m_overflowingCells.add(cell); | 1293 m_overflowingCells.add(cell); |
1289 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) { | 1294 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) { |
1290 // We need to set m_forcesSlowPaintPath only if there is a least one | 1295 // We need to set m_forcesSlowPaintPath only if there is a least one |
(...skipping 15 matching lines...) Expand all Loading... | |
1306 clearChildNeedsOverflowRecalcAfterStyleChange(); | 1311 clearChildNeedsOverflowRecalcAfterStyleChange(); |
1307 unsigned totalRows = m_grid.size(); | 1312 unsigned totalRows = m_grid.size(); |
1308 bool childrenOverflowChanged = false; | 1313 bool childrenOverflowChanged = false; |
1309 for (unsigned r = 0; r < totalRows; r++) { | 1314 for (unsigned r = 0; r < totalRows; r++) { |
1310 LayoutTableRow* rowLayouter = rowLayoutObjectAt(r); | 1315 LayoutTableRow* rowLayouter = rowLayoutObjectAt(r); |
1311 if (!rowLayouter || | 1316 if (!rowLayouter || |
1312 !rowLayouter->childNeedsOverflowRecalcAfterStyleChange()) | 1317 !rowLayouter->childNeedsOverflowRecalcAfterStyleChange()) |
1313 continue; | 1318 continue; |
1314 rowLayouter->clearChildNeedsOverflowRecalcAfterStyleChange(); | 1319 rowLayouter->clearChildNeedsOverflowRecalcAfterStyleChange(); |
1315 bool rowChildrenOverflowChanged = false; | 1320 bool rowChildrenOverflowChanged = false; |
1316 for (unsigned c = 0; c < numCols(r); c++) { | 1321 unsigned nCols = numCols(r); |
1322 for (unsigned c = 0; c < nCols; c++) { | |
1317 CellStruct& cs = cellAt(r, c); | 1323 CellStruct& cs = cellAt(r, c); |
1318 LayoutTableCell* cell = cs.primaryCell(); | 1324 LayoutTableCell* cell = cs.primaryCell(); |
1319 if (!cell || cs.inColSpan || !cell->needsOverflowRecalcAfterStyleChange()) | 1325 if (!cell || cs.inColSpan || !cell->needsOverflowRecalcAfterStyleChange()) |
1320 continue; | 1326 continue; |
1321 rowChildrenOverflowChanged |= cell->recalcOverflowAfterStyleChange(); | 1327 rowChildrenOverflowChanged |= cell->recalcOverflowAfterStyleChange(); |
1322 } | 1328 } |
1323 if (rowChildrenOverflowChanged) | 1329 if (rowChildrenOverflowChanged) |
1324 rowLayouter->computeOverflow(); | 1330 rowLayouter->computeOverflow(); |
1325 childrenOverflowChanged |= rowChildrenOverflowChanged; | 1331 childrenOverflowChanged |= rowChildrenOverflowChanged; |
1326 } | 1332 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1359 const BorderValue& rb = side == BorderBefore | 1365 const BorderValue& rb = side == BorderBefore |
1360 ? firstRow()->style()->borderBefore() | 1366 ? firstRow()->style()->borderBefore() |
1361 : lastRow()->style()->borderAfter(); | 1367 : lastRow()->style()->borderAfter(); |
1362 if (rb.style() == BorderStyleHidden) | 1368 if (rb.style() == BorderStyleHidden) |
1363 return -1; | 1369 return -1; |
1364 if (rb.style() > BorderStyleHidden && rb.width() > borderWidth) | 1370 if (rb.style() > BorderStyleHidden && rb.width() > borderWidth) |
1365 borderWidth = rb.width(); | 1371 borderWidth = rb.width(); |
1366 | 1372 |
1367 bool allHidden = true; | 1373 bool allHidden = true; |
1368 unsigned r = side == BorderBefore ? 0 : m_grid.size() - 1; | 1374 unsigned r = side == BorderBefore ? 0 : m_grid.size() - 1; |
1369 for (unsigned c = 0; c < numCols(r); c++) { | 1375 unsigned nCols = numCols(r); |
1376 for (unsigned c = 0; c < nCols; c++) { | |
1370 const CellStruct& current = cellAt(r, c); | 1377 const CellStruct& current = cellAt(r, c); |
1371 if (current.inColSpan || !current.hasCells()) | 1378 if (current.inColSpan || !current.hasCells()) |
1372 continue; | 1379 continue; |
1373 const ComputedStyle& primaryCellStyle = current.primaryCell()->styleRef(); | 1380 const ComputedStyle& primaryCellStyle = current.primaryCell()->styleRef(); |
1374 // FIXME: Make this work with perpendicular and flipped cells. | 1381 // FIXME: Make this work with perpendicular and flipped cells. |
1375 const BorderValue& cb = side == BorderBefore | 1382 const BorderValue& cb = side == BorderBefore |
1376 ? primaryCellStyle.borderBefore() | 1383 ? primaryCellStyle.borderBefore() |
1377 : primaryCellStyle.borderAfter(); | 1384 : primaryCellStyle.borderAfter(); |
1378 // FIXME: Don't repeat for the same col group | 1385 // FIXME: Don't repeat for the same col group |
1379 LayoutTableCol* col = | 1386 LayoutTableCol* col = |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1680 void LayoutTableSection::setNeedsCellRecalc() { | 1687 void LayoutTableSection::setNeedsCellRecalc() { |
1681 m_needsCellRecalc = true; | 1688 m_needsCellRecalc = true; |
1682 if (LayoutTable* t = table()) | 1689 if (LayoutTable* t = table()) |
1683 t->setNeedsSectionRecalc(); | 1690 t->setNeedsSectionRecalc(); |
1684 } | 1691 } |
1685 | 1692 |
1686 unsigned LayoutTableSection::numEffectiveColumns() const { | 1693 unsigned LayoutTableSection::numEffectiveColumns() const { |
1687 unsigned result = 0; | 1694 unsigned result = 0; |
1688 | 1695 |
1689 for (unsigned r = 0; r < m_grid.size(); ++r) { | 1696 for (unsigned r = 0; r < m_grid.size(); ++r) { |
1690 for (unsigned c = result; c < numCols(r); ++c) { | 1697 unsigned nCols = numCols(r); |
1698 for (unsigned c = result; c < nCols; ++c) { | |
1691 const CellStruct& cell = cellAt(r, c); | 1699 const CellStruct& cell = cellAt(r, c); |
1692 if (cell.hasCells() || cell.inColSpan) | 1700 if (cell.hasCells() || cell.inColSpan) |
1693 result = c; | 1701 result = c; |
1694 } | 1702 } |
1695 } | 1703 } |
1696 | 1704 |
1697 return result + 1; | 1705 return result + 1; |
1698 } | 1706 } |
1699 | 1707 |
1700 const BorderValue& LayoutTableSection::borderAdjoiningStartCell( | 1708 const BorderValue& LayoutTableSection::borderAdjoiningStartCell( |
1701 const LayoutTableCell* cell) const { | 1709 const LayoutTableCell* cell) const { |
1702 ASSERT(cell->isFirstOrLastCellInRow()); | 1710 ASSERT(cell->isFirstOrLastCellInRow()); |
1703 return hasSameDirectionAs(cell) ? style()->borderStart() | 1711 return hasSameDirectionAs(cell) ? style()->borderStart() |
1704 : style()->borderEnd(); | 1712 : style()->borderEnd(); |
1705 } | 1713 } |
1706 | 1714 |
1707 const BorderValue& LayoutTableSection::borderAdjoiningEndCell( | 1715 const BorderValue& LayoutTableSection::borderAdjoiningEndCell( |
1708 const LayoutTableCell* cell) const { | 1716 const LayoutTableCell* cell) const { |
1709 ASSERT(cell->isFirstOrLastCellInRow()); | 1717 ASSERT(cell->isFirstOrLastCellInRow()); |
1710 return hasSameDirectionAs(cell) ? style()->borderEnd() | 1718 return hasSameDirectionAs(cell) ? style()->borderEnd() |
1711 : style()->borderStart(); | 1719 : style()->borderStart(); |
1712 } | 1720 } |
1713 | 1721 |
1714 const LayoutTableCell* LayoutTableSection::firstRowCellAdjoiningTableStart() | 1722 const LayoutTableCell* LayoutTableSection::firstRowCellAdjoiningTableStart() |
1715 const { | 1723 const { |
1716 unsigned adjoiningStartCellColumnIndex = | 1724 unsigned adjoiningStartCellColumnIndex = |
1717 hasSameDirectionAs(table()) ? 0 : table()->lastEffectiveColumnIndex(); | 1725 hasSameDirectionAs(table()) ? 0 : table()->lastEffectiveColumnIndex(); |
1718 return primaryCellAt(0, adjoiningStartCellColumnIndex); | 1726 return adjoiningStartCellColumnIndex < numCols(0) |
1727 ? primaryCellAt(0, adjoiningStartCellColumnIndex) | |
1728 : nullptr; | |
1719 } | 1729 } |
1720 | 1730 |
1721 const LayoutTableCell* LayoutTableSection::firstRowCellAdjoiningTableEnd() | 1731 const LayoutTableCell* LayoutTableSection::firstRowCellAdjoiningTableEnd() |
1722 const { | 1732 const { |
1723 unsigned adjoiningEndCellColumnIndex = | 1733 unsigned adjoiningEndCellColumnIndex = |
1724 hasSameDirectionAs(table()) ? table()->lastEffectiveColumnIndex() : 0; | 1734 hasSameDirectionAs(table()) ? table()->lastEffectiveColumnIndex() : 0; |
1725 return primaryCellAt(0, adjoiningEndCellColumnIndex); | 1735 return adjoiningEndCellColumnIndex < numCols(0) |
1736 ? primaryCellAt(0, adjoiningEndCellColumnIndex) | |
1737 : nullptr; | |
1726 } | 1738 } |
1727 | 1739 |
1728 void LayoutTableSection::appendEffectiveColumn(unsigned pos) { | 1740 void LayoutTableSection::appendEffectiveColumn(unsigned pos) { |
1729 ASSERT(!m_needsCellRecalc); | 1741 ASSERT(!m_needsCellRecalc); |
1730 | 1742 |
1731 for (unsigned row = 0; row < m_grid.size(); ++row) | 1743 for (unsigned row = 0; row < m_grid.size(); ++row) |
1732 m_grid[row].row.resize(pos + 1); | 1744 m_grid[row].row.resize(pos + 1); |
1733 } | 1745 } |
1734 | 1746 |
1735 void LayoutTableSection::splitEffectiveColumn(unsigned pos, unsigned first) { | 1747 void LayoutTableSection::splitEffectiveColumn(unsigned pos, unsigned first) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1798 LayoutRect hitTestRect = LayoutRect(locationInContainer.boundingBox()); | 1810 LayoutRect hitTestRect = LayoutRect(locationInContainer.boundingBox()); |
1799 hitTestRect.moveBy(-adjustedLocation); | 1811 hitTestRect.moveBy(-adjustedLocation); |
1800 | 1812 |
1801 LayoutRect tableAlignedRect = | 1813 LayoutRect tableAlignedRect = |
1802 logicalRectForWritingModeAndDirection(hitTestRect); | 1814 logicalRectForWritingModeAndDirection(hitTestRect); |
1803 CellSpan rowSpan = spannedRows(tableAlignedRect); | 1815 CellSpan rowSpan = spannedRows(tableAlignedRect); |
1804 CellSpan columnSpan = spannedEffectiveColumns(tableAlignedRect); | 1816 CellSpan columnSpan = spannedEffectiveColumns(tableAlignedRect); |
1805 | 1817 |
1806 // Now iterate over the spanned rows and columns. | 1818 // Now iterate over the spanned rows and columns. |
1807 for (unsigned hitRow = rowSpan.start(); hitRow < rowSpan.end(); ++hitRow) { | 1819 for (unsigned hitRow = rowSpan.start(); hitRow < rowSpan.end(); ++hitRow) { |
1808 for (unsigned hitColumn = columnSpan.start(); hitColumn < columnSpan.end(); | 1820 unsigned nCols = numCols(hitRow); |
1809 ++hitColumn) { | 1821 for (unsigned hitColumn = columnSpan.start(); |
1810 if (hitColumn >= numCols(hitRow)) | 1822 hitColumn < nCols && hitColumn < columnSpan.end(); ++hitColumn) { |
1811 break; | |
1812 | |
1813 CellStruct& current = cellAt(hitRow, hitColumn); | 1823 CellStruct& current = cellAt(hitRow, hitColumn); |
1814 | 1824 |
1815 // If the cell is empty, there's nothing to do | 1825 // If the cell is empty, there's nothing to do |
1816 if (!current.hasCells()) | 1826 if (!current.hasCells()) |
1817 continue; | 1827 continue; |
1818 | 1828 |
1819 for (unsigned i = current.cells.size(); i;) { | 1829 for (unsigned i = current.cells.size(); i;) { |
1820 --i; | 1830 --i; |
1821 LayoutTableCell* cell = current.cells[i]; | 1831 LayoutTableCell* cell = current.cells[i]; |
1822 LayoutPoint cellPoint = | 1832 LayoutPoint cellPoint = |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2071 // the header in all columns. | 2081 // the header in all columns. |
2072 // Note that this is in flow thread coordinates, not visual coordinates. The | 2082 // Note that this is in flow thread coordinates, not visual coordinates. The |
2073 // enclosing LayoutFlowThread will convert to visual coordinates. | 2083 // enclosing LayoutFlowThread will convert to visual coordinates. |
2074 if (table()->header() == this && isRepeatingHeaderGroup()) | 2084 if (table()->header() == this && isRepeatingHeaderGroup()) |
2075 rect.setHeight(table()->logicalHeight()); | 2085 rect.setHeight(table()->logicalHeight()); |
2076 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpace(ancestor, rect, | 2086 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpace(ancestor, rect, |
2077 flags); | 2087 flags); |
2078 } | 2088 } |
2079 | 2089 |
2080 } // namespace blink | 2090 } // namespace blink |
OLD | NEW |