blob: 86f35a550287f4b77e6b0bcb06397b07021ce51f [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
#include "base/containers/span.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/ng/ng_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_link.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
class NGContainerFragmentBuilder;
struct NGPhysicalOutOfFlowPositionedNode;
enum class NGOutlineType;
class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
public:
// Same as |base::span<const NGLink>|, except that each |NGLink| has the
// latest generation of post-layout. See
// |NGPhysicalFragment::UpdatedFragment()| for more details.
class PostLayoutChildLinkList {
public:
PostLayoutChildLinkList(wtf_size_t count, const NGLink* buffer)
: count_(count), buffer_(buffer) {}
class ConstIterator {
STACK_ALLOCATED();
public:
ConstIterator(const NGLink* current) : current_(current) {}
const NGLink& operator*() const { return *PostLayoutOrCurrent(); }
const NGLink* operator->() const { return PostLayoutOrCurrent(); }
ConstIterator& operator++() {
++current_;
return *this;
}
bool operator==(const ConstIterator& other) const {
return current_ == other.current_;
}
bool operator!=(const ConstIterator& other) const {
return current_ != other.current_;
}
private:
const NGLink* PostLayoutOrCurrent() const {
post_layout_.fragment = current_->fragment->PostLayout();
if (!post_layout_.fragment)
return current_;
post_layout_.offset = current_->offset;
return &post_layout_;
}
const NGLink* current_;
mutable NGLink post_layout_;
};
using const_iterator = ConstIterator;
const_iterator begin() const { return const_iterator(buffer_); }
const_iterator end() const { return const_iterator(buffer_ + count_); }
const NGLink operator[](wtf_size_t idx) const {
CHECK_LT(idx, count_);
return buffer_[idx].PostLayout();
}
const NGLink front() const { return (*this)[0]; }
const NGLink back() const { return (*this)[count_ - 1]; }
wtf_size_t size() const { return count_; }
bool empty() const { return count_ == 0; }
private:
wtf_size_t count_;
const NGLink* buffer_;
};
~NGPhysicalContainerFragment();
const NGBreakToken* BreakToken() const { return break_token_.get(); }
// Returns the children of |this|.
//
// Note, children in this collection maybe old generations. Items in this
// collection are safe, but their children (grandchildren of |this|) maybe
// from deleted nodes or LayoutObjects. Also see |PostLayoutChildren()|.
base::span<const NGLink> Children() const {
return base::make_span(buffer_, num_children_);
}
// Similar to |Children()| but all children are the latest generation of
// post-layout, and therefore all descendants are safe.
PostLayoutChildLinkList PostLayoutChildren() const {
return PostLayoutChildLinkList(num_children_, buffer_);
}
// Returns true if we have any floating descendants.
bool HasFloatingDescendants() const { return has_floating_descendants_; }
// Returns true if we have any adjoining-object descendants (floats, or
// inline-level OOF-positioned objects).
bool HasAdjoiningObjectDescendants() const {
return has_adjoining_object_descendants_;
}
bool HasOrthogonalFlowRoots() const { return has_orthogonal_flow_roots_; }
// Returns true if we have a descendant within this formatting context, which
// is potentially above our block-start edge.
bool MayHaveDescendantAboveBlockStart() const {
return may_have_descendant_above_block_start_;
}
// Returns true if we aren't able to re-use this fragment if the
// |NGConstraintSpace::PercentageResolutionBlockSize| changes.
bool DependsOnPercentageBlockSize() const {
return depends_on_percentage_block_size_;
}
bool HasOutOfFlowPositionedDescendants() const {
DCHECK(!oof_positioned_descendants_ ||
!oof_positioned_descendants_->IsEmpty());
return oof_positioned_descendants_.get();
}
base::span<NGPhysicalOutOfFlowPositionedNode> OutOfFlowPositionedDescendants()
const {
if (!HasOutOfFlowPositionedDescendants())
return base::span<NGPhysicalOutOfFlowPositionedNode>();
return {oof_positioned_descendants_->data(),
oof_positioned_descendants_->size()};
}
protected:
// block_or_line_writing_mode is used for converting the child offsets.
NGPhysicalContainerFragment(NGContainerFragmentBuilder*,
WritingMode block_or_line_writing_mode,
NGLink* buffer,
NGFragmentType,
unsigned sub_type);
void AddOutlineRectsForNormalChildren(
Vector<PhysicalRect>* outline_rects,
const PhysicalOffset& additional_offset,
NGOutlineType outline_type,
const LayoutBoxModelObject* containing_block) const;
void AddOutlineRectsForDescendant(
const NGLink& descendant,
Vector<PhysicalRect>* rects,
const PhysicalOffset& additional_offset,
NGOutlineType outline_type,
const LayoutBoxModelObject* containing_block) const;
static bool DependsOnPercentageBlockSize(const NGContainerFragmentBuilder&);
scoped_refptr<const NGBreakToken> break_token_;
const std::unique_ptr<Vector<NGPhysicalOutOfFlowPositionedNode>>
oof_positioned_descendants_;
// Because flexible arrays need to be the last member in a class, the actual
// storage is in the subclass and we just keep a pointer to it here.
const NGLink* buffer_;
wtf_size_t num_children_;
};
template <>
struct DowncastTraits<NGPhysicalContainerFragment> {
static bool AllowFrom(const NGPhysicalFragment& fragment) {
return fragment.IsContainer();
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_