mirror of https://github.com/vitalif/phantomjs
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 https://github.com/ariya/phantomjs/pull/112911.x
parent
644f379588
commit
edf2d90a11
|
@ -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
|
||||
|
Loading…
Reference in New Issue