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 1214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1225 } | 1225 } |
1226 | 1226 |
1227 DCHECK(!NeedsLayout()); | 1227 DCHECK(!NeedsLayout()); |
1228 | 1228 |
1229 SetLogicalHeight(LayoutUnit(row_pos_[total_rows])); | 1229 SetLogicalHeight(LayoutUnit(row_pos_[total_rows])); |
1230 | 1230 |
1231 ComputeOverflowFromCells(total_rows, Table()->NumEffectiveColumns()); | 1231 ComputeOverflowFromCells(total_rows, Table()->NumEffectiveColumns()); |
1232 } | 1232 } |
1233 | 1233 |
1234 int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row, | 1234 int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row, |
1235 LayoutUnit logical_offset) const { | 1235 LayoutUnit logical_offset, |
1236 bool& can_repeat_footer) const { | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
I think calculating can_repeat_footer should be om
| |
1236 DCHECK(row); | 1237 DCHECK(row); |
1237 if (row->GetPaginationBreakability() == kAllowAnyBreaks) | 1238 if (row->GetPaginationBreakability() == kAllowAnyBreaks) |
1238 return 0; | 1239 return 0; |
1239 LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset); | 1240 LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset); |
1240 if (!page_logical_height) | 1241 if (!page_logical_height) |
1241 return 0; | 1242 return 0; |
1242 // If the row is too tall for the page don't insert a strut. | 1243 // If the row is too tall for the page don't insert a strut. |
1243 LayoutUnit row_logical_height = row->LogicalHeight(); | 1244 LayoutUnit row_logical_height = row->LogicalHeight(); |
1244 if (row_logical_height > page_logical_height) | 1245 if (row_logical_height > page_logical_height) |
1245 return 0; | 1246 return 0; |
1246 | 1247 |
1248 LayoutTableSection* footer = Table()->Footer(); | |
1249 bool footer_wants_to_repeat = | |
1250 footer && footer != this && | |
1251 footer->GetPaginationBreakability() != kAllowAnyBreaks && | |
1252 Table()->RowOffsetFromRepeatingHeader() && row->RowIndex(); | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
RowOffsetFromRepeatingHeader() suggests that we de
| |
1253 if (footer_wants_to_repeat) { | |
1254 if (row_logical_height + footer->LogicalHeight() <= page_logical_height) { | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
... however, if there *is* a repeating header, we
| |
1255 row_logical_height += footer->LogicalHeight(); | |
1256 } | |
1257 } | |
1258 | |
1247 LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( | 1259 LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset( |
1248 logical_offset, LayoutBlock::kAssociateWithLatterPage); | 1260 logical_offset, LayoutBlock::kAssociateWithLatterPage); |
1249 if (remaining_logical_height >= row_logical_height) | 1261 if (remaining_logical_height >= row_logical_height) |
1250 return 0; // It fits fine where it is. No need to break. | 1262 return 0; // It fits fine where it is. No need to break. |
1251 LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent( | 1263 LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent( |
1252 logical_offset, remaining_logical_height, row_logical_height); | 1264 logical_offset, remaining_logical_height, row_logical_height); |
1253 if (pagination_strut == remaining_logical_height && | 1265 if (pagination_strut == remaining_logical_height && |
1254 remaining_logical_height == page_logical_height) { | 1266 remaining_logical_height == page_logical_height) { |
1255 // Don't break if we were at the top of a page, and we failed to fit the | 1267 // Don't break if we were at the top of a page, and we failed to fit the |
1256 // content completely. No point in leaving a page completely blank. | 1268 // content completely. No point in leaving a page completely blank. |
1257 return 0; | 1269 return 0; |
1258 } | 1270 } |
1271 | |
1272 if (footer && remaining_logical_height >= | |
1273 (footer->LogicalHeight() - Table()->VBorderSpacing())) | |
1274 can_repeat_footer = true; | |
1259 // Table layout parts only work on integers, so we have to round. Round up, to | 1275 // Table layout parts only work on integers, so we have to round. Round up, to |
1260 // make sure that no fraction ever gets left behind in the previous | 1276 // make sure that no fraction ever gets left behind in the previous |
1261 // fragmentainer. | 1277 // fragmentainer. |
1262 return pagination_strut.Ceil(); | 1278 return pagination_strut.Ceil(); |
1263 } | 1279 } |
1264 | 1280 |
1265 void LayoutTableSection::ComputeOverflowFromCells() { | 1281 void LayoutTableSection::ComputeOverflowFromCells() { |
1266 unsigned total_rows = grid_.size(); | 1282 unsigned total_rows = grid_.size(); |
1267 unsigned n_eff_cols = Table()->NumEffectiveColumns(); | 1283 unsigned n_eff_cols = Table()->NumEffectiveColumns(); |
1268 ComputeOverflowFromCells(total_rows, n_eff_cols); | 1284 ComputeOverflowFromCells(total_rows, n_eff_cols); |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2044 MinimumValueForLength(grid_[row_index].logical_height, LayoutUnit()); | 2060 MinimumValueForLength(grid_[row_index].logical_height, LayoutUnit()); |
2045 logical_height = std::max(logical_height, specified_logical_height.ToInt()); | 2061 logical_height = std::max(logical_height, specified_logical_height.ToInt()); |
2046 } | 2062 } |
2047 return logical_height; | 2063 return logical_height; |
2048 } | 2064 } |
2049 | 2065 |
2050 void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, | 2066 void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, |
2051 SubtreeLayoutScope& layouter) { | 2067 SubtreeLayoutScope& layouter) { |
2052 row_object.SetPaginationStrut(LayoutUnit()); | 2068 row_object.SetPaginationStrut(LayoutUnit()); |
2053 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); | 2069 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); |
2054 int pagination_strut = | 2070 bool can_repeat_footer = false; |
2055 PaginationStrutForRow(&row_object, row_object.LogicalTop()); | 2071 int pagination_strut = PaginationStrutForRow( |
2072 &row_object, row_object.LogicalTop(), can_repeat_footer); | |
2056 bool row_is_at_top_of_column = false; | 2073 bool row_is_at_top_of_column = false; |
2057 LayoutUnit offset_from_top_of_page; | 2074 LayoutUnit offset_from_top_of_page; |
2058 if (!pagination_strut) { | 2075 if (!pagination_strut) { |
2059 LayoutUnit page_logical_height = | 2076 LayoutUnit page_logical_height = |
2060 PageLogicalHeightForOffset(row_object.LogicalTop()); | 2077 PageLogicalHeightForOffset(row_object.LogicalTop()); |
2061 if (page_logical_height && Table()->Header() && | 2078 if (page_logical_height && Table()->Header() && |
2062 Table()->RowOffsetFromRepeatingHeader()) { | 2079 Table()->RowOffsetFromRepeatingHeader()) { |
2063 offset_from_top_of_page = | 2080 offset_from_top_of_page = |
2064 page_logical_height - | 2081 page_logical_height - |
2065 PageRemainingLogicalHeightForOffset(row_object.LogicalTop(), | 2082 PageRemainingLogicalHeightForOffset(row_object.LogicalTop(), |
(...skipping 13 matching lines...) Expand all Loading... | |
2079 | 2096 |
2080 LayoutTableSection* header = Table()->Header(); | 2097 LayoutTableSection* header = Table()->Header(); |
2081 if (row_object.IsFirstRowInSectionAfterHeader()) | 2098 if (row_object.IsFirstRowInSectionAfterHeader()) |
2082 Table()->SetRowOffsetFromRepeatingHeader(LayoutUnit()); | 2099 Table()->SetRowOffsetFromRepeatingHeader(LayoutUnit()); |
2083 // Border spacing from the previous row has pushed this row just past the top | 2100 // Border spacing from the previous row has pushed this row just past the top |
2084 // of the page, so we must reposition it to the top of the page and avoid any | 2101 // of the page, so we must reposition it to the top of the page and avoid any |
2085 // repeating header. | 2102 // repeating header. |
2086 if (row_is_at_top_of_column && offset_from_top_of_page) | 2103 if (row_is_at_top_of_column && offset_from_top_of_page) |
2087 pagination_strut -= offset_from_top_of_page.ToInt(); | 2104 pagination_strut -= offset_from_top_of_page.ToInt(); |
2088 | 2105 |
2106 LayoutTableSection* footer = Table()->Footer(); | |
2107 if (footer && footer != this && header != this && | |
2108 footer->GetPaginationBreakability() != kAllowAnyBreaks && | |
2109 Table()->RowOffsetFromRepeatingHeader() && can_repeat_footer) { | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
Check can_repeat_footer first.
| |
2110 unsigned page = FloorToInt((LogicalTop() + row_object.LogicalTop()) / | |
2111 PageLogicalHeightForOffset(LayoutUnit())); | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
PageLogicalHeightForOffset() may be 0 (initial col
| |
2112 Table()->SetPositionOfRepeatingFooterGroupOnPage( | |
2113 page, LogicalTop() + row_object.LogicalTop()); | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
Then again, do we really need to allow individual
| |
2114 } | |
2115 | |
2089 // If we have a header group we will paint it at the top of each page, | 2116 // If we have a header group we will paint it at the top of each page, |
2090 // move the rows down to accomodate it. | 2117 // move the rows down to accomodate it. |
2091 if (header && header != this) | 2118 if (header && header != this) |
2092 pagination_strut += Table()->RowOffsetFromRepeatingHeader().ToInt(); | 2119 pagination_strut += Table()->RowOffsetFromRepeatingHeader().ToInt(); |
2093 row_object.SetPaginationStrut(LayoutUnit(pagination_strut)); | 2120 row_object.SetPaginationStrut(LayoutUnit(pagination_strut)); |
2094 | 2121 |
2095 // We have inserted a pagination strut before the row. Adjust the logical top | 2122 // We have inserted a pagination strut before the row. Adjust the logical top |
2096 // and re-lay out. We no longer want to break inside the row, but rather | 2123 // and re-lay out. We no longer want to break inside the row, but rather |
2097 // *before* it. From the previous layout pass, there are most likely | 2124 // *before* it. From the previous layout pass, there are most likely |
2098 // pagination struts inside some cell in this row that we need to get rid of. | 2125 // pagination struts inside some cell in this row that we need to get rid of. |
2099 row_object.SetLogicalTop(row_object.LogicalTop() + pagination_strut); | 2126 row_object.SetLogicalTop(row_object.LogicalTop() + pagination_strut); |
2100 layouter.SetChildNeedsLayout(&row_object); | 2127 layouter.SetChildNeedsLayout(&row_object); |
2101 row_object.LayoutIfNeeded(); | 2128 row_object.LayoutIfNeeded(); |
2102 | 2129 |
2103 // It's very likely that re-laying out (and nuking pagination struts inside | 2130 // It's very likely that re-laying out (and nuking pagination struts inside |
2104 // cells) gave us a new height. | 2131 // cells) gave us a new height. |
2105 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); | 2132 row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); |
2106 } | 2133 } |
2107 | 2134 |
2135 bool LayoutTableSection::IsRepeatingFooterGroup() const { | |
2136 if (GetPaginationBreakability() == LayoutBox::kAllowAnyBreaks) | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
LayoutBox:: scope unnecessary.
| |
2137 return false; | |
2138 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
I don't think it's currently possible to have a se
| |
2139 if (HasSelfPaintingLayer()) | |
2140 return false; | |
2141 LayoutUnit page_height = Table()->PageLogicalHeightForOffset(LayoutUnit()); | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
If "page" height isn't uniform (e.g. a multicol co
| |
2142 if (!page_height) | |
2143 return false; | |
2144 if (LogicalHeight() > page_height) | |
2145 return false; | |
2146 // If the first row of the section after the header group doesn't fit on the | |
2147 // page, then don't repeat the header on each page. | |
2148 // See https://drafts.csswg.org/css-tables-3/#repeated-headers | |
2149 if (Table()->Header() && !Table()->Header()->IsRepeatingHeaderGroup()) | |
2150 return false; | |
2151 return true; | |
2152 } | |
2153 | |
2108 bool LayoutTableSection::IsRepeatingHeaderGroup() const { | 2154 bool LayoutTableSection::IsRepeatingHeaderGroup() const { |
2109 if (GetPaginationBreakability() == LayoutBox::kAllowAnyBreaks) | 2155 if (GetPaginationBreakability() == LayoutBox::kAllowAnyBreaks) |
2110 return false; | 2156 return false; |
2111 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? | 2157 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? |
2112 if (HasSelfPaintingLayer()) | 2158 if (HasSelfPaintingLayer()) |
2113 return false; | 2159 return false; |
2114 LayoutUnit page_height = Table()->PageLogicalHeightForOffset(LayoutUnit()); | 2160 LayoutUnit page_height = Table()->PageLogicalHeightForOffset(LayoutUnit()); |
2115 if (!page_height) | 2161 if (!page_height) |
2116 return false; | 2162 return false; |
2117 | 2163 |
(...skipping 14 matching lines...) Expand all Loading... | |
2132 | 2178 |
2133 return true; | 2179 return true; |
2134 } | 2180 } |
2135 | 2181 |
2136 bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal( | 2182 bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal( |
2137 const LayoutBoxModelObject* ancestor, | 2183 const LayoutBoxModelObject* ancestor, |
2138 TransformState& transform_state, | 2184 TransformState& transform_state, |
2139 VisualRectFlags flags) const { | 2185 VisualRectFlags flags) const { |
2140 if (ancestor == this) | 2186 if (ancestor == this) |
2141 return true; | 2187 return true; |
2188 | |
2189 if (Table()->Footer() == this && IsRepeatingFooterGroup()) { | |
2190 transform_state.Flatten(); | |
2191 FloatRect rect = transform_state.LastPlanarQuad().BoundingBox(); | |
2192 rect.SetHeight(Table()->LogicalHeight()); | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
Introducing a lot of duplicated code here (shared
| |
2193 transform_state.SetQuad(FloatQuad(rect)); | |
2194 bool mapped = Table()->MapToVisualRectInAncestorSpaceInternal( | |
mstensho (USE GERRIT)
2017/04/24 11:57:16
We here skip the table section, ignoring its posit
| |
2195 ancestor, transform_state, flags); | |
2196 return mapped; | |
2197 } | |
2198 | |
2142 // Repeating table headers are painted once per fragmentation page/column. | 2199 // Repeating table headers are painted once per fragmentation page/column. |
2143 // This does not go through the regular fragmentation machinery, so we need | 2200 // This does not go through the regular fragmentation machinery, so we need |
2144 // special code to expand the invalidation rect to contain all positions of | 2201 // special code to expand the invalidation rect to contain all positions of |
2145 // the header in all columns. | 2202 // the header in all columns. |
2146 // Note that this is in flow thread coordinates, not visual coordinates. The | 2203 // Note that this is in flow thread coordinates, not visual coordinates. The |
2147 // enclosing LayoutFlowThread will convert to visual coordinates. | 2204 // enclosing LayoutFlowThread will convert to visual coordinates. |
2148 if (Table()->Header() == this && IsRepeatingHeaderGroup()) { | 2205 if (Table()->Header() == this && IsRepeatingHeaderGroup()) { |
2149 transform_state.Flatten(); | 2206 transform_state.Flatten(); |
2150 FloatRect rect = transform_state.LastPlanarQuad().BoundingBox(); | 2207 FloatRect rect = transform_state.LastPlanarQuad().BoundingBox(); |
2151 rect.SetHeight(Table()->LogicalHeight()); | 2208 rect.SetHeight(Table()->LogicalHeight()); |
2152 transform_state.SetQuad(FloatQuad(rect)); | 2209 transform_state.SetQuad(FloatQuad(rect)); |
2153 } | 2210 } |
2154 return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal( | 2211 return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal( |
2155 ancestor, transform_state, flags); | 2212 ancestor, transform_state, flags); |
2156 } | 2213 } |
2157 | 2214 |
2158 bool LayoutTableSection::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() | 2215 bool LayoutTableSection::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() |
2159 const { | 2216 const { |
2160 // LayoutTableSection paints background from columns. | 2217 // LayoutTableSection paints background from columns. |
2161 if (Table()->HasColElements()) | 2218 if (Table()->HasColElements()) |
2162 return false; | 2219 return false; |
2163 return LayoutTableBoxComponent:: | 2220 return LayoutTableBoxComponent:: |
2164 PaintedOutputOfObjectHasNoEffectRegardlessOfSize(); | 2221 PaintedOutputOfObjectHasNoEffectRegardlessOfSize(); |
2165 } | 2222 } |
2166 | 2223 |
2167 } // namespace blink | 2224 } // namespace blink |
OLD | NEW |