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 |
index cb2e90637d8304842522e37722d97e4acedd59b7..87f50db71f3cccf3cf269c56f825fa15243c75cd 100644 |
--- 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 |
@@ -9,26 +9,47 @@ |
#include "core/layout/ng/ng_box_fragment.h" |
#include "core/layout/ng/ng_constraint_space_builder.h" |
#include "core/layout/ng/ng_fragment.h" |
+#include "core/layout/ng/ng_fragment_builder.h" |
#include "core/layout/ng/ng_length_utils.h" |
#include "core/layout/ng/ng_physical_fragment.h" |
#include "core/style/ComputedStyle.h" |
namespace blink { |
+namespace { |
+ |
+// True if the container will contain an absolute descendant. |
+bool IsContainingBlockForAbsoluteDescendant( |
+ const ComputedStyle& container_style, |
+ const ComputedStyle& descendant_style) { |
+ EPosition position = descendant_style.position(); |
+ bool contains_fixed = container_style.canContainFixedPositionObjects(); |
+ bool contains_absolute = |
+ container_style.canContainAbsolutePositionObjects() || contains_fixed; |
+ |
+ return (contains_absolute && position == AbsolutePosition) || |
+ (contains_fixed && position == FixedPosition); |
+} |
+ |
+} // namespace |
+ |
NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
- PassRefPtr<const ComputedStyle> container_style, |
- NGLogicalSize container_size) { |
+ const ComputedStyle& container_style, |
+ NGFragmentBuilder* container_builder) |
+ : container_style_(container_style), container_builder_(container_builder) { |
NGWritingMode writing_mode( |
- FromPlatformWritingMode(container_style->getWritingMode())); |
+ FromPlatformWritingMode(container_style_.getWritingMode())); |
- NGBoxStrut borders = ComputeBorders(*container_style); |
- parent_border_offset_ = |
+ NGBoxStrut borders = ComputeBorders(container_style_); |
+ container_border_offset_ = |
NGLogicalOffset{borders.inline_start, borders.block_start}; |
- parent_border_physical_offset_ = parent_border_offset_.ConvertToPhysical( |
- writing_mode, container_style->direction(), |
- container_size.ConvertToPhysical(writing_mode), NGPhysicalSize()); |
+ container_border_physical_offset_ = |
+ container_border_offset_.ConvertToPhysical( |
+ writing_mode, container_style_.direction(), |
+ container_builder_->Size().ConvertToPhysical(writing_mode), |
+ NGPhysicalSize()); |
- NGLogicalSize space_size = container_size; |
+ NGLogicalSize space_size = container_builder_->Size(); |
space_size.block_size -= borders.BlockSum(); |
space_size.inline_size -= borders.InlineSum(); |
@@ -37,96 +58,119 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( |
space_builder.SetAvailableSize(space_size); |
space_builder.SetPercentageResolutionSize(space_size); |
space_builder.SetIsNewFormattingContext(true); |
- space_builder.SetTextDirection(container_style->direction()); |
- parent_space_ = space_builder.ToConstraintSpace(); |
+ space_builder.SetTextDirection(container_style_.direction()); |
+ container_space_ = space_builder.ToConstraintSpace(); |
+} |
+ |
+void NGOutOfFlowLayoutPart::Run() { |
+ HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; |
+ Vector<NGStaticPosition> out_of_flow_candidate_positions; |
+ container_builder_->GetAndClearOutOfFlowDescendantCandidates( |
+ &out_of_flow_candidates, &out_of_flow_candidate_positions); |
+ |
+ size_t position_index = 0; |
+ |
+ for (auto& descendant : out_of_flow_candidates) { |
+ NGStaticPosition static_position = |
+ out_of_flow_candidate_positions[position_index++]; |
+ |
+ if (IsContainingBlockForAbsoluteDescendant(container_style_, |
+ *descendant->Style())) { |
+ NGLogicalOffset offset; |
+ NGFragment* fragment = |
+ LayoutDescendant(*descendant, static_position, &offset); |
+ // TODO(atotic) Need to adjust size of overflow rect per spec. |
+ container_builder_->AddChild(fragment, offset); |
+ } else { |
+ container_builder_->AddOutOfFlowDescendant(descendant, static_position); |
+ } |
+ } |
} |
-void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, |
- NGStaticPosition static_position, |
- NGFragment** fragment_out, |
- NGLogicalOffset* offset) { |
+NGFragment* NGOutOfFlowLayoutPart::LayoutDescendant( |
+ NGBlockNode& descendant, |
+ NGStaticPosition static_position, |
+ NGLogicalOffset* offset) { |
// Adjust the static_position origin. The static_position coordinate origin is |
- // relative to the parent's border box, ng_absolute_utils expects it to be |
- // relative to the parent's padding box. |
- static_position.offset -= parent_border_physical_offset_; |
+ // relative to the container's border box, ng_absolute_utils expects it to be |
+ // relative to the container's padding box. |
+ static_position.offset -= container_border_physical_offset_; |
NGFragment* fragment = nullptr; |
Optional<MinAndMaxContentSizes> inline_estimate; |
Optional<LayoutUnit> block_estimate; |
- if (AbsoluteNeedsChildInlineSize(*node.Style())) { |
- inline_estimate = node.ComputeMinAndMaxContentSizesSync(); |
+ if (AbsoluteNeedsChildInlineSize(*descendant.Style())) { |
+ inline_estimate = descendant.ComputeMinAndMaxContentSizesSync(); |
} |
NGAbsolutePhysicalPosition node_position = |
ComputePartialAbsoluteWithChildInlineSize( |
- *parent_space_, *node.Style(), static_position, inline_estimate); |
+ *container_space_, *descendant.Style(), static_position, |
+ inline_estimate); |
- if (AbsoluteNeedsChildBlockSize(*node.Style())) { |
- fragment = GenerateFragment(node, block_estimate, node_position); |
+ if (AbsoluteNeedsChildBlockSize(*descendant.Style())) { |
+ fragment = GenerateFragment(descendant, block_estimate, node_position); |
block_estimate = fragment->BlockSize(); |
} |
- ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), |
+ ComputeFullAbsoluteWithChildBlockSize(*container_space_, *descendant.Style(), |
static_position, block_estimate, |
&node_position); |
// Skip this step if we produced a fragment when estimating the block size. |
if (!fragment) { |
block_estimate = |
- node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
+ node_position.size.ConvertToLogical(container_space_->WritingMode()) |
.block_size; |
- fragment = GenerateFragment(node, block_estimate, node_position); |
+ fragment = GenerateFragment(descendant, block_estimate, node_position); |
} |
- *fragment_out = fragment; |
- |
// Compute logical offset, NGAbsolutePhysicalPosition is calculated relative |
- // to the padding box so add back the parent's borders. |
+ // to the padding box so add back the container's borders. |
NGBoxStrut inset = node_position.inset.ConvertToLogical( |
- parent_space_->WritingMode(), parent_space_->Direction()); |
+ container_space_->WritingMode(), container_space_->Direction()); |
offset->inline_offset = |
- inset.inline_start + parent_border_offset_.inline_offset; |
- offset->block_offset = inset.block_start + parent_border_offset_.block_offset; |
+ inset.inline_start + container_border_offset_.inline_offset; |
+ offset->block_offset = |
+ inset.block_start + container_border_offset_.block_offset; |
+ |
+ return fragment; |
} |
NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( |
- NGBlockNode& node, |
+ NGBlockNode& descendant, |
const Optional<LayoutUnit>& block_estimate, |
const NGAbsolutePhysicalPosition node_position) { |
// The fragment is generated in one of these two scenarios: |
- // 1. To estimate child's block size, in this case block_size is parent's |
- // available size. |
+ // 1. To estimate descendant's block size, in this case block_size is |
+ // container's available size. |
// 2. To compute final fragment, when block size is known from the absolute |
// position calculation. |
LayoutUnit inline_size = |
- node_position.size.ConvertToLogical(parent_space_->WritingMode()) |
+ node_position.size.ConvertToLogical(container_space_->WritingMode()) |
.inline_size; |
LayoutUnit block_size = block_estimate |
? *block_estimate |
- : parent_space_->AvailableSize().block_size; |
+ : container_space_->AvailableSize().block_size; |
NGLogicalSize available_size{inline_size, block_size}; |
- NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); |
+ NGConstraintSpaceBuilder builder(container_space_->WritingMode()); |
builder.SetAvailableSize(available_size); |
- builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); |
+ builder.SetPercentageResolutionSize(container_space_->AvailableSize()); |
if (block_estimate) |
builder.SetIsFixedSizeBlock(true); |
builder.SetIsFixedSizeInline(true); |
builder.SetIsNewFormattingContext(true); |
NGConstraintSpace* space = builder.ToConstraintSpace(); |
- NGPhysicalFragment* fragment = node.Layout(space); |
+ NGPhysicalFragment* fragment = descendant.Layout(space); |
// TODO(ikilpatrick): the writing mode switching here looks wrong. |
- return new NGBoxFragment(parent_space_->WritingMode(), |
- parent_space_->Direction(), |
+ return new NGBoxFragment(container_space_->WritingMode(), |
+ container_space_->Direction(), |
toNGPhysicalBoxFragment(fragment)); |
} |
-DEFINE_TRACE(NGOutOfFlowLayoutPart) { |
- visitor->trace(parent_space_); |
-} |
- |
} // namespace blink |