OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) |
3 * (C) 1997 Torben Weis (weis@kde.org) | 3 * (C) 1997 Torben Weis (weis@kde.org) |
4 * (C) 1998 Waldo Bastian (bastian@kde.org) | 4 * (C) 1998 Waldo Bastian (bastian@kde.org) |
5 * (C) 1999 Lars Knoll (knoll@kde.org) | 5 * (C) 1999 Lars Knoll (knoll@kde.org) |
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. |
8 * All rights reserved. | 8 * All rights reserved. |
9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
10 * | 10 * |
(...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1247 if (row->GetPaginationBreakability() == kAllowAnyBreaks) | 1247 if (row->GetPaginationBreakability() == kAllowAnyBreaks) |
1248 return 0; | 1248 return 0; |
1249 LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset); | 1249 LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset); |
1250 if (!page_logical_height) | 1250 if (!page_logical_height) |
1251 return 0; | 1251 return 0; |
1252 // If the row is too tall for the page don't insert a strut. | 1252 // If the row is too tall for the page don't insert a strut. |
1253 LayoutUnit row_logical_height = row->LogicalHeight(); | 1253 LayoutUnit row_logical_height = row->LogicalHeight(); |
1254 if (row_logical_height > page_logical_height) | 1254 if (row_logical_height > page_logical_height) |
1255 return 0; | 1255 return 0; |
1256 | 1256 |
1257 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.
| |
1258 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.
| |
1259 footer && footer != this && | |
1260 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.
| |
1261 row->RowIndex(); | |
1262 if (footer_wants_to_repeat) | |
1263 row_logical_height += footer->LogicalHeight(); | |
1264 | |
1257 LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( | 1265 LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( |
1258 logical_offset, LayoutBlock::kAssociateWithLatterPage); | 1266 logical_offset, LayoutBlock::kAssociateWithLatterPage); |
1259 if (remaining_logical_height >= row_logical_height) | 1267 if (remaining_logical_height >= row_logical_height) |
1260 return 0; // It fits fine where it is. No need to break. | 1268 return 0; // It fits fine where it is. No need to break. |
1261 LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent( | 1269 LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent( |
1262 logical_offset, remaining_logical_height, row_logical_height); | 1270 logical_offset, remaining_logical_height, row_logical_height); |
1263 if (pagination_strut == remaining_logical_height && | 1271 if (pagination_strut == remaining_logical_height && |
1264 remaining_logical_height == page_logical_height) { | 1272 remaining_logical_height == page_logical_height) { |
1265 // Don't break if we were at the top of a page, and we failed to fit the | 1273 // Don't break if we were at the top of a page, and we failed to fit the |
1266 // content completely. No point in leaving a page completely blank. | 1274 // content completely. No point in leaving a page completely blank. |
1267 return 0; | 1275 return 0; |
1268 } | 1276 } |
1277 | |
mstensho (USE GERRIT)
2017/05/08 13:55:59
Back out this?
rhogan
2017/05/09 19:57:16
Done.
| |
1269 // Table layout parts only work on integers, so we have to round. Round up, to | 1278 // Table layout parts only work on integers, so we have to round. Round up, to |
1270 // make sure that no fraction ever gets left behind in the previous | 1279 // make sure that no fraction ever gets left behind in the previous |
1271 // fragmentainer. | 1280 // fragmentainer. |
1272 return pagination_strut.Ceil(); | 1281 return pagination_strut.Ceil(); |
1273 } | 1282 } |
1274 | 1283 |
1275 void LayoutTableSection::ComputeOverflowFromCells() { | 1284 void LayoutTableSection::ComputeOverflowFromCells() { |
1276 unsigned total_rows = grid_.size(); | 1285 unsigned total_rows = grid_.size(); |
1277 unsigned n_eff_cols = Table()->NumEffectiveColumns(); | 1286 unsigned n_eff_cols = Table()->NumEffectiveColumns(); |
1278 ComputeOverflowFromCells(total_rows, n_eff_cols); | 1287 ComputeOverflowFromCells(total_rows, n_eff_cols); |
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2056 } | 2065 } |
2057 return logical_height; | 2066 return logical_height; |
2058 } | 2067 } |
2059 | 2068 |
2060 void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, | 2069 void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, |
2061 SubtreeLayoutScope& layouter) { | 2070 SubtreeLayoutScope& layouter) { |
2062 row_object.SetPaginationStrut(LayoutUnit()); | 2071 row_object.SetPaginationStrut(LayoutUnit()); |
2063 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); | 2072 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); |
2064 int pagination_strut = | 2073 int pagination_strut = |
2065 PaginationStrutForRow(&row_object, row_object.LogicalTop()); | 2074 PaginationStrutForRow(&row_object, row_object.LogicalTop()); |
2075 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.
| |
2066 bool row_is_at_top_of_column = false; | 2076 bool row_is_at_top_of_column = false; |
2067 LayoutUnit offset_from_top_of_page; | 2077 LayoutUnit offset_from_top_of_page; |
2068 if (!pagination_strut) { | 2078 if (!pagination_strut) { |
2069 LayoutUnit page_logical_height = | 2079 LayoutUnit page_logical_height = |
2070 PageLogicalHeightForOffset(row_object.LogicalTop()); | 2080 PageLogicalHeightForOffset(row_object.LogicalTop()); |
2071 if (page_logical_height && Table()->Header() && Table()->Header() != this && | 2081 if (page_logical_height && Table()->Header() && Table()->Header() != this && |
2072 Table()->RowOffsetFromRepeatingHeader()) { | 2082 Table()->RowOffsetFromRepeatingHeader()) { |
2073 offset_from_top_of_page = | 2083 offset_from_top_of_page = |
2074 page_logical_height - | 2084 page_logical_height - |
2075 PageRemainingLogicalHeightForOffset(row_object.LogicalTop(), | 2085 PageRemainingLogicalHeightForOffset(row_object.LogicalTop(), |
(...skipping 13 matching lines...) Expand all Loading... | |
2089 | 2099 |
2090 LayoutTableSection* header = Table()->Header(); | 2100 LayoutTableSection* header = Table()->Header(); |
2091 if (row_object.IsFirstRowInSectionAfterHeader()) | 2101 if (row_object.IsFirstRowInSectionAfterHeader()) |
2092 Table()->SetRowOffsetFromRepeatingHeader(LayoutUnit()); | 2102 Table()->SetRowOffsetFromRepeatingHeader(LayoutUnit()); |
2093 // Border spacing from the previous row has pushed this row just past the top | 2103 // Border spacing from the previous row has pushed this row just past the top |
2094 // of the page, so we must reposition it to the top of the page and avoid any | 2104 // of the page, so we must reposition it to the top of the page and avoid any |
2095 // repeating header. | 2105 // repeating header. |
2096 if (row_is_at_top_of_column && offset_from_top_of_page) | 2106 if (row_is_at_top_of_column && offset_from_top_of_page) |
2097 pagination_strut -= offset_from_top_of_page.ToInt(); | 2107 pagination_strut -= offset_from_top_of_page.ToInt(); |
2098 | 2108 |
2109 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.
| |
2110 footer->IsRepeatingFooterGroup(this)) { | |
2111 DCHECK(PageLogicalHeightForOffset(LayoutUnit())); | |
2112 LayoutUnit offset_from_top = LogicalTop() + row_object.LogicalTop(); | |
2113 unsigned page = | |
2114 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.
| |
2115 LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( | |
2116 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.
| |
2117 if (remaining_logical_height >= | |
2118 (footer->LogicalHeight() - Table()->VBorderSpacing())) | |
2119 Table()->SetPositionOfRepeatingFooterGroupOnPage(page, offset_from_top); | |
2120 } | |
2121 | |
2099 // If we have a header group we will paint it at the top of each page, | 2122 // If we have a header group we will paint it at the top of each page, |
2100 // move the rows down to accomodate it. | 2123 // move the rows down to accomodate it. |
2101 if (header && header != this) | 2124 if (header && header != this) |
2102 pagination_strut += Table()->RowOffsetFromRepeatingHeader().ToInt(); | 2125 pagination_strut += Table()->RowOffsetFromRepeatingHeader().ToInt(); |
2103 row_object.SetPaginationStrut(LayoutUnit(pagination_strut)); | 2126 row_object.SetPaginationStrut(LayoutUnit(pagination_strut)); |
2104 | 2127 |
2105 // We have inserted a pagination strut before the row. Adjust the logical top | 2128 // We have inserted a pagination strut before the row. Adjust the logical top |
2106 // and re-lay out. We no longer want to break inside the row, but rather | 2129 // and re-lay out. We no longer want to break inside the row, but rather |
2107 // *before* it. From the previous layout pass, there are most likely | 2130 // *before* it. From the previous layout pass, there are most likely |
2108 // pagination struts inside some cell in this row that we need to get rid of. | 2131 // pagination struts inside some cell in this row that we need to get rid of. |
2109 row_object.SetLogicalTop(row_object.LogicalTop() + pagination_strut); | 2132 row_object.SetLogicalTop(row_object.LogicalTop() + pagination_strut); |
2110 layouter.SetChildNeedsLayout(&row_object); | 2133 layouter.SetChildNeedsLayout(&row_object); |
2111 row_object.LayoutIfNeeded(); | 2134 row_object.LayoutIfNeeded(); |
2112 | 2135 |
2113 // It's very likely that re-laying out (and nuking pagination struts inside | 2136 // It's very likely that re-laying out (and nuking pagination struts inside |
2114 // cells) gave us a new height. | 2137 // cells) gave us a new height. |
2115 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); | 2138 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); |
2116 } | 2139 } |
2117 | 2140 |
2118 bool LayoutTableSection::IsRepeatingHeaderGroup() const { | 2141 bool LayoutTableSection::IsRepeatingFooterGroup( |
mstensho (USE GERRIT)
2017/05/08 13:55:59
This belongs AFTER IsRepeatingHeaderGroup().
rhogan
2017/05/09 19:57:16
Done.
| |
2119 if (GetPaginationBreakability() == LayoutBox::kAllowAnyBreaks) | 2142 LayoutTableSection* section_for_page) const { |
2143 if (GetPaginationBreakability() == kAllowAnyBreaks) | |
2120 return false; | 2144 return false; |
2121 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? | 2145 |
2146 // 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!
| |
2122 if (HasSelfPaintingLayer()) | 2147 if (HasSelfPaintingLayer()) |
2123 return false; | 2148 return false; |
2124 LayoutUnit page_height = Table()->PageLogicalHeightForOffset(LayoutUnit()); | 2149 |
2150 LayoutUnit page_height = section_for_page | |
2151 ? 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.
| |
2152 section_for_page->LogicalTop()) | |
2153 : PageLogicalHeightForOffset(LogicalTop()); | |
2125 if (!page_height) | 2154 if (!page_height) |
2126 return false; | 2155 return false; |
2127 | 2156 |
2128 if (LogicalHeight() > page_height) | 2157 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.
| |
2129 return false; | 2158 return false; |
2130 | 2159 |
2131 // If the first row of the section after the header group doesn't fit on the | 2160 return true; |
2132 // page, then don't repeat the header on each page. | 2161 } |
2133 // See https://drafts.csswg.org/css-tables-3/#repeated-headers | 2162 |
2163 bool LayoutTableSection::IsRepeatingHeaderGroup() const { | |
2164 if (GetPaginationBreakability() == kAllowAnyBreaks) | |
2165 return false; | |
2166 | |
2167 // TODO(rhogan): Sections can be self-painting. | |
2168 if (HasSelfPaintingLayer()) | |
2169 return false; | |
2170 | |
2171 LayoutUnit page_height = PageLogicalHeightForOffset(LogicalTop()); | |
2172 if (!page_height) | |
2173 return false; | |
2174 | |
2175 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.
| |
2176 return false; | |
2177 | |
2178 // TODO(crbug.com/710387): If the first row of the section after the header | |
2179 // group doesn't fit on the page, then we don't repeat the header on each page | |
2180 // and by extension only support repeating headers on the innermost table in a | |
2181 // set of nested tables. | |
2134 LayoutTableSection* section_below = Table()->SectionBelow(this); | 2182 LayoutTableSection* section_below = Table()->SectionBelow(this); |
2135 if (!section_below) | 2183 if (!section_below) |
2136 return true; | 2184 return true; |
2137 if (LayoutTableRow* first_row = section_below->FirstRow()) { | 2185 if (LayoutTableRow* first_row = section_below->FirstRow()) { |
2138 if (first_row->PaginationStrut() || | 2186 if (first_row->PaginationStrut() || |
2139 first_row->LogicalHeight() > page_height) | 2187 first_row->LogicalHeight() > page_height) |
2140 return false; | 2188 return false; |
2141 } | 2189 } |
2142 | 2190 |
2143 return true; | 2191 return true; |
2144 } | 2192 } |
2145 | 2193 |
2146 bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal( | 2194 bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal( |
2147 const LayoutBoxModelObject* ancestor, | 2195 const LayoutBoxModelObject* ancestor, |
2148 TransformState& transform_state, | 2196 TransformState& transform_state, |
2149 VisualRectFlags flags) const { | 2197 VisualRectFlags flags) const { |
2150 if (ancestor == this) | 2198 if (ancestor == this) |
2151 return true; | 2199 return true; |
2152 // Repeating table headers are painted once per fragmentation page/column. | 2200 |
2153 // This does not go through the regular fragmentation machinery, so we need | 2201 // Repeating table headers and footers are painted once per fragmentation |
2154 // special code to expand the invalidation rect to contain all positions of | 2202 // page/column. This does not go through the regular fragmentation machinery, |
2155 // the header in all columns. | 2203 // so we need special code to expand the invalidation rect to contain all |
2156 // Note that this is in flow thread coordinates, not visual coordinates. The | 2204 // positions of the header in all columns. Note that this is in flow thread |
2157 // enclosing LayoutFlowThread will convert to visual coordinates. | 2205 // coordinates, not visual coordinates. The enclosing LayoutFlowThread will |
2158 if (Table()->Header() == this && IsRepeatingHeaderGroup()) { | 2206 // convert to visual coordinates. |
2207 if ((Table()->Header() == this && IsRepeatingHeaderGroup()) || | |
2208 (Table()->Footer() == this && IsRepeatingFooterGroup())) { | |
2159 transform_state.Flatten(); | 2209 transform_state.Flatten(); |
2160 FloatRect rect = transform_state.LastPlanarQuad().BoundingBox(); | 2210 FloatRect rect = transform_state.LastPlanarQuad().BoundingBox(); |
2161 rect.SetHeight(Table()->LogicalHeight()); | 2211 rect.SetHeight(Table()->LogicalHeight()); |
2162 transform_state.SetQuad(FloatQuad(rect)); | 2212 transform_state.SetQuad(FloatQuad(rect)); |
2213 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
| |
2214 ancestor, transform_state, flags); | |
2163 } | 2215 } |
2164 return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal( | 2216 return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal( |
2165 ancestor, transform_state, flags); | 2217 ancestor, transform_state, flags); |
2166 } | 2218 } |
2167 | 2219 |
2168 bool LayoutTableSection::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() | 2220 bool LayoutTableSection::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() |
2169 const { | 2221 const { |
2170 // LayoutTableSection paints background from columns. | 2222 // LayoutTableSection paints background from columns. |
2171 if (Table()->HasColElements()) | 2223 if (Table()->HasColElements()) |
2172 return false; | 2224 return false; |
2173 return LayoutTableBoxComponent:: | 2225 return LayoutTableBoxComponent:: |
2174 PaintedOutputOfObjectHasNoEffectRegardlessOfSize(); | 2226 PaintedOutputOfObjectHasNoEffectRegardlessOfSize(); |
2175 } | 2227 } |
2176 | 2228 |
2177 } // namespace blink | 2229 } // namespace blink |
OLD | NEW |