Index: third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
index 275532bb4fd737759e67a6f72a4a27292d04d4dc..41201952a566eb3f86b48a4f1de8bb997dda9086 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp |
@@ -1244,7 +1244,12 @@ void LayoutTableSection::LayoutRows() { |
int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row, |
LayoutUnit logical_offset) const { |
DCHECK(row); |
- if (row->GetPaginationBreakability() == kAllowAnyBreaks) |
+ const LayoutTableSection* footer = Table()->Footer(); |
+ bool make_room_for_repeating_footer = footer && footer != this && |
+ footer->IsRepeatingFooterGroup(this) && |
+ row->RowIndex(); |
+ if (!make_room_for_repeating_footer && |
+ row->GetPaginationBreakability() == kAllowAnyBreaks) |
return 0; |
LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset); |
if (!page_logical_height) |
@@ -1254,6 +1259,9 @@ int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row, |
if (row_logical_height > page_logical_height) |
return 0; |
+ if (make_room_for_repeating_footer) |
+ row_logical_height += footer->LogicalHeight(); |
+ |
LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( |
logical_offset, LayoutBlock::kAssociateWithLatterPage); |
if (remaining_logical_height >= row_logical_height) |
@@ -2079,8 +2087,9 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, |
offset_from_top_of_page <= Table()->VBorderSpacing(); |
} |
- if (!row_is_at_top_of_column) |
+ if (!row_is_at_top_of_column) { |
return; |
+ } |
} |
// We need to push this row to the next fragmentainer. If there are repeated |
// table headers, we need to make room for those at the top of the next |
@@ -2096,6 +2105,19 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, |
if (row_is_at_top_of_column && offset_from_top_of_page) |
pagination_strut -= offset_from_top_of_page.ToInt(); |
+ LayoutTableSection* footer = Table()->Footer(); |
+ if (footer && footer != this && header != this && |
+ footer->IsRepeatingFooterGroup(this)) { |
+ LayoutUnit offset_from_top = LogicalTop() + row_object.LogicalTop(); |
+ unsigned page = |
+ FloorToInt(offset_from_top / PageLogicalHeightForOffset(LogicalTop())); |
+ LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( |
+ row_object.LogicalTop(), kAssociateWithLatterPage); |
+ if (remaining_logical_height >= |
+ (footer->LogicalHeight() - Table()->VBorderSpacing())) |
+ Table()->SetPositionOfRepeatingFooterGroupOnPage(page, offset_from_top); |
+ } |
+ |
// If we have a header group we will paint it at the top of each page, |
// move the rows down to accomodate it. |
if (header && header != this) |
@@ -2116,21 +2138,26 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, |
} |
bool LayoutTableSection::IsRepeatingHeaderGroup() const { |
- if (GetPaginationBreakability() == LayoutBox::kAllowAnyBreaks) |
+ if (GetPaginationBreakability() == kAllowAnyBreaks) |
return false; |
- // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? |
+ |
+ // TODO(rhogan): Sections can be self-painting. |
if (HasSelfPaintingLayer()) |
return false; |
- LayoutUnit page_height = Table()->PageLogicalHeightForOffset(LayoutUnit()); |
+ |
+ LayoutUnit page_height = PageLogicalHeightForOffset(LogicalTop()); |
if (!page_height) |
return false; |
- if (LogicalHeight() > page_height) |
+ // See https://drafts.csswg.org/css-tables-3/#repeated-headers which says |
+ // a header/footer can repeat if it takes up less than a quarter of the page. |
+ if (LogicalHeight() > 0 && page_height / LogicalHeight() < 4) |
return false; |
- // If the first row of the section after the header group doesn't fit on the |
- // page, then don't repeat the header on each page. |
- // See https://drafts.csswg.org/css-tables-3/#repeated-headers |
+ // TODO(crbug.com/710387): If the first row of the section after the header |
+ // group doesn't fit on the page, then we don't repeat the header on each page |
+ // and by extension only support repeating headers on the innermost table in a |
+ // set of nested tables. |
LayoutTableSection* section_below = Table()->SectionBelow(this); |
if (!section_below) |
return true; |
@@ -2143,23 +2170,50 @@ bool LayoutTableSection::IsRepeatingHeaderGroup() const { |
return true; |
} |
+bool LayoutTableSection::IsRepeatingFooterGroup( |
+ const LayoutTableSection* section_for_page) const { |
+ if (GetPaginationBreakability() == kAllowAnyBreaks) |
+ return false; |
+ |
+ // TODO(rhogan): Sections can be self-painting. |
+ if (HasSelfPaintingLayer()) |
+ return false; |
+ |
+ // Get the page height for the section that we want to repeat the footer on |
+ // so we can see if it fits. |
+ LayoutUnit page_height = section_for_page |
+ ? section_for_page->PageLogicalHeightForOffset( |
+ section_for_page->LogicalTop()) |
mstensho (USE GERRIT)
2017/05/10 10:59:03
First of all, you should probably pass LayoutUnit(
|
+ : PageLogicalHeightForOffset(LogicalTop()); |
mstensho (USE GERRIT)
2017/05/10 10:59:03
Ditto - LayoutUnit() is better. Getting rid of thi
|
+ if (!page_height) |
+ return false; |
+ |
+ // See https://drafts.csswg.org/css-tables-3/#repeated-headers which says |
+ // a header/footer can repeat if it takes up less than a quarter of the page. |
+ if (LogicalHeight() > 0 && page_height / LogicalHeight() < 4) |
+ return false; |
+ |
+ return true; |
+} |
+ |
bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal( |
const LayoutBoxModelObject* ancestor, |
TransformState& transform_state, |
VisualRectFlags flags) const { |
if (ancestor == this) |
return true; |
- // Repeating table headers are painted once per fragmentation page/column. |
- // This does not go through the regular fragmentation machinery, so we need |
- // special code to expand the invalidation rect to contain all positions of |
- // the header in all columns. |
- // Note that this is in flow thread coordinates, not visual coordinates. The |
- // enclosing LayoutFlowThread will convert to visual coordinates. |
- if (Table()->Header() == this && IsRepeatingHeaderGroup()) { |
+ |
+ // Repeating table headers and footers are painted once per fragmentation |
+ // page/column. So we need to use the rect for the entire table because |
+ // the repeating headers/footers will appear throughout it. |
+ if ((Table()->Header() == this && IsRepeatingHeaderGroup()) || |
+ (Table()->Footer() == this && IsRepeatingFooterGroup())) { |
transform_state.Flatten(); |
FloatRect rect = transform_state.LastPlanarQuad().BoundingBox(); |
rect.SetHeight(Table()->LogicalHeight()); |
transform_state.SetQuad(FloatQuad(rect)); |
+ return Table()->MapToVisualRectInAncestorSpaceInternal( |
+ ancestor, transform_state, flags); |
} |
return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal( |
ancestor, transform_state, flags); |