This repository has been archived by the owner on May 30, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Patch for table page break improvement.
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
Showing
1 changed file
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|