Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc |
| diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ec503ba1aac09d3ee709fe80fd0bf0eacffdcb5e |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc |
| @@ -0,0 +1,169 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/layout/ng/ng_out_of_flow_layout_part.h" |
| + |
| +#include "core/layout/ng/ng_absolute_utils.h" |
| +#include "core/layout/ng/ng_block_node.h" |
| +#include "core/layout/ng/ng_constraint_space_builder.h" |
| +#include "core/layout/ng/ng_fragment_base.h" |
| +#include "core/layout/ng/ng_length_utils.h" |
| +#include "core/style/ComputedStyle.h" |
| + |
| +namespace blink { |
| + |
| +NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
| + PassRefPtr<const ComputedStyle> container_style, |
| + NGLogicalSize container_size) { |
| + contains_fixed_ = container_style->canContainFixedPositionObjects(); |
| + contains_absolute_ = |
| + container_style->canContainAbsolutePositionObjects() || contains_fixed_; |
| + // Initialize ConstraintSpace |
| + NGLogicalSize space_size = container_size; |
| + NGBoxStrut borders = ComputeBorders(*container_style); |
| + space_size.block_size -= borders.BlockSum(); |
| + space_size.inline_size -= borders.InlineSum(); |
| + parent_offset_ = NGLogicalOffset{borders.inline_start, borders.block_start}; |
| + parent_physical_offset_ = parent_offset_.ConvertToPhysical( |
| + FromPlatformWritingMode(container_style->getWritingMode()), |
| + container_style->direction(), |
| + container_size.ConvertToPhysical( |
| + FromPlatformWritingMode(container_style->getWritingMode())), |
| + NGPhysicalSize()); |
| + NGConstraintSpaceBuilder space_builder( |
| + FromPlatformWritingMode(container_style->getWritingMode())); |
| + space_builder.SetAvailableSize(space_size); |
| + space_builder.SetIsNewFormattingContext(true); |
| + space_builder.SetTextDirection(container_style->direction()); |
| + parent_space_ = space_builder.ToConstraintSpace(); |
| +} |
| + |
| +bool NGOutOfFlowLayoutPart::StartLayout( |
| + NGBlockNode* node, |
| + const NGStaticPosition& static_position) { |
| + EPosition position = node->Style()->position(); |
| + if ((contains_absolute_ && position == AbsolutePosition) || |
| + (contains_fixed_ && position == FixedPosition)) { |
| + node_ = node; |
| + static_position_ = static_position; |
| + // Adjust static_position origin. static_position coordinate origin is |
| + // border_box, absolute position coordinate origin is padding box. |
| + static_position_.offset -= parent_physical_offset_; |
| + node_fragment_ = nullptr; |
| + node_position_ = NGAbsolutePhysicalPosition(); |
| + inline_estimate_.reset(); |
| + block_estimate_.reset(); |
| + state_ = kComputeInlineEstimate; |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +NGLayoutStatus NGOutOfFlowLayoutPart::Layout(NGFragmentBase** fragment, |
| + NGLogicalOffset* offset) { |
| + DCHECK(node_); |
| + switch (state_) { |
| + case kComputeInlineEstimate: |
| + if (ComputeInlineSizeEstimate()) |
| + state_ = kPartialPosition; |
| + break; |
| + case kPartialPosition: |
| + node_position_ = ComputePartialAbsoluteWithChildInlineSize( |
| + *parent_space_, *node_->Style(), static_position_, inline_estimate_); |
| + state_ = kComputeBlockEstimate; |
| + break; |
| + case kComputeBlockEstimate: |
| + if (ComputeBlockSizeEstimate()) |
| + state_ = kFullPosition; |
| + break; |
| + case kFullPosition: |
| + ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node_->Style(), |
| + static_position_, block_estimate_, |
| + &node_position_); |
| + state_ = kGenerateFragment; |
| + break; |
| + case kGenerateFragment: |
| + block_estimate_ = |
| + node_position_.size.ConvertToLogical(parent_space_->WritingMode()) |
| + .block_size; |
| + if (!ComputeNodeFragment()) |
| + return kNotFinished; |
| + state_ = kDone; |
| + break; |
| + case kDone: |
| + *fragment = node_fragment_; |
| + // Compute offset |
| + NGBoxStrut inset = node_position_.inset.ConvertToLogical( |
| + parent_space_->WritingMode(), parent_space_->Direction()); |
| + offset->inline_offset = inset.inline_start + parent_offset_.inline_offset; |
| + offset->block_offset = inset.block_start + parent_offset_.block_offset; |
| + return kNewFragment; |
| + } |
| + return kNotFinished; |
| +} |
| + |
| +bool NGOutOfFlowLayoutPart::ComputeInlineSizeEstimate() { |
| + if (AbsoluteNeedsChildInlineSize(*node_->Style())) { |
| + MinAndMaxContentSizes size; |
| + if (node_->ComputeMinAndMaxContentSizes(&size)) { |
| + inline_estimate_ = |
| + size.ShrinkToFit(parent_space_->AvailableSize().inline_size); |
| + return true; |
| + } |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool NGOutOfFlowLayoutPart::ComputeBlockSizeEstimate() { |
| + if (AbsoluteNeedsChildBlockSize(*node_->Style())) { |
| + if (ComputeNodeFragment()) { |
| + block_estimate_ = node_fragment_->BlockSize(); |
| + return true; |
| + } |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool NGOutOfFlowLayoutPart::ComputeNodeFragment() { |
| + if (node_fragment_) |
| + return true; |
| + if (!node_space_) { |
| + NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); |
| + LayoutUnit inline_width = |
| + node_position_.size.ConvertToLogical(parent_space_->WritingMode()) |
| + .inline_size; |
| + // Node fragment is computed in one of these two scenarios: |
| + // 1. To estimate block size |
| + // In this case, available block_size is parent's size. |
| + // 2. To compute final block fragment, when block size is known. |
| + |
| + NGLogicalSize available_size = |
| + NGLogicalSize(inline_width, parent_space_->AvailableSize().block_size); |
| + if (block_estimate_) |
|
atotic
2016/12/28 20:35:16
I was wrong. block_estimate is needed here because
cbiesinger
2017/01/04 00:13:16
I misread the code, I think. We set block_estimate
atotic
2017/01/04 01:34:35
ack.
|
| + available_size.block_size = *block_estimate_; |
| + builder.SetAvailableSize(available_size); |
| + builder.SetPercentageResolutionSize(available_size); |
| + if (block_estimate_) |
| + builder.SetIsFixedSizeBlock(true); |
| + builder.SetIsFixedSizeInline(true); |
| + builder.SetIsNewFormattingContext(true); |
| + node_space_ = builder.ToConstraintSpace(); |
| + } |
| + NGFragmentBase* fragment; |
| + if (node_->Layout(node_space_, &fragment)) { |
| + node_fragment_ = fragment; |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +DEFINE_TRACE(NGOutOfFlowLayoutPart) { |
| + visitor->trace(node_); |
| + visitor->trace(parent_space_); |
| + visitor->trace(node_fragment_); |
| + visitor->trace(node_space_); |
| +} |
| +} |