Commit 8d47c1f6 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Move inline box placeholders to before children

This patch changes |NGInlineLayoutAlgorithm| to place inline
box placeholders to before children.

Before this patch, they were created after children, only
when the inline box is not culled. This change:
1. Reduces the insertion to |Vector| in |CreateBoxFragments|,
   which involves memory copy. This is not common today, but
   will be common when |NGFragmentItem| is enabled.
2. Allows easier implementation to "disable culled inline
   boxes" when |NGFragmetnItem| is enabled.

There should be no behavior changes.

Bug: 982194
Change-Id: I0d7077e4c9b78b99276afc2e7919258b33bd4ea6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1980663Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#728439}
parent 02d4b120
...@@ -82,15 +82,15 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) { ...@@ -82,15 +82,15 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
// Floats are in the fragment tree, not in the fragment item list. // Floats are in the fragment tree, not in the fragment item list.
DCHECK(!box.IsFloating()); DCHECK(!box.IsFloating());
// Take the fast path when we know |child| does not have child items.
if (child.children_count <= 1) { if (child.children_count <= 1) {
// Compute |has_floating_descendants_for_paint_| to optimize tree // Compute |has_floating_descendants_for_paint_| to optimize tree
// traversal in paint. // traversal in paint.
if (!has_floating_descendants_for_paint_ && box.IsFloating()) if (!has_floating_descendants_for_paint_ && box.IsFloating())
has_floating_descendants_for_paint_ = true; has_floating_descendants_for_paint_ = true;
DCHECK(child.HasBidiLevel());
items_.push_back(std::make_unique<NGFragmentItem>( items_.push_back(std::make_unique<NGFragmentItem>(
box, 1, DirectionFromLevel(child.bidi_level))); box, 1, child.ResolvedDirection()));
offsets_.push_back(child.offset); offsets_.push_back(child.offset);
++child_iter; ++child_iter;
continue; continue;
...@@ -116,9 +116,8 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) { ...@@ -116,9 +116,8 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
wtf_size_t item_count = items_.size() - box_start_index; wtf_size_t item_count = items_.size() - box_start_index;
// Create an item for the start of the box. // Create an item for the start of the box.
DCHECK(child.HasBidiLevel());
items_[box_start_index] = std::make_unique<NGFragmentItem>( items_[box_start_index] = std::make_unique<NGFragmentItem>(
box, item_count, DirectionFromLevel(child.bidi_level)); box, item_count, child.ResolvedDirection());
continue; continue;
} }
......
...@@ -116,14 +116,22 @@ class CORE_EXPORT NGInlineLayoutStateStack { ...@@ -116,14 +116,22 @@ class CORE_EXPORT NGInlineLayoutStateStack {
// Initialize the box state stack for a new line. // Initialize the box state stack for a new line.
// @return The initial box state for the line. // @return The initial box state for the line.
NGInlineBoxState* OnBeginPlaceItems(const ComputedStyle&, FontBaseline, bool); NGInlineBoxState* OnBeginPlaceItems(
const ComputedStyle&,
FontBaseline,
bool line_height_quirk,
NGLineBoxFragmentBuilder::ChildList* line_box);
// Push a box state stack. // Push a box state stack.
NGInlineBoxState* OnOpenTag(const NGInlineItem&, NGInlineBoxState* OnOpenTag(const NGInlineItem&,
const NGInlineItemResult&, const NGInlineItemResult&,
FontBaseline baseline_type,
const NGLineBoxFragmentBuilder::ChildList&); const NGLineBoxFragmentBuilder::ChildList&);
NGInlineBoxState* OnOpenTag(const ComputedStyle&, // This variation adds a box placeholder to |line_box|.
const NGLineBoxFragmentBuilder::ChildList&); NGInlineBoxState* OnOpenTag(const NGInlineItem&,
const NGInlineItemResult&,
FontBaseline baseline_type,
NGLineBoxFragmentBuilder::ChildList* line_box);
// Pop a box state stack. // Pop a box state stack.
NGInlineBoxState* OnCloseTag(NGLineBoxFragmentBuilder::ChildList*, NGInlineBoxState* OnCloseTag(NGLineBoxFragmentBuilder::ChildList*,
...@@ -182,6 +190,7 @@ class CORE_EXPORT NGInlineLayoutStateStack { ...@@ -182,6 +190,7 @@ class CORE_EXPORT NGInlineLayoutStateStack {
void AddBoxFragmentPlaceholder(NGInlineBoxState*, void AddBoxFragmentPlaceholder(NGInlineBoxState*,
NGLineBoxFragmentBuilder::ChildList*, NGLineBoxFragmentBuilder::ChildList*,
FontBaseline); FontBaseline);
void AddBoxData(NGInlineBoxState*, NGLineBoxFragmentBuilder::ChildList*);
enum PositionPending { kPositionNotPending, kPositionPending }; enum PositionPending { kPositionNotPending, kPositionPending };
......
...@@ -77,8 +77,10 @@ NGInlineLayoutAlgorithm::~NGInlineLayoutAlgorithm() = default; ...@@ -77,8 +77,10 @@ NGInlineLayoutAlgorithm::~NGInlineLayoutAlgorithm() = default;
NGInlineBoxState* NGInlineLayoutAlgorithm::HandleOpenTag( NGInlineBoxState* NGInlineLayoutAlgorithm::HandleOpenTag(
const NGInlineItem& item, const NGInlineItem& item,
const NGInlineItemResult& item_result, const NGInlineItemResult& item_result,
NGLineBoxFragmentBuilder::ChildList* line_box,
NGInlineLayoutStateStack* box_states) const { NGInlineLayoutStateStack* box_states) const {
NGInlineBoxState* box = box_states->OnOpenTag(item, item_result, line_box_); NGInlineBoxState* box =
box_states->OnOpenTag(item, item_result, baseline_type_, line_box);
// Compute text metrics for all inline boxes since even empty inlines // Compute text metrics for all inline boxes since even empty inlines
// influence the line height, except when quirks mode and the box is empty // influence the line height, except when quirks mode and the box is empty
// for the purpose of empty block calculation. // for the purpose of empty block calculation.
...@@ -160,12 +162,13 @@ void NGInlineLayoutAlgorithm::RebuildBoxStates( ...@@ -160,12 +162,13 @@ void NGInlineLayoutAlgorithm::RebuildBoxStates(
} }
// Create box states for tags that are not closed yet. // Create box states for tags that are not closed yet.
NGLineBoxFragmentBuilder::ChildList line_box;
box_states->OnBeginPlaceItems(line_info.LineStyle(), baseline_type_, box_states->OnBeginPlaceItems(line_info.LineStyle(), baseline_type_,
quirks_mode_); quirks_mode_, &line_box);
for (const NGInlineItem* item : open_items) { for (const NGInlineItem* item : open_items) {
NGInlineItemResult item_result; NGInlineItemResult item_result;
NGLineBreaker::ComputeOpenTagResult(*item, ConstraintSpace(), &item_result); NGLineBreaker::ComputeOpenTagResult(*item, ConstraintSpace(), &item_result);
HandleOpenTag(*item, item_result, box_states); HandleOpenTag(*item, item_result, &line_box, box_states);
} }
} }
...@@ -175,9 +178,9 @@ void NGInlineLayoutAlgorithm::CheckBoxStates( ...@@ -175,9 +178,9 @@ void NGInlineLayoutAlgorithm::CheckBoxStates(
const NGInlineBreakToken* break_token) const { const NGInlineBreakToken* break_token) const {
NGInlineLayoutStateStack rebuilt; NGInlineLayoutStateStack rebuilt;
RebuildBoxStates(line_info, break_token, &rebuilt); RebuildBoxStates(line_info, break_token, &rebuilt);
rebuilt.OnBeginPlaceItems(line_info.LineStyle(), baseline_type_, NGLineBoxFragmentBuilder::ChildList line_box;
quirks_mode_); rebuilt.OnBeginPlaceItems(line_info.LineStyle(), baseline_type_, quirks_mode_,
&line_box);
DCHECK(box_states_); DCHECK(box_states_);
box_states_->CheckSame(rebuilt); box_states_->CheckSame(rebuilt);
} }
...@@ -201,8 +204,8 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -201,8 +204,8 @@ void NGInlineLayoutAlgorithm::CreateLine(
// The baseline is adjusted after the height of the line box is computed. // The baseline is adjusted after the height of the line box is computed.
const ComputedStyle& line_style = line_info->LineStyle(); const ComputedStyle& line_style = line_info->LineStyle();
box_states_->SetIsEmptyLine(line_info->IsEmptyLine()); box_states_->SetIsEmptyLine(line_info->IsEmptyLine());
NGInlineBoxState* box = NGInlineBoxState* box = box_states_->OnBeginPlaceItems(
box_states_->OnBeginPlaceItems(line_style, baseline_type_, quirks_mode_); line_style, baseline_type_, quirks_mode_, &line_box_);
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
if (is_box_states_from_context_) if (is_box_states_from_context_)
CheckBoxStates(*line_info, BreakToken()); CheckBoxStates(*line_info, BreakToken());
...@@ -261,7 +264,7 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -261,7 +264,7 @@ void NGInlineLayoutAlgorithm::CreateLine(
} else if (item.Type() == NGInlineItem::kControl) { } else if (item.Type() == NGInlineItem::kControl) {
PlaceControlItem(item, *line_info, &item_result, box); PlaceControlItem(item, *line_info, &item_result, box);
} else if (item.Type() == NGInlineItem::kOpenTag) { } else if (item.Type() == NGInlineItem::kOpenTag) {
box = HandleOpenTag(item, item_result, box_states_); box = HandleOpenTag(item, item_result, &line_box_, box_states_);
} 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) {
...@@ -459,7 +462,8 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline( ...@@ -459,7 +462,8 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline(
// position += item_result->margins.LineLeft(style.Direction()); // position += item_result->margins.LineLeft(style.Direction());
item_result->has_edge = true; item_result->has_edge = true;
NGInlineBoxState* box = box_states_->OnOpenTag(item, *item_result, line_box_); NGInlineBoxState* box =
box_states_->OnOpenTag(item, *item_result, baseline_type_, line_box_);
PlaceLayoutResult(item_result, box, box->margin_inline_start); PlaceLayoutResult(item_result, box, box->margin_inline_start);
return box_states_->OnCloseTag(&line_box_, box, baseline_type_); return box_states_->OnCloseTag(&line_box_, box, baseline_type_);
} }
...@@ -485,7 +489,8 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result, ...@@ -485,7 +489,8 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result,
LayoutUnit line_top = item_result->margins.line_over - metrics.ascent; LayoutUnit line_top = item_result->margins.line_over - metrics.ascent;
line_box_.AddChild(std::move(item_result->layout_result), line_box_.AddChild(std::move(item_result->layout_result),
LogicalOffset{inline_offset, line_top}, LogicalOffset{inline_offset, line_top},
item_result->inline_size, item.BidiLevel()); item_result->inline_size, /* children_count */ 0,
item.BidiLevel());
} }
// Place all out-of-flow objects in |line_box_|. // Place all out-of-flow objects in |line_box_|.
...@@ -1086,22 +1091,9 @@ void NGInlineLayoutAlgorithm::BidiReorder(TextDirection base_direction) { ...@@ -1086,22 +1091,9 @@ void NGInlineLayoutAlgorithm::BidiReorder(TextDirection base_direction) {
// For opaque items, copy bidi levels from adjacent items. // For opaque items, copy bidi levels from adjacent items.
if (has_opaque_items) { if (has_opaque_items) {
UBiDiLevel last_level = levels.front(); // Use the paragraph level for trailing opaque items.
if (last_level == kOpaqueBidiLevel) { UBiDiLevel last_level = IsLtr(base_direction) ? 0 : 1;
for (const UBiDiLevel level : levels) { for (UBiDiLevel& level : base::Reversed(levels)) {
if (level != kOpaqueBidiLevel) {
last_level = level;
break;
}
}
}
// If all items are opaque, use the base direction.
if (last_level == kOpaqueBidiLevel) {
if (IsLtr(base_direction))
return;
last_level = 1;
}
for (UBiDiLevel& level : levels) {
if (level == kOpaqueBidiLevel) if (level == kOpaqueBidiLevel)
level = last_level; level = last_level;
else else
......
...@@ -69,6 +69,7 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final ...@@ -69,6 +69,7 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
NGInlineBoxState* HandleOpenTag(const NGInlineItem&, NGInlineBoxState* HandleOpenTag(const NGInlineItem&,
const NGInlineItemResult&, const NGInlineItemResult&,
NGLineBoxFragmentBuilder::ChildList*,
NGInlineLayoutStateStack*) const; NGInlineLayoutStateStack*) const;
NGInlineBoxState* HandleCloseTag(const NGInlineItem&, NGInlineBoxState* HandleCloseTag(const NGInlineItem&,
const NGInlineItemResult&, const NGInlineItemResult&,
......
...@@ -82,6 +82,7 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final ...@@ -82,6 +82,7 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
// The offset of the border box, initially in this child coordinate system. // The offset of the border box, initially in this child coordinate system.
// |ComputeInlinePositions()| converts it to the offset within the line box. // |ComputeInlinePositions()| converts it to the offset within the line box.
LogicalOffset offset; LogicalOffset offset;
LogicalSize size;
// The offset of a positioned float wrt. the root BFC. This should only be // The offset of a positioned float wrt. the root BFC. This should only be
// set for positioned floats. // set for positioned floats.
NGBfcOffset bfc_offset; NGBfcOffset bfc_offset;
...@@ -103,7 +104,8 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final ...@@ -103,7 +104,8 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
Child() = default; Child() = default;
// Create a placeholder. A placeholder does not have a fragment nor a bidi // Create a placeholder. A placeholder does not have a fragment nor a bidi
// level. // level.
Child(LogicalOffset offset) : offset(offset) {} Child(LayoutUnit block_offset, LayoutUnit block_size)
: offset(LayoutUnit(), block_offset), size(LayoutUnit(), block_size) {}
// Crete a bidi control. A bidi control does not have a fragment, but has // Crete a bidi control. A bidi control does not have a fragment, but has
// bidi level and affects bidi reordering. // bidi level and affects bidi reordering.
Child(UBiDiLevel bidi_level) : bidi_level(bidi_level) {} Child(UBiDiLevel bidi_level) : bidi_level(bidi_level) {}
...@@ -111,10 +113,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final ...@@ -111,10 +113,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
Child(scoped_refptr<const NGLayoutResult> layout_result, Child(scoped_refptr<const NGLayoutResult> layout_result,
LogicalOffset offset, LogicalOffset offset,
LayoutUnit inline_size, LayoutUnit inline_size,
unsigned children_count,
UBiDiLevel bidi_level) UBiDiLevel bidi_level)
: layout_result(std::move(layout_result)), : layout_result(std::move(layout_result)),
offset(offset), offset(offset),
inline_size(inline_size), inline_size(inline_size),
children_count(children_count),
bidi_level(bidi_level) {} bidi_level(bidi_level) {}
// Create an in-flow |NGPhysicalTextFragment|. // Create an in-flow |NGPhysicalTextFragment|.
Child(scoped_refptr<const NGPhysicalTextFragment> fragment, Child(scoped_refptr<const NGPhysicalTextFragment> fragment,
...@@ -185,6 +189,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final ...@@ -185,6 +189,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
return &layout_result->PhysicalFragment(); return &layout_result->PhysicalFragment();
return fragment.get(); return fragment.get();
} }
TextDirection ResolvedDirection() const {
// Inline boxes are not leaves that they don't have directions.
DCHECK(HasBidiLevel() || layout_result->PhysicalFragment().IsInlineBox());
return HasBidiLevel() ? DirectionFromLevel(bidi_level)
: TextDirection::kLtr;
}
}; };
// A vector of Child. // A vector of Child.
...@@ -235,10 +245,10 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final ...@@ -235,10 +245,10 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
void InsertChild(unsigned index, void InsertChild(unsigned index,
scoped_refptr<const NGLayoutResult> layout_result, scoped_refptr<const NGLayoutResult> layout_result,
const LogicalOffset& offset, const LogicalOffset& offset,
LayoutUnit inline_size, unsigned children_count) {
UBiDiLevel bidi_level) {
children_.insert(index, Child{std::move(layout_result), offset, children_.insert(index, Child{std::move(layout_result), offset,
inline_size, bidi_level}); /* inline_size */ LayoutUnit(),
children_count, /* bidi_level */ 0});
} }
void MoveInInlineDirection(LayoutUnit); void MoveInInlineDirection(LayoutUnit);
......
...@@ -78,7 +78,7 @@ crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht ...@@ -78,7 +78,7 @@ crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht
crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht [ Failure ] crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht [ Failure ]
crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ] crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ]
crbug.com/982194 external/wpt/css/CSS2/floats/hit-test-floats-001.html [ Failure ] crbug.com/982194 external/wpt/css/CSS2/floats/hit-test-floats-001.html [ Failure ]
crbug.com/982194 external/wpt/css/CSS2/positioning/abspos-float-with-inline-container.html [ Crash ] crbug.com/982194 external/wpt/css/CSS2/positioning/abspos-float-with-inline-container.html [ Crash Failure ]
crbug.com/982194 external/wpt/css/CSS2/positioning/toogle-abspos-on-relpos-inline-child.html [ Failure ] crbug.com/982194 external/wpt/css/CSS2/positioning/toogle-abspos-on-relpos-inline-child.html [ Failure ]
crbug.com/982194 external/wpt/css/css-contain/contain-layout-017.html [ Pass ] crbug.com/982194 external/wpt/css/css-contain/contain-layout-017.html [ Pass ]
crbug.com/982194 external/wpt/css/css-contain/contain-paint-021.html [ Pass ] crbug.com/982194 external/wpt/css/css-contain/contain-paint-021.html [ Pass ]
......
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