Skip to content

Commit

Permalink
Stylo integration (#693)
Browse files Browse the repository at this point in the history
* Make return type of grid track list functions generic

* Initial taffy_stylo crate (flexbox only)

* Use blitz branch of stylo

* Implement grid type conversions in taffy_stylo

* Fix clippy lints

* Use stylo main

* Module rename / reorganisation
  • Loading branch information
nicoburns committed Aug 4, 2024
1 parent 902c322 commit 9915b96
Show file tree
Hide file tree
Showing 10 changed files with 1,033 additions and 52 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,5 @@ members = [
"scripts/format-fixtures",
"scripts/import-yoga-tests",
"benches",
"taffy_stylo",
]
144 changes: 121 additions & 23 deletions src/compute/grid/explicit_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ use num_traits::float::FloatCore;
/// Compute the number of rows and columns in the explicit grid
pub(crate) fn compute_explicit_grid_size_in_axis(
style: &impl GridContainerStyle,
template: &[TrackSizingFunction],
inner_container_size: Size<Option<f32>>,
axis: AbsoluteAxis,
) -> u16 {
// Load the grid-template-rows or grid-template-columns definition (depending on the axis)
let template = style.grid_template_tracks(axis);

// If template contains no tracks, then there are trivially zero explicit tracks
if template.is_empty() {
return 0;
Expand Down Expand Up @@ -294,8 +292,18 @@ mod test {
fn explicit_grid_sizing_no_repeats() {
let grid_style = (600.0, 600.0, 2, 4).into_grid();
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 2);
assert_eq!(height, 4);
}
Expand All @@ -311,8 +319,18 @@ mod test {
..Default::default()
};
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 3);
assert_eq!(height, 4);
}
Expand All @@ -328,8 +346,18 @@ mod test {
..Default::default()
};
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 3);
assert_eq!(height, 4);
}
Expand All @@ -345,8 +373,18 @@ mod test {
..Default::default()
};
let inner_container_size = Size { width: Some(120.0), height: Some(80.0) };
let width = compute_explicit_grid_size_in_axis(&grid_style, inner_container_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, inner_container_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
inner_container_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
inner_container_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 3);
assert_eq!(height, 4);
}
Expand All @@ -362,8 +400,18 @@ mod test {
..Default::default()
};
let inner_container_size = Size { width: Some(140.0), height: Some(90.0) };
let width = compute_explicit_grid_size_in_axis(&grid_style, inner_container_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, inner_container_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
inner_container_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
inner_container_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 4);
assert_eq!(height, 5);
}
Expand All @@ -379,8 +427,18 @@ mod test {
..Default::default()
};
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 4); // 2 repetitions * 2 repeated tracks = 4 tracks in total
assert_eq!(height, 6); // 3 repetitions * 2 repeated tracks = 4 tracks in total
}
Expand All @@ -397,8 +455,18 @@ mod test {
..Default::default()
};
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 2); // 2 tracks + 1 gap
assert_eq!(height, 3); // 3 tracks + 2 gaps
}
Expand All @@ -414,8 +482,18 @@ mod test {
..Default::default()
};
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 3);
assert_eq!(height, 1);
}
Expand All @@ -432,8 +510,18 @@ mod test {
..Default::default()
};
let preferred_size = grid_style.size.map(|s| s.into_option());
let width = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, preferred_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
preferred_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
preferred_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 3); // 3 tracks + 2 gaps
assert_eq!(height, 2); // 2 tracks + 1 gap
}
Expand All @@ -450,8 +538,18 @@ mod test {
..Default::default()
};
let inner_container_size = Size { width: Some(100.0), height: Some(80.0) };
let width = compute_explicit_grid_size_in_axis(&grid_style, inner_container_size, AbsoluteAxis::Horizontal);
let height = compute_explicit_grid_size_in_axis(&grid_style, inner_container_size, AbsoluteAxis::Vertical);
let width = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_columns,
inner_container_size,
AbsoluteAxis::Horizontal,
);
let height = compute_explicit_grid_size_in_axis(
&grid_style,
&grid_style.grid_template_rows,
inner_container_size,
AbsoluteAxis::Vertical,
);
assert_eq!(width, 5); // 40px horizontal padding
assert_eq!(height, 4); // 20px vertical padding
}
Expand Down
37 changes: 29 additions & 8 deletions src/compute/grid/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! This module is a partial implementation of the CSS Grid Level 1 specification
//! <https://www.w3.org/TR/css-grid-1>
use core::borrow::Borrow;

use crate::geometry::{AbsoluteAxis, AbstractAxis, InBothAbsAxis};
use crate::geometry::{Line, Point, Rect, Size};
use crate::style::{AlignItems, AlignSelf, AvailableSpace, Overflow, Position};
Expand Down Expand Up @@ -89,6 +91,13 @@ pub fn compute_grid_layout(tree: &mut impl LayoutGridContainer, node: NodeId, in
let align_items = style.align_items();
let justify_items = style.justify_items();

// Note: we avoid accessing the grid rows/columns methods more than once as this can
// cause an expensive-ish computation
let grid_template_columms = style.grid_template_columns();
let grid_template_rows = style.grid_template_rows();
let grid_auto_columms = style.grid_auto_columns();
let grid_auto_rows = style.grid_auto_rows();

let constrained_available_space = known_dimensions
.or(preferred_size)
.map(|size| size.map(AvailableSpace::Definite))
Expand Down Expand Up @@ -137,10 +146,18 @@ pub fn compute_grid_layout(tree: &mut impl LayoutGridContainer, node: NodeId, in
.maybe_sub(content_box_inset.sum_axes());

// Exactly compute the number of rows and columns in the explicit grid.
let explicit_col_count =
compute_explicit_grid_size_in_axis(&style, auto_fit_container_size, AbsoluteAxis::Horizontal);
let explicit_row_count =
compute_explicit_grid_size_in_axis(&style, auto_fit_container_size, AbsoluteAxis::Vertical);
let explicit_col_count = compute_explicit_grid_size_in_axis(
&style,
grid_template_columms.borrow(),
auto_fit_container_size,
AbsoluteAxis::Horizontal,
);
let explicit_row_count = compute_explicit_grid_size_in_axis(
&style,
grid_template_rows.borrow(),
auto_fit_container_size,
AbsoluteAxis::Vertical,
);

// 3. Implicit Grid: Estimate Track Counts
// Estimate the number of rows and columns in the implicit grid (= the entire grid)
Expand Down Expand Up @@ -181,20 +198,24 @@ pub fn compute_grid_layout(tree: &mut impl LayoutGridContainer, node: NodeId, in
initialize_grid_tracks(
&mut columns,
final_col_counts,
style.grid_template_columns(),
style.grid_auto_columns(),
grid_template_columms.borrow(),
grid_auto_columms.borrow(),
style.gap().width,
|column_index| cell_occupancy_matrix.column_is_occupied(column_index),
);
initialize_grid_tracks(
&mut rows,
final_row_counts,
style.grid_template_rows(),
style.grid_auto_rows(),
grid_template_rows.borrow(),
grid_auto_rows.borrow(),
style.gap().height,
|row_index| cell_occupancy_matrix.row_is_occupied(row_index),
);

drop(grid_template_rows);
drop(grid_template_columms);
drop(grid_auto_rows);
drop(grid_auto_columms);
drop(style);

// 6. Track Sizing
Expand Down
36 changes: 19 additions & 17 deletions src/style/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,33 @@ use crate::compute::grid::{GridCoordinate, GridLine, OriginZeroLine};
use crate::geometry::{AbsoluteAxis, AbstractAxis, Line, MinMax, Size};
use crate::style_helpers::*;
use crate::util::sys::GridTrackVec;
use core::borrow::Borrow;
use core::cmp::{max, min};
use core::convert::Infallible;

/// The set of styles required for a CSS Grid container
pub trait GridContainerStyle: CoreStyle {
/// The type returned by grid_template_rows and grid_template_columns
type TemplateTrackList<'a>: Borrow<[TrackSizingFunction]>
where
Self: 'a;
/// The type returned by grid_auto_rows and grid_auto_columns
type AutoTrackList<'a>: Borrow<[NonRepeatedTrackSizingFunction]>
where
Self: 'a;

// FIXME: re-add default implemenations for grid_{template,auto}_{rows,columns} once the
// associated_type_defaults feature (https://github.com/rust-lang/rust/issues/29661) is stabilised.

/// Defines the track sizing functions (heights) of the grid rows
#[inline(always)]
fn grid_template_rows(&self) -> &[TrackSizingFunction] {
&[]
}
fn grid_template_rows(&self) -> Self::TemplateTrackList<'_>;
/// Defines the track sizing functions (widths) of the grid columns
#[inline(always)]
fn grid_template_columns(&self) -> &[TrackSizingFunction] {
&[]
}
fn grid_template_columns(&self) -> Self::TemplateTrackList<'_>;
/// Defines the size of implicitly created rows
#[inline(always)]
fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] {
&[]
}
fn grid_auto_rows(&self) -> Self::AutoTrackList<'_>;
/// Defined the size of implicitly created columns
#[inline(always)]
fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] {
&[]
}
fn grid_auto_columns(&self) -> Self::AutoTrackList<'_>;

/// Controls how items get placed into the grid for auto-placed items
#[inline(always)]
fn grid_auto_flow(&self) -> GridAutoFlow {
Expand Down Expand Up @@ -66,7 +68,7 @@ pub trait GridContainerStyle: CoreStyle {

/// Get a grid item's row or column placement depending on the axis passed
#[inline(always)]
fn grid_template_tracks(&self, axis: AbsoluteAxis) -> &[TrackSizingFunction] {
fn grid_template_tracks(&self, axis: AbsoluteAxis) -> Self::TemplateTrackList<'_> {
match axis {
AbsoluteAxis::Horizontal => self.grid_template_columns(),
AbsoluteAxis::Vertical => self.grid_template_rows(),
Expand Down
Loading

0 comments on commit 9915b96

Please sign in to comment.