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_) |
+ 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_); |
+} |
+} |