diff --git a/src/style/compact_length.rs b/src/style/compact_length.rs
new file mode 100644
index 000000000..fa32308a4
--- /dev/null
+++ b/src/style/compact_length.rs
@@ -0,0 +1,309 @@
+//! A tagged-pointer abstraction that allows size styles in Taffy to be represented
+//! in just 64 bits. Wrapped by types in the `super::dimension` and `super::grid` modules.
+use super::LengthPercentage;
+use crate::style_helpers::{
+ FromFr, FromLength, FromPercent, TaffyAuto, TaffyFitContent, TaffyMaxContent, TaffyMinContent, TaffyZero,
+};
+use compat::{f32_from_bits, f32_to_bits};
+
+/// A representation of a length as a compact 64-bit tagged pointer
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct CompactLength(u64);
+
+impl CompactLength {
+ // Masks
+
+ /// The low byte (8 bits)
+ pub const TAG_MASK: u64 = 0b11111111;
+ /// The low 3 bits
+ pub const CALC_TAG_MASK: u64 = 0b111;
+ /// The high 63 bits
+ pub const CALC_PTR_MASK: u64 = u64::MAX ^ 0b111;
+
+ // Primary tags
+
+ /// The tag indicating a calc() value
+ pub const CALC_TAG: u64 = 0b000;
+ /// The tag indicating a length value
+ pub const LENGTH_TAG: u64 = 0b0000_0001;
+ /// The tag indicating a percentage value
+ pub const PERCENT_TAG: u64 = 0b0000_0010;
+ /// The tag indicating an auto value
+ pub const AUTO_TAG: u64 = 0b0000_0011;
+ /// The tag indicating an fr value
+ pub const FR_TAG: u64 = 0b0000_0100;
+ /// The tag indicating a min-content value
+ pub const MIN_CONTENT_TAG: u64 = 0b00000111;
+ /// The tag indicating a max-content value
+ pub const MAX_CONTENT_TAG: u64 = 0b00001111;
+ /// The tag indicating a fit-content value with px limit
+ pub const FIT_CONTENT_PX_TAG: u64 = 0b00010111;
+ /// The tag indicating a fit-content value with percent limit
+ pub const FIT_CONTENT_PERCENT_TAG: u64 = 0b00011111;
+}
+
+impl CompactLength {
+ /// An absolute length in some abstract units. Users of Taffy may define what they correspond
+ /// to in their application (pixels, logical pixels, mm, etc) as they see fit.
+ #[inline(always)]
+ pub const fn length(val: f32) -> Self {
+ Self(((f32_to_bits(val) as u64) << 32) | Self::LENGTH_TAG)
+ }
+
+ /// A percentage length relative to the size of the containing block.
+ ///
+ /// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
+ #[inline(always)]
+ pub const fn percent(val: f32) -> Self {
+ Self(((f32_to_bits(val) as u64) << 32) | Self::PERCENT_TAG)
+ }
+
+ /// A `calc()` value. The value passed here is treated as an opaque handle to
+ /// the actual calc representation and may be a pointer, index, etc.
+ ///
+ /// The low 3 bits are used as a tag value and will be returned as 0.
+ #[inline]
+ pub fn calc(ptr: *const ()) -> Self {
+ assert_ne!(ptr as u64, 0);
+ assert_eq!(ptr as u64 & 0b111, 0);
+ Self(ptr as u64 | Self::CALC_TAG)
+ }
+
+ /// The dimension should be automatically computed according to algorithm-specific rules
+ /// regarding the default size of boxes.
+ #[inline(always)]
+ pub const fn auto() -> Self {
+ Self(Self::AUTO_TAG)
+ }
+
+ /// The dimension as a fraction of the total available grid space (`fr` units in CSS)
+ /// Specified value is the numerator of the fraction. Denominator is the sum of all fraction specified in that grid dimension
+ /// Spec: <https://www.w3.org/TR/css3-grid-layout/#fr-unit>
+ #[inline(always)]
+ pub const fn fr(val: f32) -> Self {
+ Self(((f32_to_bits(val) as u64) << 32) | Self::FR_TAG)
+ }
+
+ /// The size should be the "min-content" size.
+ /// This is the smallest size that can fit the item's contents with ALL soft line-wrapping opportunities taken
+ #[inline(always)]
+ pub const fn min_content() -> Self {
+ Self(Self::MIN_CONTENT_TAG)
+ }
+
+ /// The size should be the "max-content" size.
+ /// This is the smallest size that can fit the item's contents with NO soft line-wrapping opportunities taken
+ #[inline(always)]
+ pub const fn max_content() -> Self {
+ Self(Self::MAX_CONTENT_TAG)
+ }
+
+ /// The size should be computed according to the "fit content" formula:
+ /// `max(min_content, min(max_content, limit))`
+ /// where:
+ /// - `min_content` is the [min-content](Self::min_content) size
+ /// - `max_content` is the [max-content](Self::max_content) size
+ /// - `limit` is a LENGTH value passed to this function
+ ///
+ /// The effect of this is that the item takes the size of `limit` clamped
+ /// by the min-content and max-content sizes.
+ #[inline(always)]
+ pub const fn fit_content_px(limit: f32) -> Self {
+ Self(((f32_to_bits(limit) as u64) << 32) | Self::FIT_CONTENT_PX_TAG)
+ }
+
+ /// The size should be computed according to the "fit content" formula:
+ /// `max(min_content, min(max_content, limit))`
+ /// where:
+ /// - `min_content` is the [min-content](Self::min_content) size
+ /// - `max_content` is the [max-content](Self::max_content) size
+ /// - `limit` is a PERCENTAGE value passed to this function
+ ///
+ /// The effect of this is that the item takes the size of `limit` clamped
+ /// by the min-content and max-content sizes.
+ #[inline(always)]
+ pub const fn fit_content_percent(limit: f32) -> Self {
+ Self(((f32_to_bits(limit) as u64) << 32) | Self::FIT_CONTENT_PERCENT_TAG)
+ }
+
+ /// Get the primary tag
+ #[inline(always)]
+ pub const fn tag(self) -> u64 {
+ self.0 & Self::TAG_MASK
+ }
+
+ /// Get the numeric value associated with the `CompactLength`
+ /// (e.g. the pixel value for a LENGTH variant)
+ #[inline(always)]
+ pub const fn value(self) -> f32 {
+ f32_from_bits((self.0 >> 32) as u32)
+ }
+
+ /// Get the numeric value associated with the `CompactLength`
+ /// (e.g. the pixel value for a LENGTH variant)
+ #[inline(always)]
+ pub const fn calc_value(self) -> u64 {
+ self.0
+ }
+
+ /// Returns true if the value is 0 px
+ #[inline(always)]
+ pub const fn is_calc(self) -> bool {
+ self.0 & Self::CALC_TAG_MASK == 0
+ }
+
+ /// Returns true if the value is 0 px
+ #[inline(always)]
+ pub const fn is_zero(self) -> bool {
+ self.0 == Self::ZERO.0
+ }
+
+ /// Returns true if the value is a length or percentage value
+ #[inline(always)]
+ pub const fn is_length_or_percentage(self) -> bool {
+ matches!(self.tag(), Self::LENGTH_TAG | Self::PERCENT_TAG)
+ }
+
+ /// Returns true if the value is auto
+ #[inline(always)]
+ pub const fn is_auto(self) -> bool {
+ self.tag() == Self::AUTO_TAG
+ }
+
+ /// Returns true if the value is min-content
+ #[inline(always)]
+ pub const fn is_min_content(self) -> bool {
+ matches!(self.tag(), Self::MIN_CONTENT_TAG)
+ }
+
+ /// Returns true if the value is max-content
+ #[inline(always)]
+ pub const fn is_max_content(self) -> bool {
+ matches!(self.tag(), Self::MAX_CONTENT_TAG)
+ }
+
+ /// Returns true if the value is a fit-content(...) value
+ #[inline(always)]
+ pub const fn is_fit_content(self) -> bool {
+ matches!(self.tag(), Self::FIT_CONTENT_PX_TAG | Self::FIT_CONTENT_PERCENT_TAG)
+ }
+
+ /// Returns true if the value is max-content or a fit-content(...) value
+ #[inline(always)]
+ pub const fn is_max_or_fit_content(self) -> bool {
+ matches!(self.tag(), Self::MAX_CONTENT_TAG | Self::FIT_CONTENT_PX_TAG | Self::FIT_CONTENT_PERCENT_TAG)
+ }
+
+ /// Returns true if the max track sizing function is `MaxContent`, `FitContent` or `Auto` else false.
+ /// "In all cases, treat auto and fit-content() as max-content, except where specified otherwise for fit-content()."
+ /// See: <https://www.w3.org/TR/css-grid-1/#algo-terms>
+ #[inline(always)]
+ pub fn is_max_content_alike(&self) -> bool {
+ matches!(
+ self.tag(),
+ CompactLength::AUTO_TAG
+ | CompactLength::MAX_CONTENT_TAG
+ | CompactLength::FIT_CONTENT_PX_TAG
+ | CompactLength::FIT_CONTENT_PERCENT_TAG
+ )
+ }
+
+ /// Returns true if the min track sizing function is `MinContent` or `MaxContent`, else false.
+ #[inline(always)]
+ pub fn is_min_or_max_content(&self) -> bool {
+ matches!(self.tag(), Self::MIN_CONTENT_TAG | Self::MAX_CONTENT_TAG)
+ }
+
+ /// Returns true if the value is auto, min-content, max-content, or fit-content(...)
+ #[inline(always)]
+ pub const fn is_intrinsic(self) -> bool {
+ matches!(
+ self.tag(),
+ Self::AUTO_TAG
+ | Self::MIN_CONTENT_TAG
+ | Self::MAX_CONTENT_TAG
+ | Self::FIT_CONTENT_PX_TAG
+ | Self::FIT_CONTENT_PERCENT_TAG
+ )
+ }
+
+ /// Returns true if the value is and fr value
+ #[inline(always)]
+ pub const fn is_fr(self) -> bool {
+ self.tag() == Self::FR_TAG
+ }
+
+ /// Whether the track sizing functions depends on the size of the parent node
+ #[inline(always)]
+ pub const fn uses_percentage(self) -> bool {
+ // TODO: handle calc() values
+ matches!(self.tag(), CompactLength::PERCENT_TAG | CompactLength::FIT_CONTENT_PERCENT_TAG) || self.is_calc()
+ }
+
+ /// Resolve percentage values against the passed parent_size, returning Some(value)
+ /// Non-percentage values always return None.
+ #[inline(always)]
+ pub fn resolved_percentage_size(self, parent_size: f32, calc_resolver: impl Fn(u64, f32) -> f32) -> Option<f32> {
+ match self.tag() {
+ CompactLength::PERCENT_TAG => Some(self.value() * parent_size),
+ _ if self.is_calc() => Some(calc_resolver(self.0, parent_size)),
+ _ => None,
+ }
+ }
+}
+
+impl TaffyZero for CompactLength {
+ const ZERO: Self = Self::length(0.0);
+}
+impl TaffyAuto for CompactLength {
+ const AUTO: Self = Self::auto();
+}
+impl TaffyMinContent for CompactLength {
+ const MIN_CONTENT: Self = Self::min_content();
+}
+impl TaffyMaxContent for CompactLength {
+ const MAX_CONTENT: Self = Self::max_content();
+}
+impl FromLength for CompactLength {
+ fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
+ Self::length(value.into())
+ }
+}
+impl FromPercent for CompactLength {
+ fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
+ Self::percent(value.into())
+ }
+}
+impl FromFr for CompactLength {
+ fn from_fr<Input: Into<f32> + Copy>(value: Input) -> Self {
+ Self::fr(value.into())
+ }
+}
+impl TaffyFitContent for CompactLength {
+ fn fit_content(lp: LengthPercentage) -> Self {
+ let value = lp.0.value();
+ match lp.0.tag() {
+ Self::LENGTH_TAG => Self::fit_content_px(value),
+ Self::PERCENT_TAG => Self::fit_content_percent(value),
+ _ => unreachable!(),
+ }
+ }
+}
+
+/// Note: these two functions are copied directly from the std (core) library. But by duplicating them
+/// here we can reduce MSRV from 1.83 all the way down to 1.65 while retaining const constructors.
+mod compat {
+ #![allow(unsafe_code)]
+
+ /// Raw transmutation from `f32` to `u32`.
+ pub const fn f32_to_bits(val: f32) -> u32 {
+ // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
+ unsafe { core::mem::transmute(val) }
+ }
+ /// Raw transmutation from `u32` to `f32`.
+ pub const fn f32_from_bits(v: u32) -> f32 {
+ // SAFETY: `u32` is a plain old datatype so we can always transmute from it.
+ unsafe { core::mem::transmute(v) }
+ }
+}
diff --git a/src/style/dimension.rs b/src/style/dimension.rs
index 57e7f98eb..de5b3c9cd 100644
--- a/src/style/dimension.rs
+++ b/src/style/dimension.rs
@@ -1,313 +1,7 @@
//! Style types for representing lengths / sizes
+use super::CompactLength;
use crate::geometry::Rect;
-use crate::style_helpers::{
- FromFr, FromLength, FromPercent, TaffyAuto, TaffyFitContent, TaffyMaxContent, TaffyMinContent, TaffyZero,
-};
-
-// Note: these two functions are copied directly from the std (core) library. But by duplicating them
-// here we can reduce MSRV from 1.83 all the way down to 1.65 while retaining const constructors.
-
-/// Raw transmutation from `f32` to `u32`.
-const fn to_bits(val: f32) -> u32 {
- // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
- #[allow(unsafe_code)]
- unsafe {
- core::mem::transmute(val)
- }
-}
-/// Raw transmutation from `u32` to `f32`.
-const fn from_bits(v: u32) -> f32 {
- // SAFETY: `u32` is a plain old datatype so we can always transmute from it.
- #[allow(unsafe_code)]
- unsafe {
- core::mem::transmute(v)
- }
-}
-
-/// A representation of a length as a compact 64-bit tagged pointer
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub struct CompactLength(u64);
-
-impl CompactLength {
- // Masks
-
- /// The low byte (8 bits)
- pub const TAG_MASK: u64 = 0b11111111;
- /// The low 3 bits
- pub const CALC_TAG_MASK: u64 = 0b111;
- /// The high 63 bits
- pub const CALC_PTR_MASK: u64 = u64::MAX ^ 0b111;
-
- // Primary tags
-
- /// The tag indicating a calc() value
- pub const CALC_TAG: u64 = 0b000;
- /// The tag indicating a length value
- pub const LENGTH_TAG: u64 = 0b0000_0001;
- /// The tag indicating a percentage value
- pub const PERCENT_TAG: u64 = 0b0000_0010;
- /// The tag indicating an auto value
- pub const AUTO_TAG: u64 = 0b0000_0011;
- /// The tag indicating an fr value
- pub const FR_TAG: u64 = 0b0000_0100;
- /// The tag indicating a min-content value
- pub const MIN_CONTENT_TAG: u64 = 0b00000111;
- /// The tag indicating a max-content value
- pub const MAX_CONTENT_TAG: u64 = 0b00001111;
- /// The tag indicating a fit-content value with px limit
- pub const FIT_CONTENT_PX_TAG: u64 = 0b00010111;
- /// The tag indicating a fit-content value with percent limit
- pub const FIT_CONTENT_PERCENT_TAG: u64 = 0b00011111;
-}
-
-impl CompactLength {
- /// An absolute length in some abstract units. Users of Taffy may define what they correspond
- /// to in their application (pixels, logical pixels, mm, etc) as they see fit.
- #[inline(always)]
- pub const fn length(val: f32) -> Self {
- Self(((to_bits(val) as u64) << 32) | Self::LENGTH_TAG)
- }
-
- /// A percentage length relative to the size of the containing block.
- ///
- /// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
- #[inline(always)]
- pub const fn percent(val: f32) -> Self {
- Self(((to_bits(val) as u64) << 32) | Self::PERCENT_TAG)
- }
-
- /// A `calc()` value. The value passed here is treated as an opaque handle to
- /// the actual calc representation and may be a pointer, index, etc.
- ///
- /// The low 3 bits are used as a tag value and will be returned as 0.
- #[inline]
- pub fn calc(ptr: *const ()) -> Self {
- assert_ne!(ptr as u64, 0);
- assert_eq!(ptr as u64 & 0b111, 0);
- Self(ptr as u64 | Self::CALC_TAG)
- }
-
- /// The dimension should be automatically computed according to algorithm-specific rules
- /// regarding the default size of boxes.
- #[inline(always)]
- pub const fn auto() -> Self {
- Self(Self::AUTO_TAG)
- }
-
- /// The dimension as a fraction of the total available grid space (`fr` units in CSS)
- /// Specified value is the numerator of the fraction. Denominator is the sum of all fraction specified in that grid dimension
- /// Spec: <https://www.w3.org/TR/css3-grid-layout/#fr-unit>
- #[inline(always)]
- pub const fn fr(val: f32) -> Self {
- Self(((to_bits(val) as u64) << 32) | Self::FR_TAG)
- }
-
- /// The size should be the "min-content" size.
- /// This is the smallest size that can fit the item's contents with ALL soft line-wrapping opportunities taken
- #[inline(always)]
- pub const fn min_content() -> Self {
- Self(Self::MIN_CONTENT_TAG)
- }
-
- /// The size should be the "max-content" size.
- /// This is the smallest size that can fit the item's contents with NO soft line-wrapping opportunities taken
- #[inline(always)]
- pub const fn max_content() -> Self {
- Self(Self::MAX_CONTENT_TAG)
- }
-
- /// The size should be computed according to the "fit content" formula:
- /// `max(min_content, min(max_content, limit))`
- /// where:
- /// - `min_content` is the [min-content](Self::min_content) size
- /// - `max_content` is the [max-content](Self::max_content) size
- /// - `limit` is a LENGTH value passed to this function
- ///
- /// The effect of this is that the item takes the size of `limit` clamped
- /// by the min-content and max-content sizes.
- #[inline(always)]
- pub const fn fit_content_px(limit: f32) -> Self {
- Self(((to_bits(limit) as u64) << 32) | Self::FIT_CONTENT_PX_TAG)
- }
-
- /// The size should be computed according to the "fit content" formula:
- /// `max(min_content, min(max_content, limit))`
- /// where:
- /// - `min_content` is the [min-content](Self::min_content) size
- /// - `max_content` is the [max-content](Self::max_content) size
- /// - `limit` is a PERCENTAGE value passed to this function
- ///
- /// The effect of this is that the item takes the size of `limit` clamped
- /// by the min-content and max-content sizes.
- #[inline(always)]
- pub const fn fit_content_percent(limit: f32) -> Self {
- Self(((to_bits(limit) as u64) << 32) | Self::FIT_CONTENT_PERCENT_TAG)
- }
-
- /// Get the primary tag
- #[inline(always)]
- pub const fn tag(self) -> u64 {
- self.0 & Self::TAG_MASK
- }
-
- /// Get the numeric value associated with the `CompactLength`
- /// (e.g. the pixel value for a LENGTH variant)
- #[inline(always)]
- pub const fn value(self) -> f32 {
- from_bits((self.0 >> 32) as u32)
- }
-
- /// Get the numeric value associated with the `CompactLength`
- /// (e.g. the pixel value for a LENGTH variant)
- #[inline(always)]
- pub const fn calc_value(self) -> u64 {
- self.0
- }
-
- /// Returns true if the value is 0 px
- #[inline(always)]
- pub const fn is_calc(self) -> bool {
- self.0 & Self::CALC_TAG_MASK == 0
- }
-
- /// Returns true if the value is 0 px
- #[inline(always)]
- pub const fn is_zero(self) -> bool {
- self.0 == Self::ZERO.0
- }
-
- /// Returns true if the value is a length or percentage value
- #[inline(always)]
- pub const fn is_length_or_percentage(self) -> bool {
- matches!(self.tag(), Self::LENGTH_TAG | Self::PERCENT_TAG)
- }
-
- /// Returns true if the value is auto
- #[inline(always)]
- pub const fn is_auto(self) -> bool {
- self.tag() == Self::AUTO_TAG
- }
-
- /// Returns true if the value is min-content
- #[inline(always)]
- pub const fn is_min_content(self) -> bool {
- matches!(self.tag(), Self::MIN_CONTENT_TAG)
- }
-
- /// Returns true if the value is max-content
- #[inline(always)]
- pub const fn is_max_content(self) -> bool {
- matches!(self.tag(), Self::MAX_CONTENT_TAG)
- }
-
- /// Returns true if the value is a fit-content(...) value
- #[inline(always)]
- pub const fn is_fit_content(self) -> bool {
- matches!(self.tag(), Self::FIT_CONTENT_PX_TAG | Self::FIT_CONTENT_PERCENT_TAG)
- }
-
- /// Returns true if the value is max-content or a fit-content(...) value
- #[inline(always)]
- pub const fn is_max_or_fit_content(self) -> bool {
- matches!(self.tag(), Self::MAX_CONTENT_TAG | Self::FIT_CONTENT_PX_TAG | Self::FIT_CONTENT_PERCENT_TAG)
- }
-
- /// Returns true if the max track sizing function is `MaxContent`, `FitContent` or `Auto` else false.
- /// "In all cases, treat auto and fit-content() as max-content, except where specified otherwise for fit-content()."
- /// See: <https://www.w3.org/TR/css-grid-1/#algo-terms>
- #[inline(always)]
- pub fn is_max_content_alike(&self) -> bool {
- matches!(
- self.tag(),
- CompactLength::AUTO_TAG
- | CompactLength::MAX_CONTENT_TAG
- | CompactLength::FIT_CONTENT_PX_TAG
- | CompactLength::FIT_CONTENT_PERCENT_TAG
- )
- }
-
- /// Returns true if the min track sizing function is `MinContent` or `MaxContent`, else false.
- #[inline(always)]
- pub fn is_min_or_max_content(&self) -> bool {
- matches!(self.tag(), Self::MIN_CONTENT_TAG | Self::MAX_CONTENT_TAG)
- }
-
- /// Returns true if the value is auto, min-content, max-content, or fit-content(...)
- #[inline(always)]
- pub const fn is_intrinsic(self) -> bool {
- matches!(
- self.tag(),
- Self::AUTO_TAG
- | Self::MIN_CONTENT_TAG
- | Self::MAX_CONTENT_TAG
- | Self::FIT_CONTENT_PX_TAG
- | Self::FIT_CONTENT_PERCENT_TAG
- )
- }
-
- /// Returns true if the value is and fr value
- #[inline(always)]
- pub const fn is_fr(self) -> bool {
- self.tag() == Self::FR_TAG
- }
-
- /// Whether the track sizing functions depends on the size of the parent node
- #[inline(always)]
- pub const fn uses_percentage(self) -> bool {
- // TODO: handle calc() values
- matches!(self.tag(), CompactLength::PERCENT_TAG | CompactLength::FIT_CONTENT_PERCENT_TAG) || self.is_calc()
- }
-
- /// Resolve percentage values against the passed parent_size, returning Some(value)
- /// Non-percentage values always return None.
- #[inline(always)]
- pub fn resolved_percentage_size(self, parent_size: f32, calc_resolver: impl Fn(u64, f32) -> f32) -> Option<f32> {
- match self.tag() {
- CompactLength::PERCENT_TAG => Some(self.value() * parent_size),
- _ if self.is_calc() => Some(calc_resolver(self.0, parent_size)),
- _ => None,
- }
- }
-}
-
-impl TaffyZero for CompactLength {
- const ZERO: Self = Self::length(0.0);
-}
-impl TaffyAuto for CompactLength {
- const AUTO: Self = Self::auto();
-}
-impl TaffyMinContent for CompactLength {
- const MIN_CONTENT: Self = Self::min_content();
-}
-impl TaffyMaxContent for CompactLength {
- const MAX_CONTENT: Self = Self::max_content();
-}
-impl FromLength for CompactLength {
- fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
- Self::length(value.into())
- }
-}
-impl FromPercent for CompactLength {
- fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
- Self::percent(value.into())
- }
-}
-impl FromFr for CompactLength {
- fn from_fr<Input: Into<f32> + Copy>(value: Input) -> Self {
- Self::fr(value.into())
- }
-}
-impl TaffyFitContent for CompactLength {
- fn fit_content(lp: LengthPercentage) -> Self {
- let value = lp.0.value();
- match lp.0.tag() {
- Self::LENGTH_TAG => Self::fit_content_px(value),
- Self::PERCENT_TAG => Self::fit_content_percent(value),
- _ => unreachable!(),
- }
- }
-}
+use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyZero};
/// A unit of linear measurement
///
diff --git a/src/style/mod.rs b/src/style/mod.rs
index 371277e93..e1709ef2a 100644
--- a/src/style/mod.rs
+++ b/src/style/mod.rs
@@ -1,6 +1,7 @@
//! A typed representation of [CSS style properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust. Used as input to layout computation.
mod alignment;
mod available_space;
+mod compact_length;
mod dimension;
#[cfg(feature = "block_layout")]
@@ -12,7 +13,8 @@ mod grid;
pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
pub use self::available_space::AvailableSpace;
-pub use self::dimension::{CompactLength, Dimension, LengthPercentage, LengthPercentageAuto};
+pub use self::compact_length::CompactLength;
+pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
#[cfg(feature = "block_layout")]
pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};