Commit 6287f21e authored by robhogan's avatar robhogan Committed by Commit bot

Don't repeat thead if the first row exceeds the height of the page

BUG=669690
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2

Review-Url: https://codereview.chromium.org/2545243002
Cr-Commit-Position: refs/heads/master@{#438084}
parent 120bb61b
<!DOCTYPE html>
<style>
td, th {
background-color: #ddd;
border: 1px solid black;
}
</style>
<p>crbug.com/669690: If the body's first row doesn't fit on a page then don't repeat headers.</p>
<div style="columns:3; line-height: 18px; column-fill: auto; height:74px; background-color: yellow;">
<table>
<thead>
<tr>
<th>Col 1</th>
</tr>
</thead>
<tr><td>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
<p>10</p>
<p>11</p>
<p>12</p>
<p>13</p>
<p>14</p>
<p>15</p>
<p>16</p>
<p>17</p>
<p>18</p>
<p>19</p>
</td></tr>
</table>
</div>
<!DOCTYPE html>
<style>
td, th {
background-color: #ddd;
border: 1px solid black;
}
thead, tr {
break-inside: avoid;
}
</style>
<p>crbug.com/669690: If the body's first row doesn't fit on a page then don't repeat headers.</p>
<div style="columns:3; line-height: 18px; column-fill: auto; height:74px; background-color: yellow;">
<table>
<thead>
<tr>
<th>Col 1</th>
</tr>
</thead>
<tr><td>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
<p>10</p>
<p>11</p>
<p>12</p>
<p>13</p>
<p>14</p>
<p>15</p>
<p>16</p>
<p>17</p>
<p>18</p>
<p>19</p>
</td></tr>
</table>
</div>
......@@ -32,10 +32,8 @@ tr {
</tr></td>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -44,22 +42,20 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
</table>
......
......@@ -28,7 +28,6 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -38,9 +37,9 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -49,7 +48,6 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
</table>
......
......@@ -28,7 +28,6 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -38,9 +37,9 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -49,7 +48,6 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
</table>
......
......@@ -28,7 +28,6 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -38,9 +37,9 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
<tr><td class="header" colspan=2>Col 1</td></tr>
<tr><td style="padding-top: 0px;">
<table>
<tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
......@@ -49,7 +48,6 @@ tr {
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
<tr><td>Te</td><td>xt</td></tr>
</table>
</tr></td>
</table>
......
......@@ -53,7 +53,6 @@ LayoutState::LayoutState(LayoutBox& layoutObject,
m_flowThread = m_next->flowThread();
m_paginationStateChanged = m_next->m_paginationStateChanged;
layoutObject.view()->pushLayoutState(*this);
m_heightOffsetForTableHeaders = m_next->heightOffsetForTableHeaders();
if (layoutObject.isLayoutFlowThread()) {
// Entering a new pagination context.
......
......@@ -84,13 +84,6 @@ class LayoutState {
LayoutUnit pageLogicalOffset(const LayoutBox&,
const LayoutUnit& childLogicalOffset) const;
LayoutUnit heightOffsetForTableHeaders() const {
return m_heightOffsetForTableHeaders;
};
void setHeightOffsetForTableHeaders(LayoutUnit offset) {
m_heightOffsetForTableHeaders = offset;
};
const LayoutSize& paginationOffset() const { return m_paginationOffset; }
bool containingBlockLogicalWidthChanged() const {
return m_containingBlockLogicalWidthChanged;
......@@ -121,10 +114,6 @@ class LayoutState {
// relative positioning or scroll offsets.
LayoutSize m_paginationOffset;
// The height we need to make available for repeating table headers in
// paginated layout.
LayoutUnit m_heightOffsetForTableHeaders;
LayoutObject& m_layoutObject;
};
......
......@@ -635,16 +635,12 @@ void LayoutTable::layout() {
if (sectionLogicalHeight <
section->pageLogicalHeightForOffset(section->logicalTop()) &&
section->getPaginationBreakability() != AllowAnyBreaks) {
LayoutUnit offsetForTableHeaders =
state.heightOffsetForTableHeaders();
// Don't include any strut in the header group - we only want the
// height from its content.
offsetForTableHeaders += sectionLogicalHeight;
LayoutUnit offsetForTableHeaders = sectionLogicalHeight;
if (LayoutTableRow* row = section->firstRow())
offsetForTableHeaders -= row->paginationStrut();
section->setOffsetForRepeatingHeader(
state.heightOffsetForTableHeaders());
state.setHeightOffsetForTableHeaders(offsetForTableHeaders);
setRowOffsetFromRepeatingHeader(offsetForTableHeaders);
}
}
}
......
......@@ -256,6 +256,13 @@ class CORE_EXPORT LayoutTable final : public LayoutBlock {
LayoutTableSection* footer() const { return m_foot; }
LayoutTableSection* firstBody() const { return m_firstBody; }
void setRowOffsetFromRepeatingHeader(LayoutUnit offset) {
m_rowOffsetFromRepeatingHeader = offset;
}
LayoutUnit rowOffsetFromRepeatingHeader() const {
return m_rowOffsetFromRepeatingHeader;
}
// This function returns 0 if the table has no section.
LayoutTableSection* topSection() const;
LayoutTableSection* bottomSection() const;
......@@ -575,6 +582,7 @@ class CORE_EXPORT LayoutTable final : public LayoutBlock {
int m_borderEnd;
LayoutUnit m_blockOffsetToFirstRepeatableHeader;
LayoutUnit m_rowOffsetFromRepeatingHeader;
};
inline LayoutTableSection* LayoutTable::topSection() const {
......
......@@ -106,8 +106,7 @@ LayoutTableSection::LayoutTableSection(Element* element)
m_outerBorderAfter(0),
m_needsCellRecalc(false),
m_forceSlowPaintPathWithOverflowingCell(false),
m_hasMultipleCellLevels(false),
m_offsetForRepeatingHeader(LayoutUnit()) {
m_hasMultipleCellLevels(false) {
// init LayoutObject attributes
setInline(false); // our object is not Inline
}
......@@ -1983,7 +1982,6 @@ int LayoutTableSection::logicalHeightForRow(
void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject,
SubtreeLayoutScope& layouter) {
LayoutState& state = *view()->layoutState();
rowObject.setPaginationStrut(LayoutUnit());
rowObject.setLogicalHeight(LayoutUnit(logicalHeightForRow(rowObject)));
int paginationStrut =
......@@ -1991,9 +1989,12 @@ void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject,
bool rowIsAtTopOfColumn = false;
LayoutUnit offsetFromTopOfPage;
if (!paginationStrut) {
if (state.heightOffsetForTableHeaders()) {
LayoutUnit pageLogicalHeight =
pageLogicalHeightForOffset(rowObject.logicalTop());
if (pageLogicalHeight && table()->header() &&
table()->rowOffsetFromRepeatingHeader()) {
offsetFromTopOfPage =
pageLogicalHeightForOffset(rowObject.logicalTop()) -
pageLogicalHeight -
pageRemainingLogicalHeightForOffset(rowObject.logicalTop(),
AssociateWithLatterPage);
rowIsAtTopOfColumn = !offsetFromTopOfPage ||
......@@ -2014,8 +2015,7 @@ void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject,
if (!rowObject.rowIndex() && header &&
table()->sectionAbove(this) == header &&
header->getPaginationBreakability() != AllowAnyBreaks) {
state.setHeightOffsetForTableHeaders(state.heightOffsetForTableHeaders() -
header->logicalHeight());
table()->setRowOffsetFromRepeatingHeader(LayoutUnit());
}
// Border spacing from the previous row has pushed this row just past the top
// of the page, so we must reposition it to the top of the page and avoid any
......@@ -2025,7 +2025,8 @@ void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject,
// 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();
if (header)
paginationStrut += table()->rowOffsetFromRepeatingHeader().toInt();
rowObject.setPaginationStrut(LayoutUnit(paginationStrut));
// We have inserted a pagination strut before the row. Adjust the logical top
......@@ -2058,9 +2059,12 @@ bool LayoutTableSection::isRepeatingHeaderGroup() const {
// page, then don't repeat the header on each page.
// See https://drafts.csswg.org/css-tables-3/#repeated-headers
LayoutTableSection* sectionBelow = table()->sectionBelow(this);
if (sectionBelow && sectionBelow->firstRow() &&
sectionBelow->firstRow()->paginationStrut())
return false;
if (!sectionBelow)
return true;
if (LayoutTableRow* firstRow = sectionBelow->firstRow()) {
if (firstRow->paginationStrut() || firstRow->logicalHeight() > pageHeight)
return false;
}
return true;
}
......
......@@ -318,13 +318,6 @@ class CORE_EXPORT LayoutTableSection final : public LayoutTableBoxComponent {
int paginationStrutForRow(LayoutTableRow*, LayoutUnit logicalOffset) const;
void setOffsetForRepeatingHeader(LayoutUnit offset) {
m_offsetForRepeatingHeader = offset;
}
LayoutUnit offsetForRepeatingHeader() const {
return m_offsetForRepeatingHeader;
}
bool mapToVisualRectInAncestorSpace(
const LayoutBoxModelObject* ancestor,
LayoutRect&,
......@@ -470,8 +463,6 @@ class CORE_EXPORT LayoutTableSection final : public LayoutTableBoxComponent {
// The use is to disable a painting optimization where we just paint the
// invalidated cells.
bool m_hasMultipleCellLevels;
LayoutUnit m_offsetForRepeatingHeader;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutTableSection, isTableSection());
......
......@@ -81,14 +81,12 @@ void TableSectionPainter::paintRepeatingHeaderGroup(
paintOffset.y() + totalHeightOfRows);
while (paginationOffset.y() < bottomBound) {
LayoutPoint nestedOffset =
paginationOffset +
LayoutPoint(LayoutUnit(),
m_layoutTableSection.offsetForRepeatingHeader());
if (itemToPaint == PaintCollapsedBorders)
paintCollapsedSectionBorders(paintInfo, nestedOffset, currentBorderValue);
else
paintSection(paintInfo, nestedOffset);
if (itemToPaint == PaintCollapsedBorders) {
paintCollapsedSectionBorders(paintInfo, paginationOffset,
currentBorderValue);
} else {
paintSection(paintInfo, paginationOffset);
}
paginationOffset.move(0, pageHeight.toInt());
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment