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