Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

Table page-break improvements #11291

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -329,6 +329,28 @@ void RenderTable::layout()
if (m_caption)
m_caption->layoutIfNeeded();

// Bump table to next page if we can't fit the caption, thead and first body cell
setPaginationStrut(0);
if (view()->layoutState()->pageLogicalHeight()) {
LayoutState* layoutState = view()->layoutState();
const int pageLogicalHeight = layoutState->m_pageLogicalHeight;
const int remainingLogicalHeight = pageLogicalHeight - layoutState->pageLogicalOffset(0) % pageLogicalHeight;
if (remainingLogicalHeight > 0) {
int requiredHeight = headHeight;
if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
requiredHeight += m_caption->logicalHeight() + m_caption->marginBefore() + m_caption->marginAfter();
}
if (m_firstBody) {
// FIXME: Calculate maximum required height across all cells in first body row
RenderTableCell* firstCell = m_firstBody->primaryCellAt(0, 0);
requiredHeight += firstCell->contentLogicalHeight() + firstCell->paddingTop(false) + firstCell->paddingBottom(false) + vBorderSpacing();
}
if (requiredHeight > remainingLogicalHeight) {
setPaginationStrut(remainingLogicalHeight);
}
}
}

// If any table section moved vertically, we will just repaint everything from that
// section down (it is quite unlikely that any of the following sections
// did not shift).
Expand Down Expand Up @@ -361,12 +383,6 @@ void RenderTable::layout()
computedLogicalHeight = computePercentageLogicalHeight(logicalHeightLength);
computedLogicalHeight = max(0, computedLogicalHeight);

for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableSection())
// FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
toRenderTableSection(child)->layoutRows(child == m_firstBody ? max(0, computedLogicalHeight - totalSectionLogicalHeight) : 0, headHeight, footHeight);
}

if (!m_firstBody && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
// Completely empty tables (with no sections or anything) should at least honor specified height
// in strict mode.
Expand All @@ -386,6 +402,9 @@ void RenderTable::layout()
}
section->setLogicalLocation(sectionLogicalLeft, logicalHeight());

// FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
section->layoutRows(section == m_firstBody ? max(0, computedLogicalHeight - totalSectionLogicalHeight) : 0, section == m_head ? 0 : headHeight, section == m_foot ? 0 : footHeight);

setLogicalHeight(logicalHeight() + section->logicalHeight());
section = sectionBelow(section);
}
Expand Down Expand Up @@ -521,15 +540,15 @@ void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
// re-paint header/footer if table is split over multiple pages
if (m_head) {
IntPoint childPoint = flipForWritingMode(m_head, IntPoint(tx, ty), ParentToChildFlippingAdjustment);
if (!info.rect.contains(childPoint.x() + m_head->x(), childPoint.y() + m_head->y())) {
if (info.rect.y() > childPoint.y() + m_head->y()) {
repaintedHeadPoint = IntPoint(childPoint.x(), info.rect.y() - m_head->y());
repaintedHead = true;
dynamic_cast<RenderObject*>(m_head)->paint(info, repaintedHeadPoint.x(), repaintedHeadPoint.y());
}
}
if (m_foot) {
IntPoint childPoint = flipForWritingMode(m_foot, IntPoint(tx, ty), ParentToChildFlippingAdjustment);
if (!info.rect.contains(childPoint.x() + m_foot->x(), childPoint.y() + m_foot->y())) {
if (info.rect.y() + info.rect.height() < childPoint.y() + m_foot->y()) {
// find actual end of table on current page
int dy = 0;
const int max_dy = info.rect.y() + info.rect.height();
Expand Down Expand Up @@ -1291,4 +1310,4 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
return false;
}

}
}
Expand Up @@ -496,23 +496,34 @@ int RenderTableSection::layoutRows(int toAdd, int headHeight, int footHeight)

LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode());

WTF::Vector<int> logicalHeightsForPrinting;
// make sure that rows do not overlap a page break
// Calculate logical row heights
Vector<int> logicalRowHeights;
logicalRowHeights.resize(totalRows);
for (int r = 0; r < totalRows; r++) {
logicalRowHeights[r] = m_rowPos[r + 1] - m_rowPos[r] - vspacing;
}

// Make sure that cell contents do not overlap a page break
if (view()->layoutState()->pageLogicalHeight()) {
logicalHeightsForPrinting.resize(totalRows);
LayoutState* layoutState = view()->layoutState();
int pageLogicalHeight = layoutState->m_pageLogicalHeight;
int pageOffset = 0;
for(int r = 0; r < totalRows; ++r) {
const int childLogicalHeight = m_rowPos[r + 1] - m_rowPos[r] - (m_grid[r].rowRenderer ? vspacing : 0);
logicalHeightsForPrinting[r] = childLogicalHeight;
LayoutState* layoutState = view()->layoutState();
const int pageLogicalHeight = layoutState->m_pageLogicalHeight;
if (childLogicalHeight < pageLogicalHeight - footHeight) {
const IntSize delta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
const int logicalOffset = m_rowPos[r] + pageOffset;
const int offset = isHorizontalWritingMode() ? delta.height() : delta.width();
const int remainingLogicalHeight = (pageLogicalHeight - (offset + logicalOffset) % pageLogicalHeight) % pageLogicalHeight;
if (remainingLogicalHeight - footHeight < childLogicalHeight) {

for (int r = 0; r < totalRows; ++r) {
int rowLogicalOffset = m_rowPos[r] + pageOffset;
int remainingLogicalHeight = pageLogicalHeight - layoutState->pageLogicalOffset(rowLogicalOffset) % pageLogicalHeight;

for (int c = 0; c < nEffCols; c++) {
CellStruct& cs = cellAt(r, c);
RenderTableCell* cell = cs.primaryCell();

if (!cell || cs.inColSpan || cell->row() != r)
continue;

int cellRequiredHeight = cell->contentLogicalHeight() + cell->paddingTop(false) + cell->paddingBottom(false);
if (max(logicalRowHeights[r], cellRequiredHeight) > remainingLogicalHeight - footHeight - vspacing) {
pageOffset += remainingLogicalHeight + headHeight;
break;
}
}
m_rowPos[r] += pageOffset;
Expand All @@ -525,11 +536,7 @@ int RenderTableSection::layoutRows(int toAdd, int headHeight, int footHeight)
if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
rowRenderer->setLocation(0, m_rowPos[r]);
rowRenderer->setLogicalWidth(logicalWidth());
if (view()->layoutState()->pageLogicalHeight()) {
rowRenderer->setLogicalHeight(logicalHeightsForPrinting[r]);
} else {
rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
}
rowRenderer->setLogicalHeight(logicalRowHeights[r]);
rowRenderer->updateLayerTransform();
}

Expand All @@ -541,8 +548,8 @@ int RenderTableSection::layoutRows(int toAdd, int headHeight, int footHeight)
continue;

rindx = cell->row();
if (view()->layoutState()->pageLogicalHeight() && cell->rowSpan() == 1) {
rHeight = logicalHeightsForPrinting[rindx];
if (cell->rowSpan() == 1) {
rHeight = logicalRowHeights[rindx];
} else {
rHeight = m_rowPos[rindx + cell->rowSpan()] - m_rowPos[rindx] - vspacing;
}
Expand Down Expand Up @@ -1253,4 +1260,4 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul

}

} // namespace WebCore
} // namespace WebCore