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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp

Issue 2874933005: Distinguish between row (fragmentainer group) height and column (fragmentainer) height. (Closed)
Patch Set: 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 } 72 }
73 73
74 const MultiColumnFragmentainerGroup& 74 const MultiColumnFragmentainerGroup&
75 LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint( 75 LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint(
76 const LayoutPoint& visual_point) const { 76 const LayoutPoint& visual_point) const {
77 DCHECK_GT(fragmentainer_groups_.size(), 0u); 77 DCHECK_GT(fragmentainer_groups_.size(), 0u);
78 LayoutUnit block_offset = 78 LayoutUnit block_offset =
79 IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X(); 79 IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X();
80 for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) { 80 for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) {
81 const auto& row = fragmentainer_groups_[index]; 81 const auto& row = fragmentainer_groups_[index];
82 if (row.LogicalTop() + row.LogicalHeight() > block_offset) 82 if (row.LogicalTop() + row.GroupLogicalHeight() > block_offset)
83 return row; 83 return row;
84 } 84 }
85 return fragmentainer_groups_.Last(); 85 return fragmentainer_groups_.Last();
86 } 86 }
87 87
88 LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset( 88 LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset(
89 LayoutUnit offset_in_flow_thread) const { 89 LayoutUnit offset_in_flow_thread) const {
90 const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup(); 90 const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup();
91 if (!last_row.LogicalHeight() && fragmentainer_groups_.size() == 1) { 91 if (!last_row.GroupLogicalHeight() && fragmentainer_groups_.size() == 1) {
92 // In the first layout pass of an auto-height multicol container, height 92 // In the first layout pass of an auto-height multicol container, height
93 // isn't set. No need to perform the series of complicated dance steps below 93 // isn't set. No need to perform the series of complicated dance steps below
94 // to figure out that we should simply return 0. Bail now. 94 // to figure out that we should simply return 0. Bail now.
95 return LayoutUnit(); 95 return LayoutUnit();
96 } 96 }
97 if (offset_in_flow_thread >= last_row.LogicalTopInFlowThread() + 97 if (offset_in_flow_thread >= last_row.LogicalTopInFlowThread() +
98 FragmentainerGroupCapacity(last_row)) { 98 FragmentainerGroupCapacity(last_row)) {
99 // The offset is outside the bounds of the fragmentainer groups that we have 99 // The offset is outside the bounds of the fragmentainer groups that we have
100 // established at this point. If we're nested inside another fragmentation 100 // established at this point. If we're nested inside another fragmentation
101 // context, we need to calculate the height on our own. 101 // context, we need to calculate the height on our own.
102 const LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread(); 102 const LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread();
103 if (FragmentationContext* enclosing_fragmentation_context = 103 if (FragmentationContext* enclosing_fragmentation_context =
104 flow_thread->EnclosingFragmentationContext()) { 104 flow_thread->EnclosingFragmentationContext()) {
105 // We'd ideally like to translate |offsetInFlowThread| to an offset in the 105 // We'd ideally like to translate |offsetInFlowThread| to an offset in the
106 // coordinate space of the enclosing fragmentation context here, but 106 // coordinate space of the enclosing fragmentation context here, but
107 // that's hard, since the offset is out of bounds. So just use the bottom 107 // that's hard, since the offset is out of bounds. So just use the bottom
108 // we have found so far. 108 // we have found so far.
109 LayoutUnit enclosing_context_bottom = 109 LayoutUnit enclosing_context_bottom =
110 last_row.BlockOffsetInEnclosingFragmentationContext() + 110 last_row.BlockOffsetInEnclosingFragmentationContext() +
111 last_row.LogicalHeight(); 111 last_row.GroupLogicalHeight();
112 LayoutUnit enclosing_fragmentainer_height = 112 LayoutUnit enclosing_fragmentainer_height =
113 enclosing_fragmentation_context->FragmentainerLogicalHeightAt( 113 enclosing_fragmentation_context->FragmentainerLogicalHeightAt(
114 enclosing_context_bottom); 114 enclosing_context_bottom);
115 // Constrain against specified height / max-height. 115 // Constrain against specified height / max-height.
116 LayoutUnit current_multicol_height = LogicalTopFromMulticolContentEdge() + 116 LayoutUnit current_multicol_height = LogicalTopFromMulticolContentEdge() +
117 last_row.LogicalTop() + 117 last_row.LogicalTop() +
118 last_row.LogicalHeight(); 118 last_row.GroupLogicalHeight();
119 LayoutUnit multicol_height_with_extra_row = 119 LayoutUnit multicol_height_with_extra_row =
120 current_multicol_height + enclosing_fragmentainer_height; 120 current_multicol_height + enclosing_fragmentainer_height;
121 multicol_height_with_extra_row = 121 multicol_height_with_extra_row =
122 std::min(multicol_height_with_extra_row, 122 std::min(multicol_height_with_extra_row,
123 flow_thread->MaxColumnLogicalHeight()); 123 flow_thread->MaxColumnLogicalHeight());
124 return std::max(LayoutUnit(1), 124 return std::max(LayoutUnit(1),
125 multicol_height_with_extra_row - current_multicol_height); 125 multicol_height_with_extra_row - current_multicol_height);
126 } 126 }
127 } 127 }
128 return FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, 128 return FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread,
129 kAssociateWithLatterPage) 129 kAssociateWithLatterPage)
130 .LogicalHeight(); 130 .ColumnLogicalHeight();
131 } 131 }
132 132
133 LayoutUnit LayoutMultiColumnSet::PageRemainingLogicalHeightForOffset( 133 LayoutUnit LayoutMultiColumnSet::PageRemainingLogicalHeightForOffset(
134 LayoutUnit offset_in_flow_thread, 134 LayoutUnit offset_in_flow_thread,
135 PageBoundaryRule page_boundary_rule) const { 135 PageBoundaryRule page_boundary_rule) const {
136 const MultiColumnFragmentainerGroup& row = 136 const MultiColumnFragmentainerGroup& row =
137 FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, 137 FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread,
138 page_boundary_rule); 138 page_boundary_rule);
139 LayoutUnit page_logical_height = row.LogicalHeight(); 139 LayoutUnit page_logical_height = row.ColumnLogicalHeight();
140 LayoutUnit page_logical_bottom = 140 LayoutUnit page_logical_bottom =
141 row.ColumnLogicalTopForOffset(offset_in_flow_thread) + 141 row.ColumnLogicalTopForOffset(offset_in_flow_thread) +
142 page_logical_height; 142 page_logical_height;
143 LayoutUnit remaining_logical_height = 143 LayoutUnit remaining_logical_height =
144 page_logical_bottom - offset_in_flow_thread; 144 page_logical_bottom - offset_in_flow_thread;
145 145
146 if (page_boundary_rule == kAssociateWithFormerPage) { 146 if (page_boundary_rule == kAssociateWithFormerPage) {
147 // An offset exactly at a column boundary will act as being part of the 147 // An offset exactly at a column boundary will act as being part of the
148 // former column in question (i.e. no remaining space), rather than being 148 // former column in question (i.e. no remaining space), rather than being
149 // part of the latter (i.e. one whole column length of remaining space). 149 // part of the latter (i.e. one whole column length of remaining space).
150 remaining_logical_height = 150 remaining_logical_height =
151 IntMod(remaining_logical_height, page_logical_height); 151 IntMod(remaining_logical_height, page_logical_height);
152 } else if (!remaining_logical_height) { 152 } else if (!remaining_logical_height) {
153 // When pageBoundaryRule is AssociateWithLatterPage, we shouldn't just 153 // When pageBoundaryRule is AssociateWithLatterPage, we shouldn't just
154 // return 0 if there's no space left, because in that case we're at a 154 // return 0 if there's no space left, because in that case we're at a
155 // column boundary, in which case we should return the amount of space 155 // column boundary, in which case we should return the amount of space
156 // remaining in the *next* column. Note that the page height itself may be 156 // remaining in the *next* column. Note that the page height itself may be
157 // 0, though. 157 // 0, though.
158 remaining_logical_height = page_logical_height; 158 remaining_logical_height = page_logical_height;
159 } 159 }
160 return remaining_logical_height; 160 return remaining_logical_height;
161 } 161 }
162 162
163 bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const { 163 bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const {
164 return FirstFragmentainerGroup().LogicalHeight(); 164 return FirstFragmentainerGroup().ColumnLogicalHeight();
165 } 165 }
166 166
167 bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const { 167 bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const {
168 if (!IsPageLogicalHeightKnown()) { 168 if (!IsPageLogicalHeightKnown()) {
169 // If we have no clue about the height of the multicol container, bail. This 169 // If we have no clue about the height of the multicol container, bail. This
170 // situation occurs initially when an auto-height multicol container is 170 // situation occurs initially when an auto-height multicol container is
171 // nested inside another auto-height multicol container. We need at least an 171 // nested inside another auto-height multicol container. We need at least an
172 // estimated height of the outer multicol container before we can check what 172 // estimated height of the outer multicol container before we can check what
173 // an inner fragmentainer group has room for. 173 // an inner fragmentainer group has room for.
174 // Its height is indefinite for now. 174 // Its height is indefinite for now.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // multicol), we need to look beyond the first row here. 207 // multicol), we need to look beyond the first row here.
208 const MultiColumnFragmentainerGroup& first_row = FirstFragmentainerGroup(); 208 const MultiColumnFragmentainerGroup& first_row = FirstFragmentainerGroup();
209 LayoutUnit first_row_logical_bottom_in_flow_thread = 209 LayoutUnit first_row_logical_bottom_in_flow_thread =
210 first_row.LogicalTopInFlowThread() + 210 first_row.LogicalTopInFlowThread() +
211 FragmentainerGroupCapacity(first_row); 211 FragmentainerGroupCapacity(first_row);
212 if (flow_thread_offset >= first_row_logical_bottom_in_flow_thread) 212 if (flow_thread_offset >= first_row_logical_bottom_in_flow_thread)
213 return flow_thread_offset; // We're not in the first row. Give up. 213 return flow_thread_offset; // We're not in the first row. Give up.
214 LayoutUnit new_logical_height = 214 LayoutUnit new_logical_height =
215 enclosing_fragmentation_context->FragmentainerLogicalHeightAt( 215 enclosing_fragmentation_context->FragmentainerLogicalHeightAt(
216 first_row.BlockOffsetInEnclosingFragmentationContext() + 216 first_row.BlockOffsetInEnclosingFragmentationContext() +
217 first_row.LogicalHeight()); 217 first_row.GroupLogicalHeight());
218 if (content_logical_height > new_logical_height) { 218 if (content_logical_height > new_logical_height) {
219 // The next outer column or page doesn't have enough space either. Give up 219 // The next outer column or page doesn't have enough space either. Give up
220 // and stay where we are. 220 // and stay where we are.
221 return flow_thread_offset; 221 return flow_thread_offset;
222 } 222 }
223 return first_row_logical_bottom_in_flow_thread; 223 return first_row_logical_bottom_in_flow_thread;
224 } 224 }
225 225
226 LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const { 226 LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const {
227 for (LayoutObject* sibling = NextSibling(); sibling; 227 for (LayoutObject* sibling = NextSibling(); sibling;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 // multicol container. When setting up a new fragmentainer group, we always 276 // multicol container. When setting up a new fragmentainer group, we always
277 // constrain against the remaining portion of any specified 277 // constrain against the remaining portion of any specified
278 // height/max-height. This means that we shouldn't allow creation of 278 // height/max-height. This means that we shouldn't allow creation of
279 // fragmentainer groups below the bottom of the multicol container, or we'd 279 // fragmentainer groups below the bottom of the multicol container, or we'd
280 // end up with zero-height fragmentainer groups (or actually 1px; see 280 // end up with zero-height fragmentainer groups (or actually 1px; see
281 // heightAdjustedForRowOffset() in MultiColumnFragmentainerGroup, which 281 // heightAdjustedForRowOffset() in MultiColumnFragmentainerGroup, which
282 // guards against zero-height groups), i.e. potentially a lot of pretty 282 // guards against zero-height groups), i.e. potentially a lot of pretty
283 // useless fragmentainer groups, and possibly broken layout too. Instead, 283 // useless fragmentainer groups, and possibly broken layout too. Instead,
284 // we'll just allow additional (overflowing) columns to be created in the 284 // we'll just allow additional (overflowing) columns to be created in the
285 // last fragmentainer group, similar to what we do when we're not nested. 285 // last fragmentainer group, similar to what we do when we're not nested.
286 LayoutUnit logical_bottom = last_row.LogicalTop() + last_row.LogicalHeight(); 286 LayoutUnit logical_bottom =
287 last_row.LogicalTop() + last_row.GroupLogicalHeight();
287 LayoutUnit space_used = logical_bottom + LogicalTopFromMulticolContentEdge(); 288 LayoutUnit space_used = logical_bottom + LogicalTopFromMulticolContentEdge();
288 LayoutUnit max_column_height = 289 LayoutUnit max_column_height =
289 MultiColumnFlowThread()->MaxColumnLogicalHeight(); 290 MultiColumnFlowThread()->MaxColumnLogicalHeight();
290 return max_column_height - space_used > LayoutUnit(); 291 return max_column_height - space_used > LayoutUnit();
291 } 292 }
292 293
293 MultiColumnFragmentainerGroup& 294 MultiColumnFragmentainerGroup&
294 LayoutMultiColumnSet::AppendNewFragmentainerGroup() { 295 LayoutMultiColumnSet::AppendNewFragmentainerGroup() {
295 MultiColumnFragmentainerGroup new_group(*this); 296 MultiColumnFragmentainerGroup new_group(*this);
296 { // Extra scope here for previousGroup; it's potentially invalid once we 297 { // Extra scope here for previousGroup; it's potentially invalid once we
297 // modify the m_fragmentainerGroups Vector. 298 // modify the m_fragmentainerGroups Vector.
298 MultiColumnFragmentainerGroup& previous_group = 299 MultiColumnFragmentainerGroup& previous_group =
299 fragmentainer_groups_.Last(); 300 fragmentainer_groups_.Last();
300 301
301 // This is the flow thread block offset where |previousGroup| ends and 302 // This is the flow thread block offset where |previousGroup| ends and
302 // |newGroup| takes over. 303 // |newGroup| takes over.
303 LayoutUnit block_offset_in_flow_thread = 304 LayoutUnit block_offset_in_flow_thread =
304 previous_group.LogicalTopInFlowThread() + 305 previous_group.LogicalTopInFlowThread() +
305 FragmentainerGroupCapacity(previous_group); 306 FragmentainerGroupCapacity(previous_group);
306 previous_group.SetLogicalBottomInFlowThread(block_offset_in_flow_thread); 307 previous_group.SetLogicalBottomInFlowThread(block_offset_in_flow_thread);
307 new_group.SetLogicalTopInFlowThread(block_offset_in_flow_thread); 308 new_group.SetLogicalTopInFlowThread(block_offset_in_flow_thread);
308 new_group.SetLogicalTop(previous_group.LogicalTop() + 309 new_group.SetLogicalTop(previous_group.LogicalTop() +
309 previous_group.LogicalHeight()); 310 previous_group.GroupLogicalHeight());
310 new_group.ResetColumnHeight(); 311 new_group.ResetColumnHeight();
311 } 312 }
312 fragmentainer_groups_.Append(new_group); 313 fragmentainer_groups_.Append(new_group);
313 return fragmentainer_groups_.Last(); 314 return fragmentainer_groups_.Last();
314 } 315 }
315 316
316 LayoutUnit LayoutMultiColumnSet::LogicalTopFromMulticolContentEdge() const { 317 LayoutUnit LayoutMultiColumnSet::LogicalTopFromMulticolContentEdge() const {
317 // We subtract the position of the first column set or spanner placeholder, 318 // We subtract the position of the first column set or spanner placeholder,
318 // rather than the "before" border+padding of the multicol container. This 319 // rather than the "before" border+padding of the multicol container. This
319 // distinction doesn't matter after layout, but during layout it does: 320 // distinction doesn't matter after layout, but during layout it does:
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 min_logical_width = flow_thread_->MinPreferredLogicalWidth(); 456 min_logical_width = flow_thread_->MinPreferredLogicalWidth();
456 max_logical_width = flow_thread_->MaxPreferredLogicalWidth(); 457 max_logical_width = flow_thread_->MaxPreferredLogicalWidth();
457 } 458 }
458 459
459 void LayoutMultiColumnSet::ComputeLogicalHeight( 460 void LayoutMultiColumnSet::ComputeLogicalHeight(
460 LayoutUnit, 461 LayoutUnit,
461 LayoutUnit logical_top, 462 LayoutUnit logical_top,
462 LogicalExtentComputedValues& computed_values) const { 463 LogicalExtentComputedValues& computed_values) const {
463 LayoutUnit logical_height; 464 LayoutUnit logical_height;
464 for (const auto& group : fragmentainer_groups_) 465 for (const auto& group : fragmentainer_groups_)
465 logical_height += group.LogicalHeight(); 466 logical_height += group.GroupLogicalHeight();
466 computed_values.extent_ = logical_height; 467 computed_values.extent_ = logical_height;
467 computed_values.position_ = logical_top; 468 computed_values.position_ = logical_top;
468 } 469 }
469 470
470 PositionWithAffinity LayoutMultiColumnSet::PositionForPoint( 471 PositionWithAffinity LayoutMultiColumnSet::PositionForPoint(
471 const LayoutPoint& point) { 472 const LayoutPoint& point) {
472 // Convert the visual point to a flow thread point. 473 // Convert the visual point to a flow thread point.
473 const MultiColumnFragmentainerGroup& row = 474 const MultiColumnFragmentainerGroup& row =
474 FragmentainerGroupAtVisualPoint(point); 475 FragmentainerGroupAtVisualPoint(point);
475 LayoutPoint flow_thread_point = row.VisualPointToFlowThreadPoint( 476 LayoutPoint flow_thread_point = row.VisualPointToFlowThreadPoint(
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 // Now add in column rule bounds, if present. 626 // Now add in column rule bounds, if present.
626 Vector<LayoutRect> column_rule_bounds; 627 Vector<LayoutRect> column_rule_bounds;
627 if (ComputeColumnRuleBounds(LayoutPoint(), column_rule_bounds)) { 628 if (ComputeColumnRuleBounds(LayoutPoint(), column_rule_bounds)) {
628 for (auto& bound : column_rule_bounds) 629 for (auto& bound : column_rule_bounds)
629 block_flow_bounds.Unite(bound); 630 block_flow_bounds.Unite(bound);
630 } 631 }
631 return block_flow_bounds; 632 return block_flow_bounds;
632 } 633 }
633 634
634 } // namespace blink 635 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698