summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc204
1 files changed, 113 insertions, 91 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index 39f44dbe3bb..e62ccbc378e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -7,48 +7,61 @@
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/text/writing_mode.h"
namespace blink {
+namespace {
+// This routine returns true if inline_container should replace descendant's
+// inline container.
+bool IsInlineContainerForDescendant(
+ const NGOutOfFlowPositionedDescendant& descendant,
+ const LayoutObject* inline_container) {
+ return !descendant.inline_container && inline_container &&
+ inline_container->IsLayoutInline() &&
+ inline_container->CanContainOutOfFlowPositionedElement(
+ descendant.node.Style().GetPosition());
+}
+} // namespace
+
NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
- const NGLayoutResult& child,
- const NGLogicalOffset& child_offset) {
+ const NGPhysicalContainerFragment& child,
+ const LogicalOffset& child_offset,
+ const LayoutInline* inline_container) {
// Collect the child's out of flow descendants.
// child_offset is offset of inline_start/block_start vertex.
// Candidates need offset of top/left vertex.
- const auto& out_of_flow_descendants = child.OutOfFlowPositionedDescendants();
- if (!out_of_flow_descendants.IsEmpty()) {
- NGLogicalOffset top_left_offset;
- NGPhysicalSize child_size = child.PhysicalFragment()->Size();
+ if (child.HasOutOfFlowPositionedDescendants()) {
+ const auto& out_of_flow_descendants =
+ child.OutOfFlowPositionedDescendants();
+ LogicalOffset top_left_offset;
+ PhysicalSize child_size = child.Size();
switch (GetWritingMode()) {
case WritingMode::kHorizontalTb:
top_left_offset =
(IsRtl(Direction()))
- ? NGLogicalOffset{child_offset.inline_offset + child_size.width,
- child_offset.block_offset}
+ ? LogicalOffset{child_offset.inline_offset + child_size.width,
+ child_offset.block_offset}
: child_offset;
break;
case WritingMode::kVerticalRl:
case WritingMode::kSidewaysRl:
top_left_offset =
(IsRtl(Direction()))
- ? NGLogicalOffset{child_offset.inline_offset +
- child_size.height,
- child_offset.block_offset + child_size.width}
- : NGLogicalOffset{child_offset.inline_offset,
- child_offset.block_offset + child_size.width};
+ ? LogicalOffset{child_offset.inline_offset + child_size.height,
+ child_offset.block_offset + child_size.width}
+ : LogicalOffset{child_offset.inline_offset,
+ child_offset.block_offset + child_size.width};
break;
case WritingMode::kVerticalLr:
case WritingMode::kSidewaysLr:
- top_left_offset = (IsRtl(Direction()))
- ? NGLogicalOffset{child_offset.inline_offset +
- child_size.height,
- child_offset.block_offset}
- : child_offset;
+ top_left_offset =
+ (IsRtl(Direction()))
+ ? LogicalOffset{child_offset.inline_offset + child_size.height,
+ child_offset.block_offset}
+ : child_offset;
break;
}
@@ -62,44 +75,62 @@ NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
// </div>
// TODO(layout-dev): This code should eventually be removed once we handle
// relative positioned objects directly in the fragment tree.
- if (LayoutBox* child_box =
- ToLayoutBoxOrNull(child.PhysicalFragment()->GetLayoutObject())) {
- top_left_offset +=
- NGPhysicalOffset(child_box->OffsetForInFlowPosition())
- .ConvertToLogical(GetWritingMode(), Direction(), NGPhysicalSize(),
- NGPhysicalSize());
+ if (const LayoutBox* child_box =
+ ToLayoutBoxOrNull(child.GetLayoutObject())) {
+ top_left_offset += PhysicalOffset(child_box->OffsetForInFlowPosition())
+ .ConvertToLogical(GetWritingMode(), Direction(),
+ PhysicalSize(), PhysicalSize());
}
- for (const NGOutOfFlowPositionedDescendant& descendant :
+ for (NGOutOfFlowPositionedDescendant& descendant :
out_of_flow_descendants) {
+ if (IsInlineContainerForDescendant(descendant, inline_container)) {
+ descendant.inline_container = inline_container;
+ }
oof_positioned_candidates_.push_back(
NGOutOfFlowPositionedCandidate(descendant, top_left_offset));
}
}
- if (child.HasOrthogonalFlowRoots())
+ // For the |has_orthogonal_flow_roots_| flag, we don't care about the type of
+ // child (OOF-positioned, etc), it is for *any* descendant.
+ if (child.HasOrthogonalFlowRoots() ||
+ !IsParallelWritingMode(child.Style().GetWritingMode(),
+ Style().GetWritingMode()))
has_orthogonal_flow_roots_ = true;
// We only need to report if inflow or floating elements depend on the
// percentage resolution block-size. OOF-positioned children resolve their
// percentages against the "final" size of their parent.
- if (child.DependsOnPercentageBlockSize() &&
- !child.PhysicalFragment()->IsOutOfFlowPositioned())
- has_child_that_depends_on_percentage_block_size_ = true;
-
- if (child.MayHaveDescendantAboveBlockStart() &&
- !child.PhysicalFragment()->IsBlockFormattingContextRoot())
+ if (child.DependsOnPercentageBlockSize() && !child.IsOutOfFlowPositioned())
+ has_descendant_that_depends_on_percentage_block_size_ = true;
+
+ // The |may_have_descendant_above_block_start_| flag is used to determine if
+ // a fragment can be re-used when floats are present. We only are about:
+ // - Inflow children who are positioned above our block-start edge.
+ // - Any inflow descendants (within the same formatting-context) that *may*
+ // be positioned above our block-start edge.
+ if ((child_offset.block_offset < LayoutUnit() &&
+ !child.IsOutOfFlowPositioned()) ||
+ (!child.IsBlockFormattingContextRoot() &&
+ child.MayHaveDescendantAboveBlockStart()))
may_have_descendant_above_block_start_ = true;
- return AddChild(child.PhysicalFragment(), child_offset);
-}
+ // Compute |has_floating_descendants_| to optimize tree traversal in paint.
+ if (!has_floating_descendants_) {
+ if (child.IsFloating()) {
+ has_floating_descendants_ = true;
+ } else {
+ if (!child.IsBlockFormattingContextRoot() &&
+ child.HasFloatingDescendants())
+ has_floating_descendants_ = true;
+ }
+ }
-NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
- scoped_refptr<const NGPhysicalFragment> child,
- const NGLogicalOffset& child_offset) {
- NGBreakToken* child_break_token = child->BreakToken();
+ // Collect any (block) break tokens.
+ NGBreakToken* child_break_token = child.BreakToken();
if (child_break_token && has_block_fragmentation_) {
- switch (child->Type()) {
+ switch (child.Type()) {
case NGPhysicalFragment::kFragmentBox:
case NGPhysicalFragment::kFragmentRenderedLegend:
if (To<NGBlockBreakToken>(child_break_token)->HasLastResortBreak())
@@ -119,61 +150,54 @@ NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
}
}
- // Compute |has_floating_descendants_| to optimize tree traversal in paint.
- if (!has_floating_descendants_) {
- if (child->IsFloating()) {
- has_floating_descendants_ = true;
- } else {
- auto* child_container = DynamicTo<NGPhysicalContainerFragment>(*child);
- if (child_container && !child->IsBlockFormattingContextRoot() &&
- child_container->HasFloatingDescendants())
- has_floating_descendants_ = true;
- }
- }
-
- if (child_offset.block_offset < LayoutUnit())
- may_have_descendant_above_block_start_ = true;
+ AddChildInternal(&child, child_offset);
+ return *this;
+}
- if (!IsParallelWritingMode(child->Style().GetWritingMode(),
- Style().GetWritingMode()))
- has_orthogonal_flow_roots_ = true;
+void NGContainerFragmentBuilder::AddChildInternal(
+ scoped_refptr<const NGPhysicalFragment> child,
+ const LogicalOffset& child_offset) {
+ // In order to know where list-markers are within the children list (for the
+ // |NGSimplifiedLayoutAlgorithm|) we always place them as the first child.
+ if (child->IsListMarker()) {
+ children_.push_front(ChildWithOffset(child_offset, std::move(child)));
+ return;
+ }
- children_.emplace_back(std::move(child));
- offsets_.push_back(child_offset);
- return *this;
+ children_.emplace_back(child_offset, std::move(child));
}
-NGLogicalOffset NGContainerFragmentBuilder::GetChildOffset(
- const LayoutObject* child) const {
- for (wtf_size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->GetLayoutObject() == child)
- return offsets_[i];
+LogicalOffset NGContainerFragmentBuilder::GetChildOffset(
+ const LayoutObject* object) const {
+ for (const auto& child : children_) {
+ if (child.fragment->GetLayoutObject() == object)
+ return child.offset;
// TODO(layout-dev): ikilpatrick thinks we may need to traverse
// further than the initial line-box children for a nested inline
// container. We could not come up with a testcase, it would be
// something with split inlines, and nested oof/fixed descendants maybe.
- if (children_[i]->IsLineBox()) {
+ if (child.fragment->IsLineBox()) {
const auto& line_box_fragment =
- To<NGPhysicalLineBoxFragment>(*children_[i]);
+ To<NGPhysicalLineBoxFragment>(*child.fragment);
for (const auto& line_box_child : line_box_fragment.Children()) {
- if (line_box_child->GetLayoutObject() == child) {
- return offsets_[i] + line_box_child.Offset().ConvertToLogical(
- GetWritingMode(), Direction(),
- line_box_fragment.Size(),
- line_box_child->Size());
+ if (line_box_child->GetLayoutObject() == object) {
+ return child.offset + line_box_child.Offset().ConvertToLogical(
+ GetWritingMode(), Direction(),
+ line_box_fragment.Size(),
+ line_box_child->Size());
}
}
}
}
NOTREACHED();
- return NGLogicalOffset();
+ return LogicalOffset();
}
NGContainerFragmentBuilder&
NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
NGBlockNode child,
- const NGLogicalOffset& child_offset,
+ const LogicalOffset& child_offset,
base::Optional<TextDirection> container_direction) {
DCHECK(child);
DCHECK(layout_object_ && !layout_object_->IsLayoutInline() ||
@@ -188,7 +212,7 @@ NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
oof_positioned_candidates_.push_back(NGOutOfFlowPositionedCandidate(
NGOutOfFlowPositionedDescendant(
child, NGStaticPosition::Create(GetWritingMode(), direction,
- NGPhysicalOffset())),
+ PhysicalOffset())),
child_offset));
return *this;
@@ -212,12 +236,11 @@ void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
DCHECK_GE(InlineSize(), LayoutUnit());
DCHECK_GE(BlockSize(), LayoutUnit());
- NGPhysicalSize builder_physical_size =
- ToNGPhysicalSize(Size(), GetWritingMode());
+ PhysicalSize builder_physical_size = ToPhysicalSize(Size(), GetWritingMode());
for (NGOutOfFlowPositionedCandidate& candidate : oof_positioned_candidates_) {
- NGPhysicalOffset child_offset = candidate.child_offset.ConvertToPhysical(
- GetWritingMode(), Direction(), builder_physical_size, NGPhysicalSize());
+ PhysicalOffset child_offset = candidate.child_offset.ConvertToPhysical(
+ GetWritingMode(), Direction(), builder_physical_size, PhysicalSize());
NGStaticPosition builder_relative_position;
builder_relative_position.type = candidate.descendant.static_position.type;
@@ -230,21 +253,20 @@ void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
//
// This checks if the object creating this box will be the container for
// the given descendant.
- const LayoutObject* inline_container =
+ const LayoutInline* inline_container =
candidate.descendant.inline_container;
- if (!inline_container && layout_object_ &&
- layout_object_->IsLayoutInline() &&
- layout_object_->CanContainOutOfFlowPositionedElement(
- candidate.descendant.node.Style().GetPosition()))
- inline_container = layout_object_;
-
+ if (IsInlineContainerForDescendant(candidate.descendant, layout_object_)) {
+ inline_container = ToLayoutInline(layout_object_);
+ }
descendant_candidates->push_back(NGOutOfFlowPositionedDescendant(
candidate.descendant.node, builder_relative_position,
- inline_container));
- NGLogicalOffset container_offset =
+ inline_container ? ToLayoutInline(inline_container->ContinuationRoot())
+ : nullptr));
+
+ LogicalOffset container_offset =
builder_relative_position.offset.ConvertToLogical(
GetWritingMode(), Direction(), builder_physical_size,
- NGPhysicalSize());
+ PhysicalSize());
candidate.descendant.node.SaveStaticOffsetForLegacy(container_offset,
current_container);
}
@@ -259,7 +281,7 @@ void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
oof_positioned_candidates_.Shrink(0);
}
-#ifndef NDEBUG
+#if DCHECK_IS_ON()
String NGContainerFragmentBuilder::ToString() const {
StringBuilder builder;
@@ -267,7 +289,7 @@ String NGContainerFragmentBuilder::ToString() const {
InlineSize().ToFloat(), BlockSize().ToFloat(),
children_.size());
for (auto& child : children_) {
- builder.Append(child->DumpFragmentTree(
+ builder.Append(child.fragment->DumpFragmentTree(
NGPhysicalFragment::DumpAll & ~NGPhysicalFragment::DumpHeaderText));
}
return builder.ToString();