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