Commit 1f132c9c authored by Ian Kilpatrick's avatar Ian Kilpatrick Committed by Commit Bot

[LayoutNG] Simplify determining the inline OOF container.

This went through a couple of simplifying revisions, however this now
simplifies where we calculate if an inline level box can contain
something that is out of flow.

There is also a couple of small fixups left over when I was simplifying
this code.

Bug: 636993
Change-Id: I5b660df11ff26d3a7aaf72fdd087a13be65739cf
Reviewed-on: https://chromium-review.googlesource.com/c/1351262
Commit-Queue: Aleks Totic <atotic@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612359}
parent 88c15d0b
...@@ -168,10 +168,8 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag( ...@@ -168,10 +168,8 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
NGInlineBoxState* box = OnOpenTag(*item.Style(), line_box); NGInlineBoxState* box = OnOpenTag(*item.Style(), line_box);
box->item = &item; box->item = &item;
if (item.ShouldCreateBoxFragment()) { if (item.ShouldCreateBoxFragment())
box->SetNeedsBoxFragment( box->SetNeedsBoxFragment();
ContainingLayoutObjectForAbsolutePositionObjects());
}
// Compute box properties regardless of needs_box_fragment since close tag may // Compute box properties regardless of needs_box_fragment since close tag may
// also set needs_box_fragment. // also set needs_box_fragment.
...@@ -252,13 +250,10 @@ void NGInlineLayoutStateStack::EndBoxState( ...@@ -252,13 +250,10 @@ void NGInlineLayoutStateStack::EndBoxState(
parent_box.metrics.Unite(box->metrics); parent_box.metrics.Unite(box->metrics);
} }
void NGInlineBoxState::SetNeedsBoxFragment( void NGInlineBoxState::SetNeedsBoxFragment() {
const LayoutObject* inline_container) {
DCHECK(item); DCHECK(item);
DCHECK(!needs_box_fragment); DCHECK(!needs_box_fragment);
needs_box_fragment = true; needs_box_fragment = true;
DCHECK(!this->inline_container);
this->inline_container = inline_container;
} }
// Crete a placeholder for a box fragment. // Crete a placeholder for a box fragment.
...@@ -294,7 +289,6 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder( ...@@ -294,7 +289,6 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
BoxData& box_data = box_data_list_.emplace_back( BoxData& box_data = box_data_list_.emplace_back(
box->fragment_start, fragment_end, box->item, size); box->fragment_start, fragment_end, box->item, size);
box_data.padding = box->padding; box_data.padding = box->padding;
box_data.inline_container = box->inline_container;
if (box->has_start_edge) { if (box->has_start_edge) {
box_data.has_line_left_edge = true; box_data.has_line_left_edge = true;
box_data.margin_line_left = box->margin_inline_start; box_data.margin_line_left = box->margin_inline_start;
...@@ -338,7 +332,7 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder( ...@@ -338,7 +332,7 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
box_data.size.inline_size = box_data.size.inline_size =
advance - box_data.margin_line_left - box_data.margin_line_right; advance - box_data.margin_line_left - box_data.margin_line_right;
line_box->AddChild(box_data.CreateBoxFragment(line_box), offset, advance, line_box->AddChild(box_data.CreateBoxFragment(line_box), offset, advance,
0); /* bidi_level */ 0);
box_data_list_.pop_back(); box_data_list_.pop_back();
} }
} }
...@@ -619,7 +613,8 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment( ...@@ -619,7 +613,8 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
// NGInlineLayoutAlgorithm can handle them later. // NGInlineLayoutAlgorithm can handle them later.
DCHECK(!child.HasInFlowFragment()); DCHECK(!child.HasInFlowFragment());
} }
box.MoveOutOfFlowDescendantCandidatesToDescendants(inline_container);
box.MoveOutOfFlowDescendantCandidatesToDescendants();
return box.ToInlineBoxFragment(); return box.ToInlineBoxFragment();
} }
...@@ -804,7 +799,6 @@ void NGInlineBoxState::CheckSame(const NGInlineBoxState& other) const { ...@@ -804,7 +799,6 @@ void NGInlineBoxState::CheckSame(const NGInlineBoxState& other) const {
DCHECK_EQ(fragment_start, other.fragment_start); DCHECK_EQ(fragment_start, other.fragment_start);
DCHECK_EQ(item, other.item); DCHECK_EQ(item, other.item);
DCHECK_EQ(style, other.style); DCHECK_EQ(style, other.style);
DCHECK_EQ(inline_container, other.inline_container);
DCHECK_EQ(metrics, other.metrics); DCHECK_EQ(metrics, other.metrics);
DCHECK_EQ(text_metrics, other.text_metrics); DCHECK_EQ(text_metrics, other.text_metrics);
......
...@@ -40,7 +40,6 @@ struct NGInlineBoxState { ...@@ -40,7 +40,6 @@ struct NGInlineBoxState {
unsigned fragment_start = 0; unsigned fragment_start = 0;
const NGInlineItem* item = nullptr; const NGInlineItem* item = nullptr;
const ComputedStyle* style = nullptr; const ComputedStyle* style = nullptr;
const LayoutObject* inline_container = nullptr;
// The united metrics for the current box. This includes all objects in this // The united metrics for the current box. This includes all objects in this
// box, including descendants, and adjusted by placement properties such as // box, including descendants, and adjusted by placement properties such as
...@@ -91,7 +90,7 @@ struct NGInlineBoxState { ...@@ -91,7 +90,7 @@ struct NGInlineBoxState {
LayoutUnit TextTop(FontBaseline baseline_type) const; LayoutUnit TextTop(FontBaseline baseline_type) const;
// Create a box fragment for this box. // Create a box fragment for this box.
void SetNeedsBoxFragment(const LayoutObject* inline_container); void SetNeedsBoxFragment();
// Returns if the text style can be added without open-tag. // Returns if the text style can be added without open-tag.
// Text with different font or vertical-align needs to be wrapped with an // Text with different font or vertical-align needs to be wrapped with an
...@@ -216,7 +215,6 @@ class CORE_EXPORT NGInlineLayoutStateStack { ...@@ -216,7 +215,6 @@ class CORE_EXPORT NGInlineLayoutStateStack {
fragment_end(end), fragment_end(end),
item(other.item), item(other.item),
size(other.size), size(other.size),
inline_container(other.inline_container),
offset(other.offset) {} offset(other.offset) {}
// The range of child fragments this box contains. // The range of child fragments this box contains.
...@@ -226,7 +224,6 @@ class CORE_EXPORT NGInlineLayoutStateStack { ...@@ -226,7 +224,6 @@ class CORE_EXPORT NGInlineLayoutStateStack {
const NGInlineItem* item; const NGInlineItem* item;
NGLogicalSize size; NGLogicalSize size;
const LayoutObject* inline_container = nullptr;
bool has_line_left_edge = false; bool has_line_left_edge = false;
bool has_line_right_edge = false; bool has_line_right_edge = false;
NGLineBoxStrut padding; NGLineBoxStrut padding;
......
...@@ -289,7 +289,7 @@ void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info, ...@@ -289,7 +289,7 @@ void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info,
} else if (item.Type() == NGInlineItem::kCloseTag) { } else if (item.Type() == NGInlineItem::kCloseTag) {
box = HandleCloseTag(item, item_result, box); box = HandleCloseTag(item, item_result, box);
} else if (item.Type() == NGInlineItem::kAtomicInline) { } else if (item.Type() == NGInlineItem::kAtomicInline) {
box = PlaceAtomicInline(item, &item_result, *line_info); box = PlaceAtomicInline(item, *line_info, &item_result);
} else if (item.Type() == NGInlineItem::kListMarker) { } else if (item.Type() == NGInlineItem::kListMarker) {
PlaceListMarker(item, &item_result, *line_info); PlaceListMarker(item, &item_result, *line_info);
} else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) { } else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) {
...@@ -451,8 +451,8 @@ void NGInlineLayoutAlgorithm::PlaceGeneratedContent( ...@@ -451,8 +451,8 @@ void NGInlineLayoutAlgorithm::PlaceGeneratedContent(
NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline( NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline(
const NGInlineItem& item, const NGInlineItem& item,
NGInlineItemResult* item_result, const NGLineInfo& line_info,
const NGLineInfo& line_info) { NGInlineItemResult* item_result) {
DCHECK(item_result->layout_result); DCHECK(item_result->layout_result);
// The input |position| is the line-left edge of the margin box. // The input |position| is the line-left edge of the margin box.
...@@ -841,7 +841,7 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() { ...@@ -841,7 +841,7 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
DCHECK(unpositioned_floats_.IsEmpty() || is_empty_inline); DCHECK(unpositioned_floats_.IsEmpty() || is_empty_inline);
container_builder_.SwapPositionedFloats(&positioned_floats_); container_builder_.SwapPositionedFloats(&positioned_floats_);
container_builder_.SetExclusionSpace(std::move(exclusion_space)); container_builder_.SetExclusionSpace(std::move(exclusion_space));
container_builder_.MoveOutOfFlowDescendantCandidatesToDescendants(nullptr); container_builder_.MoveOutOfFlowDescendantCandidatesToDescendants();
return container_builder_.ToLineBoxFragment(); return container_builder_.ToLineBoxFragment();
} }
......
...@@ -83,8 +83,8 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final ...@@ -83,8 +83,8 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
UBiDiLevel, UBiDiLevel,
NGInlineBoxState*); NGInlineBoxState*);
NGInlineBoxState* PlaceAtomicInline(const NGInlineItem&, NGInlineBoxState* PlaceAtomicInline(const NGInlineItem&,
NGInlineItemResult*, const NGLineInfo&,
const NGLineInfo&); NGInlineItemResult*);
void PlaceLayoutResult(NGInlineItemResult*, void PlaceLayoutResult(NGInlineItemResult*,
NGInlineBoxState*, NGInlineBoxState*,
LayoutUnit inline_offset = LayoutUnit()); LayoutUnit inline_offset = LayoutUnit());
......
...@@ -52,8 +52,24 @@ NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild( ...@@ -52,8 +52,24 @@ NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
} }
for (const NGOutOfFlowPositionedDescendant& descendant : for (const NGOutOfFlowPositionedDescendant& descendant :
out_of_flow_descendants) { out_of_flow_descendants) {
oof_positioned_candidates_.push_back( // If we are inside the inline algorithm, (and creating a fragment for a
NGOutOfFlowPositionedCandidate{descendant, top_left_offset}); // <span> or similar), we may add a child (e.g. an atomic-inline) which
// has OOF descandants.
//
// This checks if the object creating this box will be the container for
// the given descendant.
if (layout_object_ && layout_object_->IsLayoutInline() &&
layout_object_->CanContainOutOfFlowPositionedElement(
descendant.node.Style().GetPosition()) &&
!descendant.inline_container) {
NGOutOfFlowPositionedDescendant descendant_copy(descendant);
descendant_copy.inline_container = layout_object_;
oof_positioned_candidates_.push_back(
NGOutOfFlowPositionedCandidate(descendant_copy, top_left_offset));
} else {
oof_positioned_candidates_.push_back(
NGOutOfFlowPositionedCandidate{descendant, top_left_offset});
}
} }
} }
...@@ -190,16 +206,10 @@ void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates( ...@@ -190,16 +206,10 @@ void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
oof_positioned_candidates_.Shrink(0); oof_positioned_candidates_.Shrink(0);
} }
void NGContainerFragmentBuilder::MoveOutOfFlowDescendantCandidatesToDescendants( void NGContainerFragmentBuilder::
const LayoutObject* inline_container) { MoveOutOfFlowDescendantCandidatesToDescendants() {
GetAndClearOutOfFlowDescendantCandidates(&oof_positioned_descendants_, GetAndClearOutOfFlowDescendantCandidates(&oof_positioned_descendants_,
nullptr); nullptr);
if (inline_container) {
for (auto& descendant : oof_positioned_descendants_) {
if (!descendant.inline_container)
descendant.inline_container = inline_container;
}
}
} }
#ifndef NDEBUG #ifndef NDEBUG
......
...@@ -136,10 +136,14 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -136,10 +136,14 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
return !oof_positioned_candidates_.IsEmpty(); return !oof_positioned_candidates_.IsEmpty();
} }
// Utility routine to move all OOF descendant candidates to descendants. // This method should only be used within the inline layout algorithm. It is
// Use if fragment cannot position any OOF children. // used to convert all OOF descendant candidates to descendants.
void MoveOutOfFlowDescendantCandidatesToDescendants( //
const LayoutObject* inline_container); // During the inline layout algorithm, we don't have enough information to
// position OOF candidates yet, (as a containing box may be split over
// multiple lines), instead we bubble all the descendants up to the parent
// block layout algorithm, to perform the final OOF layout and positioning.
void MoveOutOfFlowDescendantCandidatesToDescendants();
NGContainerFragmentBuilder& SetIsPushedByFloats() { NGContainerFragmentBuilder& SetIsPushedByFloats() {
is_pushed_by_floats_ = true; is_pushed_by_floats_ = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment