Commit 3099ebc0 authored by Ana SollanoKim's avatar Ana SollanoKim Committed by Commit Bot

[GridNG] Percentage resolution for grid gap with auto-sized grids

This change addresses a TODO for the resolution of grid gaps that are
percent or calculated. The available size used to calculate the gap is
based on the column/row definitions, as the grid's width/height are
'auto'. The intrinsic block size does not include the gap when it is
percent or calculated.

The rest of the failing grid-gutters WPT tests depend on 'auto' inline
sizes. A couple of TODOs were added to address the changes that will be
needed in order to mark those as passing.

Bug: 1045599
Change-Id: Ia226f179eb4b3a0034e3701567dce6458b79736d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2503402
Commit-Queue: Ana Sollano Kim <ansollan@microsoft.com>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarEthan Jimenez <ethavar@microsoft.com>
Reviewed-by: default avatarKurt Catti-Schmidt <kschmi@microsoft.com>
Reviewed-by: default avatarChristian Biesinger <cbiesinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#826297}
parent c54f44f5
......@@ -991,6 +991,9 @@ void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems(
sets_to_grow.Shrink(0);
sets_to_grow_beyond_limit.Shrink(0);
// TODO(ansollan): If the grid is auto-sized and has a calc or percent row
// gap, then the gap can't be calculated on the first pass as we wouldn't
// know our block size.
LayoutUnit spanned_tracks_size =
GridGap(track_direction) * (grid_item->SpanSize(track_direction) - 1);
for (auto set_iterator = GetSetIteratorForItem(*grid_item, track_direction);
......@@ -1102,37 +1105,28 @@ GridTrackSizingDirection NGGridLayoutAlgorithm::AutoFlowDirection() const {
}
void NGGridLayoutAlgorithm::PlaceGridItems() {
LayoutUnit column_grid_gap = GridGap(GridTrackSizingDirection::kForColumns);
LayoutUnit row_grid_gap = GridGap(GridTrackSizingDirection::kForRows);
LayoutUnit column_set_offset = BorderScrollbarPadding().inline_start;
Vector<LayoutUnit> column_set_offsets = {column_set_offset};
column_set_offsets.ReserveCapacity(
algorithm_column_track_collection_.SetCount() + 1);
for (auto column_set_iterator =
algorithm_column_track_collection_.GetSetIterator();
!column_set_iterator.IsAtEnd(); column_set_iterator.MoveToNextSet()) {
const auto& set = column_set_iterator.CurrentSet();
column_set_offset += set.BaseSize() + set.TrackCount() * column_grid_gap;
column_set_offsets.push_back(column_set_offset);
}
LayoutUnit row_set_offset = BorderScrollbarPadding().block_start;
Vector<LayoutUnit> row_set_offsets = {row_set_offset};
row_set_offsets.ReserveCapacity(algorithm_row_track_collection_.SetCount() +
1);
for (auto row_set_iterator = algorithm_row_track_collection_.GetSetIterator();
!row_set_iterator.IsAtEnd(); row_set_iterator.MoveToNextSet()) {
const auto& set = row_set_iterator.CurrentSet();
row_set_offset += set.BaseSize() + set.TrackCount() * row_grid_gap;
row_set_offsets.push_back(row_set_offset);
LayoutUnit column_grid_gap =
GridGap(kForColumns, ChildAvailableSize().inline_size);
LayoutUnit row_grid_gap = GridGap(kForRows, ChildAvailableSize().block_size);
Vector<LayoutUnit> column_set_offsets =
ComputeSetOffsets(kForColumns, column_grid_gap);
Vector<LayoutUnit> row_set_offsets =
ComputeSetOffsets(kForRows, row_grid_gap);
// Store the total size of row definitions as the intrinsic block size.
intrinsic_block_size_ =
row_set_offsets.back() -
(row_set_offsets.size() == 1 ? LayoutUnit() : row_grid_gap) +
BorderScrollbarPadding().block_end;
// If the row gap is percent or calc, it should be computed now that the
// intrinsic size is known. However, the gap should not be added to the
// intrinsic block size.
if (IsRowGridGapUnresolvable(ChildAvailableSize().block_size)) {
row_grid_gap = GridGap(kForRows, intrinsic_block_size_);
row_set_offsets = ComputeSetOffsets(kForRows, row_grid_gap);
}
// Store the total size of row definitions (summed with
// BorderScrollbarPadding) as the intrinsic block size.
intrinsic_block_size_ = BorderScrollbarPadding().BlockSum() +
(row_set_offsets.back() - row_grid_gap);
for (GridItemData& grid_item : grid_items_) {
wtf_size_t column_start_index = grid_item.columns_begin_set_index;
wtf_size_t column_end_index = grid_item.columns_end_set_index;
......@@ -1238,21 +1232,42 @@ void NGGridLayoutAlgorithm::PlaceGridItem(const GridItemData& grid_item,
}
LayoutUnit NGGridLayoutAlgorithm::GridGap(
GridTrackSizingDirection track_direction) {
GridTrackSizingDirection track_direction,
LayoutUnit available_size) {
const base::Optional<Length>& gap =
track_direction == kForColumns ? Style().ColumnGap() : Style().RowGap();
if (!gap)
return LayoutUnit();
LayoutUnit available_size = track_direction == kForColumns
? ChildAvailableSize().inline_size
: ChildAvailableSize().block_size;
// TODO (ansollan): handle block axis % resolution for grid-gap with
// auto-sized grids.
if (gap->IsPercentOrCalc() && available_size == kIndefiniteSize)
// TODO(ansollan): Update behavior based on outcome of working group
// discussions. See https://github.com/w3c/csswg-drafts/issues/5566.
if (!gap || IsRowGridGapUnresolvable(available_size))
return LayoutUnit();
return MinimumValueForLength(*gap, available_size);
}
Vector<LayoutUnit> NGGridLayoutAlgorithm::ComputeSetOffsets(
GridTrackSizingDirection track_direction,
LayoutUnit grid_gap) {
LayoutUnit set_offset = track_direction == kForColumns
? BorderScrollbarPadding().inline_start
: BorderScrollbarPadding().block_start;
Vector<LayoutUnit> set_offsets = {set_offset};
auto& track_collection = (track_direction == kForColumns)
? algorithm_column_track_collection_
: algorithm_row_track_collection_;
set_offsets.ReserveCapacity(track_collection.SetCount() + 1);
for (auto set_iterator = track_collection.GetSetIterator();
!set_iterator.IsAtEnd(); set_iterator.MoveToNextSet()) {
const auto& set = set_iterator.CurrentSet();
set_offset += set.BaseSize() + set.TrackCount() * grid_gap;
set_offsets.push_back(set_offset);
}
return set_offsets;
}
bool NGGridLayoutAlgorithm::IsRowGridGapUnresolvable(
LayoutUnit available_size) {
const base::Optional<Length>& row_gap = Style().RowGap();
return row_gap && row_gap->IsPercentOrCalc() &&
available_size == kIndefiniteSize;
}
} // namespace blink
......@@ -187,7 +187,16 @@ class CORE_EXPORT NGGridLayoutAlgorithm
LogicalSize size);
// Gets the row or column gap of the grid.
LayoutUnit GridGap(GridTrackSizingDirection track_direction);
LayoutUnit GridGap(GridTrackSizingDirection track_direction,
LayoutUnit available_size = kIndefiniteSize);
// Calculates inline and block offsets for all tracks.
Vector<LayoutUnit> ComputeSetOffsets(GridTrackSizingDirection track_direction,
LayoutUnit grid_gap);
// Tests whether the row gap is unresolvable based on its type and the
// available size.
bool IsRowGridGapUnresolvable(LayoutUnit available_size);
GridTrackSizingDirection AutoFlowDirection() const;
......
......@@ -1531,6 +1531,59 @@ TEST_F(NGGridLayoutAlgorithmTest, AutoSizedGridWithGap) {
EXPECT_EQ(expectation, dump);
}
TEST_F(NGGridLayoutAlgorithmTest, AutoSizedGridWithPercentageGap) {
if (!RuntimeEnabledFeatures::LayoutNGGridEnabled())
return;
LoadAhem();
SetBodyInnerHTML(R"HTML(
<style>
body {
font: 10px/1 Ahem;
}
#grid {
display: grid;
width: auto;
height: auto;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px;
gap: 5%;
}
</style>
<div id="wrapper">
<div id="grid">
<div style="background: orange;"></div>
<div style="background: green;"></div>
<div style="background: blueviolet;"></div>
<div style="background: orange;"></div>
<div style="background: green;"></div>
<div style="background: blueviolet;"></div>
</div>
</div>
)HTML");
String dump = DumpFragmentTree(GetElementById("wrapper"));
// TODO(ansollan): Change this expectation string as it is currently
// incorrect. The 'auto' inline size of the second node should be resolved to
// 300, based on the column definitions. After that work is implemented, the
// first two nodes in the output should look like this:
// offset:unplaced size:1000x200
// offset:0,0 size:300x200
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x200
offset:0,0 size:1000x200
offset:0,0 size:100x100
offset:150,0 size:100x100
offset:300,0 size:100x100
offset:0,110 size:100x100
offset:150,110 size:100x100
offset:300,110 size:100x100
)DUMP";
EXPECT_EQ(expectation, dump);
}
TEST_F(NGGridLayoutAlgorithmTest, ItemsSizeWithGap) {
if (!RuntimeEnabledFeatures::LayoutNGGridEnabled())
return;
......
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