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