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. All r
ights reserved. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. All r
ights reserved. |
8 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 8 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "core/rendering/RenderTableCol.h" | 34 #include "core/rendering/RenderTableCol.h" |
35 #include "core/rendering/RenderTableRow.h" | 35 #include "core/rendering/RenderTableRow.h" |
36 #include "core/rendering/RenderView.h" | 36 #include "core/rendering/RenderView.h" |
37 #include "core/rendering/SubtreeLayoutScope.h" | 37 #include "core/rendering/SubtreeLayoutScope.h" |
38 #include "wtf/HashSet.h" | 38 #include "wtf/HashSet.h" |
39 | 39 |
40 namespace blink { | 40 namespace blink { |
41 | 41 |
42 using namespace HTMLNames; | 42 using namespace HTMLNames; |
43 | 43 |
44 // Those 2 variables are used to balance the memory consumption vs the repaint t
ime on big tables. | 44 // Those 2 variables are used to balance the memory consumption vs the paint inv
alidation time on big tables. |
45 static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75; | 45 static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75; |
46 static float gMaxAllowedOverflowingCellRatioForFastPaintPath = 0.1f; | 46 static float gMaxAllowedOverflowingCellRatioForFastPaintPath = 0.1f; |
47 | 47 |
48 static inline void setRowLogicalHeightToRowStyleLogicalHeight(RenderTableSection
::RowStruct& row) | 48 static inline void setRowLogicalHeightToRowStyleLogicalHeight(RenderTableSection
::RowStruct& row) |
49 { | 49 { |
50 ASSERT(row.rowRenderer); | 50 ASSERT(row.rowRenderer); |
51 row.logicalHeight = row.rowRenderer->style()->logicalHeight(); | 51 row.logicalHeight = row.rowRenderer->style()->logicalHeight(); |
52 } | 52 } |
53 | 53 |
54 static inline void updateLogicalHeightForCell(RenderTableSection::RowStruct& row
, const RenderTableCell* cell) | 54 static inline void updateLogicalHeightForCell(RenderTableSection::RowStruct& row
, const RenderTableCell* cell) |
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 // either. It's at least stable though and won't result in an in
finite # of relayouts that may never stabilize. | 1006 // either. It's at least stable though and won't result in an in
finite # of relayouts that may never stabilize. |
1007 LayoutUnit oldLogicalHeight = cell->logicalHeight(); | 1007 LayoutUnit oldLogicalHeight = cell->logicalHeight(); |
1008 if (oldLogicalHeight > rHeight) | 1008 if (oldLogicalHeight > rHeight) |
1009 rowHeightIncreaseForPagination = std::max<int>(rowHeightIncr
easeForPagination, oldLogicalHeight - rHeight); | 1009 rowHeightIncreaseForPagination = std::max<int>(rowHeightIncr
easeForPagination, oldLogicalHeight - rHeight); |
1010 cell->setLogicalHeight(rHeight); | 1010 cell->setLogicalHeight(rHeight); |
1011 cell->computeOverflow(oldLogicalHeight, false); | 1011 cell->computeOverflow(oldLogicalHeight, false); |
1012 } | 1012 } |
1013 | 1013 |
1014 LayoutSize childOffset(cell->location() - oldCellRect.location()); | 1014 LayoutSize childOffset(cell->location() - oldCellRect.location()); |
1015 if (childOffset.width() || childOffset.height()) { | 1015 if (childOffset.width() || childOffset.height()) { |
1016 // If the child moved, we have to repaint it as well as any floa
ting/positioned | 1016 // If the child moved, we have to issue paint invalidations to i
t as well as any floating/positioned |
1017 // descendants. An exception is if we need a layout. In this cas
e, we know we're going to | 1017 // descendants. An exception is if we need a layout. In this cas
e, we know we're going to |
1018 // repaint ourselves (and the child) anyway. | 1018 // issue paint invalidations ourselves (and the child) anyway. |
1019 if (!table()->selfNeedsLayout() && cell->checkForPaintInvalidati
on()) | 1019 if (!table()->selfNeedsLayout() && cell->checkForPaintInvalidati
on()) |
1020 cell->setMayNeedPaintInvalidation(true); | 1020 cell->setMayNeedPaintInvalidation(true); |
1021 } | 1021 } |
1022 } | 1022 } |
1023 if (rowHeightIncreaseForPagination) { | 1023 if (rowHeightIncreaseForPagination) { |
1024 for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++) | 1024 for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++) |
1025 m_rowPos[rowIndex] += rowHeightIncreaseForPagination; | 1025 m_rowPos[rowIndex] += rowHeightIncreaseForPagination; |
1026 for (unsigned c = 0; c < nEffCols; ++c) { | 1026 for (unsigned c = 0; c < nEffCols; ++c) { |
1027 WillBeHeapVector<RawPtrWillBeMember<RenderTableCell>, 1>& cells
= cellAt(r, c).cells; | 1027 WillBeHeapVector<RawPtrWillBeMember<RenderTableCell>, 1>& cells
= cellAt(r, c).cells; |
1028 for (size_t i = 0; i < cells.size(); ++i) { | 1028 for (size_t i = 0; i < cells.size(); ++i) { |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && style(
)->visibility() == VISIBLE) | 1243 if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && style(
)->visibility() == VISIBLE) |
1244 paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size())); | 1244 paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size())); |
1245 } | 1245 } |
1246 | 1246 |
1247 static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell*
elem2) | 1247 static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell*
elem2) |
1248 { | 1248 { |
1249 return elem1->rowIndex() < elem2->rowIndex(); | 1249 return elem1->rowIndex() < elem2->rowIndex(); |
1250 } | 1250 } |
1251 | 1251 |
1252 // This comparison is used only when we have overflowing cells as we have an uns
orted array to sort. We thus need | 1252 // This comparison is used only when we have overflowing cells as we have an uns
orted array to sort. We thus need |
1253 // to sort both on rows and columns to properly repaint. | 1253 // to sort both on rows and columns to properly issue paint invalidations. |
1254 static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* ele
m1, RenderTableCell* elem2) | 1254 static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* ele
m1, RenderTableCell* elem2) |
1255 { | 1255 { |
1256 if (elem1->rowIndex() != elem2->rowIndex()) | 1256 if (elem1->rowIndex() != elem2->rowIndex()) |
1257 return elem1->rowIndex() < elem2->rowIndex(); | 1257 return elem1->rowIndex() < elem2->rowIndex(); |
1258 | 1258 |
1259 return elem1->col() < elem2->col(); | 1259 return elem1->col() < elem2->col(); |
1260 } | 1260 } |
1261 | 1261 |
1262 void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo,
const LayoutPoint& paintOffset) | 1262 void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo,
const LayoutPoint& paintOffset) |
1263 { | 1263 { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 return tableAlignedRect; | 1308 return tableAlignedRect; |
1309 } | 1309 } |
1310 | 1310 |
1311 CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const | 1311 CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const |
1312 { | 1312 { |
1313 if (m_forceSlowPaintPathWithOverflowingCell) | 1313 if (m_forceSlowPaintPathWithOverflowingCell) |
1314 return fullTableRowSpan(); | 1314 return fullTableRowSpan(); |
1315 | 1315 |
1316 CellSpan coveredRows = spannedRows(damageRect); | 1316 CellSpan coveredRows = spannedRows(damageRect); |
1317 | 1317 |
1318 // To repaint the border we might need to repaint first or last row even if
they are not spanned themselves. | 1318 // To issue paint invalidations for the border we might need to paint invali
date the first or last row even if they are not spanned themselves. |
1319 if (coveredRows.start() >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() -
1] + table()->outerBorderAfter() >= damageRect.y()) | 1319 if (coveredRows.start() >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() -
1] + table()->outerBorderAfter() >= damageRect.y()) |
1320 --coveredRows.start(); | 1320 --coveredRows.start(); |
1321 | 1321 |
1322 if (!coveredRows.end() && m_rowPos[0] - table()->outerBorderBefore() <= dama
geRect.maxY()) | 1322 if (!coveredRows.end() && m_rowPos[0] - table()->outerBorderBefore() <= dama
geRect.maxY()) |
1323 ++coveredRows.end(); | 1323 ++coveredRows.end(); |
1324 | 1324 |
1325 return coveredRows; | 1325 return coveredRows; |
1326 } | 1326 } |
1327 | 1327 |
1328 CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const | 1328 CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const |
1329 { | 1329 { |
1330 if (m_forceSlowPaintPathWithOverflowingCell) | 1330 if (m_forceSlowPaintPathWithOverflowingCell) |
1331 return fullTableColumnSpan(); | 1331 return fullTableColumnSpan(); |
1332 | 1332 |
1333 CellSpan coveredColumns = spannedColumns(damageRect); | 1333 CellSpan coveredColumns = spannedColumns(damageRect); |
1334 | 1334 |
1335 const Vector<int>& columnPos = table()->columnPositions(); | 1335 const Vector<int>& columnPos = table()->columnPositions(); |
1336 // To repaint the border we might need to repaint first or last column even
if they are not spanned themselves. | 1336 // To issue paint invalidations for the border we might need to paint invali
date the first or last column even if they are not spanned themselves. |
1337 if (coveredColumns.start() >= columnPos.size() - 1 && columnPos[columnPos.si
ze() - 1] + table()->outerBorderEnd() >= damageRect.x()) | 1337 if (coveredColumns.start() >= columnPos.size() - 1 && columnPos[columnPos.si
ze() - 1] + table()->outerBorderEnd() >= damageRect.x()) |
1338 --coveredColumns.start(); | 1338 --coveredColumns.start(); |
1339 | 1339 |
1340 if (!coveredColumns.end() && columnPos[0] - table()->outerBorderStart() <= d
amageRect.maxX()) | 1340 if (!coveredColumns.end() && columnPos[0] - table()->outerBorderStart() <= d
amageRect.maxX()) |
1341 ++coveredColumns.end(); | 1341 ++coveredColumns.end(); |
1342 | 1342 |
1343 return coveredColumns; | 1343 return coveredColumns; |
1344 } | 1344 } |
1345 | 1345 |
1346 CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect) const | 1346 CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect) const |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 if (endColumn == columnPos.size()) | 1391 if (endColumn == columnPos.size()) |
1392 endColumn = columnPos.size() - 1; | 1392 endColumn = columnPos.size() - 1; |
1393 } | 1393 } |
1394 | 1394 |
1395 return CellSpan(startColumn, endColumn); | 1395 return CellSpan(startColumn, endColumn); |
1396 } | 1396 } |
1397 | 1397 |
1398 | 1398 |
1399 void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) | 1399 void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) |
1400 { | 1400 { |
1401 LayoutRect localRepaintRect = paintInfo.rect; | 1401 LayoutRect localPaintInvalidationRect = paintInfo.rect; |
1402 localRepaintRect.moveBy(-paintOffset); | 1402 localPaintInvalidationRect.moveBy(-paintOffset); |
1403 | 1403 |
1404 LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRep
aintRect); | 1404 LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localPai
ntInvalidationRect); |
1405 | 1405 |
1406 CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect); | 1406 CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect); |
1407 CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect); | 1407 CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect); |
1408 | 1408 |
1409 if (dirtiedColumns.start() < dirtiedColumns.end()) { | 1409 if (dirtiedColumns.start() < dirtiedColumns.end()) { |
1410 if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) { | 1410 if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) { |
1411 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { | 1411 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { |
1412 // Collapsed borders are painted from the bottom right to the to
p left so that precedence | 1412 // Collapsed borders are painted from the bottom right to the to
p left so that precedence |
1413 // due to cell position is respected. | 1413 // due to cell position is respected. |
1414 for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r-
-) { | 1414 for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r-
-) { |
(...skipping 24 matching lines...) Expand all Loading... |
1439 } | 1439 } |
1440 } | 1440 } |
1441 } else { | 1441 } else { |
1442 // The overflowing cells should be scarce to avoid adding a lot of c
ells to the HashSet. | 1442 // The overflowing cells should be scarce to avoid adding a lot of c
ells to the HashSet. |
1443 #if ENABLE(ASSERT) | 1443 #if ENABLE(ASSERT) |
1444 unsigned totalRows = m_grid.size(); | 1444 unsigned totalRows = m_grid.size(); |
1445 unsigned totalCols = table()->columns().size(); | 1445 unsigned totalCols = table()->columns().size(); |
1446 ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllow
edOverflowingCellRatioForFastPaintPath); | 1446 ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllow
edOverflowingCellRatioForFastPaintPath); |
1447 #endif | 1447 #endif |
1448 | 1448 |
1449 // To make sure we properly repaint the section, we repaint all the
overflowing cells that we collected. | 1449 // To make sure we properly paint invalidate the section, we paint i
nvalidated all the overflowing cells that we collected. |
1450 Vector<RenderTableCell*> cells; | 1450 Vector<RenderTableCell*> cells; |
1451 copyToVector(m_overflowingCells, cells); | 1451 copyToVector(m_overflowingCells, cells); |
1452 | 1452 |
1453 HashSet<RenderTableCell*> spanningCells; | 1453 HashSet<RenderTableCell*> spanningCells; |
1454 | 1454 |
1455 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { | 1455 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { |
1456 RenderTableRow* row = m_grid[r].rowRenderer; | 1456 RenderTableRow* row = m_grid[r].rowRenderer; |
1457 if (row && !row->hasSelfPaintingLayer()) | 1457 if (row && !row->hasSelfPaintingLayer()) |
1458 row->paintOutlineForRowIfNeeded(paintInfo, paintOffset); | 1458 row->paintOutlineForRowIfNeeded(paintInfo, paintOffset); |
1459 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end
(); c++) { | 1459 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end
(); c++) { |
(...skipping 28 matching lines...) Expand all Loading... |
1488 } else { | 1488 } else { |
1489 for (unsigned i = 0; i < cells.size(); ++i) | 1489 for (unsigned i = 0; i < cells.size(); ++i) |
1490 paintCell(cells[i], paintInfo, paintOffset); | 1490 paintCell(cells[i], paintInfo, paintOffset); |
1491 } | 1491 } |
1492 } | 1492 } |
1493 } | 1493 } |
1494 } | 1494 } |
1495 | 1495 |
1496 void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*) | 1496 void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*) |
1497 { | 1497 { |
1498 // FIXME: Examine cells and repaint only the rect the image paints in. | 1498 // FIXME: Examine cells and issue paint invalidations of only the rect the i
mage paints in. |
1499 paintInvalidationForWholeRenderer(); | 1499 paintInvalidationForWholeRenderer(); |
1500 } | 1500 } |
1501 | 1501 |
1502 void RenderTableSection::recalcCells() | 1502 void RenderTableSection::recalcCells() |
1503 { | 1503 { |
1504 ASSERT(m_needsCellRecalc); | 1504 ASSERT(m_needsCellRecalc); |
1505 // We reset the flag here to ensure that |addCell| works. This is safe to do
as | 1505 // We reset the flag here to ensure that |addCell| works. This is safe to do
as |
1506 // fillRowsWithDefaultStartingAtPosition makes sure we match the table's col
umns | 1506 // fillRowsWithDefaultStartingAtPosition makes sure we match the table's col
umns |
1507 // representation. | 1507 // representation. |
1508 m_needsCellRecalc = false; | 1508 m_needsCellRecalc = false; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1728 // FIXME: The table's direction should determine our row's direction, not th
e section's (see bug 96691). | 1728 // FIXME: The table's direction should determine our row's direction, not th
e section's (see bug 96691). |
1729 if (!style()->isLeftToRightDirection()) | 1729 if (!style()->isLeftToRightDirection()) |
1730 cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - ta
ble()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] +
horizontalBorderSpacing); | 1730 cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - ta
ble()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] +
horizontalBorderSpacing); |
1731 else | 1731 else |
1732 cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizont
alBorderSpacing); | 1732 cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizont
alBorderSpacing); |
1733 | 1733 |
1734 cell->setLogicalLocation(cellLocation); | 1734 cell->setLogicalLocation(cellLocation); |
1735 } | 1735 } |
1736 | 1736 |
1737 } // namespace blink | 1737 } // namespace blink |
OLD | NEW |