Chromium Code Reviews| 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 and | |
| 228 // {@code floating_object}'s space and margins. | |
| 229 void UpdateFloatingObjectLeftOffset( | |
| 230 const NGConstraintSpace& 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. | |
|
ikilpatrick
2017/02/10 01:53:41
By this you mean the value we copy back into the o
Gleb Lanbin
2017/02/10 20:11:12
yes
| |
| 234 floating_object->left_offset = float_space->BfcOffset().inline_offset - | |
| 235 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& 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; | |
| 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(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 |
|
ikilpatrick
2017/02/10 01:53:41
I assume this was intentional? Don't you still wan
Gleb Lanbin
2017/02/10 20:11:12
I don't remember why I added that. I ran tests tha
| |
| 808 if (!CurrentChildStyle().isFloating()) { | |
| 779 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; | 809 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
| 780 } | 810 } |
| 811 | |
| 781 space_builder_->SetBfcOffset(curr_bfc_offset_); | 812 space_builder_->SetBfcOffset(curr_bfc_offset_); |
| 782 | 813 |
| 783 return space_builder_->ToConstraintSpace(); | 814 return space_builder_->ToConstraintSpace(); |
| 784 } | 815 } |
| 785 | 816 |
| 786 } // namespace blink | 817 } // namespace blink |
| OLD | NEW |