Skip to content

Commit

Permalink
Feature flag calc values
Browse files Browse the repository at this point in the history
Signed-off-by: Nico Burns <[email protected]>
  • Loading branch information
nicoburns committed Feb 20, 2025
1 parent bd0150f commit 0629dca
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 15 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ default = [
"flexbox",
"grid",
"block_layout",
"calc",
"content_size",
"detailed_layout_info",
]
Expand All @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/compute/grid/track_sizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ fn resolve_intrinsic_track_sizes<Tree: LayoutPartialTree>(
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))
Expand Down
37 changes: 25 additions & 12 deletions src/style/compact_length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
Expand All @@ -440,6 +446,7 @@ impl CompactLength {
) -> Option<f32> {
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,
}
Expand Down Expand Up @@ -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())
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/style/dimension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down Expand Up @@ -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))
}
Expand Down Expand Up @@ -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"),
}
Expand Down Expand Up @@ -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))
}
Expand Down
14 changes: 13 additions & 1 deletion src/style/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down Expand Up @@ -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,
}
Expand All @@ -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,
}
Expand Down Expand Up @@ -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))
}
Expand Down Expand Up @@ -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,
}
Expand All @@ -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)
}
}
}

Expand Down
15 changes: 14 additions & 1 deletion src/tree/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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<T: LayoutPartialTree> LayoutPartialTreeExt for T {}
3 changes: 3 additions & 0 deletions src/util/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ impl MaybeResolve<Option<f32>, Option<f32>> 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!(),
}
Expand All @@ -46,6 +47,7 @@ impl MaybeResolve<Option<f32>, Option<f32>> 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!(),
}
Expand All @@ -61,6 +63,7 @@ impl MaybeResolve<Option<f32>, Option<f32>> 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!(),
}
Expand Down

0 comments on commit 0629dca

Please sign in to comment.