| 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_node.h" | 5 #include "core/layout/ng/ng_block_node.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutBlockFlow.h" | 7 #include "core/layout/LayoutBlockFlow.h" |
| 8 #include "core/layout/api/LineLayoutAPIShim.h" | 8 #include "core/layout/api/LineLayoutAPIShim.h" |
| 9 #include "core/layout/line/InlineIterator.h" | 9 #include "core/layout/line/InlineIterator.h" |
| 10 #include "core/layout/ng/layout_ng_block_flow.h" | 10 #include "core/layout/ng/layout_ng_block_flow.h" |
| 11 #include "core/layout/ng/ng_block_layout_algorithm.h" | 11 #include "core/layout/ng/ng_block_layout_algorithm.h" |
| 12 #include "core/layout/ng/ng_box_fragment.h" | 12 #include "core/layout/ng/ng_box_fragment.h" |
| 13 #include "core/layout/ng/ng_constraint_space.h" | 13 #include "core/layout/ng/ng_constraint_space.h" |
| 14 #include "core/layout/ng/ng_constraint_space_builder.h" | 14 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 15 #include "core/layout/ng/ng_fragment_builder.h" | 15 #include "core/layout/ng/ng_fragment_builder.h" |
| 16 #include "core/layout/ng/ng_inline_node.h" | 16 #include "core/layout/ng/ng_inline_node.h" |
| 17 #include "core/layout/ng/ng_layout_result.h" |
| 17 #include "core/layout/ng/ng_length_utils.h" | 18 #include "core/layout/ng/ng_length_utils.h" |
| 18 #include "core/layout/ng/ng_writing_mode.h" | 19 #include "core/layout/ng/ng_writing_mode.h" |
| 19 #include "core/paint/PaintLayer.h" | 20 #include "core/paint/PaintLayer.h" |
| 20 #include "platform/RuntimeEnabledFeatures.h" | 21 #include "platform/RuntimeEnabledFeatures.h" |
| 21 | 22 |
| 22 namespace blink { | 23 namespace blink { |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 // Copies data back to the legacy layout tree for a given child fragment. | 27 // Copies data back to the legacy layout tree for a given child fragment. |
| 27 void FragmentPositionUpdated(const NGPhysicalBoxFragment& box_fragment) { | 28 void FragmentPositionUpdated(const NGPhysicalFragment& fragment) { |
| 28 LayoutBox* layout_box = toLayoutBox(box_fragment.GetLayoutObject()); | 29 LayoutBox* layout_box = toLayoutBox(fragment.GetLayoutObject()); |
| 29 if (!layout_box) | 30 if (!layout_box) |
| 30 return; | 31 return; |
| 31 | 32 |
| 32 DCHECK(layout_box->parent()) << "Should be called on children only."; | 33 DCHECK(layout_box->parent()) << "Should be called on children only."; |
| 33 | 34 |
| 34 layout_box->setX(box_fragment.LeftOffset()); | 35 layout_box->setX(fragment.LeftOffset()); |
| 35 layout_box->setY(box_fragment.TopOffset()); | 36 layout_box->setY(fragment.TopOffset()); |
| 36 } | 37 } |
| 37 | 38 |
| 38 // Similar to FragmentPositionUpdated but for floats. | 39 // Similar to FragmentPositionUpdated but for floats. |
| 39 // - Updates layout object's geometric information. | 40 // - Updates layout object's geometric information. |
| 40 // - Creates legacy FloatingObject and attached it to the provided parent. | 41 // - Creates legacy FloatingObject and attached it to the provided parent. |
| 41 void FloatingObjectPositionedUpdated(NGFloatingObject* ng_floating_object, | 42 void FloatingObjectPositionedUpdated(NGFloatingObject* ng_floating_object, |
| 42 LayoutBox* parent) { | 43 LayoutBox* parent) { |
| 43 NGPhysicalBoxFragment* box_fragment = | 44 NGPhysicalBoxFragment* box_fragment = |
| 44 toNGPhysicalBoxFragment(ng_floating_object->fragment.get()); | 45 toNGPhysicalBoxFragment(ng_floating_object->fragment.get()); |
| 45 FragmentPositionUpdated(*box_fragment); | 46 FragmentPositionUpdated(*box_fragment); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 69 layout_box_(nullptr), | 70 layout_box_(nullptr), |
| 70 style_(style) { | 71 style_(style) { |
| 71 DCHECK(style_); | 72 DCHECK(style_); |
| 72 } | 73 } |
| 73 | 74 |
| 74 // Need an explicit destructor in the .cc file, or the MSWIN compiler will | 75 // Need an explicit destructor in the .cc file, or the MSWIN compiler will |
| 75 // produce an error when attempting to generate a default one, if the .h file is | 76 // produce an error when attempting to generate a default one, if the .h file is |
| 76 // included from a compilation unit that lacks the ComputedStyle definition. | 77 // included from a compilation unit that lacks the ComputedStyle definition. |
| 77 NGBlockNode::~NGBlockNode() {} | 78 NGBlockNode::~NGBlockNode() {} |
| 78 | 79 |
| 79 RefPtr<NGPhysicalFragment> NGBlockNode::Layout( | 80 RefPtr<NGLayoutResult> NGBlockNode::Layout( |
| 80 NGConstraintSpace* constraint_space) { | 81 NGConstraintSpace* constraint_space) { |
| 81 // Use the old layout code and synthesize a fragment. | 82 // Use the old layout code and synthesize a fragment. |
| 82 if (!CanUseNewLayout()) { | 83 if (!CanUseNewLayout()) { |
| 83 DCHECK(layout_box_); | 84 DCHECK(layout_box_); |
| 84 fragment_ = RunOldLayout(*constraint_space); | 85 layout_result_ = RunOldLayout(*constraint_space); |
| 85 return fragment_; | 86 return layout_result_; |
| 86 } | 87 } |
| 87 | 88 |
| 88 RefPtr<NGPhysicalFragment> fragment = | 89 layout_result_ = |
| 89 NGBlockLayoutAlgorithm(GetLayoutObject(), &Style(), FirstChild(), | 90 NGBlockLayoutAlgorithm(GetLayoutObject(), &Style(), FirstChild(), |
| 90 constraint_space, CurrentBreakToken()) | 91 constraint_space, CurrentBreakToken()) |
| 91 .Layout(); | 92 .Layout(); |
| 92 | 93 |
| 93 fragment_ = toNGPhysicalBoxFragment(fragment.get()); | |
| 94 CopyFragmentDataToLayoutBox(*constraint_space); | 94 CopyFragmentDataToLayoutBox(*constraint_space); |
| 95 return fragment_; | 95 return layout_result_; |
| 96 } | 96 } |
| 97 | 97 |
| 98 MinAndMaxContentSizes NGBlockNode::ComputeMinAndMaxContentSizes() { | 98 MinAndMaxContentSizes NGBlockNode::ComputeMinAndMaxContentSizes() { |
| 99 MinAndMaxContentSizes sizes; | 99 MinAndMaxContentSizes sizes; |
| 100 if (!CanUseNewLayout()) { | 100 if (!CanUseNewLayout()) { |
| 101 DCHECK(layout_box_); | 101 DCHECK(layout_box_); |
| 102 // TODO(layout-ng): This could be somewhat optimized by directly calling | 102 // TODO(layout-ng): This could be somewhat optimized by directly calling |
| 103 // computeIntrinsicLogicalWidths, but that function is currently private. | 103 // computeIntrinsicLogicalWidths, but that function is currently private. |
| 104 // Consider doing that if this becomes a performance issue. | 104 // Consider doing that if this becomes a performance issue. |
| 105 LayoutUnit borderAndPadding = layout_box_->borderAndPaddingLogicalWidth(); | 105 LayoutUnit borderAndPadding = layout_box_->borderAndPaddingLogicalWidth(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 122 | 122 |
| 123 // TODO(cbiesinger): For orthogonal children, we need to always synthesize. | 123 // TODO(cbiesinger): For orthogonal children, we need to always synthesize. |
| 124 NGBlockLayoutAlgorithm minmax_algorithm(layout_box_, &Style(), FirstChild(), | 124 NGBlockLayoutAlgorithm minmax_algorithm(layout_box_, &Style(), FirstChild(), |
| 125 constraint_space); | 125 constraint_space); |
| 126 Optional<MinAndMaxContentSizes> maybe_sizes = | 126 Optional<MinAndMaxContentSizes> maybe_sizes = |
| 127 minmax_algorithm.ComputeMinAndMaxContentSizes(); | 127 minmax_algorithm.ComputeMinAndMaxContentSizes(); |
| 128 if (maybe_sizes.has_value()) | 128 if (maybe_sizes.has_value()) |
| 129 return *maybe_sizes; | 129 return *maybe_sizes; |
| 130 | 130 |
| 131 // Have to synthesize this value. | 131 // Have to synthesize this value. |
| 132 RefPtr<NGPhysicalFragment> physical_fragment = Layout(constraint_space); | 132 RefPtr<NGLayoutResult> layout_result = Layout(constraint_space); |
| 133 NGPhysicalFragment* physical_fragment = |
| 134 layout_result->PhysicalFragment().get(); |
| 133 NGBoxFragment min_fragment(FromPlatformWritingMode(Style().getWritingMode()), | 135 NGBoxFragment min_fragment(FromPlatformWritingMode(Style().getWritingMode()), |
| 134 toNGPhysicalBoxFragment(physical_fragment.get())); | 136 toNGPhysicalBoxFragment(physical_fragment)); |
| 135 sizes.min_content = min_fragment.InlineOverflow(); | 137 sizes.min_content = min_fragment.InlineOverflow(); |
| 136 | 138 |
| 137 // Now, redo with infinite space for max_content | 139 // Now, redo with infinite space for max_content |
| 138 constraint_space = | 140 constraint_space = |
| 139 NGConstraintSpaceBuilder( | 141 NGConstraintSpaceBuilder( |
| 140 FromPlatformWritingMode(Style().getWritingMode())) | 142 FromPlatformWritingMode(Style().getWritingMode())) |
| 141 .SetTextDirection(Style().direction()) | 143 .SetTextDirection(Style().direction()) |
| 142 .SetAvailableSize({LayoutUnit::max(), LayoutUnit()}) | 144 .SetAvailableSize({LayoutUnit::max(), LayoutUnit()}) |
| 143 .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()}) | 145 .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()}) |
| 144 .ToConstraintSpace(FromPlatformWritingMode(Style().getWritingMode())); | 146 .ToConstraintSpace(FromPlatformWritingMode(Style().getWritingMode())); |
| 145 | 147 |
| 146 physical_fragment = Layout(constraint_space); | 148 layout_result = Layout(constraint_space); |
| 149 physical_fragment = layout_result->PhysicalFragment().get(); |
| 147 NGBoxFragment max_fragment(FromPlatformWritingMode(Style().getWritingMode()), | 150 NGBoxFragment max_fragment(FromPlatformWritingMode(Style().getWritingMode()), |
| 148 toNGPhysicalBoxFragment(physical_fragment.get())); | 151 toNGPhysicalBoxFragment(physical_fragment)); |
| 149 sizes.max_content = max_fragment.InlineOverflow(); | 152 sizes.max_content = max_fragment.InlineOverflow(); |
| 150 return sizes; | 153 return sizes; |
| 151 } | 154 } |
| 152 | 155 |
| 153 const ComputedStyle& NGBlockNode::Style() const { | 156 const ComputedStyle& NGBlockNode::Style() const { |
| 154 if (style_) | 157 if (style_) |
| 155 return *style_.get(); | 158 return *style_.get(); |
| 156 DCHECK(layout_box_); | 159 DCHECK(layout_box_); |
| 157 return layout_box_->styleRef(); | 160 return layout_box_->styleRef(); |
| 158 } | 161 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 187 | 190 |
| 188 void NGBlockNode::SetNextSibling(NGBlockNode* sibling) { | 191 void NGBlockNode::SetNextSibling(NGBlockNode* sibling) { |
| 189 next_sibling_ = sibling; | 192 next_sibling_ = sibling; |
| 190 } | 193 } |
| 191 | 194 |
| 192 void NGBlockNode::SetFirstChild(NGLayoutInputNode* child) { | 195 void NGBlockNode::SetFirstChild(NGLayoutInputNode* child) { |
| 193 first_child_ = child; | 196 first_child_ = child; |
| 194 } | 197 } |
| 195 | 198 |
| 196 NGBreakToken* NGBlockNode::CurrentBreakToken() const { | 199 NGBreakToken* NGBlockNode::CurrentBreakToken() const { |
| 197 return fragment_ ? fragment_->BreakToken() : nullptr; | 200 return layout_result_ ? layout_result_->PhysicalFragment()->BreakToken() |
| 201 : nullptr; |
| 198 } | 202 } |
| 199 | 203 |
| 200 DEFINE_TRACE(NGBlockNode) { | 204 DEFINE_TRACE(NGBlockNode) { |
| 201 visitor->trace(next_sibling_); | 205 visitor->trace(next_sibling_); |
| 202 visitor->trace(first_child_); | 206 visitor->trace(first_child_); |
| 203 NGLayoutInputNode::trace(visitor); | 207 NGLayoutInputNode::trace(visitor); |
| 204 } | 208 } |
| 205 | 209 |
| 206 bool NGBlockNode::CanUseNewLayout() { | 210 bool NGBlockNode::CanUseNewLayout() { |
| 207 if (!layout_box_) | 211 if (!layout_box_) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 228 | 232 |
| 229 return false; | 233 return false; |
| 230 } | 234 } |
| 231 | 235 |
| 232 void NGBlockNode::CopyFragmentDataToLayoutBox( | 236 void NGBlockNode::CopyFragmentDataToLayoutBox( |
| 233 const NGConstraintSpace& constraint_space) { | 237 const NGConstraintSpace& constraint_space) { |
| 234 // We may not have a layout_box_ during unit tests. | 238 // We may not have a layout_box_ during unit tests. |
| 235 if (!layout_box_) | 239 if (!layout_box_) |
| 236 return; | 240 return; |
| 237 | 241 |
| 238 layout_box_->setWidth(fragment_->Width()); | 242 NGPhysicalBoxFragment* fragment = |
| 239 layout_box_->setHeight(fragment_->Height()); | 243 toNGPhysicalBoxFragment(layout_result_->PhysicalFragment().get()); |
| 244 |
| 245 layout_box_->setWidth(fragment->Width()); |
| 246 layout_box_->setHeight(fragment->Height()); |
| 240 NGBoxStrut border_and_padding = | 247 NGBoxStrut border_and_padding = |
| 241 ComputeBorders(Style()) + ComputePadding(constraint_space, Style()); | 248 ComputeBorders(Style()) + ComputePadding(constraint_space, Style()); |
| 242 LayoutUnit intrinsic_logical_height = | 249 LayoutUnit intrinsic_logical_height = |
| 243 layout_box_->style()->isHorizontalWritingMode() | 250 layout_box_->style()->isHorizontalWritingMode() |
| 244 ? fragment_->HeightOverflow() | 251 ? fragment->HeightOverflow() |
| 245 : fragment_->WidthOverflow(); | 252 : fragment->WidthOverflow(); |
| 246 intrinsic_logical_height -= border_and_padding.BlockSum(); | 253 intrinsic_logical_height -= border_and_padding.BlockSum(); |
| 247 layout_box_->setIntrinsicContentLogicalHeight(intrinsic_logical_height); | 254 layout_box_->setIntrinsicContentLogicalHeight(intrinsic_logical_height); |
| 248 | 255 |
| 249 // TODO(layout-dev): Currently we are not actually performing layout on | 256 // TODO(layout-dev): Currently we are not actually performing layout on |
| 250 // inline children. For now just clear the needsLayout bit so that we can | 257 // inline children. For now just clear the needsLayout bit so that we can |
| 251 // run unittests. | 258 // run unittests. |
| 252 if (HasInlineChildren()) { | 259 if (HasInlineChildren()) { |
| 253 for (InlineWalker walker( | 260 for (InlineWalker walker( |
| 254 LineLayoutBlockFlow(toLayoutBlockFlow(layout_box_))); | 261 LineLayoutBlockFlow(toLayoutBlockFlow(layout_box_))); |
| 255 !walker.atEnd(); walker.advance()) { | 262 !walker.atEnd(); walker.advance()) { |
| 256 LayoutObject* o = LineLayoutAPIShim::layoutObjectFrom(walker.current()); | 263 LayoutObject* o = LineLayoutAPIShim::layoutObjectFrom(walker.current()); |
| 257 o->clearNeedsLayout(); | 264 o->clearNeedsLayout(); |
| 258 } | 265 } |
| 259 | 266 |
| 260 // Ensure the position of the children are copied across to the | 267 // Ensure the position of the children are copied across to the |
| 261 // LayoutObject tree. | 268 // LayoutObject tree. |
| 262 } else { | 269 } else { |
| 263 for (const auto& child_fragment : fragment_->Children()) { | 270 for (const auto& child_fragment : fragment->Children()) { |
| 264 if (child_fragment->IsPlaced()) | 271 if (child_fragment->IsPlaced()) |
| 265 FragmentPositionUpdated(toNGPhysicalBoxFragment(*child_fragment)); | 272 FragmentPositionUpdated(toNGPhysicalBoxFragment(*child_fragment)); |
| 266 | 273 |
| 267 for (const auto& floating_object : child_fragment->PositionedFloats()) { | 274 for (const auto& floating_object : |
| 275 toNGPhysicalBoxFragment(child_fragment.get())->PositionedFloats()) { |
| 268 FloatingObjectPositionedUpdated(floating_object, layout_box_); | 276 FloatingObjectPositionedUpdated(floating_object, layout_box_); |
| 269 } | 277 } |
| 270 } | 278 } |
| 271 } | 279 } |
| 272 | 280 |
| 273 if (layout_box_->isLayoutBlock()) | 281 if (layout_box_->isLayoutBlock()) |
| 274 toLayoutBlock(layout_box_)->layoutPositionedObjects(true); | 282 toLayoutBlock(layout_box_)->layoutPositionedObjects(true); |
| 275 layout_box_->clearNeedsLayout(); | 283 layout_box_->clearNeedsLayout(); |
| 276 if (layout_box_->isLayoutBlockFlow()) { | 284 if (layout_box_->isLayoutBlockFlow()) { |
| 277 toLayoutBlockFlow(layout_box_)->updateIsSelfCollapsing(); | 285 toLayoutBlockFlow(layout_box_)->updateIsSelfCollapsing(); |
| 278 } | 286 } |
| 279 } | 287 } |
| 280 | 288 |
| 281 RefPtr<NGPhysicalBoxFragment> NGBlockNode::RunOldLayout( | 289 RefPtr<NGLayoutResult> NGBlockNode::RunOldLayout( |
| 282 const NGConstraintSpace& constraint_space) { | 290 const NGConstraintSpace& constraint_space) { |
| 283 NGLogicalSize available_size = constraint_space.PercentageResolutionSize(); | 291 NGLogicalSize available_size = constraint_space.PercentageResolutionSize(); |
| 284 layout_box_->setOverrideContainingBlockContentLogicalWidth( | 292 layout_box_->setOverrideContainingBlockContentLogicalWidth( |
| 285 available_size.inline_size); | 293 available_size.inline_size); |
| 286 layout_box_->setOverrideContainingBlockContentLogicalHeight( | 294 layout_box_->setOverrideContainingBlockContentLogicalHeight( |
| 287 available_size.block_size); | 295 available_size.block_size); |
| 288 // TODO(layout-ng): Does this handle scrollbars correctly? | 296 // TODO(layout-ng): Does this handle scrollbars correctly? |
| 289 if (constraint_space.IsFixedSizeInline()) { | 297 if (constraint_space.IsFixedSizeInline()) { |
| 290 layout_box_->setOverrideLogicalContentWidth( | 298 layout_box_->setOverrideLogicalContentWidth( |
| 291 constraint_space.AvailableSize().inline_size - | 299 constraint_space.AvailableSize().inline_size - |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 // Save static position for legacy AbsPos layout. | 333 // Save static position for legacy AbsPos layout. |
| 326 void NGBlockNode::SaveStaticOffsetForLegacy(const NGLogicalOffset& offset) { | 334 void NGBlockNode::SaveStaticOffsetForLegacy(const NGLogicalOffset& offset) { |
| 327 DCHECK(layout_box_); | 335 DCHECK(layout_box_); |
| 328 DCHECK(layout_box_->isOutOfFlowPositioned()); | 336 DCHECK(layout_box_->isOutOfFlowPositioned()); |
| 329 DCHECK(layout_box_->layer()); | 337 DCHECK(layout_box_->layer()); |
| 330 layout_box_->layer()->setStaticBlockPosition(offset.block_offset); | 338 layout_box_->layer()->setStaticBlockPosition(offset.block_offset); |
| 331 layout_box_->layer()->setStaticInlinePosition(offset.inline_offset); | 339 layout_box_->layer()->setStaticInlinePosition(offset.inline_offset); |
| 332 } | 340 } |
| 333 | 341 |
| 334 } // namespace blink | 342 } // namespace blink |
| OLD | NEW |