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_block_layout_algorithm.h" | 5 #include "core/layout/ng/ng_block_layout_algorithm.h" |
6 | 6 |
7 #include "core/layout/ng/inline/ng_inline_node.h" | 7 #include "core/layout/ng/inline/ng_inline_node.h" |
8 #include "core/layout/ng/ng_absolute_utils.h" | 8 #include "core/layout/ng/ng_absolute_utils.h" |
9 #include "core/layout/ng/ng_block_child_iterator.h" | 9 #include "core/layout/ng/ng_block_child_iterator.h" |
10 #include "core/layout/ng/ng_box_fragment.h" | |
11 #include "core/layout/ng/ng_constraint_space.h" | 10 #include "core/layout/ng/ng_constraint_space.h" |
12 #include "core/layout/ng/ng_constraint_space_builder.h" | 11 #include "core/layout/ng/ng_constraint_space_builder.h" |
13 #include "core/layout/ng/ng_floats_utils.h" | 12 #include "core/layout/ng/ng_floats_utils.h" |
14 #include "core/layout/ng/ng_fragment.h" | 13 #include "core/layout/ng/ng_fragment.h" |
15 #include "core/layout/ng/ng_fragment_builder.h" | 14 #include "core/layout/ng/ng_fragment_builder.h" |
16 #include "core/layout/ng/ng_layout_opportunity_iterator.h" | 15 #include "core/layout/ng/ng_layout_opportunity_iterator.h" |
17 #include "core/layout/ng/ng_length_utils.h" | 16 #include "core/layout/ng/ng_length_utils.h" |
18 #include "core/layout/ng/ng_out_of_flow_layout_part.h" | 17 #include "core/layout/ng/ng_out_of_flow_layout_part.h" |
19 #include "core/layout/ng/ng_space_utils.h" | 18 #include "core/layout/ng/ng_space_utils.h" |
20 #include "core/style/ComputedStyle.h" | 19 #include "core/style/ComputedStyle.h" |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 sizes.min_content = std::max(sizes.min_content, child_sizes.min_content); | 122 sizes.min_content = std::max(sizes.min_content, child_sizes.min_content); |
124 sizes.max_content = std::max(sizes.max_content, child_sizes.max_content); | 123 sizes.max_content = std::max(sizes.max_content, child_sizes.max_content); |
125 } | 124 } |
126 | 125 |
127 sizes.max_content = std::max(sizes.min_content, sizes.max_content); | 126 sizes.max_content = std::max(sizes.min_content, sizes.max_content); |
128 return sizes; | 127 return sizes; |
129 } | 128 } |
130 | 129 |
131 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( | 130 NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset( |
132 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { | 131 const WTF::Optional<NGLogicalOffset>& known_fragment_offset) { |
132 if (known_fragment_offset) | |
133 return known_fragment_offset.value() - ContainerBfcOffset(); | |
133 LayoutUnit inline_offset = | 134 LayoutUnit inline_offset = |
134 border_and_padding_.inline_start + curr_child_margins_.inline_start; | 135 border_and_padding_.inline_start + curr_child_margins_.inline_start; |
135 LayoutUnit block_offset = content_size_; | 136 return {inline_offset, content_size_}; |
136 if (known_fragment_offset) { | |
137 block_offset = known_fragment_offset.value().block_offset - | |
138 ContainerBfcOffset().block_offset; | |
139 } | |
140 return {inline_offset, block_offset}; | |
141 } | 137 } |
142 | 138 |
143 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { | 139 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { |
144 WTF::Optional<MinMaxContentSize> min_max_size; | 140 WTF::Optional<MinMaxContentSize> min_max_size; |
145 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) | 141 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) |
146 min_max_size = ComputeMinMaxContentSize(); | 142 min_max_size = ComputeMinMaxContentSize(); |
147 | 143 |
148 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + | 144 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + |
149 ComputePadding(ConstraintSpace(), Style()); | 145 ComputePadding(ConstraintSpace(), Style()); |
150 | 146 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 content_size_ + curr_margin_strut_.Sum()}; | 210 content_size_ + curr_margin_strut_.Sum()}; |
215 container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), | 211 container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child), |
216 offset); | 212 offset); |
217 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); | 213 NGBlockChildIterator::Entry entry = child_iterator.NextChild(); |
218 child = entry.node; | 214 child = entry.node; |
219 child_break_token = entry.token; | 215 child_break_token = entry.token; |
220 continue; | 216 continue; |
221 } | 217 } |
222 } | 218 } |
223 | 219 |
224 PrepareChildLayout(child); | 220 NGLogicalOffset child_bfc_offset = PrepareChildLayout(child); |
225 RefPtr<NGConstraintSpace> child_space = | 221 RefPtr<NGConstraintSpace> child_space = |
226 CreateConstraintSpaceForChild(child); | 222 CreateConstraintSpaceForChild(child_bfc_offset, child); |
227 RefPtr<NGLayoutResult> layout_result = | 223 RefPtr<NGLayoutResult> layout_result = |
228 child->Layout(child_space.Get(), child_break_token); | 224 child->Layout(child_space.Get(), child_break_token); |
229 | 225 |
230 FinishChildLayout(child, child_space.Get(), layout_result); | 226 if (child->IsFloating()) |
227 FinishFloatChildLayout(child->Style(), *child_space, &*layout_result); | |
228 else | |
229 FinishChildLayout(&*child_space, &*layout_result); | |
231 | 230 |
232 entry = child_iterator.NextChild(); | 231 entry = child_iterator.NextChild(); |
233 child = entry.node; | 232 child = entry.node; |
234 child_break_token = entry.token; | 233 child_break_token = entry.token; |
235 | 234 |
236 if (IsOutOfSpace(ConstraintSpace(), content_size_)) | 235 if (IsOutOfSpace(ConstraintSpace(), content_size_)) |
237 break; | 236 break; |
238 } | 237 } |
239 | 238 |
240 // Margins collapsing: | 239 // Margins collapsing: |
(...skipping 13 matching lines...) Expand all Loading... | |
254 container_builder_.SetBlockSize(size.block_size); | 253 container_builder_.SetBlockSize(size.block_size); |
255 | 254 |
256 // Layout our absolute and fixed positioned children. | 255 // Layout our absolute and fixed positioned children. |
257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run(); | 256 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run(); |
258 | 257 |
259 // Non-empty blocks always know their position in space: | 258 // Non-empty blocks always know their position in space: |
260 if (size.block_size) { | 259 if (size.block_size) { |
261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 260 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 261 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
263 &container_builder_); | 262 &container_builder_); |
264 PositionPendingFloats(curr_bfc_offset_.block_offset, | 263 PositionPendingFloats(curr_bfc_offset_.block_offset); |
265 MutableConstraintSpace(), &container_builder_); | |
266 } | 264 } |
267 | 265 |
268 // Margins collapsing: | 266 // Margins collapsing: |
269 // Do not collapse margins between the last in-flow child and bottom margin | 267 // Do not collapse margins between the last in-flow child and bottom margin |
270 // of its parent if the parent has height != auto() | 268 // of its parent if the parent has height != auto() |
271 if (!Style().LogicalHeight().IsAuto()) { | 269 if (!Style().LogicalHeight().IsAuto()) { |
272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. | 270 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. |
273 curr_margin_strut_ = NGMarginStrut(); | 271 curr_margin_strut_ = NGMarginStrut(); |
274 } | 272 } |
275 container_builder_.SetEndMarginStrut(curr_margin_strut_); | 273 container_builder_.SetEndMarginStrut(curr_margin_strut_); |
276 | 274 |
277 container_builder_.SetOverflowSize( | 275 container_builder_.SetOverflowSize( |
278 NGLogicalSize(max_inline_size_, content_size_)); | 276 NGLogicalSize(max_inline_size_, content_size_)); |
279 | 277 |
280 if (ConstraintSpace().HasBlockFragmentation()) | 278 if (ConstraintSpace().HasBlockFragmentation()) |
281 FinalizeForFragmentation(); | 279 FinalizeForFragmentation(); |
282 | 280 |
283 return container_builder_.ToBoxFragment(); | 281 return container_builder_.ToBoxFragment(); |
284 } | 282 } |
285 | 283 |
286 void NGBlockLayoutAlgorithm::PrepareChildLayout(NGLayoutInputNode* child) { | 284 NGLogicalOffset NGBlockLayoutAlgorithm::PrepareChildLayout( |
285 NGLayoutInputNode* child) { | |
287 DCHECK(child); | 286 DCHECK(child); |
288 | 287 |
288 curr_bfc_offset_ = container_builder_.BfcOffset() | |
289 ? container_builder_.BfcOffset().value() | |
290 : ConstraintSpace().BfcOffset(); | |
291 curr_bfc_offset_ += {border_and_padding_.inline_start, content_size_}; | |
292 | |
289 // Calculate margins in parent's writing mode. | 293 // Calculate margins in parent's writing mode. |
290 curr_child_margins_ = CalculateMargins( | 294 curr_child_margins_ = CalculateMargins( |
291 child, *space_builder_.ToConstraintSpace( | 295 child, *space_builder_.ToConstraintSpace( |
292 FromPlatformWritingMode(Style().GetWritingMode()))); | 296 FromPlatformWritingMode(Style().GetWritingMode()))); |
293 | 297 |
294 // Set estimated BFC offset to the next child's constraint space. | |
295 curr_bfc_offset_ = container_builder_.BfcOffset() | |
296 ? container_builder_.BfcOffset().value() | |
297 : ConstraintSpace().BfcOffset(); | |
298 curr_bfc_offset_.block_offset += content_size_; | |
299 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | |
300 | |
301 bool is_floating = child->IsBlock() && child->Style().IsFloating(); | |
302 | |
303 bool should_position_pending_floats = | 298 bool should_position_pending_floats = |
304 child->IsBlock() && !is_floating && | 299 !child->IsFloating() && |
305 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && | 300 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && |
306 ClearanceMayAffectLayout(ConstraintSpace(), | 301 ClearanceMayAffectLayout(ConstraintSpace(), |
307 container_builder_.UnpositionedFloats(), | 302 container_builder_.UnpositionedFloats(), |
308 child->Style()); | 303 child->Style()); |
309 | 304 |
310 // Children which may clear a float need to force all the pending floats to | 305 // Children which may clear a float need to force all the pending floats to |
311 // be positioned before layout. This also resolves the fragment's bfc offset. | 306 // be positioned before layout. This also resolves the fragment's bfc offset. |
312 if (should_position_pending_floats) { | 307 if (should_position_pending_floats) { |
313 LayoutUnit origin_point_block_offset = | 308 LayoutUnit origin_point_block_offset = |
314 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); | 309 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); |
315 MaybeUpdateFragmentBfcOffset( | 310 MaybeUpdateFragmentBfcOffset( |
316 ConstraintSpace(), | 311 ConstraintSpace(), |
317 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, | 312 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, |
318 &container_builder_); | 313 &container_builder_); |
319 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), | 314 PositionPendingFloats(origin_point_block_offset); |
320 &container_builder_); | |
321 } | 315 } |
322 | 316 |
323 bool is_inflow = child->IsInline() || !is_floating; | 317 bool is_inflow = child->IsInline() || !child->IsFloating(); |
324 | 318 |
319 NGLogicalOffset child_bfc_offset = curr_bfc_offset_; | |
325 // Only inflow children (e.g. not floats) are included in the child's margin | 320 // Only inflow children (e.g. not floats) are included in the child's margin |
326 // strut as they do not participate in margin collapsing. | 321 // strut as they do not participate in margin collapsing. |
327 if (is_inflow) { | 322 if (is_inflow) { |
328 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 323 child_bfc_offset.inline_offset += curr_child_margins_.inline_start; |
329 // Append the current margin strut with child's block start margin. | 324 // Append the current margin strut with child's block start margin. |
330 // Non empty border/padding use cases are handled inside of the child's | 325 // Non empty border/padding, new FC use cases are handled inside of the |
ikilpatrick
2017/04/18 13:19:55
.nit Non empty border/padding, and new FC use case
Gleb Lanbin
2017/04/18 17:30:20
Done.
| |
331 // layout. | 326 // child's layout. |
332 curr_margin_strut_.Append(curr_child_margins_.block_start); | 327 if (!IsNewFormattingContextForBlockLevelChild(Style(), *child)) |
328 curr_margin_strut_.Append(curr_child_margins_.block_start); | |
333 } | 329 } |
334 | 330 |
335 // TODO(ikilpatrick): Children which establish new formatting contexts need | 331 if (bool should_collapse_margins_if_inline = child->IsInline()) { |
336 // to be placed using the opportunity iterator before we can collapse margins. | |
337 // If the child is placed at the block_start of this fragment, then its | |
338 // margins do impact the position of its parent, if not (its placed below a | |
339 // float for example) it doesn't. \o/ | |
340 | |
341 bool should_collapse_margins = | |
342 child->IsInline() || | |
343 (!is_floating && | |
344 IsNewFormattingContextForBlockLevelChild(Style(), *child)); | |
345 | |
346 // Inline children or children which establish a block formatting context | |
347 // collapse margins and position themselves immediately as they need to know | |
348 // their BFC offset for fragmentation purposes. | |
349 if (should_collapse_margins) { | |
350 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 332 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
351 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 333 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, |
352 &container_builder_); | 334 &container_builder_); |
353 PositionPendingFloats(curr_bfc_offset_.block_offset, | 335 PositionPendingFloats(curr_bfc_offset_.block_offset); |
354 MutableConstraintSpace(), &container_builder_); | |
355 curr_margin_strut_ = {}; | 336 curr_margin_strut_ = {}; |
356 } | 337 } |
338 child_bfc_offset.block_offset = curr_bfc_offset_.block_offset; | |
339 return child_bfc_offset; | |
357 } | 340 } |
358 | 341 |
359 void NGBlockLayoutAlgorithm::FinishChildLayout( | 342 void NGBlockLayoutAlgorithm::FinishChildLayout( |
360 NGLayoutInputNode* child, | 343 const NGConstraintSpace* child_space, |
361 NGConstraintSpace* child_space, | 344 NGLayoutResult* layout_result) { |
362 RefPtr<NGLayoutResult> layout_result) { | |
363 NGBoxFragment fragment( | |
364 ConstraintSpace().WritingMode(), | |
365 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); | |
366 | |
367 // Pull out unpositioned floats to the current fragment. This may needed if | 345 // Pull out unpositioned floats to the current fragment. This may needed if |
368 // for example the child fragment could not position its floats because it's | 346 // for example the child fragment could not position its floats because it's |
369 // empty and therefore couldn't determine its position in space. | 347 // empty and therefore couldn't determine its position in space. |
370 container_builder_.MutableUnpositionedFloats().AppendVector( | 348 container_builder_.MutableUnpositionedFloats().AppendVector( |
371 layout_result->UnpositionedFloats()); | 349 layout_result->UnpositionedFloats()); |
372 | 350 |
373 if (child->IsBlock() && child->Style().IsFloating()) { | 351 NGBoxFragment fragment( |
374 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); | 352 ConstraintSpace().WritingMode(), |
375 origin_offset.inline_offset += border_and_padding_.inline_start; | 353 ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get())); |
376 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( | |
377 child->Style(), child_space->WritingMode(), | |
378 child_space->AvailableSize(), origin_offset, | |
379 constraint_space_->BfcOffset(), curr_child_margins_, | |
380 layout_result->PhysicalFragment().Get()); | |
381 container_builder_.AddUnpositionedFloat(floating_object); | |
382 // No need to postpone the positioning if we know the correct offset. | |
383 if (container_builder_.BfcOffset()) { | |
384 NGLogicalOffset origin_point = curr_bfc_offset_; | |
385 // Adjust origin point to the margins of the last child. | |
386 // Example: <div style="margin-bottom: 20px"><float></div> | |
387 // <div style="margin-bottom: 30px"></div> | |
388 origin_point.block_offset += curr_margin_strut_.Sum(); | |
389 PositionPendingFloats(origin_point.block_offset, MutableConstraintSpace(), | |
390 &container_builder_); | |
391 } | |
392 return; | |
393 } | |
394 | 354 |
395 // Determine the fragment's position in the parent space either by using | 355 // Determine the fragment's position in the parent space. |
396 // content_size_ or known fragment's BFC offset. | 356 WTF::Optional<NGLogicalOffset> child_bfc_offset; |
397 WTF::Optional<NGLogicalOffset> bfc_offset; | 357 if (child_space->IsNewFormattingContext()) |
398 if (child_space->IsNewFormattingContext()) { | 358 child_bfc_offset = PositionNewFc(fragment, *child_space); |
399 bfc_offset = curr_bfc_offset_; | 359 else if (fragment.BfcOffset()) |
400 } else if (fragment.BfcOffset()) { | 360 child_bfc_offset = PositionWithBfcOffset(fragment); |
401 // Fragment that knows its offset can be used to set parent's BFC position. | 361 else if (container_builder_.BfcOffset()) |
402 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 362 child_bfc_offset = PositionWithParentBfc(); |
403 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | 363 |
404 &container_builder_); | 364 NGLogicalOffset logical_offset = CalculateLogicalOffset(child_bfc_offset); |
405 PositionPendingFloats(curr_bfc_offset_.block_offset, | |
406 MutableConstraintSpace(), &container_builder_); | |
407 bfc_offset = curr_bfc_offset_; | |
408 } else if (container_builder_.BfcOffset()) { | |
409 // Fragment doesn't know its offset but we can still calculate its BFC | |
410 // position because the parent fragment's BFC is known. | |
411 // Example: | |
412 // BFC Offset is known here because of the padding. | |
413 // <div style="padding: 1px"> | |
414 // <div id="empty-div" style="margins: 1px"></div> | |
415 bfc_offset = curr_bfc_offset_; | |
416 bfc_offset.value().block_offset += curr_margin_strut_.Sum(); | |
417 } | |
418 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | |
419 | 365 |
420 // Update margin strut. | 366 // Update margin strut. |
421 curr_margin_strut_ = fragment.EndMarginStrut(); | 367 curr_margin_strut_ = fragment.EndMarginStrut(); |
422 curr_margin_strut_.Append(curr_child_margins_.block_end); | 368 curr_margin_strut_.Append(curr_child_margins_.block_end); |
423 | 369 |
424 // Only modify content_size if BlockSize is not empty. It's needed to prevent | 370 // Only modify content_size if BlockSize is not empty. It's needed to prevent |
425 // the situation when logical_offset is included in content_size for empty | 371 // the situation when logical_offset is included in content_size for empty |
426 // blocks. Example: | 372 // blocks. Example: |
427 // <div style="overflow:hidden"> | 373 // <div style="overflow:hidden"> |
428 // <div style="margin-top: 8px"></div> | 374 // <div style="margin-top: 8px"></div> |
429 // <div style="margin-top: 10px"></div> | 375 // <div style="margin-top: 10px"></div> |
430 // </div> | 376 // </div> |
431 if (fragment.BlockSize()) | 377 if (fragment.BlockSize()) |
432 content_size_ = fragment.BlockSize() + logical_offset.block_offset; | 378 content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
433 max_inline_size_ = | 379 max_inline_size_ = |
434 std::max(max_inline_size_, fragment.InlineSize() + | 380 std::max(max_inline_size_, fragment.InlineSize() + |
435 curr_child_margins_.InlineSum() + | 381 curr_child_margins_.InlineSum() + |
436 border_and_padding_.InlineSum()); | 382 border_and_padding_.InlineSum()); |
437 | 383 |
438 container_builder_.AddChild(layout_result, logical_offset); | 384 container_builder_.AddChild(layout_result, logical_offset); |
439 } | 385 } |
440 | 386 |
387 NGLogicalOffset NGBlockLayoutAlgorithm::PositionNewFc( | |
388 const NGBoxFragment& fragment, | |
389 const NGConstraintSpace& child_space) { | |
390 // 1. Position all pending floats to a temporary space. | |
391 RefPtr<NGConstraintSpace> tmp_space = | |
392 NGConstraintSpaceBuilder(&child_space) | |
393 .SetIsNewFormattingContext(false) | |
394 .ToConstraintSpace(child_space.WritingMode()); | |
395 PositionFloats(curr_bfc_offset_.block_offset, curr_bfc_offset_.block_offset, | |
396 container_builder_.UnpositionedFloats(), tmp_space.Get()); | |
397 | |
398 // 2. Find an estimated layout opportunity for our fragment. | |
399 NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment( | |
400 tmp_space->Exclusions().get(), child_space.AvailableSize(), | |
401 curr_bfc_offset_, curr_child_margins_, fragment); | |
402 | |
403 // 3. If the found opportunity lies on the same line with our estimated | |
404 // child's BFC offset then merge fragment's margins with the current | |
405 // MarginStrut. | |
406 if (opportunity.offset.block_offset == curr_bfc_offset_.block_offset) | |
407 curr_margin_strut_.Append(curr_child_margins_.block_start); | |
408 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | |
409 curr_margin_strut_ = {}; | |
410 | |
411 // 4. The child's BFC block offset is known here. | |
412 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | |
413 &container_builder_); | |
414 PositionPendingFloats(curr_bfc_offset_.block_offset); | |
415 | |
416 // 5. Find the final layout opportunity for the fragment after all pending | |
417 // floats are positioned at the correct BFC block's offset. | |
418 opportunity = FindLayoutOpportunityForFragment( | |
ikilpatrick
2017/04/18 13:19:55
will this always be just:
LayoutUnit block_offset
Gleb Lanbin
2017/04/18 17:30:20
we need to call FindLayoutOpportunityForFragment o
ikilpatrick
2017/04/18 21:04:11
thanks, yup.
| |
419 MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(), | |
420 curr_bfc_offset_, curr_child_margins_, fragment); | |
421 | |
422 curr_bfc_offset_ = opportunity.offset; | |
423 return curr_bfc_offset_; | |
424 } | |
425 | |
426 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithBfcOffset( | |
427 const NGBoxFragment& fragment) { | |
428 DCHECK(fragment.BfcOffset()); | |
429 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | |
430 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_, | |
431 &container_builder_); | |
432 PositionPendingFloats(curr_bfc_offset_.block_offset); | |
433 return fragment.BfcOffset().value(); | |
434 } | |
435 | |
436 NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc() { | |
437 curr_bfc_offset_ += | |
438 {curr_child_margins_.inline_start, curr_margin_strut_.Sum()}; | |
439 return curr_bfc_offset_; | |
440 } | |
441 | |
442 void NGBlockLayoutAlgorithm::FinishFloatChildLayout( | |
443 const ComputedStyle& child_style, | |
444 const NGConstraintSpace& child_space, | |
445 const NGLayoutResult* layout_result) { | |
446 NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); | |
447 origin_offset.inline_offset += border_and_padding_.inline_start; | |
448 RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( | |
449 child_style, child_space.WritingMode(), child_space.AvailableSize(), | |
450 origin_offset, constraint_space_->BfcOffset(), curr_child_margins_, | |
451 layout_result->PhysicalFragment().Get()); | |
452 container_builder_.AddUnpositionedFloat(floating_object); | |
453 | |
454 // No need to postpone the positioning if we know the correct offset. | |
455 if (container_builder_.BfcOffset()) { | |
456 NGLogicalOffset origin_point = curr_bfc_offset_; | |
457 // Adjust origin point to the margins of the last child. | |
458 // Example: <div style="margin-bottom: 20px"><float></div> | |
459 // <div style="margin-bottom: 30px"></div> | |
460 origin_point.block_offset += curr_margin_strut_.Sum(); | |
461 PositionPendingFloats(origin_point.block_offset); | |
462 } | |
463 } | |
464 | |
441 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { | 465 void NGBlockLayoutAlgorithm::FinalizeForFragmentation() { |
442 LayoutUnit used_block_size = | 466 LayoutUnit used_block_size = |
443 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); | 467 BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit(); |
444 LayoutUnit block_size = ComputeBlockSizeForFragment( | 468 LayoutUnit block_size = ComputeBlockSizeForFragment( |
445 ConstraintSpace(), Style(), used_block_size + content_size_); | 469 ConstraintSpace(), Style(), used_block_size + content_size_); |
446 | 470 |
447 block_size -= used_block_size; | 471 block_size -= used_block_size; |
448 DCHECK_GE(block_size, LayoutUnit()) | 472 DCHECK_GE(block_size, LayoutUnit()) |
449 << "Adding and subtracting the used_block_size shouldn't leave the " | 473 << "Adding and subtracting the used_block_size shouldn't leave the " |
450 "block_size for this fragment smaller than zero."; | 474 "block_size for this fragment smaller than zero."; |
(...skipping 22 matching lines...) Expand all Loading... | |
473 | 497 |
474 // The end of the block fits in the current fragmentainer. | 498 // The end of the block fits in the current fragmentainer. |
475 container_builder_.SetBlockSize(block_size); | 499 container_builder_.SetBlockSize(block_size); |
476 container_builder_.SetBlockOverflow(content_size_); | 500 container_builder_.SetBlockOverflow(content_size_); |
477 } | 501 } |
478 | 502 |
479 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( | 503 NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins( |
480 NGLayoutInputNode* child, | 504 NGLayoutInputNode* child, |
481 const NGConstraintSpace& space) { | 505 const NGConstraintSpace& space) { |
482 DCHECK(child); | 506 DCHECK(child); |
507 if (child->IsInline()) | |
508 return {}; | |
483 const ComputedStyle& child_style = child->Style(); | 509 const ComputedStyle& child_style = child->Style(); |
484 | 510 |
485 WTF::Optional<MinMaxContentSize> sizes; | 511 WTF::Optional<MinMaxContentSize> sizes; |
486 if (NeedMinMaxContentSize(space, child_style)) | 512 if (NeedMinMaxContentSize(space, child_style)) |
487 sizes = child->ComputeMinMaxContentSize(); | 513 sizes = child->ComputeMinMaxContentSize(); |
488 | 514 |
489 LayoutUnit child_inline_size = | 515 LayoutUnit child_inline_size = |
490 ComputeInlineSizeForFragment(space, child_style, sizes); | 516 ComputeInlineSizeForFragment(space, child_style, sizes); |
491 NGBoxStrut margins = ComputeMargins(space, child_style, space.WritingMode(), | 517 NGBoxStrut margins = ComputeMargins(space, child_style, space.WritingMode(), |
492 space.Direction()); | 518 space.Direction()); |
493 if (!child_style.IsFloating()) { | 519 if (!child->IsFloating()) { |
494 ApplyAutoMargins(space, child_style, child_inline_size, &margins); | 520 ApplyAutoMargins(space, child_style, child_inline_size, &margins); |
495 } | 521 } |
496 return margins; | 522 return margins; |
497 } | 523 } |
498 | 524 |
499 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( | 525 RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild( |
526 const NGLogicalOffset& child_bfc_offset, | |
500 NGLayoutInputNode* child) { | 527 NGLayoutInputNode* child) { |
501 DCHECK(child); | 528 DCHECK(child); |
502 | 529 |
503 const ComputedStyle& child_style = child->Style(); | 530 const ComputedStyle& child_style = child->Style(); |
504 bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), *child); | 531 bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), *child); |
505 space_builder_.SetIsNewFormattingContext(is_new_bfc) | 532 space_builder_.SetIsNewFormattingContext(is_new_bfc) |
506 .SetBfcOffset(curr_bfc_offset_); | 533 .SetBfcOffset(child_bfc_offset); |
507 | 534 |
508 if (child->IsInline()) { | 535 if (child->IsInline()) { |
509 // TODO(kojii): Setup space_builder_ appropriately for inline child. | 536 // TODO(kojii): Setup space_builder_ appropriately for inline child. |
510 space_builder_.SetBfcOffset(curr_bfc_offset_) | 537 space_builder_.SetClearanceOffset(ConstraintSpace().ClearanceOffset()); |
511 .SetClearanceOffset(ConstraintSpace().ClearanceOffset()); | |
512 return space_builder_.ToConstraintSpace( | 538 return space_builder_.ToConstraintSpace( |
513 FromPlatformWritingMode(Style().GetWritingMode())); | 539 FromPlatformWritingMode(Style().GetWritingMode())); |
514 } | 540 } |
515 | 541 |
516 space_builder_ | 542 space_builder_ |
517 .SetClearanceOffset( | 543 .SetClearanceOffset( |
518 GetClearanceOffset(constraint_space_->Exclusions(), child_style)) | 544 GetClearanceOffset(constraint_space_->Exclusions(), child_style)) |
519 .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) | 545 .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) |
520 .SetTextDirection(child_style.Direction()); | 546 .SetTextDirection(child_style.Direction()); |
521 | 547 |
522 // Float's margins are not included in child's space because: | 548 // Float's margins are not included in child's space because: |
523 // 1) Floats do not participate in margins collapsing. | 549 // 1) Floats do not participate in margins collapsing. |
524 // 2) Floats margins are used separately to calculate floating exclusions. | 550 // 2) Floats margins are used separately to calculate floating exclusions. |
525 space_builder_.SetMarginStrut(child_style.IsFloating() ? NGMarginStrut() | 551 space_builder_.SetMarginStrut(child->IsFloating() ? NGMarginStrut() |
526 : curr_margin_strut_); | 552 : curr_margin_strut_); |
527 | 553 |
528 LayoutUnit space_available; | 554 LayoutUnit space_available; |
529 if (constraint_space_->HasBlockFragmentation()) { | 555 if (constraint_space_->HasBlockFragmentation()) { |
530 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); | 556 space_available = ConstraintSpace().FragmentainerSpaceAvailable(); |
531 // If a block establishes a new formatting context we must know our | 557 // If a block establishes a new formatting context we must know our |
532 // position in the formatting context, and are able to adjust the | 558 // position in the formatting context, and are able to adjust the |
533 // fragmentation line. | 559 // fragmentation line. |
534 if (is_new_bfc) { | 560 if (is_new_bfc) { |
535 space_available -= curr_bfc_offset_.block_offset; | 561 space_available -= child_bfc_offset.block_offset; |
536 } | 562 } |
537 } | 563 } |
538 space_builder_.SetFragmentainerSpaceAvailable(space_available); | 564 space_builder_.SetFragmentainerSpaceAvailable(space_available); |
539 | 565 |
540 return space_builder_.ToConstraintSpace( | 566 return space_builder_.ToConstraintSpace( |
541 FromPlatformWritingMode(child_style.GetWritingMode())); | 567 FromPlatformWritingMode(child_style.GetWritingMode())); |
542 } | 568 } |
543 } // namespace blink | 569 } // namespace blink |
OLD | NEW |