use super::*; /// A combined relative and absolute length. #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct Linear { /// The relative part. pub rel: Relative, /// The absolute part. pub abs: Length, } impl Linear { /// The zero linear. pub const fn zero() -> Self { Self { rel: Relative::zero(), abs: Length::zero(), } } /// The linear with a relative part of `100%` and no absolute part. pub const fn one() -> Self { Self { rel: Relative::one(), abs: Length::zero(), } } /// Create a new linear. pub const fn new(rel: Relative, abs: Length) -> Self { Self { rel, abs } } /// Resolve this linear's relative component to the given `length`. pub fn resolve(self, length: Length) -> Length { self.rel.resolve(length) + self.abs } /// Compose with another linear. /// /// The resulting linear is (self ∘ inner)(x) = self(inner(x)). pub fn compose(self, inner: Self) -> Self { Self { rel: self.rel * inner.rel, abs: self.rel.resolve(inner.abs) + self.abs, } } /// Whether both parts are zero. pub fn is_zero(self) -> bool { self.rel.is_zero() && self.abs.is_zero() } /// Whether there is a linear component. pub fn is_relative(self) -> bool { !self.rel.is_zero() } } impl Debug for Linear { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?} + {:?}", self.rel, self.abs) } } impl From for Linear { fn from(abs: Length) -> Self { Self { rel: Relative::zero(), abs } } } impl From for Linear { fn from(rel: Relative) -> Self { Self { rel, abs: Length::zero() } } } impl Neg for Linear { type Output = Self; fn neg(self) -> Self { Self { rel: -self.rel, abs: -self.abs } } } impl Add for Linear { type Output = Self; fn add(self, other: Self) -> Self { Self { rel: self.rel + other.rel, abs: self.abs + other.abs, } } } impl Add for Length { type Output = Linear; fn add(self, other: Relative) -> Linear { Linear { rel: other, abs: self } } } impl Add for Relative { type Output = Linear; fn add(self, other: Length) -> Linear { other + self } } impl Add for Linear { type Output = Self; fn add(self, other: Length) -> Self { Self { rel: self.rel, abs: self.abs + other } } } impl Add for Length { type Output = Linear; fn add(self, other: Linear) -> Linear { other + self } } impl Add for Linear { type Output = Self; fn add(self, other: Relative) -> Self { Self { rel: self.rel + other, abs: self.abs } } } impl Add for Relative { type Output = Linear; fn add(self, other: Linear) -> Linear { other + self } } sub_impl!(Linear - Linear -> Linear); sub_impl!(Length - Relative -> Linear); sub_impl!(Relative - Length -> Linear); sub_impl!(Linear - Length -> Linear); sub_impl!(Length - Linear -> Linear); sub_impl!(Linear - Relative -> Linear); sub_impl!(Relative - Linear -> Linear); impl Mul for Linear { type Output = Self; fn mul(self, other: f64) -> Self { Self { rel: self.rel * other, abs: self.abs * other, } } } impl Mul for f64 { type Output = Linear; fn mul(self, other: Linear) -> Linear { other * self } } impl Div for Linear { type Output = Self; fn div(self, other: f64) -> Self { Self { rel: self.rel / other, abs: self.abs / other, } } } assign_impl!(Linear += Linear); assign_impl!(Linear += Length); assign_impl!(Linear += Relative); assign_impl!(Linear -= Linear); assign_impl!(Linear -= Length); assign_impl!(Linear -= Relative); assign_impl!(Linear *= f64); assign_impl!(Linear /= f64);