blob: 1eb55b3a816b5a1b7cf574cfcde5da663d68a833 [file] [log] [blame]
// Copyright 2016 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.
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include <memory>
#include <utility>
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
namespace blink {
NGLayoutResult::NGLayoutResult(
scoped_refptr<const NGPhysicalFragment> physical_fragment,
NGBoxFragmentBuilder* builder)
: unpositioned_list_marker_(builder->unpositioned_list_marker_),
exclusion_space_(std::move(builder->exclusion_space_)),
bfc_line_offset_(builder->bfc_line_offset_),
bfc_block_offset_(builder->bfc_block_offset_),
end_margin_strut_(builder->end_margin_strut_),
intrinsic_block_size_(builder->intrinsic_block_size_),
minimal_space_shortage_(builder->minimal_space_shortage_),
initial_break_before_(builder->initial_break_before_),
final_break_after_(builder->previous_break_after_),
has_forced_break_(builder->has_forced_break_),
is_pushed_by_floats_(builder->is_pushed_by_floats_),
adjoining_floats_(builder->adjoining_floats_),
has_orthogonal_flow_roots_(builder->has_orthogonal_flow_roots_),
depends_on_percentage_block_size_(DependsOnPercentageBlockSize(*builder)),
status_(kSuccess) {
DCHECK(physical_fragment) << "Use the other constructor for aborting layout";
root_fragment_.fragment_ = std::move(physical_fragment);
oof_positioned_descendants_ = std::move(builder->oof_positioned_descendants_);
}
NGLayoutResult::NGLayoutResult(NGLayoutResultStatus status,
NGBoxFragmentBuilder* builder)
: bfc_line_offset_(builder->bfc_line_offset_),
bfc_block_offset_(builder->bfc_block_offset_),
end_margin_strut_(builder->end_margin_strut_),
initial_break_before_(EBreakBetween::kAuto),
final_break_after_(EBreakBetween::kAuto),
has_forced_break_(false),
is_pushed_by_floats_(false),
adjoining_floats_(kFloatTypeNone),
has_orthogonal_flow_roots_(builder->has_orthogonal_flow_roots_),
depends_on_percentage_block_size_(false),
status_(status) {
DCHECK_NE(status, kSuccess)
<< "Use the other constructor for successful layout";
}
NGLayoutResult::NGLayoutResult(
scoped_refptr<const NGPhysicalFragment> physical_fragment,
NGLineBoxFragmentBuilder* builder)
: unpositioned_list_marker_(builder->unpositioned_list_marker_),
exclusion_space_(std::move(builder->exclusion_space_)),
bfc_line_offset_(builder->bfc_line_offset_),
bfc_block_offset_(builder->bfc_block_offset_),
end_margin_strut_(builder->end_margin_strut_),
minimal_space_shortage_(LayoutUnit::Max()),
initial_break_before_(EBreakBetween::kAuto),
final_break_after_(EBreakBetween::kAuto),
has_forced_break_(false),
is_pushed_by_floats_(builder->is_pushed_by_floats_),
adjoining_floats_(builder->adjoining_floats_),
has_orthogonal_flow_roots_(builder->has_orthogonal_flow_roots_),
depends_on_percentage_block_size_(DependsOnPercentageBlockSize(*builder)),
status_(kSuccess) {
root_fragment_.fragment_ = std::move(physical_fragment);
oof_positioned_descendants_ = std::move(builder->oof_positioned_descendants_);
}
// We can't use =default here because RefCounted can't be copied.
NGLayoutResult::NGLayoutResult(const NGLayoutResult& other,
base::Optional<LayoutUnit> bfc_block_offset)
: root_fragment_(other.root_fragment_),
oof_positioned_descendants_(other.oof_positioned_descendants_),
unpositioned_list_marker_(other.unpositioned_list_marker_),
exclusion_space_(other.exclusion_space_),
bfc_line_offset_(other.bfc_line_offset_),
bfc_block_offset_(bfc_block_offset),
end_margin_strut_(other.end_margin_strut_),
intrinsic_block_size_(other.intrinsic_block_size_),
minimal_space_shortage_(other.minimal_space_shortage_),
initial_break_before_(other.initial_break_before_),
final_break_after_(other.final_break_after_),
has_forced_break_(other.has_forced_break_),
is_pushed_by_floats_(other.is_pushed_by_floats_),
adjoining_floats_(other.adjoining_floats_),
has_orthogonal_flow_roots_(other.has_orthogonal_flow_roots_),
depends_on_percentage_block_size_(
other.depends_on_percentage_block_size_),
status_(other.status_) {}
// Define the destructor here, so that we can forward-declare more in the
// header.
NGLayoutResult::~NGLayoutResult() = default;
bool NGLayoutResult::DependsOnPercentageBlockSize(
const NGContainerFragmentBuilder& builder) {
NGLayoutInputNode node = builder.node_;
if (!node || node.IsInline())
return builder.has_depends_on_percentage_block_size_child_;
// NOTE: If an element is OOF positioned, and has top/bottom constraints
// which are percentage based, this function will return false.
//
// This is fine as the top/bottom constraints are computed *before* layout,
// and the result is set as a fixed-block-size constraint. (And the caching
// logic will never check the result of this function).
//
// The result of this function still may be used for an OOF positioned
// element if it has a percentage block-size however, but this will return
// the correct result from below.
const ComputedStyle& style = builder.Style();
if (style.LogicalHeight().IsAuto() &&
builder.has_depends_on_percentage_block_size_child_) {
// Quirks mode has different %-block-size behaviour, than standards mode.
// An arbitrary descendant may depend on the percentage resolution
// block-size given.
// If this is also an anonymous block we need to mark ourselves dependent
// if we have a dependent child.
if (node.IsAnonymousBlock() || node.GetDocument().InQuirksMode())
return true;
}
if (style.LogicalHeight().IsPercentOrCalc() ||
style.LogicalMinHeight().IsPercentOrCalc() ||
style.LogicalMaxHeight().IsPercentOrCalc())
return true;
return false;
}
} // namespace blink