Chromium Code Reviews| 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); |