diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d9c89742..46148c410 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,6 +78,15 @@ jobs: test-features-default-except-content-size: name: "Test Suite [default except content_size]" runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo build --no-default-features --features std,taffy_tree,grid,flexbox,block_layout + - run: cargo test --tests --no-default-features --features std,taffy_tree,grid,flexbox,block_layout,calc + + test-features-default-except-calc: + name: "Test Suite [default except calc]" + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable @@ -92,7 +101,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - run: cargo build --no-default-features --features std - run: cargo build --no-default-features --features std,taffy_tree - - run: cargo test --tests --no-default-features --features std,taffy_tree + - run: cargo test --tests --no-default-features --features std,taffy_tree,calc # With std feature test-features-flexbox: diff --git a/Cargo.toml b/Cargo.toml index c7bba5fa5..1a09ec92a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ default = [ "flexbox", "grid", "block_layout", + "calc", "content_size", "detailed_layout_info", ] @@ -53,6 +54,8 @@ block_layout = [] flexbox = [] ## Enables the CSS Grid layout algorithm. See [`compute_grid_layout`](crate::compute_grid_layout). grid = ["alloc", "dep:grid"] +## Enables calc() values for all layout algorithms +calc = [] ## Causes all algorithms to compute and output a content size for each node content_size = [] ## Causes algorithms to stores detailed information of the nodes in TaffyTree, with only CSS Grid supporting this. diff --git a/src/compute/grid/track_sizing.rs b/src/compute/grid/track_sizing.rs index 0b353b19a..49a09e365 100644 --- a/src/compute/grid/track_sizing.rs +++ b/src/compute/grid/track_sizing.rs @@ -612,6 +612,7 @@ fn resolve_intrinsic_track_sizes( track.base_size } // Handle calc() like percentage + #[cfg(feature = "calc")] _ if track.min_track_sizing_function.0.is_calc() => { if axis_inner_node_size.is_none() { f32_max(track.base_size, item_sizer.min_content_contribution(item)) diff --git a/src/style/compact_length.rs b/src/style/compact_length.rs index 89280f621..0a4b7f799 100644 --- a/src/style/compact_length.rs +++ b/src/style/compact_length.rs @@ -41,12 +41,6 @@ mod compat { #[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] std::compile_error!("Taffy only supports targets with a pointer width of 32 or 64 bits"); -// /// Error serializing -// enum SerializeErr { -// /// Serializing calc values is not supported -// CalcValue, -// } - /// CompactLengthInner implementation for 64 bit platforms #[cfg(target_pointer_width = "64")] mod inner { @@ -92,6 +86,7 @@ mod inner { /// Get the calc tag (low 3 bits) #[inline(always)] + #[cfg(feature = "calc")] pub(super) fn calc_tag(self) -> usize { (self.tagged_ptr as usize) & CALC_TAG_MASK } @@ -167,6 +162,7 @@ mod inner { /// Get the calc tag (low 3 bits) #[inline(always)] + #[cfg(feature = "calc")] pub(super) fn calc_tag(self) -> usize { self.tag } @@ -214,6 +210,7 @@ pub struct CompactLength(CompactLengthInner); impl CompactLength { /// The tag indicating a calc() value + #[cfg(feature = "calc")] pub const CALC_TAG: usize = 0b000; /// The tag indicating a length value pub const LENGTH_TAG: usize = 0b0000_0001; @@ -254,6 +251,7 @@ impl CompactLength { /// /// The low 3 bits are used as a tag value and will be returned as 0. #[inline] + #[cfg(feature = "calc")] pub fn calc(ptr: *const ()) -> Self { assert_ne!(ptr as u64, 0); assert_eq!(ptr as u64 & 0b111, 0); @@ -332,12 +330,14 @@ impl CompactLength { /// Get the calc pointer of the `CompactLength` #[inline(always)] + #[cfg(feature = "calc")] pub fn calc_value(self) -> *const () { self.0.ptr() } /// Returns true if the value is 0 px #[inline(always)] + #[cfg(feature = "calc")] pub fn is_calc(self) -> bool { self.0.calc_tag() == 0 } @@ -426,8 +426,14 @@ impl CompactLength { /// Whether the track sizing functions depends on the size of the parent node #[inline(always)] pub fn uses_percentage(self) -> bool { - // TODO: handle calc() values - matches!(self.tag(), CompactLength::PERCENT_TAG | CompactLength::FIT_CONTENT_PERCENT_TAG) || self.is_calc() + #[cfg(feature = "calc")] + { + matches!(self.tag(), CompactLength::PERCENT_TAG | CompactLength::FIT_CONTENT_PERCENT_TAG) || self.is_calc() + } + #[cfg(not(feature = "calc"))] + { + matches!(self.tag(), CompactLength::PERCENT_TAG | CompactLength::FIT_CONTENT_PERCENT_TAG) + } } /// Resolve percentage values against the passed parent_size, returning Some(value) @@ -440,6 +446,7 @@ impl CompactLength { ) -> Option { match self.tag() { CompactLength::PERCENT_TAG => Some(self.value() * parent_size), + #[cfg(feature = "calc")] _ if self.is_calc() => Some(calc_resolver(self.0.ptr(), parent_size)), _ => None, } @@ -490,11 +497,17 @@ impl serde::Serialize for CompactLength { where S: serde::Serializer, { - if self.tag() == Self::CALC_TAG { - Err(serde::ser::Error::custom("Cannot serialize Calc value")) - } else { - serializer.serialize_u64(self.0.serialized()) + #[cfg(feature = "calc")] + { + if self.tag() == Self::CALC_TAG { + Err(serde::ser::Error::custom("Cannot serialize Calc value")) + } else { + serializer.serialize_u64(self.0.serialized()) + } } + + #[cfg(not(feature = "calc"))] + serializer.serialize_u64(self.0.serialized()) } } diff --git a/src/style/dimension.rs b/src/style/dimension.rs index 2391d5ba3..ad270e48c 100644 --- a/src/style/dimension.rs +++ b/src/style/dimension.rs @@ -43,6 +43,7 @@ impl LengthPercentage { /// /// The low 3 bits are used as a tag value and will be returned as 0. #[inline(always)] + #[cfg(feature = "calc")] pub fn calc(ptr: *const ()) -> Self { Self(CompactLength::calc(ptr)) } @@ -133,6 +134,7 @@ impl LengthPercentageAuto { /// /// The low 3 bits are used as a tag value and will be returned as 0. #[inline] + #[cfg(feature = "calc")] pub fn calc(ptr: *const ()) -> Self { Self(CompactLength::calc(ptr)) } @@ -160,6 +162,7 @@ impl LengthPercentageAuto { CompactLength::LENGTH_TAG => Some(self.0.value()), CompactLength::PERCENT_TAG => Some(context * self.0.value()), CompactLength::AUTO_TAG => None, + #[cfg(feature = "calc")] _ if self.0.is_calc() => Some(calc_resolver(self.0.calc_value(), context)), _ => unreachable!("LengthPercentageAuto values cannot be constructed with other tags"), } @@ -249,6 +252,7 @@ impl Dimension { /// /// The low 3 bits are used as a tag value and will be returned as 0. #[inline] + #[cfg(feature = "calc")] pub fn calc(ptr: *const ()) -> Self { Self(CompactLength::calc(ptr)) } diff --git a/src/style/grid.rs b/src/style/grid.rs index 9f800a25b..41f5bd09b 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -524,6 +524,7 @@ impl MaxTrackSizingFunction { /// /// The low 3 bits are used as a tag value and will be returned as 0. #[inline] + #[cfg(feature = "calc")] pub fn calc(ptr: *const ()) -> Self { Self(CompactLength::calc(ptr)) } @@ -597,6 +598,7 @@ impl MaxTrackSizingFunction { match self.0.tag() { CompactLength::LENGTH_TAG => true, CompactLength::PERCENT_TAG => parent_size.is_some(), + #[cfg(feature = "calc")] _ if self.0.is_calc() => parent_size.is_some(), _ => false, } @@ -614,6 +616,7 @@ impl MaxTrackSizingFunction { match self.0.tag() { CompactLength::LENGTH_TAG => Some(self.0.value()), CompactLength::PERCENT_TAG => parent_size.map(|size| self.0.value() * size), + #[cfg(feature = "calc")] _ if self.0.is_calc() => parent_size.map(|size| calc_resolver(self.0.calc_value(), size)), _ => None, } @@ -768,6 +771,7 @@ impl MinTrackSizingFunction { /// /// The low 3 bits are used as a tag value and will be returned as 0. #[inline] + #[cfg(feature = "calc")] pub fn calc(ptr: *const ()) -> Self { Self(CompactLength::calc(ptr)) } @@ -833,6 +837,7 @@ impl MinTrackSizingFunction { match self.0.tag() { CompactLength::LENGTH_TAG => Some(self.0.value()), CompactLength::PERCENT_TAG => parent_size.map(|size| self.0.value() * size), + #[cfg(feature = "calc")] _ if self.0.is_calc() => parent_size.map(|size| calc_resolver(self.0.calc_value(), size)), _ => None, } @@ -852,7 +857,14 @@ impl MinTrackSizingFunction { /// Whether the track sizing functions depends on the size of the parent node #[inline(always)] pub fn uses_percentage(self) -> bool { - matches!(self.0.tag(), CompactLength::PERCENT_TAG) || self.0.is_calc() + #[cfg(feature = "calc")] + { + matches!(self.0.tag(), CompactLength::PERCENT_TAG) || self.0.is_calc() + } + #[cfg(not(feature = "calc"))] + { + matches!(self.0.tag(), CompactLength::PERCENT_TAG) + } } } diff --git a/src/tree/traits.rs b/src/tree/traits.rs index 191de42cb..a5b208b42 100644 --- a/src/tree/traits.rs +++ b/src/tree/traits.rs @@ -181,7 +181,12 @@ pub trait LayoutPartialTree: TraversePartialTree { fn get_core_container_style(&self, node_id: NodeId) -> Self::CoreContainerStyle<'_>; /// Resolve calc value - fn resolve_calc_value(&self, val: *const (), basis: f32) -> f32; + #[inline(always)] + fn resolve_calc_value(&self, val: *const (), basis: f32) -> f32 { + let _ = val; + let _ = basis; + 0.0 + } /// Set the node's unrounded layout fn set_unrounded_layout(&mut self, node_id: NodeId, layout: &Layout); @@ -366,9 +371,17 @@ pub(crate) trait LayoutPartialTreeExt: LayoutPartialTree { /// Alias to `resolve_calc_value` with a shorter function name #[inline(always)] + #[cfg(feature = "calc")] fn calc(&self, val: *const (), basis: f32) -> f32 { self.resolve_calc_value(val, basis) } + + /// Alias to `resolve_calc_value` with a shorter function name + #[inline(always)] + #[cfg(not(feature = "calc"))] + fn calc(&self, _val: *const (), _basis: f32) -> f32 { + 0.0 + } } impl LayoutPartialTreeExt for T {} diff --git a/src/util/resolve.rs b/src/util/resolve.rs index a0e47b0ee..c40fec300 100644 --- a/src/util/resolve.rs +++ b/src/util/resolve.rs @@ -32,6 +32,7 @@ impl MaybeResolve, Option> for LengthPercentage { match self.0.tag() { CompactLength::LENGTH_TAG => Some(self.0.value()), CompactLength::PERCENT_TAG => context.map(|dim| dim * self.0.value()), + #[cfg(feature = "calc")] _ if self.0.is_calc() => context.map(|dim| calc(self.0.calc_value(), dim)), _ => unreachable!(), } @@ -46,6 +47,7 @@ impl MaybeResolve, Option> for LengthPercentageAuto { CompactLength::AUTO_TAG => None, CompactLength::LENGTH_TAG => Some(self.0.value()), CompactLength::PERCENT_TAG => context.map(|dim| dim * self.0.value()), + #[cfg(feature = "calc")] _ if self.0.is_calc() => context.map(|dim| calc(self.0.calc_value(), dim)), _ => unreachable!(), } @@ -61,6 +63,7 @@ impl MaybeResolve, Option> for Dimension { CompactLength::AUTO_TAG => None, CompactLength::LENGTH_TAG => Some(self.0.value()), CompactLength::PERCENT_TAG => context.map(|dim| dim * self.0.value()), + #[cfg(feature = "calc")] _ if self.0.is_calc() => context.map(|dim| calc(self.0.calc_value(), dim)), _ => unreachable!(), }