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

Commit

Permalink
Patch for table page break improvement.
Browse files Browse the repository at this point in the history
From d78182d3a6451522f239ee1ecbb71863eb053792 Mon Sep 17 00:00:00 2001
From: Artem Baranovskiy <likejavascript@gmail.com>
Date: Mon, 6 May 2013 08:01:01 +0400
Subject: [PATCH] Table page-break improvements

See issue #11291 #11291
  • Loading branch information
ariya committed Jun 9, 2013
1 parent 644f379 commit edf2d90
Showing 1 changed file with 199 additions and 0 deletions.
199 changes: 199 additions & 0 deletions patches/table-page-break-improvement.patch
@@ -0,0 +1,199 @@
From d78182d3a6451522f239ee1ecbb71863eb053792 Mon Sep 17 00:00:00 2001
From: Artem Baranovskiy <likejavascript@gmail.com>
Date: Mon, 6 May 2013 08:01:01 +0400
Subject: [PATCH] Table page-break improvements

Bump tables to the next page if we cannot fit the caption, thead
and first cell on the current page. Ideally this should be checking
the height of all cells in the first row in the same manner as is
done in the table section render but as this is more of a nice to
have I've done the minimal amount of work for now.

We now only layout section rows once each section has been positioned
within the table, and only supply head and foot reservation heights
to the appropriate sections.

When re-drawing the thead and tfoot only do so if the rect we are
painting is explicitly before/after the "original" thead/tfoot
rather than simply outside of its boundaries. This prevents issues
with re-drawing a redundant head when bumping tables to the next page.

Re-work the table section row layout code so that it's a bit more
streamlined. Additionally, to cater for cells spanning multiple rows
we avoid page breaks in the middle of their content. Note that rows
are always bumped to the next page even if their content doesn't
fit on a full page so as to avoid daft situtations like having the
first 1px on the preceeding page.
---
.../Source/WebCore/rendering/RenderTable.cpp | 37 +++++++++++----
.../WebCore/rendering/RenderTableSection.cpp | 51 +++++++++++--------
2 files changed, 57 insertions(+), 31 deletions(-)

diff --git a/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp b/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp
index 94ca61a..bbc9a1c 100644
--- a/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp
+++ b/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp
@@ -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).
@@ -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.
@@ -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);
}
@@ -521,7 +540,7 @@ 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());
@@ -529,7 +548,7 @@ void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
}
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();
@@ -1291,4 +1310,4 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
return false;
}

-}
+}
\ No newline at end of file
diff --git a/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp b/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp
index 1e90ac6..b41db29 100644
--- a/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/src/qt/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp
@@ -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;
@@ -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();
}

@@ -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;
}
@@ -1253,4 +1260,4 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul

}

-} // namespace WebCore
+} // namespace WebCore
\ No newline at end of file
--
1.7.6.1

0 comments on commit edf2d90

Please sign in to comment.