Commit f007b805 authored by Ian Kilpatrick's avatar Ian Kilpatrick Committed by Commit Bot

[LayoutNG] Merge NGContainerFragmentBuilder::children_ and offsets_ vectors.

This merges the two vectors into one using a new struct
"ChildWithOffset".

There might be a (slight) positive perf impact with this change, as well
as a (very slight) decrease in stack.

Bug: 635619
Change-Id: I44a981bcf36379ffd94a1490c532c6b70a343e33
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1633019
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664158}
parent b625beba
......@@ -16,7 +16,6 @@ namespace blink {
void NGLineBoxFragmentBuilder::Reset() {
children_.Shrink(0);
offsets_.Shrink(0);
child_break_tokens_.Shrink(0);
inline_break_tokens_.Shrink(0);
oof_positioned_candidates_.Shrink(0);
......@@ -78,7 +77,6 @@ void NGLineBoxFragmentBuilder::ChildList::MoveInBlockDirection(LayoutUnit delta,
}
void NGLineBoxFragmentBuilder::AddChildren(ChildList& children) {
offsets_.ReserveCapacity(children.size());
children_.ReserveCapacity(children.size());
for (auto& child : children) {
......
......@@ -2198,23 +2198,23 @@ LayoutUnit NGBlockLayoutAlgorithm::ComputeLineBoxBaselineOffset(
// Add a baseline from a child box fragment.
// @return false if the specified child is not a box or is OOF.
bool NGBlockLayoutAlgorithm::AddBaseline(const NGBaselineRequest& request,
const NGPhysicalFragment* child,
const NGPhysicalFragment& child,
LayoutUnit child_offset) {
if (child->IsLineBox()) {
const auto* line_box = To<NGPhysicalLineBoxFragment>(child);
if (child.IsLineBox()) {
const auto& line_box = To<NGPhysicalLineBoxFragment>(child);
// Skip over a line-box which is empty. These don't have any baselines which
// should be added.
if (line_box->IsEmptyLineBox())
if (line_box.IsEmptyLineBox())
return false;
LayoutUnit offset =
ComputeLineBoxBaselineOffset(request, *line_box, child_offset);
ComputeLineBoxBaselineOffset(request, line_box, child_offset);
container_builder_.AddBaseline(request, offset);
return true;
}
if (child->IsFloatingOrOutOfFlowPositioned())
if (child.IsFloatingOrOutOfFlowPositioned())
return false;
if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(child)) {
......@@ -2236,21 +2236,20 @@ void NGBlockLayoutAlgorithm::PropagateBaselinesFromChildren() {
for (const auto& request : requests) {
switch (request.AlgorithmType()) {
case NGBaselineAlgorithmType::kAtomicInline:
case NGBaselineAlgorithmType::kAtomicInline: {
if (Node().UseLogicalBottomMarginEdgeForInlineBlockBaseline())
break;
for (unsigned i = container_builder_.Children().size(); i--;) {
if (AddBaseline(request, container_builder_.Children()[i].get(),
container_builder_.Offsets()[i].block_offset))
const auto& children = container_builder_.Children();
for (auto it = children.rbegin(); it != children.rend(); ++it) {
if (AddBaseline(request, *it->fragment, it->offset.block_offset))
break;
}
break;
}
case NGBaselineAlgorithmType::kFirstLine:
for (unsigned i = 0; i < container_builder_.Children().size(); i++) {
if (AddBaseline(request, container_builder_.Children()[i].get(),
container_builder_.Offsets()[i].block_offset))
for (const auto& child : container_builder_.Children()) {
if (AddBaseline(request, *child.fragment, child.offset.block_offset))
break;
}
break;
......
......@@ -233,7 +233,7 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
void PropagateBaselinesFromChildren();
bool AddBaseline(const NGBaselineRequest&,
const NGPhysicalFragment*,
const NGPhysicalFragment&,
LayoutUnit child_offset);
// Compute the baseline offset of a line box from the content box.
......
......@@ -31,9 +31,10 @@ using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*,
void GatherInlineContainerFragmentsFromLinebox(
NGBoxFragmentBuilder::InlineContainingBlockMap* inline_containing_block_map,
HashMap<const LayoutObject*, LineBoxPair>* containing_linebox_map,
const NGPhysicalLineBoxFragment* linebox,
const NGPhysicalLineBoxFragment& linebox,
const PhysicalOffset linebox_offset) {
for (auto& descendant : NGInlineFragmentTraversal::DescendantsOf(*linebox)) {
for (const auto& descendant :
NGInlineFragmentTraversal::DescendantsOf(linebox)) {
if (!descendant.fragment->IsBox())
continue;
const LayoutObject* key = descendant.fragment->GetLayoutObject();
......@@ -58,19 +59,19 @@ void GatherInlineContainerFragmentsFromLinebox(
PhysicalRect fragment_rect(
linebox_offset + descendant.offset_to_container_box,
descendant.fragment->Size());
if (containing_lineboxes.first == linebox) {
if (containing_lineboxes.first == &linebox) {
containing_block_geometry->start_fragment_union_rect.Unite(fragment_rect);
} else if (!containing_lineboxes.first) {
containing_lineboxes.first = linebox;
containing_lineboxes.first = &linebox;
containing_block_geometry =
NGBoxFragmentBuilder::InlineContainingBlockGeometry{fragment_rect,
PhysicalRect()};
}
// Skip fragments within an empty line boxes for the end fragment.
if (containing_lineboxes.second == linebox) {
if (containing_lineboxes.second == &linebox) {
containing_block_geometry->end_fragment_union_rect.Unite(fragment_rect);
} else if (!containing_lineboxes.second || !linebox->IsEmptyLineBox()) {
containing_lineboxes.second = linebox;
} else if (!containing_lineboxes.second || !linebox.IsEmptyLineBox()) {
containing_lineboxes.second = &linebox;
containing_block_geometry->end_fragment_union_rect = fragment_rect;
}
}
......@@ -82,7 +83,6 @@ void NGBoxFragmentBuilder::RemoveChildren() {
child_break_tokens_.resize(0);
inline_break_tokens_.resize(0);
children_.resize(0);
offsets_.resize(0);
}
NGBoxFragmentBuilder& NGBoxFragmentBuilder::AddBreakBeforeChild(
......@@ -121,13 +121,12 @@ NGBoxFragmentBuilder& NGBoxFragmentBuilder::AddBreakBeforeLine(
DCHECK_GT(children_.size(), 0UL);
for (int i = children_.size() - 1; i >= 0; i--) {
DCHECK_NE(i, 0);
if (!children_[i]->IsLineBox())
if (!children_[i].fragment->IsLineBox())
continue;
if (!--lines_to_remove) {
// This is the first line that is going to the next fragment. Remove it,
// and everything after it.
children_.resize(i);
offsets_.resize(i);
break;
}
}
......@@ -287,20 +286,20 @@ void NGBoxFragmentBuilder::ComputeInlineContainerFragments(
#endif
HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map;
for (wtf_size_t i = 0; i < children_.size(); i++) {
if (children_[i]->IsLineBox()) {
const auto* linebox = To<NGPhysicalLineBoxFragment>(children_[i].get());
const PhysicalOffset linebox_offset = offsets_[i].ConvertToPhysical(
for (const auto& child : children_) {
if (child.fragment->IsLineBox()) {
const auto& linebox = To<NGPhysicalLineBoxFragment>(*child.fragment);
const PhysicalOffset linebox_offset = child.offset.ConvertToPhysical(
GetWritingMode(), Direction(),
ToPhysicalSize(Size(), GetWritingMode()), linebox->Size());
ToPhysicalSize(Size(), GetWritingMode()), linebox.Size());
GatherInlineContainerFragmentsFromLinebox(inline_containing_block_map,
&containing_linebox_map,
linebox, linebox_offset);
} else if (children_[i]->IsBox()) {
const auto* box_fragment = To<NGPhysicalBoxFragment>(children_[i].get());
} else if (child.fragment->IsBox()) {
const auto& box_fragment = To<NGPhysicalBoxFragment>(*child.fragment);
bool is_anonymous_container =
box_fragment->GetLayoutObject() &&
box_fragment->GetLayoutObject()->IsAnonymousBlock();
box_fragment.GetLayoutObject() &&
box_fragment.GetLayoutObject()->IsAnonymousBlock();
if (!is_anonymous_container)
continue;
// If child is an anonymous container, this might be a special case of
......@@ -309,15 +308,15 @@ void NGBoxFragmentBuilder::ComputeInlineContainerFragments(
// lineboxes inside anonymous box.
// For more on this special case, see "css container is an inline, with
// inline splitting" comment in NGOutOfFlowLayoutPart::LayoutDescendant.
const PhysicalOffset box_offset = offsets_[i].ConvertToPhysical(
const PhysicalOffset box_offset = child.offset.ConvertToPhysical(
GetWritingMode(), Direction(),
ToPhysicalSize(Size(), GetWritingMode()), box_fragment->Size());
ToPhysicalSize(Size(), GetWritingMode()), box_fragment.Size());
// Traverse lineboxes of anonymous box.
for (const auto& child : box_fragment->Children()) {
if (child->IsLineBox()) {
const auto* linebox = To<NGPhysicalLineBoxFragment>(child.get());
const PhysicalOffset linebox_offset = child.Offset() + box_offset;
for (const auto& box_child : box_fragment.Children()) {
if (box_child->IsLineBox()) {
const auto& linebox = To<NGPhysicalLineBoxFragment>(*box_child);
const PhysicalOffset linebox_offset = box_child.Offset() + box_offset;
GatherInlineContainerFragmentsFromLinebox(inline_containing_block_map,
&containing_linebox_map,
linebox, linebox_offset);
......
......@@ -172,9 +172,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
scoped_refptr<const NGLayoutResult> Abort(
NGLayoutResult::NGLayoutResultStatus);
// A vector of child offsets. Initially set by AddChild().
const OffsetVector& Offsets() const { return offsets_; }
NGPhysicalFragment::NGBoxType BoxType() const;
NGBoxFragmentBuilder& SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
box_type_ = box_type;
......
......@@ -142,34 +142,32 @@ void NGContainerFragmentBuilder::AddChildInternal(
// 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(std::move(child));
offsets_.push_front(child_offset);
children_.push_front(ChildWithOffset(child_offset, std::move(child)));
return;
}
children_.emplace_back(std::move(child));
offsets_.push_back(child_offset);
children_.emplace_back(child_offset, std::move(child));
}
LogicalOffset NGContainerFragmentBuilder::GetChildOffset(
const LayoutObject* child) const {
for (wtf_size_t i = 0; i < children_.size(); ++i) {
if (children_[i]->GetLayoutObject() == child)
return offsets_[i];
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());
}
}
}
......@@ -275,7 +273,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();
......
......@@ -31,8 +31,18 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
STACK_ALLOCATED();
public:
typedef Vector<scoped_refptr<const NGPhysicalFragment>, 4> ChildrenVector;
typedef Vector<LogicalOffset, 4> OffsetVector;
struct ChildWithOffset {
DISALLOW_NEW();
ChildWithOffset(LogicalOffset offset,
scoped_refptr<const NGPhysicalFragment> fragment)
: offset(offset), fragment(std::move(fragment)) {}
// We store logical offsets (instead of the final physical), as we can't
// convert into the physical coordinate space until we know our final size.
LogicalOffset offset;
scoped_refptr<const NGPhysicalFragment> fragment;
};
typedef Vector<ChildWithOffset, 4> ChildrenVector;
LayoutUnit BfcLineOffset() const { return bfc_line_offset_; }
NGContainerFragmentBuilder& SetBfcLineOffset(LayoutUnit bfc_line_offset) {
......@@ -40,8 +50,8 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
return *this;
}
// The NGBfcOffset is where this fragment was positioned within the BFC. If
// it is not set, this fragment may be placed anywhere within the BFC.
// The BFC block-offset is where this fragment was positioned within the BFC.
// If it is not set, this fragment may be placed anywhere within the BFC.
const base::Optional<LayoutUnit>& BfcBlockOffset() const {
return bfc_block_offset_;
}
......@@ -241,11 +251,6 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
ChildrenVector children_;
// Logical offsets for the children. Stored as logical offsets as we can't
// convert to physical offsets until layout of all children has been
// determined.
OffsetVector offsets_;
// Only used by the NGBoxFragmentBuilder subclass, but defined here to avoid
// a virtual function call.
NGBreakTokenVector child_break_tokens_;
......@@ -267,4 +272,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
} // namespace blink
WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
blink::NGContainerFragmentBuilder::ChildWithOffset)
#endif // NGContainerFragmentBuilder
......@@ -45,17 +45,16 @@ NGPhysicalContainerFragment::NGPhysicalContainerFragment(
builder->may_have_descendant_above_block_start_;
depends_on_percentage_block_size_ = DependsOnPercentageBlockSize(*builder);
DCHECK_EQ(builder->children_.size(), builder->offsets_.size());
// Because flexible arrays need to be the last member in a class, we need to
// have the buffer passed as a constructor argument and have the actual
// storage be part of the subclass.
wtf_size_t i = 0;
for (auto& child : builder->children_) {
buffer[i].fragment = child.get();
buffer[i].fragment = child.fragment.get();
buffer[i].fragment->AddRef();
buffer[i].offset = builder->offsets_[i].ConvertToPhysical(
buffer[i].offset = child.offset.ConvertToPhysical(
block_or_line_writing_mode, builder->Direction(), Size(),
child->Size());
child.fragment->Size());
++i;
}
}
......
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