| 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
|
|
|