Index: third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
index fc9f44e0d97d2a0a8977329d1046105973921c7e..25fb70ab90f774205c1b74dae700f9f6112bb61c 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
@@ -860,6 +860,9 @@ int LayoutTableSection::calcRowLogicalHeight() { |
m_grid[r].baseline = -1; |
int baselineDescent = 0; |
+ if (state.isPaginated() && m_grid[r].rowLayoutObject) |
+ m_rowPos[r] += m_grid[r].rowLayoutObject->paginationStrut().ceil(); |
+ |
if (m_grid[r].logicalHeight.isSpecified()) { |
// Our base size is the biggest logical height from our cells' styles |
// (excluding row spanning cells). |
@@ -978,8 +981,7 @@ void LayoutTableSection::layout() { |
} |
rowLayoutObject->layoutIfNeeded(); |
if (state.isPaginated()) { |
- rowLayoutObject->setLogicalHeight( |
- LayoutUnit(logicalHeightForRow(*rowLayoutObject))); |
+ adjustRowForPagination(*rowLayoutObject, layouter); |
rowLogicalTop = rowLayoutObject->logicalBottom(); |
rowLogicalTop += LayoutUnit(table()->vBorderSpacing()); |
} |
@@ -1118,57 +1120,29 @@ void LayoutTableSection::layoutRows() { |
int vspacing = table()->vBorderSpacing(); |
unsigned nEffCols = table()->numEffectiveColumns(); |
- bool isPaginated = view()->layoutState()->isPaginated(); |
- |
- if (isPaginated) { |
- LayoutTableSection* header = table()->header(); |
- // If we're a table header nested inside a table cell then we want to repeat |
- // on each page, but below the header we're nested inside. Note we don't try |
- // to match the padding on the cell on each repeated header. |
- if (header && header == this) |
- setOffsetForRepeatingHeader( |
- view()->layoutState()->heightOffsetForTableHeaders()); |
- } |
- |
LayoutState state(*this, locationOffset()); |
+ // Set the rows' location and size. |
for (unsigned r = 0; r < totalRows; r++) { |
- // Set the row's x/y position and width/height. |
LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; |
- int paginationStrutOnRow = 0; |
if (rowLayoutObject) { |
rowLayoutObject->setLogicalLocation(LayoutPoint(0, m_rowPos[r])); |
rowLayoutObject->setLogicalWidth(logicalWidth()); |
- rowLayoutObject->setLogicalHeight( |
- LayoutUnit(m_rowPos[r + 1] - m_rowPos[r] - vspacing)); |
- rowLayoutObject->updateLayerTransformAfterLayout(); |
- if (isPaginated) { |
- paginationStrutOnRow = |
- paginationStrutForRow(rowLayoutObject, LayoutUnit(m_rowPos[r])); |
- rowLayoutObject->setPaginationStrut(LayoutUnit(paginationStrutOnRow)); |
- bool rowIsAtTopOfColumn = |
- state.heightOffsetForTableHeaders() && |
- pageRemainingLogicalHeightForOffset(LayoutUnit(m_rowPos[r]), |
- AssociateWithLatterPage) == |
- pageLogicalHeightForOffset(LayoutUnit(m_rowPos[r])); |
- if (paginationStrutOnRow || rowIsAtTopOfColumn) { |
- // If there isn't room for at least one content row on a page with a |
- // header group, then we won't repeat the header on each page. |
- if (!r && table()->header() && |
- table()->sectionAbove(this) == table()->header() && |
- table()->header()->getPaginationBreakability() != AllowAnyBreaks) |
- state.setHeightOffsetForTableHeaders( |
- state.heightOffsetForTableHeaders() - |
- table()->header()->logicalHeight()); |
- // If we have a header group we will paint it at the top of each page, |
- // move the rows down to accomodate it. |
- paginationStrutOnRow += state.heightOffsetForTableHeaders().toInt(); |
- for (unsigned rowIndex = r; rowIndex <= totalRows; rowIndex++) |
- m_rowPos[rowIndex] += paginationStrutOnRow; |
- } |
+ LayoutUnit rowLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing); |
+ if (state.isPaginated() && r + 1 < totalRows) { |
+ // If the next row has a pagination strut, we need to subtract it. It |
+ // should not be included in this row's height. |
+ if (LayoutTableRow* nextRowObject = m_grid[r + 1].rowLayoutObject) |
+ rowLogicalHeight -= nextRowObject->paginationStrut(); |
} |
+ rowLayoutObject->setLogicalHeight(rowLogicalHeight); |
+ rowLayoutObject->updateLayerTransformAfterLayout(); |
} |
+ } |
+ // Vertically align and flex the cells in each row. |
+ for (unsigned r = 0; r < totalRows; r++) { |
+ LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; |
int rowHeightIncreaseForPagination = INT_MIN; |
for (unsigned c = 0; c < nEffCols; c++) { |
@@ -1178,14 +1152,25 @@ void LayoutTableSection::layoutRows() { |
if (!cell || cs.inColSpan) |
continue; |
- int rowIndex = cell->rowIndex(); |
- int rHeight = |
- m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing; |
+ if (cell->rowIndex() != r) |
+ continue; // Rowspanned cells are handled in the first row they occur. |
+ |
+ int rHeight; |
+ int rowLogicalTop; |
+ unsigned rowSpan = std::max(1U, cell->rowSpan()); |
+ unsigned endRowIndex = std::min(r + rowSpan, totalRows) - 1; |
+ LayoutTableRow* lastRowObject = m_grid[endRowIndex].rowLayoutObject; |
+ if (lastRowObject && rowLayoutObject) { |
+ rowLogicalTop = rowLayoutObject->logicalTop().toInt(); |
+ rHeight = lastRowObject->logicalBottom().toInt() - rowLogicalTop; |
+ } else { |
+ rHeight = m_rowPos[endRowIndex + 1] - m_rowPos[r] - vspacing; |
+ rowLogicalTop = m_rowPos[r]; |
+ } |
relayoutCellIfFlexed(*cell, r, rHeight); |
SubtreeLayoutScope layouter(*cell); |
- LayoutUnit rowLogicalTop(m_rowPos[rowIndex]); |
EVerticalAlign cellVerticalAlign; |
// If the cell crosses a fragmentainer boundary, just align it at the |
// top. That's how it was laid out initially, before we knew the final |
@@ -1194,7 +1179,7 @@ void LayoutTableSection::layoutRows() { |
// the requested alignment. Give up instead of risking circular |
// dependencies and unstable layout. |
if (state.isPaginated() && |
- crossesPageBoundary(rowLogicalTop, LayoutUnit(rHeight))) |
+ crossesPageBoundary(LayoutUnit(rowLogicalTop), LayoutUnit(rHeight))) |
cellVerticalAlign = VerticalAlignTop; |
else |
cellVerticalAlign = cell->style()->verticalAlign(); |
@@ -1998,6 +1983,54 @@ int LayoutTableSection::logicalHeightForRow( |
return logicalHeight; |
} |
+void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject, |
+ SubtreeLayoutScope& layouter) { |
+ LayoutState& state = *view()->layoutState(); |
+ rowObject.setPaginationStrut(LayoutUnit()); |
+ rowObject.setLogicalHeight(LayoutUnit(logicalHeightForRow(rowObject))); |
+ int paginationStrut = |
+ paginationStrutForRow(&rowObject, rowObject.logicalTop()); |
+ if (!paginationStrut) { |
+ bool rowIsAtTopOfColumn = |
+ state.heightOffsetForTableHeaders() && |
+ pageLogicalHeightForOffset(rowObject.logicalTop()) == |
+ pageRemainingLogicalHeightForOffset(rowObject.logicalTop(), |
+ AssociateWithLatterPage); |
+ if (!rowIsAtTopOfColumn) |
+ return; |
+ } |
+ // We need to push this row to the next fragmentainer. If there are repeated |
+ // table headers, we need to make room for those at the top of the next |
+ // fragmentainer, above this row. Otherwise, this row will just go at the top |
+ // of the next fragmentainer. |
+ |
+ // If there isn't room for at least one content row on a page with a |
+ // header group, then we won't repeat the header on each page. |
+ LayoutTableSection* header = table()->header(); |
+ if (!rowObject.rowIndex() && header && |
+ table()->sectionAbove(this) == header && |
+ header->getPaginationBreakability() != AllowAnyBreaks) { |
+ state.setHeightOffsetForTableHeaders(state.heightOffsetForTableHeaders() - |
+ header->logicalHeight()); |
+ } |
+ // If we have a header group we will paint it at the top of each page, |
+ // move the rows down to accomodate it. |
+ paginationStrut += state.heightOffsetForTableHeaders().toInt(); |
+ rowObject.setPaginationStrut(LayoutUnit(paginationStrut)); |
+ |
+ // We have inserted a pagination strut before the row. Adjust the logical top |
+ // and re-lay out. We no longer want to break inside the row, but rather |
+ // *before* it. From the previous layout pass, there are most likely |
+ // pagination struts inside some cell in this row that we need to get rid of. |
+ rowObject.setLogicalTop(rowObject.logicalTop() + paginationStrut); |
+ layouter.setChildNeedsLayout(&rowObject); |
+ rowObject.layoutIfNeeded(); |
+ |
+ // It's very likely that re-laying out (and nuking pagination struts inside |
+ // cells) gave us a new height. |
+ rowObject.setLogicalHeight(LayoutUnit(logicalHeightForRow(rowObject))); |
+} |
+ |
bool LayoutTableSection::isRepeatingHeaderGroup() const { |
if (getPaginationBreakability() == LayoutBox::AllowAnyBreaks) |
return false; |