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(
const NGPhysicalBoxStrut borders =
builder->initial_fragment_geometry_->border.ConvertToPhysical(
builder->GetWritingMode(), builder->Direction());
bool has_borders = !borders.IsZero();
const NGPhysicalBoxStrut padding =
builder->initial_fragment_geometry_->padding.ConvertToPhysical(
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 =
builder->mathml_paint_info_ ||
!builder->oof_positioned_fragmentainer_descendants_.IsEmpty() ||
......@@ -58,9 +63,9 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
wtf_size_t num_fragment_items =
builder->ItemsBuilder() ? builder->ItemsBuilder()->Size() : 0;
size_t byte_size =
ByteSize(num_fragment_items, builder->children_.size(), !borders.IsZero(),
!padding.IsZero(), has_rare_data);
size_t byte_size = ByteSize(num_fragment_items, builder->children_.size(),
has_layout_overflow, has_borders, has_padding,
inflow_bounds.has_value(), has_rare_data);
// We store the children list inline in the fragment as a flexible
// array. Therefore, we need to make sure to allocate enough space for
......@@ -69,7 +74,9 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
// we pass the buffer as a constructor argument.
void* data = ::WTF::Partitions::FastMalloc(
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);
return base::AdoptRef(static_cast<NGPhysicalBoxFragment*>(data));
}
......@@ -80,9 +87,10 @@ NGPhysicalBoxFragment::CloneWithPostLayoutFragments(
const NGPhysicalBoxFragment& other) {
// 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;
size_t byte_size =
ByteSize(num_fragment_items, other.num_children_, other.has_borders_,
other.has_padding_, other.has_rare_data_);
size_t byte_size = ByteSize(num_fragment_items, other.num_children_,
other.has_layout_overflow_, other.has_borders_,
other.has_padding_, other.has_inflow_bounds_,
other.has_rare_data_);
void* data = ::WTF::Partitions::FastMalloc(
byte_size, ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>());
......@@ -93,22 +101,31 @@ NGPhysicalBoxFragment::CloneWithPostLayoutFragments(
// static
size_t NGPhysicalBoxFragment::ByteSize(wtf_size_t num_fragment_items,
wtf_size_t num_children,
bool has_layout_overflow,
bool has_borders,
bool has_padding,
bool has_inflow_bounds,
bool has_rare_data) {
return sizeof(NGPhysicalBoxFragment) +
NGFragmentItems::ByteSizeFor(num_fragment_items) +
sizeof(NGLink) * num_children +
(has_layout_overflow ? sizeof(PhysicalRect) : 0) +
(has_borders ? sizeof(NGPhysicalBoxStrut) : 0) +
(has_padding ? sizeof(NGPhysicalBoxStrut) : 0) +
(has_inflow_bounds ? sizeof(PhysicalRect) : 0) +
(has_rare_data ? sizeof(NGPhysicalBoxFragment::RareData) : 0);
}
NGPhysicalBoxFragment::NGPhysicalBoxFragment(
PassKey key,
NGBoxFragmentBuilder* builder,
bool has_layout_overflow,
const PhysicalRect& layout_overflow,
bool has_borders,
const NGPhysicalBoxStrut& borders,
bool has_padding,
const NGPhysicalBoxStrut& padding,
const base::Optional<PhysicalRect>& inflow_bounds,
bool has_rare_data,
WritingMode block_or_line_writing_mode)
: NGPhysicalContainerFragment(builder,
......@@ -119,8 +136,6 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
DCHECK(layout_object_);
DCHECK(layout_object_->IsBoxModelObject());
has_rare_data_ = has_rare_data;
has_fragment_items_ = false;
if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) {
// Omit |NGFragmentItems| if there were no items; e.g., display-lock.
......@@ -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_)
*const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = borders;
has_padding_ = !padding.IsZero();
has_padding_ = has_padding;
if (has_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_) {
new (const_cast<RareData*>(ComputeRareDataAddress()))
RareData(builder, Size());
......@@ -192,6 +216,10 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(PassKey key,
const_cast<NGFragmentItems*>(ComputeItemsAddress());
new (items) NGFragmentItems(*other.ComputeItemsAddress());
}
if (has_layout_overflow_) {
*const_cast<PhysicalRect*>(ComputeLayoutOverflowAddress()) =
*other.ComputeLayoutOverflowAddress();
}
if (has_borders_) {
*const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) =
*other.ComputeBordersAddress();
......@@ -200,6 +228,10 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(PassKey key,
*const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()) =
*other.ComputePaddingAddress();
}
if (has_inflow_bounds_) {
*const_cast<PhysicalRect*>(ComputeInflowBoundsAddress()) =
*other.ComputeInflowBoundsAddress();
}
if (has_rare_data_) {
new (const_cast<RareData*>(ComputeRareDataAddress()))
RareData(*other.ComputeRareDataAddress());
......
......@@ -35,8 +35,13 @@ class CORE_EXPORT NGPhysicalBoxFragment final
using PassKey = util::PassKey<NGPhysicalBoxFragment>;
NGPhysicalBoxFragment(PassKey,
NGBoxFragmentBuilder* builder,
bool has_layout_overflow,
const PhysicalRect& layout_overflow,
bool has_borders,
const NGPhysicalBoxStrut& borders,
bool has_padding,
const NGPhysicalBoxStrut& padding,
const base::Optional<PhysicalRect>& inflow_bounds,
bool has_rare_data,
WritingMode block_or_line_writing_mode);
......@@ -98,6 +103,15 @@ class CORE_EXPORT NGPhysicalBoxFragment final
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 {
if (!has_borders_)
return NGPhysicalBoxStrut();
......@@ -110,6 +124,16 @@ class CORE_EXPORT NGPhysicalBoxFragment final
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 {
if (!has_rare_data_)
return false;
......@@ -232,8 +256,10 @@ class CORE_EXPORT NGPhysicalBoxFragment final
private:
static size_t ByteSize(wtf_size_t num_fragment_items,
wtf_size_t num_children,
bool has_layout_overflow,
bool has_borders,
bool has_padding,
bool has_inflow_bounds,
bool has_rare_data);
struct RareData {
......@@ -254,33 +280,51 @@ class CORE_EXPORT NGPhysicalBoxFragment final
};
const NGFragmentItems* ComputeItemsAddress() const {
DCHECK(has_fragment_items_ || has_borders_ || has_padding_ ||
has_rare_data_);
DCHECK(has_fragment_items_ || has_layout_overflow_ || has_borders_ ||
has_padding_ || has_inflow_bounds_ || has_rare_data_);
const NGLink* children_end = children_ + Children().size();
return reinterpret_cast<const NGFragmentItems*>(children_end);
}
const NGPhysicalBoxStrut* ComputeBordersAddress() const {
DCHECK(has_borders_ || has_padding_ || has_rare_data_);
const PhysicalRect* ComputeLayoutOverflowAddress() const {
DCHECK(has_layout_overflow_ || has_borders_ || has_padding_ ||
has_inflow_bounds_ || has_rare_data_);
const NGFragmentItems* items = ComputeItemsAddress();
if (!has_fragment_items_)
return reinterpret_cast<const NGPhysicalBoxStrut*>(items);
return reinterpret_cast<const NGPhysicalBoxStrut*>(
return reinterpret_cast<const PhysicalRect*>(items);
return reinterpret_cast<const PhysicalRect*>(
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 {
DCHECK(has_padding_ || has_rare_data_);
DCHECK(has_padding_ || has_inflow_bounds_ || has_rare_data_);
const NGPhysicalBoxStrut* address = ComputeBordersAddress();
return has_borders_ ? address + 1 : address;
}
const RareData* ComputeRareDataAddress() const {
DCHECK(has_rare_data_);
const PhysicalRect* ComputeInflowBoundsAddress() const {
DCHECK(has_inflow_bounds_ || has_rare_data_);
NGPhysicalBoxStrut* address =
const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress());
return has_padding_ ? reinterpret_cast<RareData*>(address + 1)
: reinterpret_cast<RareData*>(address);
return has_padding_ ? reinterpret_cast<PhysicalRect*>(address + 1)
: 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()
......
......@@ -288,6 +288,8 @@ NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object,
NGFragmentType type,
unsigned sub_type)
: has_floating_descendants_for_paint_(false),
has_layout_overflow_(false),
has_inflow_bounds_(false),
has_rare_data_(false),
layout_object_(layout_object),
size_(size),
......@@ -320,10 +322,12 @@ NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other)
include_border_right_(other.include_border_right_),
include_border_bottom_(other.include_border_bottom_),
include_border_left_(other.include_border_left_),
has_layout_overflow_(other.has_layout_overflow_),
has_borders_(other.has_borders_),
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_),
is_first_for_node_(other.is_first_for_node_),
layout_object_(other.layout_object_),
size_(other.size_),
type_(other.type_),
......
......@@ -454,10 +454,12 @@ class CORE_EXPORT NGPhysicalFragment
unsigned include_border_right_ : 1;
unsigned include_border_bottom_ : 1;
unsigned include_border_left_ : 1;
unsigned has_layout_overflow_ : 1;
unsigned has_borders_ : 1;
unsigned has_padding_ : 1;
unsigned is_first_for_node_ : 1;
unsigned has_inflow_bounds_ : 1;
unsigned has_rare_data_ : 1;
unsigned is_first_for_node_ : 1;
LayoutObject* layout_object_;
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