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/ng_absolute_utils.h" | 7 #include "core/layout/ng/ng_absolute_utils.h" |
8 #include "core/layout/ng/ng_block_break_token.h" | 8 #include "core/layout/ng/ng_block_break_token.h" |
9 #include "core/layout/ng/ng_box_fragment.h" | 9 #include "core/layout/ng/ng_box_fragment.h" |
10 #include "core/layout/ng/ng_column_mapper.h" | 10 #include "core/layout/ng/ng_column_mapper.h" |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 | 162 |
163 opportunity_candidate = opportunity_iter.Next(); | 163 opportunity_candidate = opportunity_iter.Next(); |
164 } | 164 } |
165 return opportunity; | 165 return opportunity; |
166 } | 166 } |
167 | 167 |
168 // Calculates the logical offset for opportunity. | 168 // Calculates the logical offset for opportunity. |
169 NGLogicalOffset CalculateLogicalOffsetForOpportunity( | 169 NGLogicalOffset CalculateLogicalOffsetForOpportunity( |
170 const NGLayoutOpportunity& opportunity, | 170 const NGLayoutOpportunity& opportunity, |
171 const LayoutUnit float_offset, | 171 const LayoutUnit float_offset, |
172 const NGBoxStrut& margins, | 172 const NGLogicalOffset& from_offset, |
173 const NGLogicalOffset& space_offset) { | 173 NGFloatingObject* floating_object) { |
174 auto margins = floating_object->margins; | |
174 // Adjust to child's margin. | 175 // Adjust to child's margin. |
175 LayoutUnit inline_offset = margins.inline_start; | 176 LayoutUnit inline_offset = margins.inline_start; |
176 LayoutUnit block_offset = margins.block_start; | 177 LayoutUnit block_offset = margins.block_start; |
177 | 178 |
178 // Offset from the opportunity's block/inline start. | 179 // Offset from the opportunity's block/inline start. |
179 inline_offset += opportunity.offset.inline_offset; | 180 inline_offset += opportunity.offset.inline_offset; |
180 block_offset += opportunity.offset.block_offset; | 181 block_offset += opportunity.offset.block_offset; |
181 | 182 |
183 // Adjust to float: right offset if needed. | |
182 inline_offset += float_offset; | 184 inline_offset += float_offset; |
183 | 185 |
184 block_offset -= space_offset.block_offset; | 186 block_offset -= from_offset.block_offset; |
185 inline_offset -= space_offset.inline_offset; | 187 inline_offset -= from_offset.inline_offset; |
186 | 188 |
187 return NGLogicalOffset(inline_offset, block_offset); | 189 return NGLogicalOffset(inline_offset, block_offset); |
188 } | 190 } |
189 | 191 |
190 // Calculates the relative position from {@code from_offset} of the | 192 // Calculates the relative position from {@code from_offset} of the |
191 // floating object that is requested to be positioned from {@code origin_point}. | 193 // floating object that is requested to be positioned from {@code origin_point}. |
192 NGLogicalOffset PositionFloat(const NGLogicalOffset& origin_point, | 194 NGLogicalOffset PositionFloat(const NGLogicalOffset& origin_point, |
193 const NGLogicalOffset& from_offset, | 195 const NGLogicalOffset& from_offset, |
194 NGFloatingObject* floating_object) { | 196 NGFloatingObject* floating_object) { |
195 NGConstraintSpace* float_space = floating_object->space; | 197 NGConstraintSpace* float_space = floating_object->space; |
(...skipping 15 matching lines...) Expand all Loading... | |
211 if (floating_object->exclusion_type == NGExclusion::kFloatRight) { | 213 if (floating_object->exclusion_type == NGExclusion::kFloatRight) { |
212 float_offset = opportunity.size.inline_size - float_fragment.InlineSize(); | 214 float_offset = opportunity.size.inline_size - float_fragment.InlineSize(); |
213 } | 215 } |
214 | 216 |
215 // Add the float as an exclusion. | 217 // Add the float as an exclusion. |
216 const NGExclusion exclusion = CreateExclusion( | 218 const NGExclusion exclusion = CreateExclusion( |
217 float_fragment, opportunity, float_offset, floating_object->margins, | 219 float_fragment, opportunity, float_offset, floating_object->margins, |
218 floating_object->exclusion_type); | 220 floating_object->exclusion_type); |
219 float_space->AddExclusion(exclusion); | 221 float_space->AddExclusion(exclusion); |
220 | 222 |
221 return CalculateLogicalOffsetForOpportunity( | 223 return CalculateLogicalOffsetForOpportunity(opportunity, float_offset, |
222 opportunity, float_offset, floating_object->margins, from_offset); | 224 from_offset, floating_object); |
225 } | |
226 | |
227 // Updates the Floating Object's left offset from the provided parent_space | |
228 // and {@code floating_object}'s space and margins. | |
229 void UpdateFloatingObjectLeftOffset( | |
ikilpatrick
2017/02/10 22:43:42
i find this a little weird that this is a one line
Gleb Lanbin
2017/02/10 22:58:39
yes this function can grow to something more than
ikilpatrick
2017/02/10 23:01:40
Ah ok, sg then.
| |
230 const NGConstraintSpace& new_parent_space, | |
231 const Persistent<NGFloatingObject>& floating_object) { | |
232 const auto& float_space = floating_object->space; | |
233 // TODO(glebl): We should use physical offset here. | |
234 floating_object->left_offset = float_space->BfcOffset().inline_offset - | |
235 new_parent_space.BfcOffset().inline_offset + | |
236 floating_object->margins.inline_start; | |
223 } | 237 } |
224 | 238 |
225 // Positions pending floats stored on the fragment builder starting from | 239 // Positions pending floats stored on the fragment builder starting from |
226 // {@code origin_point}. | 240 // {@code origin_point_block_offset}. |
227 void PositionPendingFloats(const NGLogicalOffset& origin_point, | 241 void PositionPendingFloats(const LayoutUnit origin_point_block_offset, |
242 const NGConstraintSpace& new_parent_space, | |
228 NGFragmentBuilder* builder) { | 243 NGFragmentBuilder* builder) { |
229 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; | 244 DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here"; |
230 NGLogicalOffset from_offset = builder->BfcOffset().value(); | 245 LayoutUnit bfc_block_offset = builder->BfcOffset().value().block_offset; |
231 | 246 |
232 for (auto& floating_object : builder->UnpositionedFloats()) { | 247 for (auto& floating_object : builder->UnpositionedFloats()) { |
248 Member<NGConstraintSpace> float_space = floating_object->space; | |
249 Member<const NGConstraintSpace> float_parent_space = | |
250 floating_object->parent_space; | |
ikilpatrick
2017/02/10 22:43:42
didn't rename this to original_parent_space?
Gleb Lanbin
2017/02/10 22:58:39
I thought we were talking about renaming parent_sp
ikilpatrick
2017/02/10 23:01:40
Yeah i think above would be good, (only if you agr
| |
251 | |
252 NGLogicalOffset origin_point = {float_space->BfcOffset().inline_offset, | |
253 origin_point_block_offset}; | |
254 NGLogicalOffset from_offset = { | |
255 float_parent_space->BfcOffset().inline_offset, bfc_block_offset}; | |
256 | |
233 NGLogicalOffset float_fragment_offset = | 257 NGLogicalOffset float_fragment_offset = |
234 PositionFloat(origin_point, from_offset, floating_object); | 258 PositionFloat(origin_point, from_offset, floating_object); |
235 builder->AddFloatingObject(floating_object, float_fragment_offset); | 259 builder->AddFloatingObject(floating_object, float_fragment_offset); |
260 UpdateFloatingObjectLeftOffset(new_parent_space, floating_object); | |
236 } | 261 } |
237 builder->MutableUnpositionedFloats().clear(); | 262 builder->MutableUnpositionedFloats().clear(); |
238 } | 263 } |
239 | 264 |
240 // Whether an in-flow block-level child creates a new formatting context. | 265 // Whether an in-flow block-level child creates a new formatting context. |
241 // | 266 // |
242 // This will *NOT* check the following cases: | 267 // This will *NOT* check the following cases: |
243 // - The child is out-of-flow, e.g. floating or abs-pos. | 268 // - The child is out-of-flow, e.g. floating or abs-pos. |
244 // - The child is a inline-level, e.g. "display: inline-block". | 269 // - The child is a inline-level, e.g. "display: inline-block". |
245 // - The child establishes a new formatting context, but should be a child of | 270 // - The child establishes a new formatting context, but should be a child of |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); | 472 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); |
448 builder_->SetBlockSize(block_size); | 473 builder_->SetBlockSize(block_size); |
449 | 474 |
450 // Layout our absolute and fixed positioned children. | 475 // Layout our absolute and fixed positioned children. |
451 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); | 476 NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); |
452 | 477 |
453 // Non empty blocks always know their position in space: | 478 // Non empty blocks always know their position in space: |
454 if (block_size) { | 479 if (block_size) { |
455 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 480 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
456 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | 481 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
457 PositionPendingFloats(curr_bfc_offset_, builder_.get()); | 482 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
483 builder_.get()); | |
458 } | 484 } |
459 | 485 |
460 // Margins collapsing: | 486 // Margins collapsing: |
461 // Do not collapse margins between the last in-flow child and bottom margin | 487 // Do not collapse margins between the last in-flow child and bottom margin |
462 // of its parent if the parent has height != auto() | 488 // of its parent if the parent has height != auto() |
463 if (!Style().logicalHeight().isAuto()) { | 489 if (!Style().logicalHeight().isAuto()) { |
464 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. | 490 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. |
465 curr_margin_strut_ = NGMarginStrut(); | 491 curr_margin_strut_ = NGMarginStrut(); |
466 } | 492 } |
467 builder_->SetEndMarginStrut(curr_margin_strut_); | 493 builder_->SetEndMarginStrut(curr_margin_strut_); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
501 // Pull out unpositioned floats to the current fragment. This may needed if | 527 // Pull out unpositioned floats to the current fragment. This may needed if |
502 // for example the child fragment could not position its floats because it's | 528 // for example the child fragment could not position its floats because it's |
503 // empty and therefore couldn't determine its position in space. | 529 // empty and therefore couldn't determine its position in space. |
504 builder_->MutableUnpositionedFloats().appendVector( | 530 builder_->MutableUnpositionedFloats().appendVector( |
505 physical_fragment->UnpositionedFloats()); | 531 physical_fragment->UnpositionedFloats()); |
506 | 532 |
507 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock && | 533 if (current_child_->Type() == NGLayoutInputNode::kLegacyBlock && |
508 CurrentChildStyle().isFloating()) { | 534 CurrentChildStyle().isFloating()) { |
509 NGFloatingObject* floating_object = | 535 NGFloatingObject* floating_object = |
510 new NGFloatingObject(physical_fragment.get(), space_for_current_child_, | 536 new NGFloatingObject(physical_fragment.get(), space_for_current_child_, |
511 toNGBlockNode(current_child_), CurrentChildStyle(), | 537 constraint_space_, toNGBlockNode(current_child_), |
512 curr_child_margins_); | 538 CurrentChildStyle(), curr_child_margins_); |
513 builder_->AddUnpositionedFloat(floating_object); | 539 builder_->AddUnpositionedFloat(floating_object); |
514 // No need to postpone the positioning if we know the correct offset. | 540 // No need to postpone the positioning if we know the correct offset. |
515 if (builder_->BfcOffset()) { | 541 if (builder_->BfcOffset()) { |
516 NGLogicalOffset origin_point = curr_bfc_offset_; | 542 NGLogicalOffset origin_point = curr_bfc_offset_; |
517 // Adjust origin point to the margins of the last child. | 543 // Adjust origin point to the margins of the last child. |
518 // Example: <div style="margin-bottom: 20px"><float></div> | 544 // Example: <div style="margin-bottom: 20px"><float></div> |
519 // <div style="margin-bottom: 30px"></div> | 545 // <div style="margin-bottom: 30px"></div> |
520 origin_point.block_offset += curr_margin_strut_.Sum(); | 546 origin_point.block_offset += curr_margin_strut_.Sum(); |
521 PositionPendingFloats(origin_point, builder_.get()); | 547 PositionPendingFloats(origin_point.block_offset, ConstraintSpace(), |
548 builder_.get()); | |
522 } | 549 } |
523 return; | 550 return; |
524 } | 551 } |
525 | 552 |
526 // Determine the fragment's position in the parent space either by using | 553 // Determine the fragment's position in the parent space either by using |
527 // content_size_ or known fragment's BFC offset. | 554 // content_size_ or known fragment's BFC offset. |
528 WTF::Optional<NGLogicalOffset> bfc_offset; | 555 WTF::Optional<NGLogicalOffset> bfc_offset; |
529 if (CurrentChildConstraintSpace().IsNewFormattingContext()) { | 556 if (CurrentChildConstraintSpace().IsNewFormattingContext()) { |
530 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 557 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
531 bfc_offset = curr_bfc_offset_; | 558 bfc_offset = curr_bfc_offset_; |
532 } else if (fragment.BfcOffset()) { | 559 } else if (fragment.BfcOffset()) { |
533 // Fragment that knows its offset can be used to set parent's BFC position. | 560 // Fragment that knows its offset can be used to set parent's BFC position. |
534 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; | 561 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
535 bfc_offset = curr_bfc_offset_; | 562 bfc_offset = curr_bfc_offset_; |
536 } | 563 } |
537 if (bfc_offset) { | 564 if (bfc_offset) { |
538 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | 565 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
539 PositionPendingFloats(curr_bfc_offset_, builder_.get()); | 566 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
567 builder_.get()); | |
540 } | 568 } |
541 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); | 569 NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset); |
542 | 570 |
543 if (fragmentainer_mapper_) | 571 if (fragmentainer_mapper_) |
544 fragmentainer_mapper_->ToVisualOffset(logical_offset); | 572 fragmentainer_mapper_->ToVisualOffset(logical_offset); |
545 else | 573 else |
546 logical_offset.block_offset -= PreviousBreakOffset(); | 574 logical_offset.block_offset -= PreviousBreakOffset(); |
547 | 575 |
548 // Update margin strut. | 576 // Update margin strut. |
549 curr_margin_strut_ = fragment.EndMarginStrut(); | 577 curr_margin_strut_ = fragment.EndMarginStrut(); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
752 // TODO(glebl): Fix the use case with clear: left and an intruding right. | 780 // TODO(glebl): Fix the use case with clear: left and an intruding right. |
753 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 | 781 // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847 |
754 if (current_child_style.clear() != EClear::kNone) { | 782 if (current_child_style.clear() != EClear::kNone) { |
755 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); | 783 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
756 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); | 784 UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
757 // Only collapse margins if it's an adjoining block with clearance. | 785 // Only collapse margins if it's an adjoining block with clearance. |
758 if (!content_size_) { | 786 if (!content_size_) { |
759 curr_margin_strut_ = NGMarginStrut(); | 787 curr_margin_strut_ = NGMarginStrut(); |
760 curr_child_margins_.block_start = LayoutUnit(); | 788 curr_child_margins_.block_start = LayoutUnit(); |
761 } | 789 } |
762 PositionPendingFloats(curr_bfc_offset_, builder_.get()); | 790 PositionPendingFloats(curr_bfc_offset_.block_offset, ConstraintSpace(), |
791 builder_.get()); | |
763 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, | 792 AdjustToClearance(constraint_space_->Exclusions(), current_child_style, |
764 builder_->BfcOffset().value(), &content_size_); | 793 builder_->BfcOffset().value(), &content_size_); |
765 } | 794 } |
766 | 795 |
767 // Append the current margin strut with child's block start margin. | 796 // Append the current margin strut with child's block start margin. |
768 // Non empty border/padding use cases are handled inside of the child's | 797 // Non empty border/padding use cases are handled inside of the child's |
769 // layout. | 798 // layout. |
770 curr_margin_strut_.Append(curr_child_margins_.block_start); | 799 curr_margin_strut_.Append(curr_child_margins_.block_start); |
771 space_builder_->SetMarginStrut(curr_margin_strut_); | 800 space_builder_->SetMarginStrut(curr_margin_strut_); |
772 | 801 |
773 // Set estimated BFC offset to the next child's constraint space. | 802 // Set estimated BFC offset to the next child's constraint space. |
774 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() | 803 curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() |
775 : ConstraintSpace().BfcOffset(); | 804 : ConstraintSpace().BfcOffset(); |
776 curr_bfc_offset_.block_offset += content_size_; | 805 curr_bfc_offset_.block_offset += content_size_; |
777 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; | 806 curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
778 if (ConstraintSpace().IsNewFormattingContext()) { | 807 |
808 // Floats margins are not included in child's CS because they are used to | |
809 // calculate floating exclusions. | |
810 if (!CurrentChildStyle().isFloating()) { | |
779 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 811 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
780 } | 812 } |
813 | |
781 space_builder_->SetBfcOffset(curr_bfc_offset_); | 814 space_builder_->SetBfcOffset(curr_bfc_offset_); |
782 | 815 |
783 return space_builder_->ToConstraintSpace(); | 816 return space_builder_->ToConstraintSpace(); |
784 } | 817 } |
785 | 818 |
786 } // namespace blink | 819 } // namespace blink |
OLD | NEW |