From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- servo/components/style/values/computed/ratio.rs | 115 ++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 servo/components/style/values/computed/ratio.rs (limited to 'servo/components/style/values/computed/ratio.rs') diff --git a/servo/components/style/values/computed/ratio.rs b/servo/components/style/values/computed/ratio.rs new file mode 100644 index 0000000000..ae8997cfc0 --- /dev/null +++ b/servo/components/style/values/computed/ratio.rs @@ -0,0 +1,115 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! `` computed values. + +use crate::values::animated::{Animate, Procedure}; +use crate::values::computed::NonNegativeNumber; +use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; +use crate::values::generics::ratio::Ratio as GenericRatio; +use crate::{One, Zero}; +use std::cmp::{Ordering, PartialOrd}; + +/// A computed value. +pub type Ratio = GenericRatio; + +impl PartialOrd for Ratio { + fn partial_cmp(&self, other: &Self) -> Option { + f64::partial_cmp( + &((self.0).0 as f64 * (other.1).0 as f64), + &((self.1).0 as f64 * (other.0).0 as f64), + ) + } +} + +/// https://drafts.csswg.org/css-values/#combine-ratio +impl Animate for Ratio { + fn animate(&self, other: &Self, procedure: Procedure) -> Result { + // If either is degenerate, the values cannot be interpolated. + if self.is_degenerate() || other.is_degenerate() { + return Err(()); + } + + // Addition of s is not possible, and based on + // https://drafts.csswg.org/css-values-4/#not-additive, + // we simply use the first value as the result value. + // Besides, the procedure for accumulation should be identical to addition here. + if matches!(procedure, Procedure::Add | Procedure::Accumulate { .. }) { + return Ok(self.clone()); + } + + // The interpolation of a is defined by converting each to a number by + // dividing the first value by the second (so a ratio of 3 / 2 would become 1.5), taking + // the logarithm of that result (so the 1.5 would become approximately 0.176), then + // interpolating those values. + // + // The result during the interpolation is converted back to a by inverting the + // logarithm, then interpreting the result as a with the result as the first value + // and 1 as the second value. + let start = self.to_f32().ln(); + let end = other.to_f32().ln(); + let e = std::f32::consts::E; + let result = e.powf(start.animate(&end, procedure)?); + // The range of the result is [0, inf), based on the easing function. + if result.is_zero() || result.is_infinite() { + return Err(()); + } + Ok(Ratio::new(result, 1.0f32)) + } +} + +impl ComputeSquaredDistance for Ratio { + fn compute_squared_distance(&self, other: &Self) -> Result { + if self.is_degenerate() || other.is_degenerate() { + return Err(()); + } + // Use the distance of their logarithm values. (This is used by testing, so don't need to + // care about the base. Here we use the same base as that in animate().) + self.to_f32() + .ln() + .compute_squared_distance(&other.to_f32().ln()) + } +} + +impl Zero for Ratio { + fn zero() -> Self { + Self::new(Zero::zero(), One::one()) + } + + fn is_zero(&self) -> bool { + self.0.is_zero() + } +} + +impl Ratio { + /// Returns a new Ratio. + #[inline] + pub fn new(a: f32, b: f32) -> Self { + GenericRatio(a.into(), b.into()) + } + + /// Returns the used value. A ratio of 0/0 behaves as the ratio 1/0. + /// https://drafts.csswg.org/css-values-4/#ratios + pub fn used_value(self) -> Self { + if self.0.is_zero() && self.1.is_zero() { + Ratio::new(One::one(), Zero::zero()) + } else { + self + } + } + + /// Returns true if this is a degenerate ratio. + /// https://drafts.csswg.org/css-values/#degenerate-ratio + #[inline] + pub fn is_degenerate(&self) -> bool { + self.0.is_zero() || self.1.is_zero() + } + + /// Returns the f32 value by dividing the first value by the second one. + #[inline] + fn to_f32(&self) -> f32 { + debug_assert!(!self.is_degenerate()); + (self.0).0 / (self.1).0 + } +} -- cgit v1.2.3