OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ng/ng_constraint_space.h" | 5 #include "core/layout/ng/ng_constraint_space.h" |
6 | 6 |
7 #include "core/layout/LayoutBlock.h" | 7 #include "core/layout/LayoutBlock.h" |
8 #include "core/layout/LayoutView.h" | 8 #include "core/layout/LayoutView.h" |
| 9 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
9 #include "core/layout/ng/ng_units.h" | 10 #include "core/layout/ng/ng_units.h" |
10 #include "wtf/NonCopyingSort.h" | |
11 #include <climits> | |
12 | 11 |
13 namespace blink { | 12 namespace blink { |
14 | 13 |
15 // TODO: This should set the size of the NGPhysicalConstraintSpace. Or we could | 14 // TODO: This should set the size of the NGPhysicalConstraintSpace. Or we could |
16 // remove it requiring that a NGConstraintSpace is created from a | 15 // remove it requiring that a NGConstraintSpace is created from a |
17 // NGPhysicalConstraintSpace. | 16 // NGPhysicalConstraintSpace. |
18 NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode, | 17 NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode, |
19 NGLogicalSize container_size) | 18 NGLogicalSize container_size) |
20 : physical_space_(new NGPhysicalConstraintSpace( | 19 : physical_space_(new NGPhysicalConstraintSpace( |
21 container_size.ConvertToPhysical(writing_mode))), | 20 container_size.ConvertToPhysical(writing_mode))), |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 physical_space_->width_direction_triggers_scrollbar_ = type; | 163 physical_space_->width_direction_triggers_scrollbar_ = type; |
165 } | 164 } |
166 } | 165 } |
167 | 166 |
168 String NGConstraintSpace::toString() const { | 167 String NGConstraintSpace::toString() const { |
169 return String::format("Size: %s, %s", | 168 return String::format("Size: %s, %s", |
170 size_.inline_size.toString().ascii().data(), | 169 size_.inline_size.toString().ascii().data(), |
171 size_.block_size.toString().ascii().data()); | 170 size_.block_size.toString().ascii().data()); |
172 } | 171 } |
173 | 172 |
174 static inline bool AscendingTopCompare(const NGExclusion& a, | |
175 const NGExclusion& b) { | |
176 return a.Top() > b.Top(); | |
177 } | |
178 | |
179 NGLayoutOpportunityIterator::NGLayoutOpportunityIterator( | |
180 NGConstraintSpace* space, | |
181 unsigned clear, | |
182 bool for_inline_or_bfc) | |
183 : constraint_space_(space), | |
184 clear_(clear), | |
185 for_inline_or_bfc_(for_inline_or_bfc), | |
186 current_exclusion_idx_(0) { | |
187 for (const auto& item : constraint_space_->PhysicalSpace()->Exclusions()) | |
188 filtered_exclusions_.append(item); | |
189 | |
190 nonCopyingSort(filtered_exclusions_.begin(), filtered_exclusions_.end(), | |
191 AscendingTopCompare); | |
192 | |
193 // TODO(eae): Set based on offset. | |
194 LayoutUnit left; | |
195 LayoutUnit top; | |
196 | |
197 unsigned i = filtered_exclusions_.size(); | |
198 while (i--) { | |
199 const NGExclusion& exclusion = filtered_exclusions_[i]; | |
200 | |
201 // Remove items above OR to the left of the start offset as they have no | |
202 // effect on layout opportunities within this view. | |
203 if (exclusion.Right() <= left || exclusion.Bottom() <= top) { | |
204 filtered_exclusions_.remove(i); | |
205 continue; | |
206 } | |
207 | |
208 // Remove items below AND to the right of the current exclusions as they're | |
209 // occluded and won't affect the layout opportunities. | |
210 for (unsigned j = filtered_exclusions_.size() - 1; j > i; j--) { | |
211 const NGExclusion& item = filtered_exclusions_[j]; | |
212 if (item.Top() > exclusion.Top() && item.Left() > exclusion.Left()) | |
213 filtered_exclusions_.remove(j); | |
214 } | |
215 } | |
216 } | |
217 | |
218 NGConstraintSpace* NGLayoutOpportunityIterator::Next() { | |
219 if (current_opportunities_.isEmpty() && | |
220 current_exclusion_idx_ < filtered_exclusions_.size()) { | |
221 computeForExclusion(current_exclusion_idx_); | |
222 current_exclusion_idx_++; | |
223 } | |
224 | |
225 if (!current_opportunities_.isEmpty()) { | |
226 NGConstraintSpace* opportunity = current_opportunities_.last(); | |
227 current_opportunities_.removeLast(); | |
228 return opportunity; | |
229 } | |
230 | |
231 if (filtered_exclusions_.isEmpty() && current_exclusion_idx_ == 0) { | |
232 current_exclusion_idx_++; | |
233 return new NGConstraintSpace(constraint_space_->WritingMode(), | |
234 constraint_space_->PhysicalSpace()); | |
235 } | |
236 | |
237 return nullptr; | |
238 } | |
239 | |
240 static inline bool DescendingWidthCompare(const NGConstraintSpace* a, | |
241 const NGConstraintSpace* b) { | |
242 return a->Size().inline_size > b->Size().inline_size; | |
243 } | |
244 | |
245 void NGLayoutOpportunityIterator::computeForExclusion(unsigned index) { | |
246 current_opportunities_.clear(); | |
247 | |
248 // TODO(eae): Set based on index. | |
249 LayoutUnit left; | |
250 LayoutUnit top; | |
251 | |
252 // TODO(eae): Writing modes. | |
253 LayoutUnit right = constraint_space_->Size().inline_size; | |
254 LayoutUnit bottom = constraint_space_->Size().block_size; | |
255 | |
256 // TODO(eae): Filter based on clear_ and for_inline_or_bfc_. Return early for | |
257 // now to make it clear neither are supported yet. | |
258 if (clear_ != NGClearNone || !for_inline_or_bfc_) | |
259 return; | |
260 | |
261 // Compute opportunity for the full width from the start position to the right | |
262 // edge of the NGConstraintSpace. | |
263 LayoutUnit opportunityHeight = heightForOpportunity(left, top, right, bottom); | |
264 if (opportunityHeight && right > left) | |
265 addLayoutOpportunity(left, top, right - left, opportunityHeight); | |
266 | |
267 // Compute the maximum available height between the current position and the | |
268 // left edge of each exclusion. The distance between the current horizontal | |
269 // position and the left edge of the exclusion determines the width of the | |
270 // opportunity. | |
271 for (const NGExclusion& exclusion : filtered_exclusions_) { | |
272 opportunityHeight = | |
273 heightForOpportunity(left, top, exclusion.Left(), bottom); | |
274 if (opportunityHeight && exclusion.Left() > left) | |
275 addLayoutOpportunity(left, top, exclusion.Left() - left, | |
276 opportunityHeight); | |
277 } | |
278 | |
279 nonCopyingSort(current_opportunities_.begin(), current_opportunities_.end(), | |
280 DescendingWidthCompare); | |
281 } | |
282 | |
283 // For the given 2D range (opportunity), this will return a height which makes | |
284 // it bounded by the highest exclusion in the filtered exclusion list within the | |
285 // range. Returns 0-height for an invalid opportunity (which has zero area). | |
286 LayoutUnit NGLayoutOpportunityIterator::heightForOpportunity( | |
287 LayoutUnit left, | |
288 LayoutUnit top, | |
289 LayoutUnit right, | |
290 LayoutUnit bottom) { | |
291 LayoutUnit lowestBottom = bottom; | |
292 for (const NGExclusion& exclusion : filtered_exclusions_) { | |
293 if (exclusion.Left() < right && exclusion.Right() > left && | |
294 exclusion.Bottom() > top && exclusion.Top() <= lowestBottom) | |
295 lowestBottom = exclusion.Top(); | |
296 } | |
297 return std::max(lowestBottom - top, LayoutUnit()); | |
298 } | |
299 | |
300 void NGLayoutOpportunityIterator::addLayoutOpportunity(LayoutUnit left, | |
301 LayoutUnit top, | |
302 LayoutUnit right, | |
303 LayoutUnit bottom) { | |
304 current_opportunities_.append( | |
305 new NGConstraintSpace(*constraint_space_, NGLogicalOffset(left, top), | |
306 NGLogicalSize(right - left, bottom - top))); | |
307 } | |
308 | |
309 } // namespace blink | 173 } // namespace blink |
OLD | NEW |