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

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..37d39c1e62b5e22c3a02c9f95c13a9c443ea70b5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1254,6 +1254,14 @@ int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row,
if (row_logical_height > page_logical_height)
return 0;
+ LayoutTableSection* footer = Table()->Footer();
mstensho (USE GERRIT) 2017/05/08 13:55:59 This one can be const, I guess?
rhogan 2017/05/09 19:57:16 Done.
+ bool footer_wants_to_repeat =
mstensho (USE GERRIT) 2017/05/08 13:55:59 make_room_for_repeating_footer?
rhogan 2017/05/09 19:57:16 Done.
+ footer && footer != this &&
+ footer->IsRepeatingFooterGroup(const_cast<LayoutTableSection*>(this)) &&
mstensho (USE GERRIT) 2017/05/08 13:55:59 Ugh. But is there really any reason not to let the
rhogan 2017/05/09 19:57:16 Done.
+ row->RowIndex();
+ if (footer_wants_to_repeat)
+ row_logical_height += footer->LogicalHeight();
+
LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
logical_offset, LayoutBlock::kAssociateWithLatterPage);
if (remaining_logical_height >= row_logical_height)
@@ -1266,6 +1274,7 @@ int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row,
// content completely. No point in leaving a page completely blank.
return 0;
}
+
mstensho (USE GERRIT) 2017/05/08 13:55:59 Back out this?
rhogan 2017/05/09 19:57:16 Done.
// Table layout parts only work on integers, so we have to round. Round up, to
// make sure that no fraction ever gets left behind in the previous
// fragmentainer.
@@ -2063,6 +2072,7 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object,
row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
int pagination_strut =
PaginationStrutForRow(&row_object, row_object.LogicalTop());
+ LayoutTableSection* footer = Table()->Footer();
mstensho (USE GERRIT) 2017/05/08 13:55:59 Can you push it a few lines down, next to where it
rhogan 2017/05/09 19:57:16 Done.
bool row_is_at_top_of_column = false;
LayoutUnit offset_from_top_of_page;
if (!pagination_strut) {
@@ -2096,6 +2106,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();
+ if (footer && footer != this && header != this &&
mstensho (USE GERRIT) 2017/05/08 13:55:59 If the header isn't repeating, there should be no
rhogan 2017/05/09 19:57:16 Done.
+ footer->IsRepeatingFooterGroup(this)) {
+ DCHECK(PageLogicalHeightForOffset(LayoutUnit()));
+ LayoutUnit offset_from_top = LogicalTop() + row_object.LogicalTop();
+ unsigned page =
+ FloorToInt(offset_from_top / PageLogicalHeightForOffset(LayoutUnit()));
mstensho (USE GERRIT) 2017/05/08 13:55:59 To cope with non-uniform page heights, you should
rhogan 2017/05/09 19:57:15 Done.
+ LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
+ row_object.LogicalTop(), LayoutBlock::kAssociateWithLatterPage);
mstensho (USE GERRIT) 2017/05/08 13:55:59 LayoutBlock:: scope should be unnecessary. This on
rhogan 2017/05/09 19:57:16 Done.
+ 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)
@@ -2115,22 +2138,47 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object,
row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
}
+bool LayoutTableSection::IsRepeatingFooterGroup(
mstensho (USE GERRIT) 2017/05/08 13:55:59 This belongs AFTER IsRepeatingHeaderGroup().
rhogan 2017/05/09 19:57:16 Done.
+ LayoutTableSection* section_for_page) const {
+ if (GetPaginationBreakability() == kAllowAnyBreaks)
+ return false;
+
+ // TODO(rhogan): Sections can be self-painting.
mstensho (USE GERRIT) 2017/05/08 13:55:59 Can you tell me how they can be self-painting?
rhogan 2017/05/09 19:57:16 Yes, if you put an opacity: 0.5 on them for exampl
mstensho (USE GERRIT) 2017/05/10 10:59:03 Ah, thanks!
+ if (HasSelfPaintingLayer())
+ return false;
+
+ LayoutUnit page_height = section_for_page
+ ? section_for_page->PageLogicalHeightForOffset(
mstensho (USE GERRIT) 2017/05/08 13:55:59 This is to avoid assertion failures and the bugs t
rhogan 2017/05/09 19:57:16 Correct.
+ section_for_page->LogicalTop())
+ : PageLogicalHeightForOffset(LogicalTop());
+ if (!page_height)
+ return false;
+
+ if (LogicalHeight() > 0 && page_height / LogicalHeight() < 4)
mstensho (USE GERRIT) 2017/05/08 13:55:59 The code looks fine, but I'd like a comment that m
rhogan 2017/05/09 19:57:16 Done.
+ return false;
+
+ return true;
+}
+
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)
+ if (LogicalHeight() > 0 && page_height / LogicalHeight() < 4)
mstensho (USE GERRIT) 2017/05/08 13:55:59 The code looks fine, but I'd like a comment that m
rhogan 2017/05/09 19:57:16 Done.
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;
@@ -2149,17 +2197,21 @@ bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal(
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. 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()) ||
+ (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(
mstensho (USE GERRIT) 2017/05/08 13:55:59 How can we just skip one ancestor in the chain lik
rhogan 2017/05/09 19:57:16 I've updated the comment to explain this. For both
+ ancestor, transform_state, flags);
}
return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal(
ancestor, transform_state, flags);

Powered by Google App Engine
This is Rietveld 408576698