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

[layout] Add NGPhysicalBoxFragment::{LayoutOverflow,InflowBounds}.

This adds two new fields to NGPhysicalBoxFragment. The calculated
LayoutOverflow, and the bounds of any inflow children.

LayoutOverflow is placed first in the flexible object as it is accessed
more frequently, and will always be present if there is borders
present.

InflowBounds is placed last as it is only accessed when recalculating
layout-overflow for a fragment.

There should be no behaviour change.

Bug: 1066616
Change-Id: I42a08d28d2c5ac5b93aa36c137868a901a848822
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412694
Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811960}
parent f9788a96
...@@ -45,9 +45,14 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create( ...@@ -45,9 +45,14 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
const NGPhysicalBoxStrut borders = const NGPhysicalBoxStrut borders =
builder->initial_fragment_geometry_->border.ConvertToPhysical( builder->initial_fragment_geometry_->border.ConvertToPhysical(
builder->GetWritingMode(), builder->Direction()); builder->GetWritingMode(), builder->Direction());
bool has_borders = !borders.IsZero();
const NGPhysicalBoxStrut padding = const NGPhysicalBoxStrut padding =
builder->initial_fragment_geometry_->padding.ConvertToPhysical( builder->initial_fragment_geometry_->padding.ConvertToPhysical(
builder->GetWritingMode(), builder->Direction()); builder->GetWritingMode(), builder->Direction());
bool has_padding = !padding.IsZero();
base::Optional<PhysicalRect> inflow_bounds;
const PhysicalRect layout_overflow;
bool has_layout_overflow = false;
bool has_rare_data = bool has_rare_data =
builder->mathml_paint_info_ || builder->mathml_paint_info_ ||
!builder->oof_positioned_fragmentainer_descendants_.IsEmpty() || !builder->oof_positioned_fragmentainer_descendants_.IsEmpty() ||
...@@ -58,9 +63,9 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create( ...@@ -58,9 +63,9 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
wtf_size_t num_fragment_items = wtf_size_t num_fragment_items =
builder->ItemsBuilder() ? builder->ItemsBuilder()->Size() : 0; builder->ItemsBuilder() ? builder->ItemsBuilder()->Size() : 0;
size_t byte_size = size_t byte_size = ByteSize(num_fragment_items, builder->children_.size(),
ByteSize(num_fragment_items, builder->children_.size(), !borders.IsZero(), has_layout_overflow, has_borders, has_padding,
!padding.IsZero(), has_rare_data); inflow_bounds.has_value(), has_rare_data);
// We store the children list inline in the fragment as a flexible // We store the children list inline in the fragment as a flexible
// array. Therefore, we need to make sure to allocate enough space for // array. Therefore, we need to make sure to allocate enough space for
...@@ -69,7 +74,9 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create( ...@@ -69,7 +74,9 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
// we pass the buffer as a constructor argument. // we pass the buffer as a constructor argument.
void* data = ::WTF::Partitions::FastMalloc( void* data = ::WTF::Partitions::FastMalloc(
byte_size, ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>()); byte_size, ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>());
new (data) NGPhysicalBoxFragment(PassKey(), builder, borders, padding, new (data) NGPhysicalBoxFragment(PassKey(), builder, has_layout_overflow,
layout_overflow, has_borders, borders,
has_padding, padding, inflow_bounds,
has_rare_data, block_or_line_writing_mode); has_rare_data, block_or_line_writing_mode);
return base::AdoptRef(static_cast<NGPhysicalBoxFragment*>(data)); return base::AdoptRef(static_cast<NGPhysicalBoxFragment*>(data));
} }
...@@ -80,9 +87,10 @@ NGPhysicalBoxFragment::CloneWithPostLayoutFragments( ...@@ -80,9 +87,10 @@ NGPhysicalBoxFragment::CloneWithPostLayoutFragments(
const NGPhysicalBoxFragment& other) { const NGPhysicalBoxFragment& other) {
// The size of the new fragment shouldn't differ from the old one. // The size of the new fragment shouldn't differ from the old one.
wtf_size_t num_fragment_items = other.Items() ? other.Items()->Size() : 0; wtf_size_t num_fragment_items = other.Items() ? other.Items()->Size() : 0;
size_t byte_size = size_t byte_size = ByteSize(num_fragment_items, other.num_children_,
ByteSize(num_fragment_items, other.num_children_, other.has_borders_, other.has_layout_overflow_, other.has_borders_,
other.has_padding_, other.has_rare_data_); other.has_padding_, other.has_inflow_bounds_,
other.has_rare_data_);
void* data = ::WTF::Partitions::FastMalloc( void* data = ::WTF::Partitions::FastMalloc(
byte_size, ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>()); byte_size, ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>());
...@@ -93,22 +101,31 @@ NGPhysicalBoxFragment::CloneWithPostLayoutFragments( ...@@ -93,22 +101,31 @@ NGPhysicalBoxFragment::CloneWithPostLayoutFragments(
// static // static
size_t NGPhysicalBoxFragment::ByteSize(wtf_size_t num_fragment_items, size_t NGPhysicalBoxFragment::ByteSize(wtf_size_t num_fragment_items,
wtf_size_t num_children, wtf_size_t num_children,
bool has_layout_overflow,
bool has_borders, bool has_borders,
bool has_padding, bool has_padding,
bool has_inflow_bounds,
bool has_rare_data) { bool has_rare_data) {
return sizeof(NGPhysicalBoxFragment) + return sizeof(NGPhysicalBoxFragment) +
NGFragmentItems::ByteSizeFor(num_fragment_items) + NGFragmentItems::ByteSizeFor(num_fragment_items) +
sizeof(NGLink) * num_children + sizeof(NGLink) * num_children +
(has_layout_overflow ? sizeof(PhysicalRect) : 0) +
(has_borders ? sizeof(NGPhysicalBoxStrut) : 0) + (has_borders ? sizeof(NGPhysicalBoxStrut) : 0) +
(has_padding ? sizeof(NGPhysicalBoxStrut) : 0) + (has_padding ? sizeof(NGPhysicalBoxStrut) : 0) +
(has_inflow_bounds ? sizeof(PhysicalRect) : 0) +
(has_rare_data ? sizeof(NGPhysicalBoxFragment::RareData) : 0); (has_rare_data ? sizeof(NGPhysicalBoxFragment::RareData) : 0);
} }
NGPhysicalBoxFragment::NGPhysicalBoxFragment( NGPhysicalBoxFragment::NGPhysicalBoxFragment(
PassKey key, PassKey key,
NGBoxFragmentBuilder* builder, NGBoxFragmentBuilder* builder,
bool has_layout_overflow,
const PhysicalRect& layout_overflow,
bool has_borders,
const NGPhysicalBoxStrut& borders, const NGPhysicalBoxStrut& borders,
bool has_padding,
const NGPhysicalBoxStrut& padding, const NGPhysicalBoxStrut& padding,
const base::Optional<PhysicalRect>& inflow_bounds,
bool has_rare_data, bool has_rare_data,
WritingMode block_or_line_writing_mode) WritingMode block_or_line_writing_mode)
: NGPhysicalContainerFragment(builder, : NGPhysicalContainerFragment(builder,
...@@ -119,8 +136,6 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment( ...@@ -119,8 +136,6 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
DCHECK(layout_object_); DCHECK(layout_object_);
DCHECK(layout_object_->IsBoxModelObject()); DCHECK(layout_object_->IsBoxModelObject());
has_rare_data_ = has_rare_data;
has_fragment_items_ = false; has_fragment_items_ = false;
if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) { if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) {
// Omit |NGFragmentItems| if there were no items; e.g., display-lock. // Omit |NGFragmentItems| if there were no items; e.g., display-lock.
...@@ -134,12 +149,21 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment( ...@@ -134,12 +149,21 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
} }
} }
has_borders_ = !borders.IsZero(); has_layout_overflow_ = has_layout_overflow;
if (has_layout_overflow_) {
*const_cast<PhysicalRect*>(ComputeLayoutOverflowAddress()) =
layout_overflow;
}
has_borders_ = has_borders;
if (has_borders_) if (has_borders_)
*const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = borders; *const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = borders;
has_padding_ = !padding.IsZero(); has_padding_ = has_padding;
if (has_padding_) if (has_padding_)
*const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()) = padding; *const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()) = padding;
has_inflow_bounds_ = inflow_bounds.has_value();
if (has_inflow_bounds_)
*const_cast<PhysicalRect*>(ComputeInflowBoundsAddress()) = *inflow_bounds;
has_rare_data_ = has_rare_data;
if (has_rare_data_) { if (has_rare_data_) {
new (const_cast<RareData*>(ComputeRareDataAddress())) new (const_cast<RareData*>(ComputeRareDataAddress()))
RareData(builder, Size()); RareData(builder, Size());
...@@ -192,6 +216,10 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(PassKey key, ...@@ -192,6 +216,10 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(PassKey key,
const_cast<NGFragmentItems*>(ComputeItemsAddress()); const_cast<NGFragmentItems*>(ComputeItemsAddress());
new (items) NGFragmentItems(*other.ComputeItemsAddress()); new (items) NGFragmentItems(*other.ComputeItemsAddress());
} }
if (has_layout_overflow_) {
*const_cast<PhysicalRect*>(ComputeLayoutOverflowAddress()) =
*other.ComputeLayoutOverflowAddress();
}
if (has_borders_) { if (has_borders_) {
*const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = *const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) =
*other.ComputeBordersAddress(); *other.ComputeBordersAddress();
...@@ -200,6 +228,10 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(PassKey key, ...@@ -200,6 +228,10 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(PassKey key,
*const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()) = *const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()) =
*other.ComputePaddingAddress(); *other.ComputePaddingAddress();
} }
if (has_inflow_bounds_) {
*const_cast<PhysicalRect*>(ComputeInflowBoundsAddress()) =
*other.ComputeInflowBoundsAddress();
}
if (has_rare_data_) { if (has_rare_data_) {
new (const_cast<RareData*>(ComputeRareDataAddress())) new (const_cast<RareData*>(ComputeRareDataAddress()))
RareData(*other.ComputeRareDataAddress()); RareData(*other.ComputeRareDataAddress());
......
...@@ -35,8 +35,13 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -35,8 +35,13 @@ class CORE_EXPORT NGPhysicalBoxFragment final
using PassKey = util::PassKey<NGPhysicalBoxFragment>; using PassKey = util::PassKey<NGPhysicalBoxFragment>;
NGPhysicalBoxFragment(PassKey, NGPhysicalBoxFragment(PassKey,
NGBoxFragmentBuilder* builder, NGBoxFragmentBuilder* builder,
bool has_layout_overflow,
const PhysicalRect& layout_overflow,
bool has_borders,
const NGPhysicalBoxStrut& borders, const NGPhysicalBoxStrut& borders,
bool has_padding,
const NGPhysicalBoxStrut& padding, const NGPhysicalBoxStrut& padding,
const base::Optional<PhysicalRect>& inflow_bounds,
bool has_rare_data, bool has_rare_data,
WritingMode block_or_line_writing_mode); WritingMode block_or_line_writing_mode);
...@@ -98,6 +103,15 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -98,6 +103,15 @@ class CORE_EXPORT NGPhysicalBoxFragment final
return ComputeRareDataAddress()->table_cell_column_index; return ComputeRareDataAddress()->table_cell_column_index;
} }
// Returns the layout-overflow for this fragment.
const PhysicalRect LayoutOverflow() const {
if (is_legacy_layout_root_)
return ToLayoutBox(GetLayoutObject())->PhysicalLayoutOverflowRect();
if (!has_layout_overflow_)
return {{}, Size()};
return *ComputeLayoutOverflowAddress();
}
const NGPhysicalBoxStrut Borders() const { const NGPhysicalBoxStrut Borders() const {
if (!has_borders_) if (!has_borders_)
return NGPhysicalBoxStrut(); return NGPhysicalBoxStrut();
...@@ -110,6 +124,16 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -110,6 +124,16 @@ class CORE_EXPORT NGPhysicalBoxFragment final
return *ComputePaddingAddress(); return *ComputePaddingAddress();
} }
// Returns the bounds of any inflow children for this fragment (specifically
// no out-of-flow positioned objects). This will return |base::nullopt| if:
// - The fragment is *not* a scroll container.
// - The scroll container contains no inflow children.
const base::Optional<PhysicalRect> InflowBounds() const {
if (!has_inflow_bounds_)
return base::nullopt;
return *ComputeInflowBoundsAddress();
}
bool HasOutOfFlowPositionedFragmentainerDescendants() const { bool HasOutOfFlowPositionedFragmentainerDescendants() const {
if (!has_rare_data_) if (!has_rare_data_)
return false; return false;
...@@ -232,8 +256,10 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -232,8 +256,10 @@ class CORE_EXPORT NGPhysicalBoxFragment final
private: private:
static size_t ByteSize(wtf_size_t num_fragment_items, static size_t ByteSize(wtf_size_t num_fragment_items,
wtf_size_t num_children, wtf_size_t num_children,
bool has_layout_overflow,
bool has_borders, bool has_borders,
bool has_padding, bool has_padding,
bool has_inflow_bounds,
bool has_rare_data); bool has_rare_data);
struct RareData { struct RareData {
...@@ -254,33 +280,51 @@ class CORE_EXPORT NGPhysicalBoxFragment final ...@@ -254,33 +280,51 @@ class CORE_EXPORT NGPhysicalBoxFragment final
}; };
const NGFragmentItems* ComputeItemsAddress() const { const NGFragmentItems* ComputeItemsAddress() const {
DCHECK(has_fragment_items_ || has_borders_ || has_padding_ || DCHECK(has_fragment_items_ || has_layout_overflow_ || has_borders_ ||
has_rare_data_); has_padding_ || has_inflow_bounds_ || has_rare_data_);
const NGLink* children_end = children_ + Children().size(); const NGLink* children_end = children_ + Children().size();
return reinterpret_cast<const NGFragmentItems*>(children_end); return reinterpret_cast<const NGFragmentItems*>(children_end);
} }
const NGPhysicalBoxStrut* ComputeBordersAddress() const { const PhysicalRect* ComputeLayoutOverflowAddress() const {
DCHECK(has_borders_ || has_padding_ || has_rare_data_); DCHECK(has_layout_overflow_ || has_borders_ || has_padding_ ||
has_inflow_bounds_ || has_rare_data_);
const NGFragmentItems* items = ComputeItemsAddress(); const NGFragmentItems* items = ComputeItemsAddress();
if (!has_fragment_items_) if (!has_fragment_items_)
return reinterpret_cast<const NGPhysicalBoxStrut*>(items); return reinterpret_cast<const PhysicalRect*>(items);
return reinterpret_cast<const NGPhysicalBoxStrut*>( return reinterpret_cast<const PhysicalRect*>(
reinterpret_cast<const uint8_t*>(items) + items->ByteSize()); reinterpret_cast<const uint8_t*>(items) + items->ByteSize());
} }
const NGPhysicalBoxStrut* ComputeBordersAddress() const {
DCHECK(has_borders_ || has_padding_ || has_inflow_bounds_ ||
has_rare_data_);
const PhysicalRect* address = ComputeLayoutOverflowAddress();
return has_layout_overflow_
? reinterpret_cast<const NGPhysicalBoxStrut*>(address + 1)
: reinterpret_cast<const NGPhysicalBoxStrut*>(address);
}
const NGPhysicalBoxStrut* ComputePaddingAddress() const { const NGPhysicalBoxStrut* ComputePaddingAddress() const {
DCHECK(has_padding_ || has_rare_data_); DCHECK(has_padding_ || has_inflow_bounds_ || has_rare_data_);
const NGPhysicalBoxStrut* address = ComputeBordersAddress(); const NGPhysicalBoxStrut* address = ComputeBordersAddress();
return has_borders_ ? address + 1 : address; return has_borders_ ? address + 1 : address;
} }
const RareData* ComputeRareDataAddress() const { const PhysicalRect* ComputeInflowBoundsAddress() const {
DCHECK(has_rare_data_); DCHECK(has_inflow_bounds_ || has_rare_data_);
NGPhysicalBoxStrut* address = NGPhysicalBoxStrut* address =
const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()); const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress());
return has_padding_ ? reinterpret_cast<RareData*>(address + 1) return has_padding_ ? reinterpret_cast<PhysicalRect*>(address + 1)
: reinterpret_cast<RareData*>(address); : reinterpret_cast<PhysicalRect*>(address);
}
const RareData* ComputeRareDataAddress() const {
DCHECK(has_rare_data_);
PhysicalRect* address =
const_cast<PhysicalRect*>(ComputeInflowBoundsAddress());
return has_inflow_bounds_ ? reinterpret_cast<RareData*>(address + 1)
: reinterpret_cast<RareData*>(address);
} }
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
......
...@@ -288,6 +288,8 @@ NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object, ...@@ -288,6 +288,8 @@ NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object,
NGFragmentType type, NGFragmentType type,
unsigned sub_type) unsigned sub_type)
: has_floating_descendants_for_paint_(false), : has_floating_descendants_for_paint_(false),
has_layout_overflow_(false),
has_inflow_bounds_(false),
has_rare_data_(false), has_rare_data_(false),
layout_object_(layout_object), layout_object_(layout_object),
size_(size), size_(size),
...@@ -320,10 +322,12 @@ NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other) ...@@ -320,10 +322,12 @@ NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other)
include_border_right_(other.include_border_right_), include_border_right_(other.include_border_right_),
include_border_bottom_(other.include_border_bottom_), include_border_bottom_(other.include_border_bottom_),
include_border_left_(other.include_border_left_), include_border_left_(other.include_border_left_),
has_layout_overflow_(other.has_layout_overflow_),
has_borders_(other.has_borders_), has_borders_(other.has_borders_),
has_padding_(other.has_padding_), has_padding_(other.has_padding_),
is_first_for_node_(other.is_first_for_node_), has_inflow_bounds_(other.has_inflow_bounds_),
has_rare_data_(other.has_rare_data_), has_rare_data_(other.has_rare_data_),
is_first_for_node_(other.is_first_for_node_),
layout_object_(other.layout_object_), layout_object_(other.layout_object_),
size_(other.size_), size_(other.size_),
type_(other.type_), type_(other.type_),
......
...@@ -454,10 +454,12 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -454,10 +454,12 @@ class CORE_EXPORT NGPhysicalFragment
unsigned include_border_right_ : 1; unsigned include_border_right_ : 1;
unsigned include_border_bottom_ : 1; unsigned include_border_bottom_ : 1;
unsigned include_border_left_ : 1; unsigned include_border_left_ : 1;
unsigned has_layout_overflow_ : 1;
unsigned has_borders_ : 1; unsigned has_borders_ : 1;
unsigned has_padding_ : 1; unsigned has_padding_ : 1;
unsigned is_first_for_node_ : 1; unsigned has_inflow_bounds_ : 1;
unsigned has_rare_data_ : 1; unsigned has_rare_data_ : 1;
unsigned is_first_for_node_ : 1;
LayoutObject* layout_object_; LayoutObject* layout_object_;
const PhysicalSize size_; const PhysicalSize size_;
......
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