1use crate::derives::*;
10use crate::typed_om::{MathSum, MathValue, NumericValue, ToTyped, TypedValue};
11use crate::values::generics::length::GenericAnchorSizeFunction;
12use crate::values::generics::position::{GenericAnchorFunction, GenericAnchorSide};
13use crate::values::generics::Optional;
14use num_traits::Zero;
15use smallvec::SmallVec;
16use std::convert::AsRef;
17use std::fmt::{self, Write};
18use std::ops::{Add, Mul, Neg, Rem, Sub};
19use std::{cmp, mem};
20use strum_macros::AsRefStr;
21use style_traits::{CssWriter, ToCss};
22
23use thin_vec::ThinVec;
24
25#[derive(
27 Clone,
28 Copy,
29 Debug,
30 Deserialize,
31 MallocSizeOf,
32 PartialEq,
33 Serialize,
34 ToAnimatedZero,
35 ToResolvedValue,
36 ToShmem,
37)]
38#[repr(u8)]
39pub enum MinMaxOp {
40 Min,
42 Max,
44}
45
46#[derive(
48 Clone,
49 Copy,
50 Debug,
51 Deserialize,
52 MallocSizeOf,
53 PartialEq,
54 Serialize,
55 ToAnimatedZero,
56 ToResolvedValue,
57 ToShmem,
58)]
59#[repr(u8)]
60pub enum ModRemOp {
61 Mod,
63 Rem,
65}
66
67impl ModRemOp {
68 fn apply(self, dividend: f32, divisor: f32) -> f32 {
69 if matches!(self, Self::Mod)
73 && divisor.is_infinite()
74 && dividend.is_sign_negative() != divisor.is_sign_negative()
75 {
76 return f32::NAN;
77 }
78
79 let (r, same_sign_as) = match self {
80 Self::Mod => (dividend - divisor * (dividend / divisor).floor(), divisor),
81 Self::Rem => (dividend - divisor * (dividend / divisor).trunc(), dividend),
82 };
83 if r == 0.0 && same_sign_as.is_sign_negative() {
84 -0.0
85 } else {
86 r
87 }
88 }
89}
90
91#[derive(
93 Clone,
94 Copy,
95 Debug,
96 Deserialize,
97 MallocSizeOf,
98 PartialEq,
99 Serialize,
100 ToAnimatedZero,
101 ToResolvedValue,
102 ToShmem,
103)]
104#[repr(u8)]
105pub enum RoundingStrategy {
106 Nearest,
109 Up,
112 Down,
115 ToZero,
118}
119
120#[derive(
122 Clone,
123 Copy,
124 Debug,
125 Deserialize,
126 MallocSizeOf,
127 Parse,
128 PartialEq,
129 Serialize,
130 ToAnimatedZero,
131 ToCss,
132 ToResolvedValue,
133 ToShmem,
134)]
135#[repr(u8)]
136pub enum ProgressClampingMode {
137 #[css(skip)]
140 Clamp,
141 NoClamp,
144}
145
146impl ProgressClampingMode {
147 fn evaluate(self, value: f32, start: f32, end: f32) -> f32 {
148 if start == end && self == Self::Clamp {
149 return 0.;
150 }
151 let progress = crate::values::normalize((value - start) / (end - start));
152 match self {
153 Self::Clamp => progress.max(0.).min(1.),
154 Self::NoClamp => progress,
155 }
156 }
157}
158
159#[derive(
163 AsRefStr, Clone, Copy, Debug, Eq, Ord, Parse, PartialEq, PartialOrd, MallocSizeOf, ToShmem,
164)]
165#[strum(serialize_all = "lowercase")]
166#[allow(missing_docs)]
167pub enum SortKey {
168 #[strum(serialize = "")]
169 Number,
170 #[css(skip)]
171 #[strum(serialize = "%")]
172 Percentage,
173 Cap,
174 Ch,
175 Cqb,
176 Cqh,
177 Cqi,
178 Cqmax,
179 Cqmin,
180 Cqw,
181 Deg,
182 Dppx,
183 Dvb,
184 Dvh,
185 Dvi,
186 Dvmax,
187 Dvmin,
188 Dvw,
189 Em,
190 Ex,
191 Ic,
192 Lh,
193 Lvb,
194 Lvh,
195 Lvi,
196 Lvmax,
197 Lvmin,
198 Lvw,
199 Ms,
200 Px,
201 Rcap,
202 Rch,
203 Rem,
204 Rex,
205 Ric,
206 Rlh,
207 S, Svb,
209 Svh,
210 Svi,
211 Svmax,
212 Svmin,
213 Svw,
214 Vb,
215 Vh,
216 Vi,
217 Vmax,
218 Vmin,
219 Vw,
220 #[css(skip)]
221 ColorComponent,
222 #[css(skip)]
223 Other,
224}
225
226#[repr(C)]
235#[derive(
236 Clone,
237 Debug,
238 Deserialize,
239 MallocSizeOf,
240 PartialEq,
241 Serialize,
242 ToAnimatedZero,
243 ToResolvedValue,
244 ToShmem,
245)]
246pub struct GenericAnchorFunctionFallback<L> {
247 #[animation(constant)]
249 is_calc_node: bool,
250 pub node: GenericCalcNode<L>,
253}
254
255impl<L> GenericAnchorFunctionFallback<L> {
256 pub fn new(is_calc_node: bool, node: GenericCalcNode<L>) -> Self {
258 Self { is_calc_node, node }
259 }
260}
261
262impl<L: CalcNodeLeaf> ToCss for GenericAnchorFunctionFallback<L> {
263 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
264 where
265 W: Write,
266 {
267 self.node.to_css_impl(
268 dest,
269 if self.is_calc_node {
270 ArgumentLevel::CalculationRoot
271 } else {
272 ArgumentLevel::ArgumentRoot
273 },
274 )
275 }
276}
277
278pub type GenericCalcAnchorFunction<L> =
280 GenericAnchorFunction<Box<GenericCalcNode<L>>, Box<GenericAnchorFunctionFallback<L>>>;
281pub type GenericCalcAnchorSizeFunction<L> =
283 GenericAnchorSizeFunction<Box<GenericAnchorFunctionFallback<L>>>;
284
285#[repr(u8)]
297#[derive(
298 Clone,
299 Debug,
300 Deserialize,
301 MallocSizeOf,
302 PartialEq,
303 Serialize,
304 ToAnimatedZero,
305 ToResolvedValue,
306 ToShmem,
307)]
308pub enum GenericCalcNode<L> {
309 Leaf(L),
311 Negate(Box<Self>),
313 Invert(Box<Self>),
316 Sum(crate::OwnedSlice<Self>),
319 Product(crate::OwnedSlice<Self>),
322 MinMax(crate::OwnedSlice<Self>, MinMaxOp),
324 Clamp {
326 min: Box<Self>,
328 center: Box<Self>,
330 max: Box<Self>,
332 },
333 Round {
335 strategy: RoundingStrategy,
337 value: Box<Self>,
339 step: Box<Self>,
341 },
342 ModRem {
344 dividend: Box<Self>,
346 divisor: Box<Self>,
348 op: ModRemOp,
350 },
351 Sin(Box<Self>),
353 Cos(Box<Self>),
355 Tan(Box<Self>),
357 Asin(Box<Self>),
359 Acos(Box<Self>),
361 Atan(Box<Self>),
363 Atan2(Box<Self>, Box<Self>),
365 Pow(Box<Self>, Box<Self>),
367 Sqrt(Box<Self>),
369 Hypot(crate::OwnedSlice<Self>),
371 Log(Box<Self>, Optional<Box<Self>>),
373 Exp(Box<Self>),
375 Abs(Box<Self>),
377 Sign(Box<Self>),
379 Progress {
381 clamping_mode: ProgressClampingMode,
383 value: Box<Self>,
385 start: Box<Self>,
387 end: Box<Self>,
389 },
390 Anchor(Box<GenericCalcAnchorFunction<L>>),
392 AnchorSize(Box<GenericCalcAnchorSizeFunction<L>>),
394}
395
396pub use self::GenericCalcNode as CalcNode;
397
398bitflags! {
399 #[derive(Clone, Copy, PartialEq, Eq)]
405 pub struct CalcUnits: u8 {
406 const LENGTH = 1 << 0;
408 const PERCENTAGE = 1 << 1;
410 const ANGLE = 1 << 2;
412 const TIME = 1 << 3;
414 const RESOLUTION = 1 << 4;
416 const LENGTH_PERCENTAGE = Self::LENGTH.bits() | Self::PERCENTAGE.bits();
418 const ALL = Self::LENGTH.bits() | Self::PERCENTAGE.bits() | Self::ANGLE.bits() |
421 Self::TIME.bits() | Self::RESOLUTION.bits();
422 }
423}
424
425impl CalcUnits {
426 #[inline]
429 fn is_single_unit(&self) -> bool {
430 self.bits() == 0 || self.bits() & (self.bits() - 1) == 0
431 }
432
433 #[inline]
435 fn can_sum_with(&self, other: Self) -> bool {
436 match *self {
437 Self::LENGTH => other.intersects(Self::LENGTH | Self::PERCENTAGE),
438 Self::PERCENTAGE => other.intersects(Self::LENGTH | Self::PERCENTAGE),
439 Self::LENGTH_PERCENTAGE => other.intersects(Self::LENGTH | Self::PERCENTAGE),
440 u => u.is_single_unit() && other == u,
441 }
442 }
443}
444
445pub enum PositivePercentageBasis {
448 Unknown,
450 Yes,
452}
453
454macro_rules! compare_helpers {
455 () => {
456 #[allow(unused)]
458 fn gt(&self, other: &Self, basis_positive: PositivePercentageBasis) -> bool {
459 self.compare(other, basis_positive) == Some(cmp::Ordering::Greater)
460 }
461
462 fn lt(&self, other: &Self, basis_positive: PositivePercentageBasis) -> bool {
464 self.compare(other, basis_positive) == Some(cmp::Ordering::Less)
465 }
466
467 fn lte(&self, other: &Self, basis_positive: PositivePercentageBasis) -> bool {
469 match self.compare(other, basis_positive) {
470 Some(cmp::Ordering::Less) => true,
471 Some(cmp::Ordering::Equal) => true,
472 Some(cmp::Ordering::Greater) => false,
473 None => false,
474 }
475 }
476 };
477}
478
479pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss + ToTyped {
481 fn unit(&self) -> CalcUnits;
483
484 fn unitless_value(&self) -> Option<f32>;
486
487 fn as_angle_radians(&self) -> Option<f32>;
489
490 fn new_angle_from_radians(radians: f32) -> Self;
492
493 fn is_same_unit_as(&self, other: &Self) -> bool {
496 std::mem::discriminant(self) == std::mem::discriminant(other)
497 }
498
499 fn compare(
501 &self,
502 other: &Self,
503 base_is_positive: PositivePercentageBasis,
504 ) -> Option<cmp::Ordering>;
505 compare_helpers!();
506
507 fn new_number(value: f32) -> Self;
509
510 fn as_number(&self) -> Option<f32>;
512
513 fn as_number_or_angle_radians(&self) -> Option<f32> {
515 self.as_number().or_else(|| self.as_angle_radians())
516 }
517
518 fn is_negative(&self) -> Result<bool, ()> {
520 self.unitless_value()
521 .map(|v| Ok(v.is_sign_negative()))
522 .unwrap_or_else(|| Err(()))
523 }
524
525 fn is_infinite(&self) -> Result<bool, ()> {
527 self.unitless_value()
528 .map(|v| Ok(v.is_infinite()))
529 .unwrap_or_else(|| Err(()))
530 }
531
532 fn is_zero(&self) -> Result<bool, ()> {
534 self.unitless_value()
535 .map(|v| Ok(v.is_zero()))
536 .unwrap_or_else(|| Err(()))
537 }
538
539 fn is_nan(&self) -> Result<bool, ()> {
541 self.unitless_value()
542 .map(|v| Ok(v.is_nan()))
543 .unwrap_or_else(|| Err(()))
544 }
545
546 fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()>;
548
549 fn try_product_in_place(&mut self, other: &mut Self) -> bool;
552
553 fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
555 where
556 O: Fn(f32, f32) -> f32;
557
558 fn map(&mut self, op: impl FnMut(f32) -> f32) -> Result<(), ()>;
560
561 fn simplify(&mut self) -> SimplificationResult;
563
564 fn sort_key(&self) -> SortKey;
566
567 fn sign_from(leaf: &impl CalcNodeLeaf) -> Result<Self, ()> {
569 let Some(value) = leaf.unitless_value() else {
570 return Err(());
571 };
572
573 Ok(Self::new_number(if value.is_nan() {
574 f32::NAN
575 } else if value.is_zero() {
576 value
577 } else if value.is_sign_negative() {
578 -1.0
579 } else {
580 1.0
581 }))
582 }
583
584 fn should_serialize_with_root_calc_wrapper(&self) -> bool {
587 true
588 }
589}
590
591#[derive(Clone)]
593enum ArgumentLevel {
594 CalculationRoot,
596 ArgumentRoot,
599 Nested,
601}
602
603#[derive(Clone, Copy)]
605pub enum SimplificationResult {
606 Simplified,
608 Unchanged,
610}
611
612impl<L: CalcNodeLeaf> CalcNode<L> {
613 fn dummy() -> Self {
615 Self::MinMax(Default::default(), MinMaxOp::Max)
616 }
617
618 fn coerce_to_value(&mut self, value: f32) -> Result<(), ()> {
622 self.map(|_| value)
623 }
624
625 #[inline]
629 pub fn is_product_distributive(&self) -> bool {
630 match self {
631 Self::Leaf(l) => l.unitless_value().is_some(),
633 Self::Sum(children) => children.iter().all(|c| c.is_product_distributive()),
634 _ => false,
635 }
636 }
637
638 pub fn unit(&self) -> Result<CalcUnits, ()> {
640 Ok(match self {
641 CalcNode::Leaf(l) => l.unit(),
642 CalcNode::Negate(child) | CalcNode::Abs(child) => child.unit()?,
643 CalcNode::Sum(children) => {
644 let mut unit = children.first().unwrap().unit()?;
645 for child in children.iter().skip(1) {
646 let child_unit = child.unit()?;
647 if !child_unit.can_sum_with(unit) {
648 return Err(());
649 }
650 unit |= child_unit;
651 }
652 unit
653 },
654 CalcNode::Product(children) => {
655 let mut unit = None;
657 for child in children.iter() {
658 let child_unit = child.unit()?;
659 if child_unit.is_empty() {
660 continue;
662 }
663
664 if unit.is_some() {
665 return Err(());
667 }
668
669 unit = Some(child_unit);
671 }
672 unit.unwrap_or(CalcUnits::empty())
675 },
676 CalcNode::MinMax(children, _) | CalcNode::Hypot(children) => {
677 let mut unit = children.first().unwrap().unit()?;
678 for child in children.iter().skip(1) {
679 let child_unit = child.unit()?;
680 if !child_unit.can_sum_with(unit) {
681 return Err(());
682 }
683 unit |= child_unit;
684 }
685 unit
686 },
687 CalcNode::Clamp { min, center, max } => {
688 let min_unit = min.unit()?;
689 let center_unit = center.unit()?;
690
691 if !min_unit.can_sum_with(center_unit) {
692 return Err(());
693 }
694
695 let max_unit = max.unit()?;
696
697 if !center_unit.can_sum_with(max_unit) {
698 return Err(());
699 }
700
701 min_unit | center_unit | max_unit
702 },
703 CalcNode::Round { value, step, .. } => {
704 let value_unit = value.unit()?;
705 let step_unit = step.unit()?;
706 if !step_unit.can_sum_with(value_unit) {
707 return Err(());
708 }
709 value_unit | step_unit
710 },
711 CalcNode::ModRem {
712 dividend, divisor, ..
713 } => {
714 let dividend_unit = dividend.unit()?;
715 let divisor_unit = divisor.unit()?;
716 if !divisor_unit.can_sum_with(dividend_unit) {
717 return Err(());
718 }
719 dividend_unit | divisor_unit
720 },
721 CalcNode::Sign(ref child) => {
722 let _ = child.unit()?;
725 CalcUnits::empty()
726 },
727 CalcNode::Anchor(..) | CalcNode::AnchorSize(..) => CalcUnits::LENGTH_PERCENTAGE,
728 CalcNode::Sin(ref child) | CalcNode::Cos(ref child) | CalcNode::Tan(ref child) => {
729 let child_unit = child.unit()?;
730 if !child_unit.is_empty() && !child_unit.intersects(CalcUnits::ANGLE) {
731 return Err(());
732 }
733 CalcUnits::empty()
734 },
735 CalcNode::Asin(ref child) | CalcNode::Acos(ref child) | CalcNode::Atan(ref child) => {
736 let child_unit = child.unit()?;
737 if !child_unit.is_empty() {
738 return Err(());
739 }
740 CalcUnits::ANGLE
741 },
742 CalcNode::Atan2(ref a, ref b) => {
743 let a_unit = a.unit()?;
744 let b_unit = b.unit()?;
745 if !a_unit.can_sum_with(b_unit) {
746 return Err(());
747 }
748 CalcUnits::ANGLE
749 },
750 CalcNode::Pow(ref a, ref b) => {
751 let a_unit = a.unit()?;
752 let b_unit = b.unit()?;
753 if !a_unit.is_empty() || !b_unit.is_empty() {
754 return Err(());
755 }
756 CalcUnits::empty()
757 },
758 CalcNode::Invert(ref c) | CalcNode::Sqrt(ref c) | CalcNode::Exp(ref c) => {
759 let child_unit = c.unit()?;
760 if !child_unit.is_empty() {
761 return Err(());
762 }
763 CalcUnits::empty()
764 },
765 CalcNode::Log(ref a, ref b) => {
766 let a_unit = a.unit()?;
767 let b_unit = match b {
768 Optional::Some(b) => b.unit()?,
769 Optional::None => CalcUnits::empty(),
770 };
771 if !a_unit.is_empty() || !b_unit.is_empty() {
772 return Err(());
773 }
774 CalcUnits::empty()
775 },
776 CalcNode::Progress {
777 value, start, end, ..
778 } => {
779 let value_unit = value.unit()?;
780 let start_unit = start.unit()?;
781 let end_unit = end.unit()?;
782 if !value_unit.can_sum_with(start_unit) || !value_unit.can_sum_with(end_unit) {
783 return Err(());
784 }
785 CalcUnits::empty()
786 },
787 })
788 }
789
790 pub fn negate(&mut self) {
793 fn wrap_self_in_negate<L: CalcNodeLeaf>(s: &mut CalcNode<L>) {
795 let result = mem::replace(s, CalcNode::dummy());
796 *s = CalcNode::Negate(Box::new(result));
797 }
798
799 match *self {
800 CalcNode::Leaf(ref mut leaf) => {
801 if leaf.map(std::ops::Neg::neg).is_err() {
802 wrap_self_in_negate(self)
803 }
804 },
805 CalcNode::Negate(ref mut value) => {
806 let result = mem::replace(value.as_mut(), Self::dummy());
808 *self = result;
809 },
810 CalcNode::Invert(_) => {
811 wrap_self_in_negate(self)
813 },
814 CalcNode::Sum(ref mut children) => {
815 for child in children.iter_mut() {
816 child.negate();
817 }
818 },
819 CalcNode::Product(_) => {
820 wrap_self_in_negate(self);
822 },
823 CalcNode::MinMax(ref mut children, ref mut op) => {
824 for child in children.iter_mut() {
825 child.negate();
826 }
827
828 *op = match *op {
830 MinMaxOp::Min => MinMaxOp::Max,
831 MinMaxOp::Max => MinMaxOp::Min,
832 };
833 },
834 CalcNode::Clamp {
835 ref mut min,
836 ref mut center,
837 ref mut max,
838 } => {
839 if min.lte(max, PositivePercentageBasis::Unknown) {
840 min.negate();
841 center.negate();
842 max.negate();
843
844 mem::swap(min, max);
845 } else {
846 wrap_self_in_negate(self);
847 }
848 },
849 CalcNode::Round {
850 ref mut strategy,
851 ref mut value,
852 ref mut step,
853 } => {
854 match *strategy {
855 RoundingStrategy::Nearest => {
856 wrap_self_in_negate(self);
861 return;
862 },
863 RoundingStrategy::Up => *strategy = RoundingStrategy::Down,
864 RoundingStrategy::Down => *strategy = RoundingStrategy::Up,
865 RoundingStrategy::ToZero => (),
866 }
867 value.negate();
868 step.negate();
869 },
870 CalcNode::ModRem {
871 ref mut dividend,
872 ref mut divisor,
873 ..
874 } => {
875 dividend.negate();
876 divisor.negate();
877 },
878 CalcNode::Hypot(ref mut children) => {
879 for child in children.iter_mut() {
880 child.negate();
881 }
882 },
883 CalcNode::Sign(ref mut child) => {
884 child.negate();
885 },
886 CalcNode::Sin(..)
887 | CalcNode::Cos(..)
888 | CalcNode::Tan(..)
889 | CalcNode::Asin(..)
890 | CalcNode::Acos(..)
891 | CalcNode::Atan(..)
892 | CalcNode::Atan2(..)
893 | CalcNode::Pow(..)
894 | CalcNode::Sqrt(..)
895 | CalcNode::Log(..)
896 | CalcNode::Exp(..)
897 | CalcNode::Abs(..)
898 | CalcNode::Progress { .. }
899 | CalcNode::Anchor(..)
900 | CalcNode::AnchorSize(..) => {
901 wrap_self_in_negate(self);
902 },
903 }
904 }
905
906 fn sort_key(&self) -> SortKey {
907 match *self {
908 Self::Leaf(ref l) => l.sort_key(),
909 Self::Anchor(..) | Self::AnchorSize(..) => SortKey::Px,
910 _ => SortKey::Other,
911 }
912 }
913
914 pub fn as_leaf(&self) -> Option<&L> {
916 match *self {
917 Self::Leaf(ref l) => Some(l),
918 _ => None,
919 }
920 }
921
922 pub fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()> {
924 match (self, other) {
925 (&mut CalcNode::Leaf(ref mut one), &CalcNode::Leaf(ref other)) => {
926 one.try_sum_in_place(other)
927 },
928 _ => Err(()),
929 }
930 }
931
932 pub fn try_product_in_place(&mut self, other: &mut Self) -> bool {
934 if let Ok(resolved) = other.resolve() {
935 if let Some(number) = resolved.as_number() {
936 if number == 1.0 {
937 return true;
938 }
939
940 if self.is_product_distributive() {
941 if self.map(|v| v * number).is_err() {
942 return false;
943 }
944 return true;
945 }
946 }
947 }
948
949 if let Ok(resolved) = self.resolve() {
950 if let Some(number) = resolved.as_number() {
951 if number == 1.0 {
952 std::mem::swap(self, other);
953 return true;
954 }
955
956 if other.is_product_distributive() {
957 if other.map(|v| v * number).is_err() {
958 return false;
959 }
960 std::mem::swap(self, other);
961 return true;
962 }
963 }
964 }
965
966 false
967 }
968
969 fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
971 where
972 O: Fn(f32, f32) -> f32,
973 {
974 match (self, other) {
975 (&CalcNode::Leaf(ref one), &CalcNode::Leaf(ref other)) => {
976 Ok(CalcNode::Leaf(one.try_op(other, op)?))
977 },
978 _ => Err(()),
979 }
980 }
981
982 pub fn map(&mut self, mut op: impl FnMut(f32) -> f32) -> Result<(), ()> {
984 fn map_internal<L: CalcNodeLeaf>(
985 node: &mut CalcNode<L>,
986 op: &mut impl FnMut(f32) -> f32,
987 ) -> Result<(), ()> {
988 match node {
989 CalcNode::Leaf(l) => l.map(op),
990 CalcNode::Negate(v) | CalcNode::Invert(v) => map_internal(v, op),
991 CalcNode::Sum(children) | CalcNode::Product(children) => {
992 for node in &mut **children {
993 map_internal(node, op)?;
994 }
995 Ok(())
996 },
997 CalcNode::MinMax(children, _) => {
998 for node in &mut **children {
999 map_internal(node, op)?;
1000 }
1001 Ok(())
1002 },
1003 CalcNode::Clamp { min, center, max } => {
1004 map_internal(min, op)?;
1005 map_internal(center, op)?;
1006 map_internal(max, op)
1007 },
1008 CalcNode::Round { value, step, .. } => {
1009 map_internal(value, op)?;
1010 map_internal(step, op)
1011 },
1012 CalcNode::ModRem {
1013 dividend, divisor, ..
1014 } => {
1015 map_internal(dividend, op)?;
1016 map_internal(divisor, op)
1017 },
1018 CalcNode::Hypot(children) => {
1019 for node in &mut **children {
1020 map_internal(node, op)?;
1021 }
1022 Ok(())
1023 },
1024 CalcNode::Abs(child) | CalcNode::Sign(child) => map_internal(child, op),
1025 CalcNode::Anchor(_) | CalcNode::AnchorSize(_) => Err(()),
1028 CalcNode::Sin(_)
1031 | CalcNode::Cos(_)
1032 | CalcNode::Tan(_)
1033 | CalcNode::Asin(_)
1034 | CalcNode::Acos(_)
1035 | CalcNode::Atan(_)
1036 | CalcNode::Atan2(..)
1037 | CalcNode::Pow(..)
1038 | CalcNode::Sqrt(_)
1039 | CalcNode::Log(..)
1040 | CalcNode::Exp(_)
1041 | CalcNode::Progress { .. } => Err(()),
1042 }
1043 }
1044
1045 map_internal(self, &mut op)
1046 }
1047
1048 pub fn map_leaves<O, F>(&self, mut map: F) -> CalcNode<O>
1050 where
1051 O: CalcNodeLeaf,
1052 F: FnMut(&L) -> O,
1053 {
1054 self.map_leaves_internal(&mut map)
1055 }
1056
1057 fn map_leaves_internal<O, F>(&self, map: &mut F) -> CalcNode<O>
1058 where
1059 O: CalcNodeLeaf,
1060 F: FnMut(&L) -> O,
1061 {
1062 fn map_children<L, O, F>(
1063 children: &[CalcNode<L>],
1064 map: &mut F,
1065 ) -> crate::OwnedSlice<CalcNode<O>>
1066 where
1067 L: CalcNodeLeaf,
1068 O: CalcNodeLeaf,
1069 F: FnMut(&L) -> O,
1070 {
1071 children
1072 .iter()
1073 .map(|c| c.map_leaves_internal(map))
1074 .collect()
1075 }
1076
1077 match *self {
1078 Self::Leaf(ref l) => CalcNode::Leaf(map(l)),
1079 Self::Negate(ref c) => CalcNode::Negate(Box::new(c.map_leaves_internal(map))),
1080 Self::Invert(ref c) => CalcNode::Invert(Box::new(c.map_leaves_internal(map))),
1081 Self::Sum(ref c) => CalcNode::Sum(map_children(c, map)),
1082 Self::Product(ref c) => CalcNode::Product(map_children(c, map)),
1083 Self::MinMax(ref c, op) => CalcNode::MinMax(map_children(c, map), op),
1084 Self::Clamp {
1085 ref min,
1086 ref center,
1087 ref max,
1088 } => {
1089 let min = Box::new(min.map_leaves_internal(map));
1090 let center = Box::new(center.map_leaves_internal(map));
1091 let max = Box::new(max.map_leaves_internal(map));
1092 CalcNode::Clamp { min, center, max }
1093 },
1094 Self::Round {
1095 strategy,
1096 ref value,
1097 ref step,
1098 } => {
1099 let value = Box::new(value.map_leaves_internal(map));
1100 let step = Box::new(step.map_leaves_internal(map));
1101 CalcNode::Round {
1102 strategy,
1103 value,
1104 step,
1105 }
1106 },
1107 Self::ModRem {
1108 ref dividend,
1109 ref divisor,
1110 op,
1111 } => {
1112 let dividend = Box::new(dividend.map_leaves_internal(map));
1113 let divisor = Box::new(divisor.map_leaves_internal(map));
1114 CalcNode::ModRem {
1115 dividend,
1116 divisor,
1117 op,
1118 }
1119 },
1120 Self::Sin(ref c) => CalcNode::Sin(Box::new(c.map_leaves_internal(map))),
1121 Self::Cos(ref c) => CalcNode::Cos(Box::new(c.map_leaves_internal(map))),
1122 Self::Tan(ref c) => CalcNode::Tan(Box::new(c.map_leaves_internal(map))),
1123 Self::Asin(ref c) => CalcNode::Asin(Box::new(c.map_leaves_internal(map))),
1124 Self::Acos(ref c) => CalcNode::Acos(Box::new(c.map_leaves_internal(map))),
1125 Self::Atan(ref c) => CalcNode::Atan(Box::new(c.map_leaves_internal(map))),
1126 Self::Atan2(ref a, ref b) => CalcNode::Atan2(
1127 Box::new(a.map_leaves_internal(map)),
1128 Box::new(b.map_leaves_internal(map)),
1129 ),
1130 Self::Pow(ref a, ref b) => CalcNode::Pow(
1131 Box::new(a.map_leaves_internal(map)),
1132 Box::new(b.map_leaves_internal(map)),
1133 ),
1134 Self::Sqrt(ref c) => CalcNode::Sqrt(Box::new(c.map_leaves_internal(map))),
1135 Self::Hypot(ref c) => CalcNode::Hypot(map_children(c, map)),
1136 Self::Log(ref a, ref b) => CalcNode::Log(
1137 Box::new(a.map_leaves_internal(map)),
1138 b.as_ref()
1139 .map(|b| Box::new(b.map_leaves_internal(map)))
1140 .into(),
1141 ),
1142 Self::Exp(ref c) => CalcNode::Exp(Box::new(c.map_leaves_internal(map))),
1143 Self::Abs(ref c) => CalcNode::Abs(Box::new(c.map_leaves_internal(map))),
1144 Self::Sign(ref c) => CalcNode::Sign(Box::new(c.map_leaves_internal(map))),
1145 Self::Progress {
1146 clamping_mode,
1147 ref value,
1148 ref start,
1149 ref end,
1150 } => {
1151 let value = Box::new(value.map_leaves_internal(map));
1152 let start = Box::new(start.map_leaves_internal(map));
1153 let end = Box::new(end.map_leaves_internal(map));
1154 CalcNode::Progress {
1155 clamping_mode,
1156 value,
1157 start,
1158 end,
1159 }
1160 },
1161 Self::Anchor(ref f) => CalcNode::Anchor(Box::new(GenericAnchorFunction {
1162 target_element: f.target_element.clone(),
1163 side: match &f.side {
1164 GenericAnchorSide::Keyword(k) => GenericAnchorSide::Keyword(*k),
1165 GenericAnchorSide::Percentage(p) => {
1166 GenericAnchorSide::Percentage(Box::new(p.map_leaves_internal(map)))
1167 },
1168 },
1169 fallback: f
1170 .fallback
1171 .as_ref()
1172 .map(|fb| {
1173 Box::new(GenericAnchorFunctionFallback::new(
1174 fb.is_calc_node,
1175 fb.node.map_leaves_internal(map),
1176 ))
1177 })
1178 .into(),
1179 })),
1180 Self::AnchorSize(ref f) => CalcNode::AnchorSize(Box::new(GenericAnchorSizeFunction {
1181 target_element: f.target_element.clone(),
1182 size: f.size,
1183 fallback: f
1184 .fallback
1185 .as_ref()
1186 .map(|fb| {
1187 Box::new(GenericAnchorFunctionFallback::new(
1188 fb.is_calc_node,
1189 fb.node.map_leaves_internal(map),
1190 ))
1191 })
1192 .into(),
1193 })),
1194 }
1195 }
1196
1197 pub fn resolve(&self) -> Result<L, ()> {
1199 self.resolve_map(|l| Ok(l.clone()))
1200 }
1201
1202 pub fn resolve_map<F>(&self, mut leaf_to_output_fn: F) -> Result<L, ()>
1204 where
1205 F: FnMut(&L) -> Result<L, ()>,
1206 {
1207 self.resolve_internal(&mut leaf_to_output_fn)
1208 }
1209
1210 fn resolve_internal<F>(&self, leaf_to_output_fn: &mut F) -> Result<L, ()>
1211 where
1212 F: FnMut(&L) -> Result<L, ()>,
1213 {
1214 match self {
1215 Self::Leaf(l) => leaf_to_output_fn(l),
1216 Self::Negate(child) => {
1217 let mut result = child.resolve_internal(leaf_to_output_fn)?;
1218 result.map(|v| v.neg())?;
1219 Ok(result)
1220 },
1221 Self::Invert(child) => {
1222 let mut result = child.resolve_internal(leaf_to_output_fn)?;
1223 result.map(|v| 1.0 / v)?;
1224 Ok(result)
1225 },
1226 Self::Sum(children) => {
1227 let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1228
1229 for child in children.iter().skip(1) {
1230 let right = child.resolve_internal(leaf_to_output_fn)?;
1231 result = result.try_op(&right, |left, right| left + right)?;
1233 }
1234
1235 Ok(result)
1236 },
1237 Self::Product(children) => {
1238 let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1239
1240 for child in children.iter().skip(1) {
1241 let right = child.resolve_internal(leaf_to_output_fn)?;
1242 match result.as_number() {
1244 Some(left) => {
1245 result = right;
1247 result.map(|v| v * left)?;
1248 },
1249 None => {
1250 match right.as_number() {
1252 Some(right) => {
1253 result.map(|v| v * right)?;
1254 },
1255 None => {
1256 return Err(());
1258 },
1259 }
1260 },
1261 }
1262 }
1263
1264 Ok(result)
1265 },
1266 Self::MinMax(children, op) => {
1267 let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1268
1269 if result.is_nan()? {
1270 return Ok(result);
1271 }
1272
1273 for child in children.iter().skip(1) {
1274 let candidate = child.resolve_internal(leaf_to_output_fn)?;
1275
1276 if !result.is_same_unit_as(&candidate) {
1278 return Err(());
1279 }
1280
1281 if candidate.is_nan()? {
1282 result = candidate;
1283 break;
1284 }
1285
1286 let candidate_wins = match op {
1287 MinMaxOp::Min => candidate.lt(&result, PositivePercentageBasis::Yes),
1288 MinMaxOp::Max => candidate.gt(&result, PositivePercentageBasis::Yes),
1289 };
1290
1291 if candidate_wins {
1292 result = candidate;
1293 }
1294 }
1295
1296 Ok(result)
1297 },
1298 Self::Clamp { min, center, max } => {
1299 let min = min.resolve_internal(leaf_to_output_fn)?;
1300 let center = center.resolve_internal(leaf_to_output_fn)?;
1301 let max = max.resolve_internal(leaf_to_output_fn)?;
1302
1303 if !min.is_same_unit_as(¢er) || !max.is_same_unit_as(¢er) {
1304 return Err(());
1305 }
1306
1307 if min.is_nan()? {
1308 return Ok(min);
1309 }
1310
1311 if center.is_nan()? {
1312 return Ok(center);
1313 }
1314
1315 if max.is_nan()? {
1316 return Ok(max);
1317 }
1318
1319 let mut result = center;
1320 if result.gt(&max, PositivePercentageBasis::Yes) {
1321 result = max;
1322 }
1323 if result.lt(&min, PositivePercentageBasis::Yes) {
1324 result = min
1325 }
1326
1327 Ok(result)
1328 },
1329 Self::Round {
1330 strategy,
1331 value,
1332 step,
1333 } => {
1334 let mut value = value.resolve_internal(leaf_to_output_fn)?;
1335 let step = step.resolve_internal(leaf_to_output_fn)?;
1336
1337 if !value.is_same_unit_as(&step) {
1338 return Err(());
1339 }
1340
1341 let Some(step) = step.unitless_value() else {
1342 return Err(());
1343 };
1344 let step = step.abs();
1345
1346 value.map(|value| {
1347 if step.is_zero() {
1351 return f32::NAN;
1352 }
1353
1354 if value.is_infinite() {
1355 if step.is_infinite() {
1356 return f32::NAN;
1357 }
1358 return value;
1359 }
1360
1361 if step.is_infinite() {
1362 match strategy {
1363 RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
1364 return if value.is_sign_negative() { -0.0 } else { 0.0 }
1365 },
1366 RoundingStrategy::Up => {
1367 return if !value.is_sign_negative() && !value.is_zero() {
1368 f32::INFINITY
1369 } else if !value.is_sign_negative() && value.is_zero() {
1370 value
1371 } else {
1372 -0.0
1373 }
1374 },
1375 RoundingStrategy::Down => {
1376 return if value.is_sign_negative() && !value.is_zero() {
1377 -f32::INFINITY
1378 } else if value.is_sign_negative() && value.is_zero() {
1379 value
1380 } else {
1381 0.0
1382 }
1383 },
1384 }
1385 }
1386
1387 let div = value / step;
1388 let lower_bound = div.floor() * step;
1389 let upper_bound = div.ceil() * step;
1390
1391 match strategy {
1392 RoundingStrategy::Nearest => {
1393 if value - lower_bound < upper_bound - value {
1395 lower_bound
1396 } else {
1397 upper_bound
1398 }
1399 },
1400 RoundingStrategy::Up => upper_bound,
1401 RoundingStrategy::Down => lower_bound,
1402 RoundingStrategy::ToZero => {
1403 if lower_bound.abs() < upper_bound.abs() {
1405 lower_bound
1406 } else {
1407 upper_bound
1408 }
1409 },
1410 }
1411 })?;
1412
1413 Ok(value)
1414 },
1415 Self::ModRem {
1416 dividend,
1417 divisor,
1418 op,
1419 } => {
1420 let mut dividend = dividend.resolve_internal(leaf_to_output_fn)?;
1421 let divisor = divisor.resolve_internal(leaf_to_output_fn)?;
1422
1423 if !dividend.is_same_unit_as(&divisor) {
1424 return Err(());
1425 }
1426
1427 let Some(divisor) = divisor.unitless_value() else {
1428 return Err(());
1429 };
1430 dividend.map(|dividend| op.apply(dividend, divisor))?;
1431 Ok(dividend)
1432 },
1433 Self::Sin(ref c) => {
1434 let result = c.resolve_internal(leaf_to_output_fn)?;
1435 let radians = result.as_number_or_angle_radians().ok_or(())?;
1436 Ok(L::new_number(radians.sin()))
1437 },
1438 Self::Cos(ref c) => {
1439 let result = c.resolve_internal(leaf_to_output_fn)?;
1440 let radians = result.as_number_or_angle_radians().ok_or(())?;
1441 Ok(L::new_number(radians.cos()))
1442 },
1443 Self::Tan(ref c) => {
1444 let result = c.resolve_internal(leaf_to_output_fn)?;
1445 let radians = result.as_number_or_angle_radians().ok_or(())?;
1446 Ok(L::new_number(radians.tan()))
1447 },
1448 Self::Asin(ref c) => {
1449 let result = c.resolve_internal(leaf_to_output_fn)?;
1450 let value = result.as_number().ok_or(())?;
1451 Ok(L::new_angle_from_radians(value.asin()))
1452 },
1453 Self::Acos(ref c) => {
1454 let result = c.resolve_internal(leaf_to_output_fn)?;
1455 let value = result.as_number().ok_or(())?;
1456 Ok(L::new_angle_from_radians(value.acos()))
1457 },
1458 Self::Atan(ref c) => {
1459 let result = c.resolve_internal(leaf_to_output_fn)?;
1460 let value = result.as_number().ok_or(())?;
1461 Ok(L::new_angle_from_radians(value.atan()))
1462 },
1463 Self::Atan2(ref a, ref b) => {
1464 let a = a.resolve_internal(leaf_to_output_fn)?;
1465 let b = b.resolve_internal(leaf_to_output_fn)?;
1466 if !a.is_same_unit_as(&b) {
1467 return Err(());
1468 }
1469 let a_val = a.unitless_value().ok_or(())?;
1470 let b_val = b.unitless_value().ok_or(())?;
1471 Ok(L::new_angle_from_radians(a_val.atan2(b_val)))
1472 },
1473 Self::Pow(ref a, ref b) => {
1474 let a = a.resolve_internal(leaf_to_output_fn)?;
1475 let b = b.resolve_internal(leaf_to_output_fn)?;
1476 let a_val = a.as_number().ok_or(())?;
1477 let b_val = b.as_number().ok_or(())?;
1478 Ok(L::new_number(a_val.powf(b_val)))
1479 },
1480 Self::Sqrt(ref c) => {
1481 let result = c.resolve_internal(leaf_to_output_fn)?;
1482 let value = result.as_number().ok_or(())?;
1483 Ok(L::new_number(value.sqrt()))
1484 },
1485 Self::Hypot(children) => {
1486 let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1487 result.map(|v| v.powi(2))?;
1488
1489 for child in children.iter().skip(1) {
1490 let child_value = child.resolve_internal(leaf_to_output_fn)?;
1491
1492 if !result.is_same_unit_as(&child_value) {
1493 return Err(());
1494 }
1495
1496 let Some(child_value) = child_value.unitless_value() else {
1497 return Err(());
1498 };
1499 result.map(|v| v + child_value.powi(2))?;
1500 }
1501
1502 result.map(|v| v.sqrt())?;
1503 Ok(result)
1504 },
1505 Self::Log(ref a, ref b) => {
1506 let a = a.resolve_internal(leaf_to_output_fn)?;
1507 let a_val = a.as_number().ok_or(())?;
1508 let result = match b {
1509 Optional::Some(ref b) => {
1510 let b = b.resolve_internal(leaf_to_output_fn)?;
1511 let b_val = b.as_number().ok_or(())?;
1512 a_val.log(b_val)
1513 },
1514 Optional::None => a_val.ln(),
1515 };
1516 Ok(L::new_number(result))
1517 },
1518 Self::Exp(ref c) => {
1519 let result = c.resolve_internal(leaf_to_output_fn)?;
1520 let value = result.as_number().ok_or(())?;
1521 Ok(L::new_number(value.exp()))
1522 },
1523 Self::Abs(ref c) => {
1524 let mut result = c.resolve_internal(leaf_to_output_fn)?;
1525
1526 result.map(|v| v.abs())?;
1527
1528 Ok(result)
1529 },
1530 Self::Sign(ref c) => {
1531 let result = c.resolve_internal(leaf_to_output_fn)?;
1532 Ok(L::sign_from(&result)?)
1533 },
1534 Self::Progress {
1535 clamping_mode,
1536 ref value,
1537 ref start,
1538 ref end,
1539 } => {
1540 let value = value.resolve_internal(leaf_to_output_fn)?;
1541 let start = start.resolve_internal(leaf_to_output_fn)?;
1542 let end = end.resolve_internal(leaf_to_output_fn)?;
1543 if !value.is_same_unit_as(&start) || !value.is_same_unit_as(&end) {
1544 return Err(());
1545 }
1546
1547 let value = value.unitless_value().ok_or(())?;
1548 let start = start.unitless_value().ok_or(())?;
1549 let end = end.unitless_value().ok_or(())?;
1550 Ok(L::new_number(clamping_mode.evaluate(value, start, end)))
1551 },
1552 Self::Anchor(_) | Self::AnchorSize(_) => Err(()),
1553 }
1554 }
1555
1556 pub fn map_node<F>(&mut self, mut mapping_fn: F) -> Result<(), ()>
1558 where
1559 F: FnMut(&CalcNode<L>) -> Result<Option<CalcNode<L>>, ()>,
1560 {
1561 self.map_node_internal(&mut mapping_fn)
1562 }
1563
1564 fn map_node_internal<F>(&mut self, mapping_fn: &mut F) -> Result<(), ()>
1565 where
1566 F: FnMut(&CalcNode<L>) -> Result<Option<CalcNode<L>>, ()>,
1567 {
1568 if let Some(node) = mapping_fn(self)? {
1569 *self = node;
1570 return Ok(());
1572 }
1573 match self {
1574 Self::Leaf(_) | Self::Anchor(_) | Self::AnchorSize(_) => (),
1575 Self::Negate(child)
1576 | Self::Invert(child)
1577 | Self::Abs(child)
1578 | Self::Sign(child)
1579 | Self::Sin(child)
1580 | Self::Cos(child)
1581 | Self::Tan(child)
1582 | Self::Asin(child)
1583 | Self::Acos(child)
1584 | Self::Atan(child)
1585 | Self::Sqrt(child)
1586 | Self::Exp(child) => {
1587 child.map_node_internal(mapping_fn)?;
1588 },
1589 Self::Atan2(a, b) => {
1590 a.map_node_internal(mapping_fn)?;
1591 b.map_node_internal(mapping_fn)?;
1592 },
1593 Self::Pow(a, b) => {
1594 a.map_node_internal(mapping_fn)?;
1595 b.map_node_internal(mapping_fn)?;
1596 },
1597 Self::Log(a, b) => {
1598 a.map_node_internal(mapping_fn)?;
1599 if let Optional::Some(b) = b {
1600 b.map_node_internal(mapping_fn)?;
1601 }
1602 },
1603 Self::Sum(children)
1604 | Self::Product(children)
1605 | Self::Hypot(children)
1606 | Self::MinMax(children, _) => {
1607 for child in children.iter_mut() {
1608 child.map_node_internal(mapping_fn)?;
1609 }
1610 },
1611 Self::Clamp { min, center, max } => {
1612 min.map_node_internal(mapping_fn)?;
1613 center.map_node_internal(mapping_fn)?;
1614 max.map_node_internal(mapping_fn)?;
1615 },
1616 Self::Round { value, step, .. } => {
1617 value.map_node_internal(mapping_fn)?;
1618 step.map_node_internal(mapping_fn)?;
1619 },
1620 Self::ModRem {
1621 dividend, divisor, ..
1622 } => {
1623 dividend.map_node_internal(mapping_fn)?;
1624 divisor.map_node_internal(mapping_fn)?;
1625 },
1626 Self::Progress {
1627 value, start, end, ..
1628 } => {
1629 value.map_node_internal(mapping_fn)?;
1630 start.map_node_internal(mapping_fn)?;
1631 end.map_node_internal(mapping_fn)?;
1632 },
1633 };
1634 Ok(())
1635 }
1636
1637 fn is_negative_leaf(&self) -> Result<bool, ()> {
1638 Ok(match *self {
1639 Self::Leaf(ref l) => l.is_negative()?,
1640 _ => false,
1641 })
1642 }
1643
1644 fn is_zero_leaf(&self) -> Result<bool, ()> {
1645 Ok(match *self {
1646 Self::Leaf(ref l) => l.is_zero()?,
1647 _ => false,
1648 })
1649 }
1650
1651 fn is_infinite_leaf(&self) -> Result<bool, ()> {
1652 Ok(match *self {
1653 Self::Leaf(ref l) => l.is_infinite()?,
1654 _ => false,
1655 })
1656 }
1657
1658 fn is_nan_leaf(&self) -> Result<bool, ()> {
1659 Ok(match *self {
1660 Self::Leaf(ref l) => l.is_nan()?,
1661 _ => false,
1662 })
1663 }
1664
1665 pub fn visit_depth_first(&mut self, mut f: impl FnMut(&mut Self)) {
1671 self.visit_depth_first_internal(&mut f)
1672 }
1673
1674 fn visit_depth_first_internal(&mut self, f: &mut impl FnMut(&mut Self)) {
1675 match *self {
1676 Self::Clamp {
1677 ref mut min,
1678 ref mut center,
1679 ref mut max,
1680 } => {
1681 min.visit_depth_first_internal(f);
1682 center.visit_depth_first_internal(f);
1683 max.visit_depth_first_internal(f);
1684 },
1685 Self::Round {
1686 ref mut value,
1687 ref mut step,
1688 ..
1689 } => {
1690 value.visit_depth_first_internal(f);
1691 step.visit_depth_first_internal(f);
1692 },
1693 Self::ModRem {
1694 ref mut dividend,
1695 ref mut divisor,
1696 ..
1697 } => {
1698 dividend.visit_depth_first_internal(f);
1699 divisor.visit_depth_first_internal(f);
1700 },
1701 Self::Sum(ref mut children)
1702 | Self::Product(ref mut children)
1703 | Self::MinMax(ref mut children, _)
1704 | Self::Hypot(ref mut children) => {
1705 for child in &mut **children {
1706 child.visit_depth_first_internal(f);
1707 }
1708 },
1709 Self::Negate(ref mut value) | Self::Invert(ref mut value) => {
1710 value.visit_depth_first_internal(f);
1711 },
1712 Self::Sin(ref mut value)
1713 | Self::Cos(ref mut value)
1714 | Self::Tan(ref mut value)
1715 | Self::Asin(ref mut value)
1716 | Self::Acos(ref mut value)
1717 | Self::Atan(ref mut value)
1718 | Self::Sqrt(ref mut value)
1719 | Self::Exp(ref mut value) => {
1720 value.visit_depth_first_internal(f);
1721 },
1722 Self::Atan2(ref mut a, ref mut b) => {
1723 a.visit_depth_first_internal(f);
1724 b.visit_depth_first_internal(f);
1725 },
1726 Self::Pow(ref mut a, ref mut b) => {
1727 a.visit_depth_first_internal(f);
1728 b.visit_depth_first_internal(f);
1729 },
1730 Self::Log(ref mut a, ref mut b) => {
1731 a.visit_depth_first_internal(f);
1732 if let Optional::Some(b) = b {
1733 b.visit_depth_first_internal(f);
1734 }
1735 },
1736 Self::Abs(ref mut value) | Self::Sign(ref mut value) => {
1737 value.visit_depth_first_internal(f);
1738 },
1739 Self::Progress {
1740 ref mut value,
1741 ref mut start,
1742 ref mut end,
1743 ..
1744 } => {
1745 value.visit_depth_first_internal(f);
1746 start.visit_depth_first_internal(f);
1747 end.visit_depth_first_internal(f);
1748 },
1749 Self::Leaf(..) | Self::Anchor(..) | Self::AnchorSize(..) => {},
1750 }
1751 f(self);
1752 }
1753
1754 pub fn simplify_and_sort_direct_children(&mut self) -> SimplificationResult {
1765 macro_rules! replace_self_with {
1766 ($slot:expr) => {{
1767 let result = mem::replace($slot, Self::dummy());
1768 *self = result;
1769 }};
1770 }
1771
1772 macro_rules! value_or_stop {
1773 ($op:expr) => {{
1774 match $op {
1775 Ok(value) => value,
1776 Err(_) => return SimplificationResult::Unchanged,
1777 }
1778 }};
1779 }
1780
1781 match *self {
1782 Self::Clamp {
1783 ref mut min,
1784 ref mut center,
1785 ref mut max,
1786 } => {
1787 let min_cmp_center = match min.compare(¢er, PositivePercentageBasis::Unknown) {
1789 Some(o) => o,
1790 None => return SimplificationResult::Unchanged,
1791 };
1792
1793 if matches!(min_cmp_center, cmp::Ordering::Greater) {
1796 replace_self_with!(&mut **min);
1797 return SimplificationResult::Simplified;
1798 }
1799
1800 let max_cmp_center = match max.compare(¢er, PositivePercentageBasis::Unknown) {
1802 Some(o) => o,
1803 None => return SimplificationResult::Unchanged,
1804 };
1805
1806 if matches!(max_cmp_center, cmp::Ordering::Less) {
1807 let max_cmp_min = match max.compare(&min, PositivePercentageBasis::Unknown) {
1810 Some(o) => o,
1811 None => return SimplificationResult::Unchanged,
1812 };
1813
1814 if matches!(max_cmp_min, cmp::Ordering::Less) {
1815 replace_self_with!(&mut **min);
1816 return SimplificationResult::Simplified;
1817 }
1818
1819 replace_self_with!(&mut **max);
1820 return SimplificationResult::Simplified;
1821 }
1822
1823 replace_self_with!(&mut **center);
1825 return SimplificationResult::Simplified;
1826 },
1827 Self::Round {
1828 strategy,
1829 ref mut value,
1830 ref mut step,
1831 } => {
1832 if value_or_stop!(step.is_zero_leaf()) {
1833 value_or_stop!(value.coerce_to_value(f32::NAN));
1834 replace_self_with!(&mut **value);
1835 return SimplificationResult::Simplified;
1836 }
1837
1838 if value_or_stop!(value.is_infinite_leaf())
1839 && value_or_stop!(step.is_infinite_leaf())
1840 {
1841 value_or_stop!(value.coerce_to_value(f32::NAN));
1842 replace_self_with!(&mut **value);
1843 return SimplificationResult::Simplified;
1844 }
1845
1846 if value_or_stop!(value.is_infinite_leaf()) {
1847 replace_self_with!(&mut **value);
1848 return SimplificationResult::Simplified;
1849 }
1850
1851 if value_or_stop!(step.is_infinite_leaf()) {
1852 match strategy {
1853 RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
1854 value_or_stop!(value.coerce_to_value(0.0));
1855 replace_self_with!(&mut **value);
1856 return SimplificationResult::Simplified;
1857 },
1858 RoundingStrategy::Up => {
1859 if !value_or_stop!(value.is_negative_leaf())
1860 && !value_or_stop!(value.is_zero_leaf())
1861 {
1862 value_or_stop!(value.coerce_to_value(f32::INFINITY));
1863 replace_self_with!(&mut **value);
1864 return SimplificationResult::Simplified;
1865 } else if !value_or_stop!(value.is_negative_leaf())
1866 && value_or_stop!(value.is_zero_leaf())
1867 {
1868 replace_self_with!(&mut **value);
1869 return SimplificationResult::Simplified;
1870 } else {
1871 value_or_stop!(value.coerce_to_value(0.0));
1872 replace_self_with!(&mut **value);
1873 return SimplificationResult::Simplified;
1874 }
1875 },
1876 RoundingStrategy::Down => {
1877 if value_or_stop!(value.is_negative_leaf())
1878 && !value_or_stop!(value.is_zero_leaf())
1879 {
1880 value_or_stop!(value.coerce_to_value(-f32::INFINITY));
1881 replace_self_with!(&mut **value);
1882 return SimplificationResult::Simplified;
1883 } else if value_or_stop!(value.is_negative_leaf())
1884 && value_or_stop!(value.is_zero_leaf())
1885 {
1886 replace_self_with!(&mut **value);
1887 return SimplificationResult::Simplified;
1888 } else {
1889 value_or_stop!(value.coerce_to_value(0.0));
1890 replace_self_with!(&mut **value);
1891 return SimplificationResult::Simplified;
1892 }
1893 },
1894 }
1895 }
1896
1897 if value_or_stop!(step.is_negative_leaf()) {
1898 step.negate();
1899 }
1900
1901 let remainder = value_or_stop!(value.try_op(step, Rem::rem));
1902 if value_or_stop!(remainder.is_zero_leaf()) {
1903 replace_self_with!(&mut **value);
1904 return SimplificationResult::Simplified;
1905 }
1906
1907 let (mut lower_bound, mut upper_bound) = if value_or_stop!(value.is_negative_leaf())
1908 {
1909 let upper_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
1910 let lower_bound = value_or_stop!(upper_bound.try_op(&step, Sub::sub));
1911
1912 (lower_bound, upper_bound)
1913 } else {
1914 let lower_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
1915 let upper_bound = value_or_stop!(lower_bound.try_op(&step, Add::add));
1916
1917 (lower_bound, upper_bound)
1918 };
1919
1920 match strategy {
1921 RoundingStrategy::Nearest => {
1922 let lower_diff = value_or_stop!(value.try_op(&lower_bound, Sub::sub));
1923 let upper_diff = value_or_stop!(upper_bound.try_op(value, Sub::sub));
1924 if lower_diff.lt(&upper_diff, PositivePercentageBasis::Unknown) {
1926 replace_self_with!(&mut lower_bound);
1927 } else {
1928 replace_self_with!(&mut upper_bound);
1929 }
1930 },
1931 RoundingStrategy::Up => {
1932 replace_self_with!(&mut upper_bound);
1933 },
1934 RoundingStrategy::Down => {
1935 replace_self_with!(&mut lower_bound);
1936 },
1937 RoundingStrategy::ToZero => {
1938 let mut lower_diff = lower_bound.clone();
1939 let mut upper_diff = upper_bound.clone();
1940
1941 if value_or_stop!(lower_diff.is_negative_leaf()) {
1942 lower_diff.negate();
1943 }
1944
1945 if value_or_stop!(upper_diff.is_negative_leaf()) {
1946 upper_diff.negate();
1947 }
1948
1949 if lower_diff.lt(&upper_diff, PositivePercentageBasis::Unknown) {
1951 replace_self_with!(&mut lower_bound);
1952 } else {
1953 replace_self_with!(&mut upper_bound);
1954 }
1955 },
1956 };
1957 return SimplificationResult::Simplified;
1958 },
1959 Self::ModRem {
1960 ref dividend,
1961 ref divisor,
1962 op,
1963 } => {
1964 let mut result = value_or_stop!(dividend.try_op(divisor, |a, b| op.apply(a, b)));
1965 replace_self_with!(&mut result);
1966 return SimplificationResult::Simplified;
1967 },
1968 Self::MinMax(ref mut children, op) => {
1969 let winning_order = match op {
1970 MinMaxOp::Min => cmp::Ordering::Less,
1971 MinMaxOp::Max => cmp::Ordering::Greater,
1972 };
1973
1974 if value_or_stop!(children[0].is_nan_leaf()) {
1975 replace_self_with!(&mut children[0]);
1976 return SimplificationResult::Simplified;
1977 }
1978
1979 let mut result = 0;
1980 for i in 1..children.len() {
1981 if value_or_stop!(children[i].is_nan_leaf()) {
1982 replace_self_with!(&mut children[i]);
1983 return SimplificationResult::Simplified;
1984 }
1985 let o = match children[i]
1986 .compare(&children[result], PositivePercentageBasis::Unknown)
1987 {
1988 None => return SimplificationResult::Unchanged,
1995 Some(o) => o,
1996 };
1997
1998 if o == winning_order {
1999 result = i;
2000 }
2001 }
2002
2003 replace_self_with!(&mut children[result]);
2004 return SimplificationResult::Simplified;
2005 },
2006 Self::Sum(ref mut children_slot) => {
2007 let mut sums_to_merge = SmallVec::<[_; 3]>::new();
2008 let mut extra_kids = 0;
2009 for (i, child) in children_slot.iter().enumerate() {
2010 if let Self::Sum(ref children) = *child {
2011 extra_kids += children.len();
2012 sums_to_merge.push(i);
2013 }
2014 }
2015
2016 if children_slot.len() == 1 {
2020 replace_self_with!(&mut children_slot[0]);
2021 return SimplificationResult::Simplified;
2022 }
2023
2024 let mut children = mem::take(children_slot).into_vec();
2025
2026 if !sums_to_merge.is_empty() {
2027 children.reserve(extra_kids - sums_to_merge.len());
2028 for i in sums_to_merge.drain(..).rev() {
2031 let kid_children = match children.swap_remove(i) {
2032 Self::Sum(c) => c,
2033 _ => unreachable!(),
2034 };
2035
2036 children.extend(kid_children.into_vec());
2039 }
2040 }
2041
2042 let children_len = children.len();
2043 debug_assert!(children_len >= 2, "Should still have multiple kids!");
2044
2045 children.sort_unstable_by_key(|c| c.sort_key());
2047
2048 children.dedup_by(|a, b| b.try_sum_in_place(a).is_ok());
2051
2052 let updated_children_len = children.len();
2053 if updated_children_len == 1 {
2054 replace_self_with!(&mut children[0]);
2056 } else {
2057 *children_slot = children.into_boxed_slice().into();
2059 }
2060
2061 return if updated_children_len != children_len {
2062 SimplificationResult::Simplified
2063 } else {
2064 SimplificationResult::Unchanged
2065 };
2066 },
2067 Self::Product(ref mut children_slot) => {
2068 let mut products_to_merge = SmallVec::<[_; 3]>::new();
2069 let mut extra_kids = 0;
2070 for (i, child) in children_slot.iter().enumerate() {
2071 if let Self::Product(ref children) = *child {
2072 extra_kids += children.len();
2073 products_to_merge.push(i);
2074 }
2075 }
2076
2077 if children_slot.len() == 1 {
2081 replace_self_with!(&mut children_slot[0]);
2082 return SimplificationResult::Unchanged;
2083 }
2084
2085 let mut children = mem::take(children_slot).into_vec();
2086 if !products_to_merge.is_empty() {
2087 children.reserve(extra_kids - products_to_merge.len());
2088 for i in products_to_merge.drain(..).rev() {
2091 let kid_children = match children.swap_remove(i) {
2092 Self::Product(c) => c,
2093 _ => unreachable!(),
2094 };
2095
2096 children.extend(kid_children.into_vec());
2099 }
2100 }
2101
2102 debug_assert!(children.len() >= 2, "Should still have multiple kids!");
2103
2104 children.sort_unstable_by_key(|c| c.sort_key());
2106
2107 children.dedup_by(|right, left| left.try_product_in_place(right));
2110
2111 if children.len() == 1 {
2112 replace_self_with!(&mut children[0]);
2114 return SimplificationResult::Simplified;
2115 } else {
2116 *children_slot = children.into_boxed_slice().into();
2118 }
2119 return SimplificationResult::Unchanged;
2120 },
2121 Self::Sin(ref mut child) => {
2122 if let CalcNode::Leaf(ref leaf) = **child {
2123 if let Some(radians) = leaf.as_number_or_angle_radians() {
2124 let mut result = Self::Leaf(L::new_number(radians.sin()));
2125 replace_self_with!(&mut result);
2126 return SimplificationResult::Simplified;
2127 }
2128 }
2129 return SimplificationResult::Unchanged;
2130 },
2131 Self::Cos(ref mut child) => {
2132 if let CalcNode::Leaf(ref leaf) = **child {
2133 if let Some(radians) = leaf.as_number_or_angle_radians() {
2134 let mut result = Self::Leaf(L::new_number(radians.cos()));
2135 replace_self_with!(&mut result);
2136 return SimplificationResult::Simplified;
2137 }
2138 }
2139 return SimplificationResult::Unchanged;
2140 },
2141 Self::Tan(ref mut child) => {
2142 if let CalcNode::Leaf(ref leaf) = **child {
2143 if let Some(radians) = leaf.as_number_or_angle_radians() {
2144 let mut result = Self::Leaf(L::new_number(radians.tan()));
2145 replace_self_with!(&mut result);
2146 return SimplificationResult::Simplified;
2147 }
2148 }
2149 return SimplificationResult::Unchanged;
2150 },
2151 Self::Asin(ref mut child) => {
2152 if let CalcNode::Leaf(ref leaf) = **child {
2153 if let Some(value) = leaf.as_number() {
2154 let mut result = Self::Leaf(L::new_angle_from_radians(value.asin()));
2155 replace_self_with!(&mut result);
2156 return SimplificationResult::Simplified;
2157 }
2158 }
2159 return SimplificationResult::Unchanged;
2160 },
2161 Self::Acos(ref mut child) => {
2162 if let CalcNode::Leaf(ref leaf) = **child {
2163 if let Some(value) = leaf.as_number() {
2164 let mut result = Self::Leaf(L::new_angle_from_radians(value.acos()));
2165 replace_self_with!(&mut result);
2166 return SimplificationResult::Simplified;
2167 }
2168 }
2169 return SimplificationResult::Unchanged;
2170 },
2171 Self::Atan(ref mut child) => {
2172 if let CalcNode::Leaf(ref leaf) = **child {
2173 if let Some(value) = leaf.as_number() {
2174 let mut result = Self::Leaf(L::new_angle_from_radians(value.atan()));
2175 replace_self_with!(&mut result);
2176 return SimplificationResult::Simplified;
2177 }
2178 }
2179 return SimplificationResult::Unchanged;
2180 },
2181 Self::Atan2(ref mut a, ref mut b) => {
2182 if let (CalcNode::Leaf(ref la), CalcNode::Leaf(ref lb)) = (&**a, &**b) {
2183 if la.is_same_unit_as(lb) {
2184 if let (Some(a_val), Some(b_val)) =
2185 (la.unitless_value(), lb.unitless_value())
2186 {
2187 let mut result =
2188 Self::Leaf(L::new_angle_from_radians(a_val.atan2(b_val)));
2189 replace_self_with!(&mut result);
2190 return SimplificationResult::Simplified;
2191 }
2192 }
2193 }
2194 return SimplificationResult::Unchanged;
2195 },
2196 Self::Pow(ref mut a, ref mut b) => {
2197 if let (CalcNode::Leaf(ref la), CalcNode::Leaf(ref lb)) = (&**a, &**b) {
2198 if let (Some(a_val), Some(b_val)) = (la.as_number(), lb.as_number()) {
2199 let mut result = Self::Leaf(L::new_number(a_val.powf(b_val)));
2200 replace_self_with!(&mut result);
2201 return SimplificationResult::Simplified;
2202 }
2203 }
2204 return SimplificationResult::Unchanged;
2205 },
2206 Self::Sqrt(ref mut child) => {
2207 if let CalcNode::Leaf(ref leaf) = **child {
2208 if let Some(value) = leaf.as_number() {
2209 let mut result = Self::Leaf(L::new_number(value.sqrt()));
2210 replace_self_with!(&mut result);
2211 return SimplificationResult::Simplified;
2212 }
2213 }
2214 return SimplificationResult::Unchanged;
2215 },
2216 Self::Hypot(ref children) => {
2217 let mut result = value_or_stop!(children[0].try_op(&children[0], Mul::mul));
2218
2219 for child in children.iter().skip(1) {
2220 let square = value_or_stop!(child.try_op(&child, Mul::mul));
2221 result = value_or_stop!(result.try_op(&square, Add::add));
2222 }
2223
2224 result = value_or_stop!(result.try_op(&result, |a, _| a.sqrt()));
2225
2226 replace_self_with!(&mut result);
2227 return SimplificationResult::Simplified;
2228 },
2229 Self::Log(ref mut a, ref mut b) => {
2230 if let CalcNode::Leaf(ref la) = **a {
2231 if let Some(a_val) = la.as_number() {
2232 let folded = match b {
2233 Optional::Some(ref b) => {
2234 if let CalcNode::Leaf(ref lb) = **b {
2235 lb.as_number().map(|b_val| a_val.log(b_val))
2236 } else {
2237 None
2238 }
2239 },
2240 Optional::None => Some(a_val.ln()),
2241 };
2242 if let Some(number) = folded {
2243 let mut result = Self::Leaf(L::new_number(number));
2244 replace_self_with!(&mut result);
2245 return SimplificationResult::Simplified;
2246 }
2247 }
2248 }
2249 return SimplificationResult::Unchanged;
2250 },
2251 Self::Exp(ref mut child) => {
2252 if let CalcNode::Leaf(ref leaf) = **child {
2253 if let Some(value) = leaf.as_number() {
2254 let mut result = Self::Leaf(L::new_number(value.exp()));
2255 replace_self_with!(&mut result);
2256 return SimplificationResult::Simplified;
2257 }
2258 }
2259 return SimplificationResult::Unchanged;
2260 },
2261 Self::Abs(ref mut child) => {
2262 if let CalcNode::Leaf(leaf) = child.as_mut() {
2263 value_or_stop!(leaf.map(|v| v.abs()));
2264 replace_self_with!(&mut **child);
2265 return SimplificationResult::Simplified;
2266 }
2267 return SimplificationResult::Unchanged;
2268 },
2269 Self::Sign(ref mut child) => {
2270 if let CalcNode::Leaf(leaf) = child.as_mut() {
2271 let mut result = Self::Leaf(value_or_stop!(L::sign_from(leaf)));
2272 replace_self_with!(&mut result);
2273 return SimplificationResult::Simplified;
2274 }
2275 return SimplificationResult::Unchanged;
2276 },
2277 Self::Negate(ref mut child) => {
2278 match &mut **child {
2280 CalcNode::Leaf(_) => {
2281 child.negate();
2284 replace_self_with!(&mut **child);
2285 return SimplificationResult::Simplified;
2286 },
2287 CalcNode::Negate(value) => {
2288 replace_self_with!(&mut **value);
2290 return SimplificationResult::Simplified;
2291 },
2292 _ => {
2293 return SimplificationResult::Unchanged;
2295 },
2296 }
2297 },
2298 Self::Invert(ref mut child) => {
2299 match &mut **child {
2301 CalcNode::Leaf(leaf) => {
2302 if leaf.unit().is_empty() {
2305 value_or_stop!(child.map(|v| 1.0 / v));
2306 replace_self_with!(&mut **child);
2307 return SimplificationResult::Simplified;
2308 }
2309 return SimplificationResult::Unchanged;
2310 },
2311 CalcNode::Invert(value) => {
2312 replace_self_with!(&mut **value);
2314 return SimplificationResult::Simplified;
2315 },
2316 _ => {
2317 return SimplificationResult::Unchanged;
2319 },
2320 }
2321 },
2322 Self::Progress {
2323 clamping_mode,
2324 ref mut value,
2325 ref mut start,
2326 ref mut end,
2327 } => {
2328 if let (
2329 CalcNode::Leaf(ref value),
2330 CalcNode::Leaf(ref start),
2331 CalcNode::Leaf(ref end),
2332 ) = (&**value, &**start, &**end)
2333 {
2334 if value.is_same_unit_as(start) && value.is_same_unit_as(end) {
2335 if let (Some(value), Some(start), Some(end)) = (
2336 value.unitless_value(),
2337 start.unitless_value(),
2338 end.unitless_value(),
2339 ) {
2340 let mut result = Self::Leaf(L::new_number(
2341 clamping_mode.evaluate(value, start, end),
2342 ));
2343 replace_self_with!(&mut result);
2344 return SimplificationResult::Simplified;
2345 }
2346 }
2347 }
2348 return SimplificationResult::Unchanged;
2349 },
2350 Self::Leaf(ref mut l) => {
2351 return l.simplify();
2352 },
2353 Self::Anchor(ref mut f) => {
2354 if let GenericAnchorSide::Percentage(ref mut n) = f.side {
2355 n.simplify_and_sort();
2356 return SimplificationResult::Simplified;
2357 }
2358 if let Some(fallback) = f.fallback.as_mut() {
2359 return fallback.node.simplify_and_sort();
2360 }
2361 return SimplificationResult::Unchanged;
2362 },
2363 Self::AnchorSize(ref mut f) => {
2364 if let Some(fallback) = f.fallback.as_mut() {
2365 return fallback.node.simplify_and_sort();
2366 }
2367 return SimplificationResult::Unchanged;
2368 },
2369 }
2370 }
2371
2372 pub fn simplify_and_sort(&mut self) -> SimplificationResult {
2374 let mut res = SimplificationResult::Unchanged;
2375 self.visit_depth_first(|node| match node.simplify_and_sort_direct_children() {
2376 SimplificationResult::Simplified => {
2377 res = SimplificationResult::Simplified;
2378 },
2379 _ => {},
2380 });
2381 res
2382 }
2383
2384 fn to_css_impl<W>(&self, dest: &mut CssWriter<W>, level: ArgumentLevel) -> fmt::Result
2385 where
2386 W: Write,
2387 {
2388 let write_closing_paren = match self {
2389 Self::MinMax(_, op) => {
2390 dest.write_str(match op {
2391 MinMaxOp::Max => "max(",
2392 MinMaxOp::Min => "min(",
2393 })?;
2394 true
2395 },
2396 Self::Clamp { .. } => {
2397 dest.write_str("clamp(")?;
2398 true
2399 },
2400 Self::Round { strategy, .. } => {
2401 match strategy {
2402 RoundingStrategy::Nearest => dest.write_str("round("),
2403 RoundingStrategy::Up => dest.write_str("round(up, "),
2404 RoundingStrategy::Down => dest.write_str("round(down, "),
2405 RoundingStrategy::ToZero => dest.write_str("round(to-zero, "),
2406 }?;
2407
2408 true
2409 },
2410 Self::ModRem { op, .. } => {
2411 dest.write_str(match op {
2412 ModRemOp::Mod => "mod(",
2413 ModRemOp::Rem => "rem(",
2414 })?;
2415
2416 true
2417 },
2418 Self::Sin(_) => {
2419 dest.write_str("sin(")?;
2420 true
2421 },
2422 Self::Cos(_) => {
2423 dest.write_str("cos(")?;
2424 true
2425 },
2426 Self::Tan(_) => {
2427 dest.write_str("tan(")?;
2428 true
2429 },
2430 Self::Asin(_) => {
2431 dest.write_str("asin(")?;
2432 true
2433 },
2434 Self::Acos(_) => {
2435 dest.write_str("acos(")?;
2436 true
2437 },
2438 Self::Atan(_) => {
2439 dest.write_str("atan(")?;
2440 true
2441 },
2442 Self::Atan2(..) => {
2443 dest.write_str("atan2(")?;
2444 true
2445 },
2446 Self::Pow(..) => {
2447 dest.write_str("pow(")?;
2448 true
2449 },
2450 Self::Sqrt(_) => {
2451 dest.write_str("sqrt(")?;
2452 true
2453 },
2454 Self::Hypot(_) => {
2455 dest.write_str("hypot(")?;
2456 true
2457 },
2458 Self::Log(..) => {
2459 dest.write_str("log(")?;
2460 true
2461 },
2462 Self::Exp(_) => {
2463 dest.write_str("exp(")?;
2464 true
2465 },
2466 Self::Abs(_) => {
2467 dest.write_str("abs(")?;
2468 true
2469 },
2470 Self::Sign(_) => {
2471 dest.write_str("sign(")?;
2472 true
2473 },
2474 Self::Progress { .. } => {
2475 dest.write_str("progress(")?;
2476 true
2477 },
2478 Self::Negate(_) => {
2479 debug_assert!(
2483 false,
2484 "We never serialize Negate nodes as they are handled inside Sum nodes."
2485 );
2486 dest.write_str("(-1 * ")?;
2487 true
2488 },
2489 Self::Invert(_) => {
2490 if matches!(level, ArgumentLevel::CalculationRoot) {
2491 dest.write_str("calc")?;
2492 }
2493 dest.write_str("(1 / ")?;
2494 true
2495 },
2496 Self::Sum(_) | Self::Product(_) => match level {
2497 ArgumentLevel::CalculationRoot => {
2498 dest.write_str("calc(")?;
2499 true
2500 },
2501 ArgumentLevel::ArgumentRoot => false,
2502 ArgumentLevel::Nested => {
2503 dest.write_str("(")?;
2504 true
2505 },
2506 },
2507 Self::Leaf(leaf) => match level {
2508 ArgumentLevel::CalculationRoot => {
2509 if leaf.should_serialize_with_root_calc_wrapper() {
2510 dest.write_str("calc(")?;
2511 true
2512 } else {
2513 false
2514 }
2515 },
2516 ArgumentLevel::ArgumentRoot | ArgumentLevel::Nested => false,
2517 },
2518 Self::Anchor(_) | Self::AnchorSize(_) => false,
2519 };
2520
2521 match *self {
2522 Self::MinMax(ref children, _) | Self::Hypot(ref children) => {
2523 let mut first = true;
2524 for child in &**children {
2525 if !first {
2526 dest.write_str(", ")?;
2527 }
2528 first = false;
2529 child.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2530 }
2531 },
2532 Self::Negate(ref value) | Self::Invert(ref value) => {
2533 value.to_css_impl(dest, ArgumentLevel::Nested)?
2534 },
2535 Self::Sum(ref children) => {
2536 let mut first = true;
2537 for child in &**children {
2538 if !first {
2539 match child {
2540 Self::Leaf(l) => {
2541 if let Ok(true) = l.is_negative() {
2542 dest.write_str(" - ")?;
2543 let mut negated = l.clone();
2544 negated.map(std::ops::Neg::neg).unwrap();
2547 negated.to_css(dest)?;
2548 } else {
2549 dest.write_str(" + ")?;
2550 l.to_css(dest)?;
2551 }
2552 },
2553 Self::Negate(n) => {
2554 dest.write_str(" - ")?;
2555 n.to_css_impl(dest, ArgumentLevel::Nested)?;
2556 },
2557 _ => {
2558 dest.write_str(" + ")?;
2559 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2560 },
2561 }
2562 } else {
2563 first = false;
2564 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2565 }
2566 }
2567 },
2568 Self::Product(ref children) => {
2569 let mut first = true;
2570 for child in &**children {
2571 if !first {
2572 match child {
2573 Self::Invert(n) => {
2574 dest.write_str(" / ")?;
2575 n.to_css_impl(dest, ArgumentLevel::Nested)?;
2576 },
2577 _ => {
2578 dest.write_str(" * ")?;
2579 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2580 },
2581 }
2582 } else {
2583 first = false;
2584 child.to_css_impl(dest, ArgumentLevel::Nested)?;
2585 }
2586 }
2587 },
2588 Self::Clamp {
2589 ref min,
2590 ref center,
2591 ref max,
2592 } => {
2593 min.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2594 dest.write_str(", ")?;
2595 center.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2596 dest.write_str(", ")?;
2597 max.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2598 },
2599 Self::Round {
2600 ref value,
2601 ref step,
2602 ..
2603 } => {
2604 value.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2605 dest.write_str(", ")?;
2606 step.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2607 },
2608 Self::ModRem {
2609 ref dividend,
2610 ref divisor,
2611 ..
2612 } => {
2613 dividend.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2614 dest.write_str(", ")?;
2615 divisor.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2616 },
2617 Self::Sin(ref v)
2618 | Self::Cos(ref v)
2619 | Self::Tan(ref v)
2620 | Self::Asin(ref v)
2621 | Self::Acos(ref v)
2622 | Self::Atan(ref v) => v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?,
2623 Self::Atan2(ref a, ref b) => {
2624 a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2625 dest.write_str(", ")?;
2626 b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2627 },
2628 Self::Pow(ref a, ref b) => {
2629 a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2630 dest.write_str(", ")?;
2631 b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2632 },
2633 Self::Sqrt(ref v) | Self::Exp(ref v) => {
2634 v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?
2635 },
2636 Self::Log(ref a, ref b) => {
2637 a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2638 if let Optional::Some(ref b) = b {
2639 dest.write_str(", ")?;
2640 b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2641 }
2642 },
2643 Self::Abs(ref v) | Self::Sign(ref v) => {
2644 v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?
2645 },
2646 Self::Progress {
2647 clamping_mode,
2648 ref value,
2649 ref start,
2650 ref end,
2651 } => {
2652 if clamping_mode == ProgressClampingMode::NoClamp {
2653 clamping_mode.to_css(dest)?;
2654 dest.write_char(' ')?;
2655 }
2656 value.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2657 dest.write_str(", ")?;
2658 start.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2659 dest.write_str(", ")?;
2660 end.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2661 },
2662 Self::Leaf(ref l) => l.to_css(dest)?,
2663 Self::Anchor(ref f) => f.to_css(dest)?,
2664 Self::AnchorSize(ref f) => f.to_css(dest)?,
2665 }
2666
2667 if write_closing_paren {
2668 dest.write_char(')')?;
2669 }
2670 Ok(())
2671 }
2672
2673 fn to_typed_impl(
2674 &self,
2675 dest: &mut ThinVec<TypedValue>,
2676 level: ArgumentLevel,
2677 ) -> Result<(), ()> {
2678 match *self {
2682 Self::Leaf(ref l) => match l.to_typed_value() {
2683 Some(TypedValue::Numeric(inner)) => {
2684 match level {
2685 ArgumentLevel::CalculationRoot => {
2686 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Sum(
2687 MathSum::try_from_numeric_values(ThinVec::from([inner]))?,
2688 ))));
2689 },
2690 ArgumentLevel::ArgumentRoot | ArgumentLevel::Nested => {
2691 dest.push(TypedValue::Numeric(inner));
2692 },
2693 }
2694 Ok(())
2695 },
2696 _ => Err(()),
2697 },
2698 Self::Negate(_) => {
2699 debug_assert!(
2703 false,
2704 "We never reify Negate nodes as they are handled inside Sum nodes."
2705 );
2706
2707 Err(())
2708 },
2709 Self::Invert(ref value) => {
2710 let inner = CalcNodeWithLevel::nested(value)
2711 .to_numeric_value()
2712 .ok_or(())?;
2713
2714 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Invert(
2715 Box::new(inner),
2716 ))));
2717 Ok(())
2718 },
2719 Self::Sum(ref children) => {
2720 let mut values = ThinVec::new();
2721 let mut first = true;
2722
2723 for child in &**children {
2724 if !first {
2725 match child {
2726 Self::Leaf(l) => {
2727 if let Ok(true) = l.is_negative() {
2728 let mut negated = l.clone();
2729
2730 negated.map(std::ops::Neg::neg).unwrap();
2733
2734 let inner = negated.to_numeric_value().ok_or(())?;
2735
2736 values.push(NumericValue::Math(MathValue::Negate(Box::new(
2737 inner,
2738 ))));
2739 } else {
2740 let inner = l.to_numeric_value().ok_or(())?;
2741
2742 values.push(inner);
2743 }
2744 },
2745 Self::Negate(n) => {
2746 let inner = CalcNodeWithLevel::nested(n.as_ref())
2747 .to_numeric_value()
2748 .ok_or(())?;
2749
2750 values.push(NumericValue::Math(MathValue::Negate(Box::new(inner))));
2751 },
2752 _ => {
2753 let inner = CalcNodeWithLevel::nested(child)
2754 .to_numeric_value()
2755 .ok_or(())?;
2756
2757 values.push(inner);
2758 },
2759 }
2760 } else {
2761 first = false;
2762
2763 let inner = CalcNodeWithLevel::nested(child)
2764 .to_numeric_value()
2765 .ok_or(())?;
2766
2767 values.push(inner);
2768 }
2769 }
2770
2771 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Sum(
2772 MathSum::try_from_numeric_values(values)?,
2773 ))));
2774 Ok(())
2775 },
2776 Self::Product(ref children) => {
2777 let mut values = ThinVec::new();
2778 let mut first = true;
2779
2780 for child in &**children {
2781 if !first {
2782 match child {
2783 Self::Invert(n) => {
2784 let inner = CalcNodeWithLevel::nested(n.as_ref())
2785 .to_numeric_value()
2786 .ok_or(())?;
2787
2788 values.push(NumericValue::Math(MathValue::Invert(Box::new(inner))));
2789 },
2790 _ => {
2791 let inner = CalcNodeWithLevel::nested(child)
2792 .to_numeric_value()
2793 .ok_or(())?;
2794
2795 values.push(inner);
2796 },
2797 }
2798 } else {
2799 first = false;
2800
2801 let inner = CalcNodeWithLevel::nested(child)
2802 .to_numeric_value()
2803 .ok_or(())?;
2804
2805 values.push(inner);
2806 }
2807 }
2808
2809 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Product(
2810 values,
2811 ))));
2812 Ok(())
2813 },
2814 Self::MinMax(ref children, op) => {
2815 let mut values = ThinVec::new();
2816
2817 for child in &**children {
2818 let inner = CalcNodeWithLevel::argument_root(child)
2819 .to_numeric_value()
2820 .ok_or(())?;
2821
2822 values.push(inner);
2823 }
2824
2825 let math_value = match op {
2826 MinMaxOp::Min => MathValue::Min(values),
2827 MinMaxOp::Max => MathValue::Max(values),
2828 };
2829
2830 dest.push(TypedValue::Numeric(NumericValue::Math(math_value)));
2831 Ok(())
2832 },
2833 Self::Clamp {
2834 ref min,
2835 ref center,
2836 ref max,
2837 } => {
2838 let lower = CalcNodeWithLevel::argument_root(min)
2839 .to_numeric_value()
2840 .ok_or(())?;
2841
2842 let value = CalcNodeWithLevel::argument_root(center)
2843 .to_numeric_value()
2844 .ok_or(())?;
2845
2846 let upper = CalcNodeWithLevel::argument_root(max)
2847 .to_numeric_value()
2848 .ok_or(())?;
2849
2850 dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Clamp(
2851 [lower, value, upper].into(),
2852 ))));
2853 Ok(())
2854 },
2855 _ => Err(()),
2856 }
2857 }
2858
2859 fn compare(
2860 &self,
2861 other: &Self,
2862 basis_positive: PositivePercentageBasis,
2863 ) -> Option<cmp::Ordering> {
2864 match (self, other) {
2865 (&CalcNode::Leaf(ref one), &CalcNode::Leaf(ref other)) => {
2866 one.compare(other, basis_positive)
2867 },
2868 _ => None,
2869 }
2870 }
2871
2872 compare_helpers!();
2873}
2874
2875impl<L: CalcNodeLeaf> ToCss for CalcNode<L> {
2876 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
2878 where
2879 W: Write,
2880 {
2881 self.to_css_impl(dest, ArgumentLevel::CalculationRoot)
2882 }
2883}
2884
2885impl<L: CalcNodeLeaf> ToTyped for CalcNode<L> {
2886 fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
2887 CalcNodeWithLevel::calculation_root(self).to_typed(dest)
2888 }
2889}
2890
2891struct CalcNodeWithLevel<'a, L> {
2892 node: &'a CalcNode<L>,
2893 level: ArgumentLevel,
2894}
2895
2896impl<'a, L> CalcNodeWithLevel<'a, L> {
2897 #[inline]
2898 fn new(node: &'a CalcNode<L>, level: ArgumentLevel) -> Self {
2899 Self { node, level }
2900 }
2901
2902 #[inline]
2903 fn calculation_root(node: &'a CalcNode<L>) -> Self {
2904 Self::new(node, ArgumentLevel::CalculationRoot)
2905 }
2906
2907 #[inline]
2908 fn argument_root(node: &'a CalcNode<L>) -> Self {
2909 Self::new(node, ArgumentLevel::ArgumentRoot)
2910 }
2911
2912 #[inline]
2913 fn nested(node: &'a CalcNode<L>) -> Self {
2914 Self::new(node, ArgumentLevel::Nested)
2915 }
2916}
2917
2918impl<'a, L: CalcNodeLeaf> ToTyped for CalcNodeWithLevel<'a, L> {
2919 fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
2920 self.node.to_typed_impl(dest, self.level.clone())
2921 }
2922}
2923
2924#[cfg(test)]
2925mod tests {
2926 use super::*;
2927
2928 #[test]
2929 fn can_sum_with_checks() {
2930 assert!(CalcUnits::LENGTH.can_sum_with(CalcUnits::LENGTH));
2931 assert!(CalcUnits::LENGTH.can_sum_with(CalcUnits::PERCENTAGE));
2932 assert!(CalcUnits::LENGTH.can_sum_with(CalcUnits::LENGTH_PERCENTAGE));
2933
2934 assert!(CalcUnits::PERCENTAGE.can_sum_with(CalcUnits::LENGTH));
2935 assert!(CalcUnits::PERCENTAGE.can_sum_with(CalcUnits::PERCENTAGE));
2936 assert!(CalcUnits::PERCENTAGE.can_sum_with(CalcUnits::LENGTH_PERCENTAGE));
2937
2938 assert!(CalcUnits::LENGTH_PERCENTAGE.can_sum_with(CalcUnits::LENGTH));
2939 assert!(CalcUnits::LENGTH_PERCENTAGE.can_sum_with(CalcUnits::PERCENTAGE));
2940 assert!(CalcUnits::LENGTH_PERCENTAGE.can_sum_with(CalcUnits::LENGTH_PERCENTAGE));
2941
2942 assert!(!CalcUnits::ANGLE.can_sum_with(CalcUnits::TIME));
2943 assert!(CalcUnits::ANGLE.can_sum_with(CalcUnits::ANGLE));
2944
2945 assert!(!(CalcUnits::ANGLE | CalcUnits::TIME).can_sum_with(CalcUnits::ANGLE));
2946 assert!(!CalcUnits::ANGLE.can_sum_with(CalcUnits::ANGLE | CalcUnits::TIME));
2947 assert!(
2948 !(CalcUnits::ANGLE | CalcUnits::TIME).can_sum_with(CalcUnits::ANGLE | CalcUnits::TIME)
2949 );
2950 }
2951}