Skip to content

Commit 618e4f8

Browse files
alisonmaherChromium LUCI CQ
authored andcommitted
[Masonry] Move grid intrinsic minimum logic to helpers
The grid implementation has special logic for intrinsic minimums that also should apply to masonry [1]. Move this logic to two new helpers: - CalculateIntrinsicMinimumContribution() that returns the contribution size to use for a given item. - ClampIntrinsicMinSize() which clamps the contribution size, if it was the min content contribution, by the total track size that the item spans. This is in preparation for reuse in masonry. This CL should produce no functional changes. [1] https://drafts.csswg.org/css-grid/#min-size-auto Bug: 343257585 Change-Id: I6b13bf9bafb59aa7b7006486aa46fd346304afd0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7013328 Reviewed-by: Kurt Catti-Schmidt <[email protected]> Reviewed-by: Ian Kilpatrick <[email protected]> Commit-Queue: Alison Maher <[email protected]> Cr-Commit-Position: refs/heads/main@{#1532392}
1 parent 0d3971b commit 618e4f8

File tree

3 files changed

+209
-113
lines changed

3 files changed

+209
-113
lines changed

third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc

Lines changed: 59 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -998,120 +998,66 @@ LayoutUnit GridLayoutAlgorithm::ContributionSizeForGridItem(
998998
: BlockContributionSize();
999999
break;
10001000
case GridItemContributionType::kForIntrinsicMinimums: {
1001-
// TODO(ikilpatrick): All of the below is incorrect for replaced elements.
1002-
const auto& main_length = is_parallel_with_track_direction
1003-
? item_style.LogicalWidth()
1004-
: item_style.LogicalHeight();
1005-
const auto& min_length = is_parallel_with_track_direction
1006-
? item_style.LogicalMinWidth()
1007-
: item_style.LogicalMinHeight();
1008-
1009-
// We could be clever is and make this an if-stmt, but each type has
1010-
// subtle consequences. This forces us in the future when we add a new
1011-
// length type to consider what the best thing is for grid.
1012-
switch (main_length.GetType()) {
1013-
case Length::kAuto:
1014-
case Length::kFitContent:
1015-
case Length::kStretch:
1016-
case Length::kPercent:
1017-
case Length::kCalculated: {
1018-
const auto border_padding =
1019-
ComputeBorders(space, node) + ComputePadding(space, item_style);
1020-
1021-
// All of the above lengths are considered 'auto' if we are querying a
1022-
// minimum contribution. They all require definite track sizes to
1023-
// determine their final size.
1024-
//
1025-
// From https://drafts.csswg.org/css-grid/#min-size-auto:
1026-
// To provide a more reasonable default minimum size for grid items,
1027-
// the used value of its automatic minimum size in a given axis is
1028-
// the content-based minimum size if all of the following are true:
1029-
// - it is not a scroll container
1030-
// - it spans at least one track in that axis whose min track
1031-
// sizing function is 'auto'
1032-
// - if it spans more than one track in that axis, none of those
1033-
// tracks are flexible
1034-
// Otherwise, the automatic minimum size is zero, as usual.
1035-
//
1036-
// Start by resolving the cases where |min_length| is non-auto or its
1037-
// automatic minimum size should be zero.
1038-
if (!min_length.HasAuto() || item_style.IsScrollContainer() ||
1039-
!grid_item->IsSpanningAutoMinimumTrack(track_direction) ||
1040-
(grid_item->IsSpanningFlexibleTrack(track_direction) &&
1041-
grid_item->SpanSize(track_direction) > 1)) {
1042-
// TODO(ikilpatrick): This block needs to respect the aspect-ratio,
1043-
// and apply the transferred min/max sizes when appropriate. We do
1044-
// this sometimes elsewhere so should unify and simplify this code.
1045-
if (is_parallel_with_track_direction) {
1046-
contribution =
1047-
ResolveMinInlineLength(space, item_style, border_padding,
1048-
MinMaxSizesFunc, min_length);
1049-
} else {
1050-
contribution = ResolveInitialMinBlockLength(
1051-
space, item_style, border_padding, min_length);
1052-
}
1053-
break;
1054-
}
1055-
1056-
// Resolve the content-based minimum size.
1057-
contribution = is_parallel_with_track_direction
1058-
? MinContentSize()
1059-
: BlockContributionSize();
1060-
1061-
auto spanned_tracks_definite_max_size =
1062-
track_collection.CalculateSetSpanSize(begin_set_index,
1063-
end_set_index);
1064-
1065-
if (spanned_tracks_definite_max_size != kIndefiniteSize) {
1066-
// Further clamp the minimum size to less than or equal to the
1067-
// stretch fit into the grid area’s maximum size in that dimension,
1068-
// as represented by the sum of those grid tracks’ max track sizing
1069-
// functions plus any intervening fixed gutters.
1070-
const auto border_padding_sum = is_parallel_with_track_direction
1071-
? border_padding.InlineSum()
1072-
: border_padding.BlockSum();
1073-
DCHECK_GE(contribution, baseline_shim + border_padding_sum);
1074-
1075-
// The stretch fit into a given size is that size, minus the box’s
1076-
// computed margins, border, and padding in the given dimension,
1077-
// flooring at zero so that the inner size is not negative.
1078-
spanned_tracks_definite_max_size =
1079-
(spanned_tracks_definite_max_size - baseline_shim - margin_sum -
1080-
border_padding_sum)
1081-
.ClampNegativeToZero();
1082-
1083-
// Add the baseline shim, border, and padding (margins will be added
1084-
// later) back to the contribution, since we don't want the outer
1085-
// size of the minimum size to overflow its grid area; these are
1086-
// already accounted for in the current value of `contribution`.
1087-
contribution =
1088-
std::min(contribution, spanned_tracks_definite_max_size +
1089-
baseline_shim + border_padding_sum);
1090-
}
1091-
break;
1092-
}
1093-
case Length::kMinContent:
1094-
case Length::kMaxContent:
1095-
case Length::kFixed: {
1096-
// All of the above lengths are "definite" (non-auto), and don't need
1097-
// the special min-size treatment above. (They will all end up being
1098-
// the specified size).
1099-
if (is_parallel_with_track_direction) {
1100-
contribution = main_length.IsMaxContent() ? MaxContentSize()
1101-
: MinContentSize();
1102-
} else {
1103-
contribution = BlockContributionSize();
1104-
}
1105-
break;
1001+
// See https://drafts.csswg.org/css-grid/#min-size-auto for more details
1002+
// on the special logic applied for intrinsic minimums.
1003+
//
1004+
// Per the spec link above, we apply the automatic min when:
1005+
// - it spans at least one track in that axis whose min track sizing
1006+
// function is auto.
1007+
// - if it spans more than one track in that axis, none of those tracks
1008+
// are flexible.
1009+
const bool special_spanning_criteria =
1010+
!grid_item->IsSpanningAutoMinimumTrack(track_direction) ||
1011+
(grid_item->IsSpanningFlexibleTrack(track_direction) &&
1012+
grid_item->SpanSize(track_direction) > 1);
1013+
1014+
const LayoutUnit min_content_contribution =
1015+
is_parallel_with_track_direction ? MinContentSize()
1016+
: BlockContributionSize();
1017+
const LayoutUnit max_content_contribution =
1018+
is_parallel_with_track_direction ? MaxContentSize()
1019+
: min_content_contribution;
1020+
1021+
MinMaxSizesResult subgrid_minmax_sizes;
1022+
if (grid_item->IsSubgrid()) {
1023+
const GridSizingSubtree& subgrid_sizing_subtree =
1024+
sizing_subtree.SubgridSizingSubtree(*grid_item);
1025+
if (subgrid_sizing_subtree.LayoutData().IsSubgridWithStandaloneAxis(
1026+
kForColumns)) {
1027+
subgrid_minmax_sizes = To<GridNode>(node).ComputeSubgridMinMaxSizes(
1028+
subgrid_sizing_subtree, space);
11061029
}
1107-
case Length::kMinIntrinsic:
1108-
case Length::kFlex:
1109-
case Length::kExtendToZoom:
1110-
case Length::kDeviceWidth:
1111-
case Length::kDeviceHeight:
1112-
case Length::kNone:
1113-
case Length::kContent:
1114-
NOTREACHED();
1030+
}
1031+
1032+
bool maybe_clamp = false;
1033+
contribution = CalculateIntrinsicMinimumContribution(
1034+
is_parallel_with_track_direction, special_spanning_criteria,
1035+
min_content_contribution, max_content_contribution, space,
1036+
subgrid_minmax_sizes, grid_item, maybe_clamp);
1037+
1038+
if (!maybe_clamp) {
1039+
break;
1040+
}
1041+
1042+
// Further clamp the minimum size to less than or equal to the
1043+
// stretch fit into the grid area’s maximum size in that dimension,
1044+
// as represented by the sum of those grid tracks’ max track sizing
1045+
// functions plus any intervening fixed gutters.
1046+
auto spanned_tracks_definite_max_size =
1047+
track_collection.CalculateSetSpanSize(begin_set_index, end_set_index);
1048+
if (spanned_tracks_definite_max_size != kIndefiniteSize) {
1049+
contribution += margin_sum;
1050+
const auto border_padding =
1051+
ComputeBorders(space, node) + ComputePadding(space, item_style);
1052+
const auto border_padding_sum = is_parallel_with_track_direction
1053+
? border_padding.InlineSum()
1054+
: border_padding.BlockSum();
1055+
1056+
contribution = ClampIntrinsicMinSize(
1057+
contribution,
1058+
/*min_clamp_size=*/margin_sum + baseline_shim + border_padding_sum,
1059+
spanned_tracks_definite_max_size);
1060+
contribution -= margin_sum;
11151061
}
11161062
break;
11171063
}

third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,4 +435,114 @@ void AlignmentOffsetForOutOfFlow(AxisEdge inline_axis_edge,
435435
}
436436
}
437437

438+
LayoutUnit CalculateIntrinsicMinimumContribution(
439+
bool is_parallel_with_track_direction,
440+
bool special_spanning_criteria,
441+
const LayoutUnit min_content_contribution,
442+
const LayoutUnit max_content_contribution,
443+
const ConstraintSpace& space,
444+
const MinMaxSizesResult& subgrid_minmax_sizes,
445+
const GridItemData* grid_item,
446+
bool& maybe_clamp) {
447+
CHECK(grid_item);
448+
const auto& node = grid_item->node;
449+
const ComputedStyle& item_style = node.Style();
450+
maybe_clamp = false;
451+
452+
// TODO(ikilpatrick): All of the below is incorrect for replaced elements.
453+
const auto& main_length = is_parallel_with_track_direction
454+
? item_style.LogicalWidth()
455+
: item_style.LogicalHeight();
456+
const auto& min_length = is_parallel_with_track_direction
457+
? item_style.LogicalMinWidth()
458+
: item_style.LogicalMinHeight();
459+
460+
// We could be clever and make this an if-stmt, but each type has
461+
// subtle consequences. This forces us in the future when we add a new
462+
// length type to consider what the best thing is for grid.
463+
switch (main_length.GetType()) {
464+
case Length::kAuto:
465+
case Length::kFitContent:
466+
case Length::kStretch:
467+
case Length::kPercent:
468+
case Length::kCalculated: {
469+
const auto border_padding =
470+
ComputeBorders(space, node) + ComputePadding(space, item_style);
471+
472+
// All of the above lengths are considered 'auto' if we are querying a
473+
// minimum contribution. They all require definite track sizes to
474+
// determine their final size.
475+
//
476+
// From https://drafts.csswg.org/css-grid/#min-size-auto:
477+
// To provide a more reasonable default minimum size for grid items,
478+
// the used value of its automatic minimum size in a given axis is
479+
// the content-based minimum size if all of the following are true:
480+
// - it is not a scroll container
481+
// - it spans at least one track in that axis whose min track
482+
// sizing function is 'auto'
483+
// - if it spans more than one track in that axis, none of those
484+
// tracks are flexible
485+
// Otherwise, the automatic minimum size is zero, as usual.
486+
//
487+
// Start by resolving the cases where |min_length| is non-auto or its
488+
// automatic minimum size should be zero.
489+
if (!min_length.HasAuto() || item_style.IsScrollContainer() ||
490+
special_spanning_criteria) {
491+
// TODO(ikilpatrick): This block needs to respect the aspect-ratio,
492+
// and apply the transferred min/max sizes when appropriate. We do
493+
// this sometimes elsewhere so should unify and simplify this code.
494+
if (is_parallel_with_track_direction) {
495+
auto MinMaxSizesFunc = [&](SizeType type) -> MinMaxSizesResult {
496+
if (grid_item->IsSubgrid()) {
497+
return subgrid_minmax_sizes;
498+
}
499+
return node.ComputeMinMaxSizes(item_style.GetWritingMode(), type,
500+
space);
501+
};
502+
return ResolveMinInlineLength(space, item_style, border_padding,
503+
MinMaxSizesFunc, min_length);
504+
} else {
505+
return ResolveInitialMinBlockLength(space, item_style, border_padding,
506+
min_length);
507+
}
508+
}
509+
510+
maybe_clamp = true;
511+
return min_content_contribution;
512+
}
513+
case Length::kMinContent:
514+
case Length::kMaxContent:
515+
case Length::kFixed: {
516+
// All of the above lengths are "definite" (non-auto), and don't need
517+
// the special min-size treatment above. (They will all end up being
518+
// the specified size).
519+
return main_length.IsMaxContent() ? max_content_contribution
520+
: min_content_contribution;
521+
}
522+
case Length::kMinIntrinsic:
523+
case Length::kFlex:
524+
case Length::kExtendToZoom:
525+
case Length::kDeviceWidth:
526+
case Length::kDeviceHeight:
527+
case Length::kNone:
528+
case Length::kContent:
529+
NOTREACHED();
530+
}
531+
}
532+
533+
LayoutUnit ClampIntrinsicMinSize(LayoutUnit min_content_contribution,
534+
LayoutUnit min_clamp_size,
535+
LayoutUnit spanned_tracks_definite_max_size) {
536+
CHECK_NE(spanned_tracks_definite_max_size, kIndefiniteSize);
537+
DCHECK_GE(min_content_contribution, min_clamp_size);
538+
539+
// Don't clamp beyond `min_clamp_size`, which usually represents
540+
// the sum of border/padding, margins, and the baseline shim for
541+
// the associated item.
542+
spanned_tracks_definite_max_size =
543+
std::max(spanned_tracks_definite_max_size, min_clamp_size);
544+
545+
return std::min(min_content_contribution, spanned_tracks_definite_max_size);
546+
}
547+
438548
} // namespace blink

third_party/blink/renderer/core/layout/grid/grid_layout_utils.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct BoxStrut;
2222
struct GridItemData;
2323
struct LogicalOffset;
2424
struct LogicalSize;
25+
struct MinMaxSizesResult;
2526

2627
// Update the provided `available_size`, `min_available_size`, and
2728
// `max_available_size` to their appropriate values.
@@ -66,6 +67,45 @@ void AlignmentOffsetForOutOfFlow(AxisEdge inline_axis_edge,
6667
LogicalStaticPosition::BlockEdge* block_edge,
6768
LogicalOffset* offset);
6869

70+
// Per the Grid spec [1] there is special logic for the contribution size to use
71+
// for intrinsic minimums. This method returns the contribution size of
72+
// `grid_item` given the provided variables.
73+
//
74+
// When `special_spanning_criteria` is true, always use the automatic minimum
75+
// size - this usually happens when an item spans at least one track with a min
76+
// track size of 'auto' or if an item spans more than one non-flexible track.
77+
// However, in masonry, we don't have this information when initially
78+
// calculating the virtual item contributions, so masonry needs this var to
79+
// force this to both true and false to get both potential contributions for use
80+
// later when more information is known about the tracks a virtual item spans.
81+
//
82+
// `min_content_contribution` and `max_content_contribution` are the content
83+
// based min and maximums for the provided `grid_item` respectively. If the item
84+
// is a subgrid, `subgrid_minmax_sizes` will be the min/max size result for the
85+
// subgrid.
86+
//
87+
// This method will set `maybe_clamp` to true if the content based contribution
88+
// was returned and should be considered for clamping. Otherwise, it will be set
89+
// to false.
90+
//
91+
// [1] https://drafts.csswg.org/css-grid/#min-size-auto
92+
LayoutUnit CalculateIntrinsicMinimumContribution(
93+
bool is_parallel_with_track_direction,
94+
bool special_spanning_criteria,
95+
const LayoutUnit min_content_contribution,
96+
const LayoutUnit max_content_contribution,
97+
const ConstraintSpace& space,
98+
const MinMaxSizesResult& subgrid_minmax_sizes,
99+
const GridItemData* grid_item,
100+
bool& maybe_clamp);
101+
102+
// Return `min_content_contribution` clamped by
103+
// `spanned_tracks_definite_max_size` up to `min_clamp_size`. `min_clamp_size`
104+
// usually represents the sum of border/padding, margins, and the baseline shim.
105+
LayoutUnit ClampIntrinsicMinSize(LayoutUnit min_content_contribution,
106+
LayoutUnit min_clamp_size,
107+
LayoutUnit spanned_tracks_definite_max_size);
108+
69109
} // namespace blink
70110

71111
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GRID_GRID_LAYOUT_UTILS_H_

0 commit comments

Comments
 (0)