summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc127
1 files changed, 78 insertions, 49 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 80d066499e2..2d1a57926ad 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -196,6 +196,10 @@ void UpdateLegacyMultiColumnFlowThread(
LayoutMultiColumnSet* column_set =
ToLayoutMultiColumnSetOrNull(flow_thread->FirstMultiColumnBox());
for (const auto& child : fragment.Children()) {
+ // TODO(almaher): Remove check for out of flow.
+ if (child->IsOutOfFlowPositioned())
+ continue;
+
if (child->GetLayoutObject() &&
child->GetLayoutObject()->IsColumnSpanAll()) {
// Column spanners are not part of the fragmentation context. We'll use
@@ -258,11 +262,16 @@ void UpdateLegacyMultiColumnFlowThread(
flow_thread->ClearNeedsLayout();
}
-NGConstraintSpace CreateConstraintSpaceForMinMax(const NGBlockNode& node) {
+NGConstraintSpace CreateConstraintSpaceForMinMax(
+ const NGBlockNode& node,
+ const MinMaxSizesInput& input) {
NGConstraintSpaceBuilder builder(node.Style().GetWritingMode(),
node.Style().GetWritingMode(),
node.CreatesNewFormattingContext());
builder.SetTextDirection(node.Style().Direction());
+ builder.SetAvailableSize(LogicalSize());
+ builder.SetPercentageResolutionSize(
+ {LayoutUnit(), input.percentage_resolution_block_size});
return builder.ToConstraintSpace();
}
@@ -351,7 +360,7 @@ bool CanUseCachedIntrinsicInlineSizes(const MinMaxSizesInput& input,
scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
const NGConstraintSpace& constraint_space,
const NGBlockBreakToken* break_token,
- const NGEarlyBreak* early_break) {
+ const NGEarlyBreak* early_break) const {
// Use the old layout code and synthesize a fragment.
if (!CanUseNewLayout())
return RunLegacyLayout(constraint_space);
@@ -508,7 +517,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
}
scoped_refptr<const NGLayoutResult> NGBlockNode::SimplifiedLayout(
- const NGPhysicalFragment& previous_fragment) {
+ const NGPhysicalFragment& previous_fragment) const {
scoped_refptr<const NGLayoutResult> previous_result =
box_->GetCachedLayoutResult();
DCHECK(previous_result);
@@ -587,7 +596,7 @@ NGBlockNode::CachedLayoutResultForOutOfFlowPositioned(
return cached_layout_result;
}
-void NGBlockNode::PrepareForLayout() {
+void NGBlockNode::PrepareForLayout() const {
auto* block = DynamicTo<LayoutBlock>(box_);
if (block && block->HasOverflowClip()) {
DCHECK(block->GetScrollableArea());
@@ -605,7 +614,7 @@ void NGBlockNode::FinishLayout(
LayoutBlockFlow* block_flow,
const NGConstraintSpace& constraint_space,
const NGBlockBreakToken* break_token,
- scoped_refptr<const NGLayoutResult> layout_result) {
+ scoped_refptr<const NGLayoutResult> layout_result) const {
// If we abort layout and don't clear the cached layout-result, we can end
// up in a state where the layout-object tree doesn't match fragment tree
// referenced by this layout-result.
@@ -676,7 +685,7 @@ void NGBlockNode::FinishLayout(
MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
WritingMode container_writing_mode,
const MinMaxSizesInput& input,
- const NGConstraintSpace* constraint_space) {
+ const NGConstraintSpace* constraint_space) const {
// TODO(layoutng) Can UpdateMarkerTextIfNeeded call be moved
// somewhere else? List items need up-to-date markers before layout.
if (IsListItem())
@@ -687,6 +696,10 @@ MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
// If we're orthogonal, run layout to compute the sizes.
if (is_orthogonal_flow_root) {
+ // If we have an aspect ratio, we may be able to avoid laying out the
+ // child as an optimization, if performance testing shows this to be
+ // important.
+
MinMaxSizes sizes;
// Some other areas of the code can query the intrinsic-sizes while outside
// of the layout phase.
@@ -706,6 +719,24 @@ MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
return {sizes, /* depends_on_percentage_block_size */ false};
}
+ // Synthesize a zero space if not provided.
+ auto zero_constraint_space = CreateConstraintSpaceForMinMax(*this, input);
+ if (!constraint_space)
+ constraint_space = &zero_constraint_space;
+
+ if (Style().AspectRatio() && input.type == MinMaxSizesType::kContent) {
+ NGFragmentGeometry fragment_geometry =
+ CalculateInitialMinMaxFragmentGeometry(*constraint_space, *this);
+ NGBoxStrut border_padding =
+ fragment_geometry.border + fragment_geometry.padding;
+ LayoutUnit size_from_ar = ComputeInlineSizeFromAspectRatio(
+ *constraint_space, Style(), border_padding);
+ if (size_from_ar != kIndefiniteSize) {
+ return {{size_from_ar, size_from_ar},
+ Style().LogicalHeight().IsPercentOrCalc()};
+ }
+ }
+
bool can_use_cached_intrinsic_inline_sizes =
CanUseCachedIntrinsicInlineSizes(input, *this);
@@ -723,11 +754,6 @@ MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
return {sizes, depends_on_percentage_block_size};
}
- // Synthesize a zero space if not provided.
- auto zero_constraint_space = CreateConstraintSpaceForMinMax(*this);
- if (!constraint_space)
- constraint_space = &zero_constraint_space;
-
NGFragmentGeometry fragment_geometry =
CalculateInitialMinMaxFragmentGeometry(*constraint_space, *this);
@@ -918,23 +944,42 @@ String NGBlockNode::ToString() const {
void NGBlockNode::CopyFragmentDataToLayoutBox(
const NGConstraintSpace& constraint_space,
const NGLayoutResult& layout_result,
- const NGBlockBreakToken* previous_break_token) {
+ const NGBlockBreakToken* previous_break_token) const {
const auto& physical_fragment =
To<NGPhysicalBoxFragment>(layout_result.PhysicalFragment());
NGBoxFragment fragment(constraint_space.GetWritingMode(),
constraint_space.Direction(), physical_fragment);
LogicalSize fragment_logical_size = fragment.Size();
- // For each fragment we process, we'll accumulate the logical height and
- // logical intrinsic content box height. We reset it at the first fragment,
- // and accumulate at each method call for fragments belonging to the same
- // layout object. Logical width will only be set at the first fragment and is
- // expected to remain the same throughout all subsequent fragments, since
- // legacy layout doesn't support non-uniform fragmentainer widths.
- LayoutUnit intrinsic_content_logical_height;
+ NGBoxStrut borders = fragment.Borders();
+ NGBoxStrut scrollbars = ComputeScrollbars(constraint_space, *this);
+ NGBoxStrut padding = fragment.Padding();
+ NGBoxStrut border_scrollbar_padding = borders + scrollbars + padding;
+ bool is_last_fragment = !physical_fragment.BreakToken();
+
+ // For each fragment we process, we'll accumulate the logical height. We reset
+ // it at the first fragment, and accumulate at each method call for fragments
+ // belonging to the same layout object. Logical width will only be set at the
+ // first fragment and is expected to remain the same throughout all subsequent
+ // fragments, since legacy layout doesn't support non-uniform fragmentainer
+ // widths.
if (LIKELY(physical_fragment.IsFirstForNode())) {
box_->SetSize(LayoutSize(physical_fragment.Size().width,
physical_fragment.Size().height));
+ // If this is a fragment from a node that didn't break into multiple
+ // fragments, write back the intrinsic size. We skip this if the node has
+ // fragmented, since intrinsic block-size is rather meaningless in that
+ // case, because the block-size may have been affected by something on the
+ // outside (i.e. the fragmentainer).
+ //
+ // If we had a fixed block size, our children will have sized themselves
+ // relative to the fixed size, which would make our intrinsic size incorrect
+ // (too big). So skip the write-back in that case, too.
+ if (LIKELY(is_last_fragment && !constraint_space.IsFixedBlockSize())) {
+ box_->SetIntrinsicContentLogicalHeight(
+ layout_result.IntrinsicBlockSize() -
+ border_scrollbar_padding.BlockSum());
+ }
} else {
DCHECK_EQ(box_->LogicalWidth(), fragment_logical_size.inline_size)
<< "Variable fragment inline size not supported";
@@ -942,24 +987,6 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
if (previous_break_token)
logical_height += previous_break_token->ConsumedBlockSize();
box_->SetLogicalHeight(logical_height);
- intrinsic_content_logical_height = box_->IntrinsicContentLogicalHeight();
- }
-
- intrinsic_content_logical_height += layout_result.IntrinsicBlockSize();
-
- NGBoxStrut borders = fragment.Borders();
- NGBoxStrut scrollbars = ComputeScrollbars(constraint_space, *this);
- NGBoxStrut padding = fragment.Padding();
- NGBoxStrut border_scrollbar_padding = borders + scrollbars + padding;
- bool is_last_fragment = !physical_fragment.BreakToken();
-
- if (LIKELY(is_last_fragment))
- intrinsic_content_logical_height -= border_scrollbar_padding.BlockSum();
- if (!constraint_space.IsFixedBlockSize()) {
- // If we had a fixed block size, our children will have sized themselves
- // relative to the fixed size, which would make our intrinsic size
- // incorrect (too big).
- box_->SetIntrinsicContentLogicalHeight(intrinsic_content_logical_height);
}
// TODO(mstensho): This should always be done by the parent algorithm, since
@@ -1041,7 +1068,7 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
void NGBlockNode::PlaceChildrenInLayoutBox(
const NGPhysicalBoxFragment& physical_fragment,
- const NGBlockBreakToken* previous_break_token) {
+ const NGBlockBreakToken* previous_break_token) const {
LayoutBox* rendered_legend = nullptr;
for (const auto& child_fragment : physical_fragment.Children()) {
// Skip any line-boxes we have as children, this is handled within
@@ -1078,12 +1105,14 @@ void NGBlockNode::PlaceChildrenInLayoutBox(
}
void NGBlockNode::PlaceChildrenInFlowThread(
- const NGPhysicalBoxFragment& physical_fragment) {
+ const NGPhysicalBoxFragment& physical_fragment) const {
const NGBlockBreakToken* previous_break_token = nullptr;
for (const auto& child : physical_fragment.Children()) {
const LayoutObject* child_object = child->GetLayoutObject();
if (child_object && child_object != box_) {
- DCHECK(child_object->IsColumnSpanAll());
+ // TODO(almaher): Remove check for out of flow.
+ DCHECK(child_object->IsColumnSpanAll() ||
+ child_object->IsOutOfFlowPositioned());
CopyChildFragmentPosition(To<NGPhysicalBoxFragment>(*child), child.offset,
physical_fragment);
continue;
@@ -1102,7 +1131,7 @@ void NGBlockNode::CopyChildFragmentPosition(
const NGPhysicalBoxFragment& child_fragment,
PhysicalOffset offset,
const NGPhysicalBoxFragment& container_fragment,
- const NGBlockBreakToken* previous_container_break_token) {
+ const NGBlockBreakToken* previous_container_break_token) const {
LayoutBox* layout_box = ToLayoutBox(child_fragment.GetMutableLayoutObject());
if (!layout_box)
return;
@@ -1140,7 +1169,7 @@ void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren(
const NGPhysicalContainerFragment& container,
LayoutUnit initial_container_width,
bool initial_container_is_flipped,
- PhysicalOffset offset) {
+ PhysicalOffset offset) const {
DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
for (const auto& child : container.Children()) {
if (child->IsContainer()) {
@@ -1185,7 +1214,7 @@ void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren(
void NGBlockNode::CopyFragmentItemsToLayoutBox(
const NGPhysicalBoxFragment& container,
- const NGFragmentItems& items) {
+ const NGFragmentItems& items) const {
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
bool initial_container_is_flipped = Style().IsFlippedBlocksWritingMode();
@@ -1321,7 +1350,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::LayoutAtomicInline(
}
scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
- const NGConstraintSpace& constraint_space) {
+ const NGConstraintSpace& constraint_space) const {
// This is an exit-point from LayoutNG to the legacy engine. This means that
// we need to be at a formatting context boundary, since NG and legacy don't
// cooperate on e.g. margin collapsing.
@@ -1371,7 +1400,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
// TODO(kojii): Implement use_first_line_style.
NGBoxFragmentBuilder builder(*this, box_->Style(), &constraint_space,
- writing_mode, box_->StyleRef().Direction());
+ {writing_mode, box_->StyleRef().Direction()});
builder.SetIsNewFormattingContext(
constraint_space.IsNewFormattingContext());
builder.SetInitialFragmentGeometry(fragment_geometry);
@@ -1452,7 +1481,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunSimplifiedLayout(
void NGBlockNode::CopyBaselinesFromLegacyLayout(
const NGConstraintSpace& constraint_space,
- NGBoxFragmentBuilder* builder) {
+ NGBoxFragmentBuilder* builder) const {
// As the calls to query baselines from legacy layout are potentially
// expensive we only ask for them if needed.
// TODO(layout-dev): Once we have flexbox, and editing switched over to
@@ -1479,7 +1508,7 @@ void NGBlockNode::CopyBaselinesFromLegacyLayout(
}
LayoutUnit NGBlockNode::AtomicInlineBaselineFromLegacyLayout(
- const NGConstraintSpace& constraint_space) {
+ const NGConstraintSpace& constraint_space) const {
LineDirectionMode line_direction = box_->IsHorizontalWritingMode()
? LineDirectionMode::kHorizontalLine
: LineDirectionMode::kVerticalLine;
@@ -1512,7 +1541,7 @@ LayoutUnit NGBlockNode::AtomicInlineBaselineFromLegacyLayout(
// in the parents writing mode.
void NGBlockNode::UpdateShapeOutsideInfoIfNeeded(
const NGLayoutResult& layout_result,
- LayoutUnit percentage_resolution_inline_size) {
+ LayoutUnit percentage_resolution_inline_size) const {
if (!box_->IsFloating() || !box_->GetShapeOutsideInfo())
return;
@@ -1550,7 +1579,7 @@ void NGBlockNode::StoreMargins(const NGPhysicalBoxStrut& physical_margins) {
void NGBlockNode::AddColumnResult(
scoped_refptr<const NGLayoutResult> result,
- const NGBlockBreakToken* incoming_break_token) {
+ const NGBlockBreakToken* incoming_break_token) const {
wtf_size_t index = FragmentIndex(incoming_break_token);
GetFlowThread(To<LayoutBlockFlow>(box_))->AddLayoutResult(result, index);
}