Skip to content

Commit

Permalink
Fix CSS Grid "auto track" / placement bugs (#481)
Browse files Browse the repository at this point in the history
* Fix divide by zero when using grid_auto_rows/grid_auto_columns with zero
"negative implicit" tracks

* Fix over-allocation in the CellOccupancyMatrix when auto-placing in grids
that contain negative implicit tracks.

* Fix axis conflation when grid_auto_flow is column

* Fix computation of auto track offset when initializing negative implicit tracks

* Add basic tests for grid_auto_rows and grid_auto_columns
  • Loading branch information
nicoburns committed Aug 14, 2023
1 parent dce28c7 commit cbfc335
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 16 deletions.
19 changes: 9 additions & 10 deletions src/compute/grid/explicit_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::resolve::ResolveOrZero;
use crate::style::{GridTrackRepetition, LengthPercentage, NonRepeatedTrackSizingFunction, Style, TrackSizingFunction};
use crate::style_helpers::TaffyAuto;
use crate::sys::{GridTrackVec, Vec};
use core::cmp::{max, min};

/// Compute the number of rows and columns in the explicit grid
pub(crate) fn compute_explicit_grid_size_in_axis(style: &Style, axis: AbsoluteAxis) -> u16 {
Expand Down Expand Up @@ -191,15 +190,15 @@ pub(super) fn initialize_grid_tracks(
tracks.push(GridTrack::gutter(gap));

// Create negative implicit tracks
if auto_tracks.is_empty() {
let iter = core::iter::repeat(NonRepeatedTrackSizingFunction::AUTO);
create_implicit_tracks(tracks, counts.negative_implicit, iter, gap)
} else {
let max_count = max(auto_tracks.len(), counts.negative_implicit as usize);
let min_count = min(auto_tracks.len(), counts.negative_implicit as usize);
let offset = max_count % min_count;
let iter = auto_tracks.iter().copied().cycle().skip(offset);
create_implicit_tracks(tracks, counts.negative_implicit, iter, gap)
if counts.negative_implicit > 0 {
if auto_tracks.is_empty() {
let iter = core::iter::repeat(NonRepeatedTrackSizingFunction::AUTO);
create_implicit_tracks(tracks, counts.negative_implicit, iter, gap)
} else {
let offset = auto_tracks.len() - (counts.negative_implicit as usize % auto_tracks.len());
let iter = auto_tracks.iter().copied().cycle().skip(offset);
create_implicit_tracks(tracks, counts.negative_implicit, iter, gap)
}
}

let mut current_track_index = (counts.negative_implicit) as usize;
Expand Down
8 changes: 5 additions & 3 deletions src/compute/grid/placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ pub(super) fn place_grid_items<'a, ChildIter>(

// 4. Position the remaining grid items
// (which either have definite position only in the secondary axis or indefinite positions in both axis)
let x_neg_tracks = cell_occupancy_matrix.track_counts(AbsoluteAxis::Horizontal).negative_implicit as i16;
let y_neg_tracks = cell_occupancy_matrix.track_counts(AbsoluteAxis::Vertical).negative_implicit as i16;
let grid_start_position = (OriginZeroLine(-x_neg_tracks), OriginZeroLine(-y_neg_tracks));
let primary_axis = grid_auto_flow.primary_axis();
let secondary_axis = primary_axis.other_axis();
let primary_neg_tracks = cell_occupancy_matrix.track_counts(primary_axis).negative_implicit as i16;
let secondary_neg_tracks = cell_occupancy_matrix.track_counts(secondary_axis).negative_implicit as i16;
let grid_start_position = (OriginZeroLine(-primary_neg_tracks), OriginZeroLine(-secondary_neg_tracks));
let mut grid_position = grid_start_position;
let mut idx = 0;
children_iter()
Expand Down
5 changes: 2 additions & 3 deletions src/compute/grid/types/cell_occupancy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,9 @@ impl CellOccupancyMatrix {
fn expand_to_fit_range(&mut self, row_range: Range<i16>, col_range: Range<i16>) {
// Calculate number of rows and columns missing to accomodate ranges (if any)
let req_negative_rows = min(row_range.start, 0);
let req_positive_rows = max(row_range.end - self.rows.explicit as i16 - self.rows.positive_implicit as i16, 0);
let req_positive_rows = max(row_range.end - self.rows.len() as i16, 0);
let req_negative_cols = min(col_range.start, 0);
let req_positive_cols =
max(col_range.end - self.columns.explicit as i16 - self.columns.positive_implicit as i16, 0);
let req_positive_cols = max(col_range.end - self.columns.len() as i16, 0);

let old_row_count = self.rows.len();
let old_col_count = self.columns.len();
Expand Down
24 changes: 24 additions & 0 deletions test_fixtures/grid_auto_columns.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../scripts/gentest/test_helper.js"></script>
<link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
<title>
Test description
</title>
</head>
<body>

<div id="test-root" style="display: grid; grid-auto-flow: column; grid-template-rows: 100px; grid-template-columns: 40px; grid-auto-columns: 10px 20px 30px;">
<div style="grid-column-start: -3;"></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

</body>
</html>
24 changes: 24 additions & 0 deletions test_fixtures/grid_auto_rows.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../scripts/gentest/test_helper.js"></script>
<link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
<title>
Test description
</title>
</head>
<body>

<div id="test-root" style="display: grid; grid-template-columns: 100px; grid-template-rows: 40px; grid-auto-rows: 10px 20px 30px;">
<div style="grid-row-start: -4;"></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

</body>
</html>
82 changes: 82 additions & 0 deletions tests/generated/grid_auto_columns.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 81 additions & 0 deletions tests/generated/grid_auto_rows.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions tests/generated/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit cbfc335

Please sign in to comment.