Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutTableSection.cpp

Issue 2584143003: Repeat footers in paginated context (Closed)
Patch Set: bug 656232 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698