Commit 4b4053d0 authored by Ian Kilpatrick's avatar Ian Kilpatrick Committed by Commit Bot

[FlexNG] Lazily calculate the MinMaxSize and IntrinsicBlockSize for flex-items.

This patch introduces variants of:
Resolve{Main,Min,Max}{Inline,Block}Length

With a callback function to provide the MinMaxSize, or IntrinsicBlockSize
as needed.

This in instead of logic used by other algorithms via. NeedMinMaxSize
et. al.

There are pros/cons to this approach:
Pro - Much more precise (and easier to maintain) calls to
      NGBlockNode::ComputeMinMaxSize and NGBlockNode::Layout.
Con - Duplicate logic for Resolve*Length.

I tried moving Resolve*InlineLength to all being callback based but some
other refactoring needs to occur first (mainly an additional ng cache).

An alternate version of this patch would be either:
1) A NeedsMinMaxSize / NeedsIntrinsicBlockSize similar to other callers
   of these functions.
2) Adding the branch before the Resolve*Length calls to check if we
   need to provide the appropriate argument.

Bug: 845235
Change-Id: I8e26e0171adc60a7e3d244af3cb21e119b2653f1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2027075Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Reviewed-by: default avatarDavid Grogan <dgrogan@chromium.org>
Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738379}
parent ecde9593
...@@ -353,7 +353,6 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -353,7 +353,6 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
const ComputedStyle& child_style = child.Style(); const ComputedStyle& child_style = child.Style();
NGConstraintSpace flex_basis_space = BuildSpaceForFlexBasis(child); NGConstraintSpace flex_basis_space = BuildSpaceForFlexBasis(child);
NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(child);
NGBoxStrut border_padding_in_child_writing_mode = NGBoxStrut border_padding_in_child_writing_mode =
ComputeBorders(flex_basis_space, child) + ComputeBorders(flex_basis_space, child) +
...@@ -370,20 +369,29 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -370,20 +369,29 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
is_horizontal_flow_ ? physical_border_padding.VerticalSum() is_horizontal_flow_ ? physical_border_padding.VerticalSum()
: physical_border_padding.HorizontalSum(); : physical_border_padding.HorizontalSum();
// TODO(dgrogan): Don't layout every time, just when you need to. base::Optional<LayoutUnit> intrinsic_block_size;
// Use ChildHasIntrinsicMainAxisSize as a guide. auto IntrinsicBlockSizeFunc = [&]() -> LayoutUnit {
scoped_refptr<const NGLayoutResult> layout_result = if (!intrinsic_block_size) {
child.Layout(child_space, /* break_token */ nullptr); NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(child);
intrinsic_block_size =
// We want the child's min/max size in its writing mode, not ours. We'll child.Layout(child_space, /* break_token */ nullptr)
// only ever use it if the child's inline axis is our main axis. ->IntrinsicBlockSize();
// }
// Always calculate the min/max sizes after a layout in order to corrrectly return *intrinsic_block_size;
// account for any scrollbars. };
MinMaxSizeInput input(
/* percentage_resolution_block_size */ content_box_size_.block_size); base::Optional<MinMaxSize> min_max_size;
MinMaxSize intrinsic_sizes_border_box = child.ComputeMinMaxSize( auto MinMaxSizeFunc = [&]() -> MinMaxSize {
child_style.GetWritingMode(), input, &child_space); if (!min_max_size) {
// We want the child's min/max size in its writing mode, not ours.
// We'll only ever use it if the child's inline axis is our main axis.
NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(child);
min_max_size = child.ComputeMinMaxSize(
child_style.GetWritingMode(),
MinMaxSizeInput(content_box_size_.block_size), &child_space);
}
return *min_max_size;
};
LayoutUnit flex_base_border_box; LayoutUnit flex_base_border_box;
const Length& specified_length_in_main_axis = const Length& specified_length_in_main_axis =
...@@ -396,9 +404,9 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -396,9 +404,9 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
// we should interpret it as flex-basis:content. // we should interpret it as flex-basis:content.
if (flex_basis.IsAuto() && specified_length_in_main_axis.IsAuto()) { if (flex_basis.IsAuto() && specified_length_in_main_axis.IsAuto()) {
if (MainAxisIsInlineAxis(child)) if (MainAxisIsInlineAxis(child))
flex_base_border_box = intrinsic_sizes_border_box.max_size; flex_base_border_box = MinMaxSizeFunc().max_size;
else else
flex_base_border_box = layout_result->IntrinsicBlockSize(); flex_base_border_box = IntrinsicBlockSizeFunc();
} else { } else {
// TODO(dgrogan): Check for definiteness. // TODO(dgrogan): Check for definiteness.
// This block covers case A in // This block covers case A in
...@@ -410,13 +418,13 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -410,13 +418,13 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
if (MainAxisIsInlineAxis(child)) { if (MainAxisIsInlineAxis(child)) {
flex_base_border_box = ResolveMainInlineLength( flex_base_border_box = ResolveMainInlineLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
intrinsic_sizes_border_box, length_to_resolve); MinMaxSizeFunc, length_to_resolve);
} else { } else {
// Flex container's main axis is in child's block direction. Child's // Flex container's main axis is in child's block direction. Child's
// flex basis is in child's block direction. // flex basis is in child's block direction.
flex_base_border_box = ResolveMainBlockLength( flex_base_border_box = ResolveMainBlockLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
length_to_resolve, layout_result->IntrinsicBlockSize(), length_to_resolve, IntrinsicBlockSizeFunc,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
} }
} }
...@@ -444,28 +452,28 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -444,28 +452,28 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
if (MainAxisIsInlineAxis(child)) { if (MainAxisIsInlineAxis(child)) {
min_max_sizes_in_main_axis_direction.max_size = ResolveMaxInlineLength( min_max_sizes_in_main_axis_direction.max_size = ResolveMaxInlineLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
intrinsic_sizes_border_box, max_property_in_main_axis, MinMaxSizeFunc, max_property_in_main_axis,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
min_max_sizes_in_cross_axis_direction.max_size = ResolveMaxBlockLength( min_max_sizes_in_cross_axis_direction.max_size = ResolveMaxBlockLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
max_property_in_cross_axis, layout_result->IntrinsicBlockSize(), max_property_in_cross_axis, IntrinsicBlockSizeFunc,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
min_max_sizes_in_cross_axis_direction.min_size = ResolveMinBlockLength( min_max_sizes_in_cross_axis_direction.min_size = ResolveMinBlockLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
min_property_in_cross_axis, layout_result->IntrinsicBlockSize(), min_property_in_cross_axis, IntrinsicBlockSizeFunc,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
} else { } else {
min_max_sizes_in_main_axis_direction.max_size = ResolveMaxBlockLength( min_max_sizes_in_main_axis_direction.max_size = ResolveMaxBlockLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
max_property_in_main_axis, layout_result->IntrinsicBlockSize(), max_property_in_main_axis, IntrinsicBlockSizeFunc,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
min_max_sizes_in_cross_axis_direction.max_size = ResolveMaxInlineLength( min_max_sizes_in_cross_axis_direction.max_size = ResolveMaxInlineLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
intrinsic_sizes_border_box, max_property_in_cross_axis, MinMaxSizeFunc, max_property_in_cross_axis,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
min_max_sizes_in_cross_axis_direction.min_size = ResolveMinInlineLength( min_max_sizes_in_cross_axis_direction.min_size = ResolveMinInlineLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
intrinsic_sizes_border_box, min_property_in_cross_axis, MinMaxSizeFunc, min_property_in_cross_axis,
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
} }
...@@ -486,9 +494,9 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -486,9 +494,9 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
// TODO(dgrogan): Do the aspect ratio parts of // TODO(dgrogan): Do the aspect ratio parts of
// https://www.w3.org/TR/css-flexbox-1/#min-size-auto // https://www.w3.org/TR/css-flexbox-1/#min-size-auto
LayoutUnit content_size_suggestion = LayoutUnit content_size_suggestion = MainAxisIsInlineAxis(child)
MainAxisIsInlineAxis(child) ? intrinsic_sizes_border_box.min_size ? MinMaxSizeFunc().min_size
: layout_result->IntrinsicBlockSize(); : IntrinsicBlockSizeFunc();
content_size_suggestion = content_size_suggestion =
std::min(content_size_suggestion, std::min(content_size_suggestion,
min_max_sizes_in_main_axis_direction.max_size); min_max_sizes_in_main_axis_direction.max_size);
...@@ -518,17 +526,16 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -518,17 +526,16 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
// calculation. Reuse that if possible. // calculation. Reuse that if possible.
specified_size_suggestion = ResolveMainInlineLength( specified_size_suggestion = ResolveMainInlineLength(
flex_basis_space, child_style, flex_basis_space, child_style,
border_padding_in_child_writing_mode, border_padding_in_child_writing_mode, MinMaxSizeFunc,
intrinsic_sizes_border_box, specified_length_in_main_axis); specified_length_in_main_axis);
} }
} else if (!BlockLengthUnresolvable(flex_basis_space, } else if (!BlockLengthUnresolvable(flex_basis_space,
specified_length_in_main_axis, specified_length_in_main_axis,
LengthResolvePhase::kLayout)) { LengthResolvePhase::kLayout)) {
specified_size_suggestion = specified_size_suggestion = ResolveMainBlockLength(
ResolveMainBlockLength(flex_basis_space, child_style, flex_basis_space, child_style,
border_padding_in_child_writing_mode, border_padding_in_child_writing_mode,
specified_length_in_main_axis, specified_length_in_main_axis, IntrinsicBlockSizeFunc,
layout_result->IntrinsicBlockSize(),
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
DCHECK_NE(specified_size_suggestion, kIndefiniteSize); DCHECK_NE(specified_size_suggestion, kIndefiniteSize);
} }
...@@ -544,12 +551,11 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { ...@@ -544,12 +551,11 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
} else if (MainAxisIsInlineAxis(child)) { } else if (MainAxisIsInlineAxis(child)) {
min_max_sizes_in_main_axis_direction.min_size = ResolveMinInlineLength( min_max_sizes_in_main_axis_direction.min_size = ResolveMinInlineLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
intrinsic_sizes_border_box, min, LengthResolvePhase::kLayout); MinMaxSizeFunc, min, LengthResolvePhase::kLayout);
} else { } else {
min_max_sizes_in_main_axis_direction.min_size = ResolveMinBlockLength( min_max_sizes_in_main_axis_direction.min_size = ResolveMinBlockLength(
flex_basis_space, child_style, border_padding_in_child_writing_mode, flex_basis_space, child_style, border_padding_in_child_writing_mode,
min, layout_result->IntrinsicBlockSize(), min, IntrinsicBlockSizeFunc, LengthResolvePhase::kLayout);
LengthResolvePhase::kLayout);
} }
min_max_sizes_in_main_axis_direction -= main_axis_border_padding; min_max_sizes_in_main_axis_direction -= main_axis_border_padding;
......
...@@ -115,7 +115,7 @@ LayoutUnit ResolveInlineLengthInternal( ...@@ -115,7 +115,7 @@ LayoutUnit ResolveInlineLengthInternal(
const NGConstraintSpace& constraint_space, const NGConstraintSpace& constraint_space,
const ComputedStyle& style, const ComputedStyle& style,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_and_max, const base::Optional<MinMaxSize>& min_max_size,
const Length& length) { const Length& length) {
DCHECK_GE(constraint_space.AvailableSize().inline_size, LayoutUnit()); DCHECK_GE(constraint_space.AvailableSize().inline_size, LayoutUnit());
DCHECK_GE(constraint_space.PercentageResolutionInlineSize(), LayoutUnit()); DCHECK_GE(constraint_space.PercentageResolutionInlineSize(), LayoutUnit());
...@@ -146,20 +146,20 @@ LayoutUnit ResolveInlineLengthInternal( ...@@ -146,20 +146,20 @@ LayoutUnit ResolveInlineLengthInternal(
case Length::kMinContent: case Length::kMinContent:
case Length::kMaxContent: case Length::kMaxContent:
case Length::kFitContent: { case Length::kFitContent: {
DCHECK(min_and_max.has_value()); DCHECK(min_max_size.has_value());
LayoutUnit available_size = constraint_space.AvailableSize().inline_size; LayoutUnit available_size = constraint_space.AvailableSize().inline_size;
LayoutUnit value; LayoutUnit value;
if (length.IsMinContent()) { if (length.IsMinContent()) {
value = min_and_max->min_size; value = min_max_size->min_size;
} else if (length.IsMaxContent() || available_size == LayoutUnit::Max()) { } else if (length.IsMaxContent() || available_size == LayoutUnit::Max()) {
// If the available space is infinite, fit-content resolves to // If the available space is infinite, fit-content resolves to
// max-content. See css-sizing section 2.1. // max-content. See css-sizing section 2.1.
value = min_and_max->max_size; value = min_max_size->max_size;
} else { } else {
NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style); NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
LayoutUnit fill_available = LayoutUnit fill_available =
std::max(LayoutUnit(), available_size - margins.InlineSum()); std::max(LayoutUnit(), available_size - margins.InlineSum());
value = min_and_max->ShrinkToFit(fill_available); value = min_max_size->ShrinkToFit(fill_available);
} }
return value; return value;
} }
...@@ -246,7 +246,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -246,7 +246,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
WritingMode parent_writing_mode, WritingMode parent_writing_mode,
const ComputedStyle& style, const ComputedStyle& style,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_and_max) { const base::Optional<MinMaxSize>& min_max_size) {
WritingMode child_writing_mode = style.GetWritingMode(); WritingMode child_writing_mode = style.GetWritingMode();
// Synthesize a zero-sized constraint space for resolving sizes against. // Synthesize a zero-sized constraint space for resolving sizes against.
...@@ -256,7 +256,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -256,7 +256,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
.ToConstraintSpace(); .ToConstraintSpace();
LayoutUnit content_size = LayoutUnit content_size =
min_and_max ? min_and_max->max_size : kIndefiniteSize; min_max_size ? min_max_size->max_size : kIndefiniteSize;
MinMaxSize computed_sizes; MinMaxSize computed_sizes;
const Length& inline_size = parent_writing_mode == WritingMode::kHorizontalTb const Length& inline_size = parent_writing_mode == WritingMode::kHorizontalTb
...@@ -264,12 +264,12 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -264,12 +264,12 @@ MinMaxSize ComputeMinAndMaxContentContribution(
: style.Height(); : style.Height();
if (inline_size.IsAuto() || inline_size.IsPercentOrCalc() || if (inline_size.IsAuto() || inline_size.IsPercentOrCalc() ||
inline_size.IsFillAvailable() || inline_size.IsFitContent()) { inline_size.IsFillAvailable() || inline_size.IsFitContent()) {
CHECK(min_and_max.has_value()); CHECK(min_max_size.has_value());
computed_sizes = *min_and_max; computed_sizes = *min_max_size;
} else { } else {
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) { if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
computed_sizes = ResolveMainInlineLength(space, style, border_padding, computed_sizes = ResolveMainInlineLength(space, style, border_padding,
min_and_max, inline_size); min_max_size, inline_size);
} else { } else {
computed_sizes = computed_sizes =
ResolveMainBlockLength(space, style, border_padding, inline_size, ResolveMainBlockLength(space, style, border_padding, inline_size,
...@@ -282,7 +282,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -282,7 +282,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
: style.MaxHeight(); : style.MaxHeight();
LayoutUnit max; LayoutUnit max;
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) { if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
max = ResolveMaxInlineLength(space, style, border_padding, min_and_max, max = ResolveMaxInlineLength(space, style, border_padding, min_max_size,
max_length, LengthResolvePhase::kIntrinsic); max_length, LengthResolvePhase::kIntrinsic);
} else { } else {
max = ResolveMaxBlockLength(space, style, border_padding, max_length, max = ResolveMaxBlockLength(space, style, border_padding, max_length,
...@@ -295,7 +295,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -295,7 +295,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
: style.MinHeight(); : style.MinHeight();
LayoutUnit min; LayoutUnit min;
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) { if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
min = ResolveMinInlineLength(space, style, border_padding, min_and_max, min = ResolveMinInlineLength(space, style, border_padding, min_max_size,
min_length, LengthResolvePhase::kIntrinsic); min_length, LengthResolvePhase::kIntrinsic);
} else { } else {
min = ResolveMinBlockLength(space, style, border_padding, min_length, min = ResolveMinBlockLength(space, style, border_padding, min_length,
...@@ -347,7 +347,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -347,7 +347,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
} }
} }
base::Optional<MinMaxSize> minmax; base::Optional<MinMaxSize> min_max_size;
if (NeedMinMaxSizeForContentContribution(parent_writing_mode, child_style)) { if (NeedMinMaxSizeForContentContribution(parent_writing_mode, child_style)) {
// We need to set up a constraint space with correct fallback available // We need to set up a constraint space with correct fallback available
// inline size in case of orthogonal children. // inline size in case of orthogonal children.
...@@ -358,7 +358,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -358,7 +358,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
CreateIndefiniteConstraintSpaceForChild(parent_style, child); CreateIndefiniteConstraintSpaceForChild(parent_style, child);
child_constraint_space = &indefinite_constraint_space; child_constraint_space = &indefinite_constraint_space;
} }
minmax = child.ComputeMinMaxSize(parent_writing_mode, input, min_max_size = child.ComputeMinMaxSize(parent_writing_mode, input,
child_constraint_space); child_constraint_space);
} }
// Synthesize a zero-sized constraint space for determining the borders, and // Synthesize a zero-sized constraint space for determining the borders, and
...@@ -371,7 +371,7 @@ MinMaxSize ComputeMinAndMaxContentContribution( ...@@ -371,7 +371,7 @@ MinMaxSize ComputeMinAndMaxContentContribution(
ComputeBorders(space, child) + ComputePadding(space, child_style); ComputeBorders(space, child) + ComputePadding(space, child_style);
MinMaxSize sizes = ComputeMinAndMaxContentContribution( MinMaxSize sizes = ComputeMinAndMaxContentContribution(
parent_writing_mode, child_style, border_padding, minmax); parent_writing_mode, child_style, border_padding, min_max_size);
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) if (IsParallelWritingMode(parent_writing_mode, child_writing_mode))
box->SetPreferredLogicalWidthsFromNG(sizes); box->SetPreferredLogicalWidthsFromNG(sizes);
return sizes; return sizes;
...@@ -411,7 +411,7 @@ LayoutUnit ComputeInlineSizeForFragment( ...@@ -411,7 +411,7 @@ LayoutUnit ComputeInlineSizeForFragment(
const NGConstraintSpace& space, const NGConstraintSpace& space,
NGLayoutInputNode node, NGLayoutInputNode node,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const MinMaxSize* override_minmax_for_test) { const MinMaxSize* override_min_max_size_for_test) {
if (space.IsFixedInlineSize() || space.IsAnonymous()) if (space.IsFixedInlineSize() || space.IsAnonymous())
return space.AvailableSize().inline_size; return space.AvailableSize().inline_size;
...@@ -427,7 +427,7 @@ LayoutUnit ComputeInlineSizeForFragment( ...@@ -427,7 +427,7 @@ LayoutUnit ComputeInlineSizeForFragment(
// the constraints on our own. We also need to discard the cached values if // the constraints on our own. We also need to discard the cached values if
// the box has certain properties (e.g. percentage padding) that cause the // the box has certain properties (e.g. percentage padding) that cause the
// cached values to be affected by extrinsic sizing. // cached values to be affected by extrinsic sizing.
if (!box->PreferredLogicalWidthsDirty() && !override_minmax_for_test && if (!box->PreferredLogicalWidthsDirty() && !override_min_max_size_for_test &&
!style.LogicalMinWidth().IsPercentOrCalc() && !style.LogicalMinWidth().IsPercentOrCalc() &&
!style.LogicalMaxWidth().IsPercentOrCalc() && !style.LogicalMaxWidth().IsPercentOrCalc() &&
!box->NeedsPreferredWidthsRecalculation()) { !box->NeedsPreferredWidthsRecalculation()) {
...@@ -436,9 +436,9 @@ LayoutUnit ComputeInlineSizeForFragment( ...@@ -436,9 +436,9 @@ LayoutUnit ComputeInlineSizeForFragment(
// to subtract inline margins from the available size. The code in // to subtract inline margins from the available size. The code in
// ResolveMainInlineLength knows how to handle that, just call that. // ResolveMainInlineLength knows how to handle that, just call that.
MinMaxSize min_and_max = {box->MinPreferredLogicalWidth(), base::Optional<MinMaxSize> min_max_size = MinMaxSize{
box->MaxPreferredLogicalWidth()}; box->MinPreferredLogicalWidth(), box->MaxPreferredLogicalWidth()};
return ResolveMainInlineLength(space, style, border_padding, min_and_max, return ResolveMainInlineLength(space, style, border_padding, min_max_size,
logical_width); logical_width);
} }
if (logical_width.IsMinContent()) if (logical_width.IsMinContent())
...@@ -447,29 +447,29 @@ LayoutUnit ComputeInlineSizeForFragment( ...@@ -447,29 +447,29 @@ LayoutUnit ComputeInlineSizeForFragment(
return box->MaxPreferredLogicalWidth(); return box->MaxPreferredLogicalWidth();
} }
base::Optional<MinMaxSize> min_and_max; base::Optional<MinMaxSize> min_max_size;
if (NeedMinMaxSize(space, style)) { if (NeedMinMaxSize(space, style)) {
if (override_minmax_for_test) { if (override_min_max_size_for_test) {
min_and_max = *override_minmax_for_test; min_max_size = *override_min_max_size_for_test;
} else { } else {
min_and_max = node.ComputeMinMaxSize( min_max_size = node.ComputeMinMaxSize(
space.GetWritingMode(), space.GetWritingMode(),
MinMaxSizeInput(space.PercentageResolutionBlockSize()), &space); MinMaxSizeInput(space.PercentageResolutionBlockSize()), &space);
// Cache these computed values // Cache these computed values
MinMaxSize contribution = ComputeMinAndMaxContentContribution( MinMaxSize contribution = ComputeMinAndMaxContentContribution(
style.GetWritingMode(), style, border_padding, min_and_max); style.GetWritingMode(), style, border_padding, min_max_size);
box->SetPreferredLogicalWidthsFromNG(contribution); box->SetPreferredLogicalWidthsFromNG(contribution);
} }
} }
LayoutUnit extent = ResolveMainInlineLength(space, style, border_padding, LayoutUnit extent = ResolveMainInlineLength(space, style, border_padding,
min_and_max, logical_width); min_max_size, logical_width);
LayoutUnit max = ResolveMaxInlineLength(space, style, border_padding, LayoutUnit max = ResolveMaxInlineLength(space, style, border_padding,
min_and_max, style.LogicalMaxWidth(), min_max_size, style.LogicalMaxWidth(),
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
LayoutUnit min = ResolveMinInlineLength(space, style, border_padding, LayoutUnit min = ResolveMinInlineLength(space, style, border_padding,
min_and_max, style.LogicalMinWidth(), min_max_size, style.LogicalMinWidth(),
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
return ConstrainByMinMax(extent, min, max); return ConstrainByMinMax(extent, min, max);
} }
...@@ -548,7 +548,7 @@ LayoutUnit ComputeBlockSizeForFragment( ...@@ -548,7 +548,7 @@ LayoutUnit ComputeBlockSizeForFragment(
// Computes size for a replaced element. // Computes size for a replaced element.
void ComputeReplacedSize(const NGLayoutInputNode& node, void ComputeReplacedSize(const NGLayoutInputNode& node,
const NGConstraintSpace& space, const NGConstraintSpace& space,
const base::Optional<MinMaxSize>& child_minmax, const base::Optional<MinMaxSize>& child_min_max_size,
base::Optional<LogicalSize>* out_replaced_size, base::Optional<LogicalSize>* out_replaced_size,
base::Optional<LogicalSize>* out_aspect_ratio) { base::Optional<LogicalSize>* out_aspect_ratio) {
DCHECK(node.IsReplaced()); DCHECK(node.IsReplaced());
...@@ -560,10 +560,10 @@ void ComputeReplacedSize(const NGLayoutInputNode& node, ...@@ -560,10 +560,10 @@ void ComputeReplacedSize(const NGLayoutInputNode& node,
NGBoxStrut border_padding = NGBoxStrut border_padding =
ComputeBorders(space, node) + ComputePadding(space, style); ComputeBorders(space, node) + ComputePadding(space, style);
LayoutUnit inline_min = ResolveMinInlineLength( LayoutUnit inline_min = ResolveMinInlineLength(
space, style, border_padding, child_minmax, style.LogicalMinWidth(), space, style, border_padding, child_min_max_size, style.LogicalMinWidth(),
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
LayoutUnit inline_max = ResolveMaxInlineLength( LayoutUnit inline_max = ResolveMaxInlineLength(
space, style, border_padding, child_minmax, style.LogicalMaxWidth(), space, style, border_padding, child_min_max_size, style.LogicalMaxWidth(),
LengthResolvePhase::kLayout); LengthResolvePhase::kLayout);
LayoutUnit block_min = ResolveMinBlockLength( LayoutUnit block_min = ResolveMinBlockLength(
space, style, border_padding, style.LogicalMinHeight(), space, style, border_padding, style.LogicalMinHeight(),
...@@ -576,8 +576,8 @@ void ComputeReplacedSize(const NGLayoutInputNode& node, ...@@ -576,8 +576,8 @@ void ComputeReplacedSize(const NGLayoutInputNode& node,
const Length& block_length = style.LogicalHeight(); const Length& block_length = style.LogicalHeight();
base::Optional<LayoutUnit> replaced_inline; base::Optional<LayoutUnit> replaced_inline;
if (!inline_length.IsAuto()) { if (!inline_length.IsAuto()) {
replaced_inline = ResolveMainInlineLength(space, style, border_padding, replaced_inline = ResolveMainInlineLength(
child_minmax, inline_length); space, style, border_padding, child_min_max_size, inline_length);
replaced_inline = replaced_inline =
ConstrainByMinMax(*replaced_inline, inline_min, inline_max); ConstrainByMinMax(*replaced_inline, inline_min, inline_max);
} }
......
...@@ -97,44 +97,100 @@ CORE_EXPORT LayoutUnit ResolveBlockLengthInternal( ...@@ -97,44 +97,100 @@ CORE_EXPORT LayoutUnit ResolveBlockLengthInternal(
nullptr); nullptr);
// Used for resolving min inline lengths, (|ComputedStyle::MinLogicalWidth|). // Used for resolving min inline lengths, (|ComputedStyle::MinLogicalWidth|).
template <typename MinMaxSizeFunc>
inline LayoutUnit ResolveMinInlineLength( inline LayoutUnit ResolveMinInlineLength(
const NGConstraintSpace& constraint_space, const NGConstraintSpace& constraint_space,
const ComputedStyle& style, const ComputedStyle& style,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_and_max, const MinMaxSizeFunc& min_max_size_func,
const Length& length, const Length& length,
LengthResolvePhase phase) { LengthResolvePhase phase) {
if (LIKELY(length.IsAuto() || InlineLengthUnresolvable(length, phase))) if (LIKELY(length.IsAuto() || InlineLengthUnresolvable(length, phase)))
return border_padding.InlineSum(); return border_padding.InlineSum();
base::Optional<MinMaxSize> min_max_size;
if (length.IsIntrinsic())
min_max_size = min_max_size_func();
return ResolveInlineLengthInternal(constraint_space, style, border_padding, return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_and_max, length); min_max_size, length);
}
template <>
inline LayoutUnit ResolveMinInlineLength<base::Optional<MinMaxSize>>(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_max_size,
const Length& length,
LengthResolvePhase phase) {
if (LIKELY(length.IsAuto() || InlineLengthUnresolvable(length, phase)))
return border_padding.InlineSum();
return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_max_size, length);
} }
// Used for resolving max inline lengths, (|ComputedStyle::MaxLogicalWidth|). // Used for resolving max inline lengths, (|ComputedStyle::MaxLogicalWidth|).
template <typename MinMaxSizeFunc>
inline LayoutUnit ResolveMaxInlineLength( inline LayoutUnit ResolveMaxInlineLength(
const NGConstraintSpace& constraint_space, const NGConstraintSpace& constraint_space,
const ComputedStyle& style, const ComputedStyle& style,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_and_max, const MinMaxSizeFunc& min_max_size_func,
const Length& length,
LengthResolvePhase phase) {
if (LIKELY(length.IsNone() || InlineLengthUnresolvable(length, phase)))
return LayoutUnit::Max();
base::Optional<MinMaxSize> min_max_size;
if (length.IsIntrinsic())
min_max_size = min_max_size_func();
return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_max_size, length);
}
template <>
inline LayoutUnit ResolveMaxInlineLength<base::Optional<MinMaxSize>>(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_max_size,
const Length& length, const Length& length,
LengthResolvePhase phase) { LengthResolvePhase phase) {
if (LIKELY(length.IsNone() || InlineLengthUnresolvable(length, phase))) if (LIKELY(length.IsNone() || InlineLengthUnresolvable(length, phase)))
return LayoutUnit::Max(); return LayoutUnit::Max();
return ResolveInlineLengthInternal(constraint_space, style, border_padding, return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_and_max, length); min_max_size, length);
} }
// Used for resolving main inline lengths, (|ComputedStyle::LogicalWidth|). // Used for resolving main inline lengths, (|ComputedStyle::LogicalWidth|).
template <typename MinMaxSizeFunc>
inline LayoutUnit ResolveMainInlineLength( inline LayoutUnit ResolveMainInlineLength(
const NGConstraintSpace& constraint_space, const NGConstraintSpace& constraint_space,
const ComputedStyle& style, const ComputedStyle& style,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_and_max, const MinMaxSizeFunc& min_max_size_func,
const Length& length) {
base::Optional<MinMaxSize> min_max_size;
if (length.IsIntrinsic())
min_max_size = min_max_size_func();
return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_max_size, length);
}
template <>
inline LayoutUnit ResolveMainInlineLength<base::Optional<MinMaxSize>>(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
const base::Optional<MinMaxSize>& min_max_size,
const Length& length) { const Length& length) {
return ResolveInlineLengthInternal(constraint_space, style, border_padding, return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_and_max, length); min_max_size, length);
} }
// Used for resolving min block lengths, (|ComputedStyle::MinLogicalHeight|). // Used for resolving min block lengths, (|ComputedStyle::MinLogicalHeight|).
...@@ -157,6 +213,30 @@ inline LayoutUnit ResolveMinBlockLength( ...@@ -157,6 +213,30 @@ inline LayoutUnit ResolveMinBlockLength(
opt_percentage_resolution_block_size_for_min_max); opt_percentage_resolution_block_size_for_min_max);
} }
template <typename IntrinsicBlockSizeFunc>
inline LayoutUnit ResolveMinBlockLength(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
const Length& length,
const IntrinsicBlockSizeFunc& intrinsic_block_size_func,
LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr) {
if (LIKELY(BlockLengthUnresolvable(
constraint_space, length, phase,
opt_percentage_resolution_block_size_for_min_max)))
return border_padding.BlockSum();
LayoutUnit intrinsic_block_size = kIndefiniteSize;
if (length.IsIntrinsicOrAuto())
intrinsic_block_size = intrinsic_block_size_func();
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, intrinsic_block_size,
phase, opt_percentage_resolution_block_size_for_min_max);
}
// Used for resolving max block lengths, (|ComputedStyle::MaxLogicalHeight|). // Used for resolving max block lengths, (|ComputedStyle::MaxLogicalHeight|).
inline LayoutUnit ResolveMaxBlockLength( inline LayoutUnit ResolveMaxBlockLength(
const NGConstraintSpace& constraint_space, const NGConstraintSpace& constraint_space,
...@@ -177,6 +257,30 @@ inline LayoutUnit ResolveMaxBlockLength( ...@@ -177,6 +257,30 @@ inline LayoutUnit ResolveMaxBlockLength(
opt_percentage_resolution_block_size_for_min_max); opt_percentage_resolution_block_size_for_min_max);
} }
template <typename IntrinsicBlockSizeFunc>
inline LayoutUnit ResolveMaxBlockLength(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
const Length& length,
const IntrinsicBlockSizeFunc& intrinsic_block_size_func,
LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr) {
if (LIKELY(BlockLengthUnresolvable(
constraint_space, length, phase,
opt_percentage_resolution_block_size_for_min_max)))
return LayoutUnit::Max();
LayoutUnit intrinsic_block_size = kIndefiniteSize;
if (length.IsIntrinsicOrAuto())
intrinsic_block_size = intrinsic_block_size_func();
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, intrinsic_block_size,
phase, opt_percentage_resolution_block_size_for_min_max);
}
// Used for resolving main block lengths, (|ComputedStyle::LogicalHeight|). // Used for resolving main block lengths, (|ComputedStyle::LogicalHeight|).
inline LayoutUnit ResolveMainBlockLength( inline LayoutUnit ResolveMainBlockLength(
const NGConstraintSpace& constraint_space, const NGConstraintSpace& constraint_space,
...@@ -198,6 +302,31 @@ inline LayoutUnit ResolveMainBlockLength( ...@@ -198,6 +302,31 @@ inline LayoutUnit ResolveMainBlockLength(
opt_percentage_resolution_block_size_for_min_max); opt_percentage_resolution_block_size_for_min_max);
} }
template <typename IntrinsicBlockSizeFunc>
inline LayoutUnit ResolveMainBlockLength(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
const Length& length,
const IntrinsicBlockSizeFunc& intrinsic_block_size_func,
LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr) {
if (UNLIKELY((length.IsPercentOrCalc() || length.IsFillAvailable()) &&
BlockLengthUnresolvable(
constraint_space, length, phase,
opt_percentage_resolution_block_size_for_min_max)))
return intrinsic_block_size_func();
LayoutUnit intrinsic_block_size = kIndefiniteSize;
if (length.IsIntrinsicOrAuto())
intrinsic_block_size = intrinsic_block_size_func();
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, intrinsic_block_size,
phase, opt_percentage_resolution_block_size_for_min_max);
}
// For the given style and min/max content sizes, computes the min and max // For the given style and min/max content sizes, computes the min and max
// content contribution (https://drafts.csswg.org/css-sizing/#contributions). // content contribution (https://drafts.csswg.org/css-sizing/#contributions).
// This is similar to ComputeInlineSizeForFragment except that it does not // This is similar to ComputeInlineSizeForFragment except that it does not
...@@ -241,12 +370,12 @@ MinMaxSize ComputeMinAndMaxContentSizeForOutOfFlow( ...@@ -241,12 +370,12 @@ MinMaxSize ComputeMinAndMaxContentSizeForOutOfFlow(
// then constraining the result by the resolved min logical width and max // then constraining the result by the resolved min logical width and max
// logical width from the ComputedStyle object. Calls Node::ComputeMinMaxSize // logical width from the ComputedStyle object. Calls Node::ComputeMinMaxSize
// if needed. // if needed.
// |override_minmax_for_test| is provided *solely* for use by unit tests. // |override_min_max_size_for_test| is provided *solely* for use by unit tests.
CORE_EXPORT LayoutUnit ComputeInlineSizeForFragment( CORE_EXPORT LayoutUnit ComputeInlineSizeForFragment(
const NGConstraintSpace&, const NGConstraintSpace&,
NGLayoutInputNode, NGLayoutInputNode,
const NGBoxStrut& border_padding, const NGBoxStrut& border_padding,
const MinMaxSize* override_minmax_for_test = nullptr); const MinMaxSize* override_min_max_size_for_test = nullptr);
// Same as ComputeInlineSizeForFragment, but uses height instead of width. // Same as ComputeInlineSizeForFragment, but uses height instead of width.
CORE_EXPORT LayoutUnit CORE_EXPORT LayoutUnit
......
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