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/animated/lists.rs | 141 ++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 servo/components/style/values/animated/lists.rs (limited to 'servo/components/style/values/animated/lists.rs') diff --git a/servo/components/style/values/animated/lists.rs b/servo/components/style/values/animated/lists.rs new file mode 100644 index 0000000000..8b3898c497 --- /dev/null +++ b/servo/components/style/values/animated/lists.rs @@ -0,0 +1,141 @@ +/* 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/. */ + +//! Lists have various ways of being animated, this module implements them. +//! +//! See https://drafts.csswg.org/web-animations-1/#animating-properties + +/// https://drafts.csswg.org/web-animations-1/#by-computed-value +pub mod by_computed_value { + use crate::values::{ + animated::{Animate, Procedure}, + distance::{ComputeSquaredDistance, SquaredDistance}, + }; + use std::iter::FromIterator; + + #[allow(missing_docs)] + pub fn animate(left: &[T], right: &[T], procedure: Procedure) -> Result + where + T: Animate, + C: FromIterator, + { + if left.len() != right.len() { + return Err(()); + } + left.iter() + .zip(right.iter()) + .map(|(left, right)| left.animate(right, procedure)) + .collect() + } + + #[allow(missing_docs)] + pub fn squared_distance(left: &[T], right: &[T]) -> Result + where + T: ComputeSquaredDistance, + { + if left.len() != right.len() { + return Err(()); + } + left.iter() + .zip(right.iter()) + .map(|(left, right)| left.compute_squared_distance(right)) + .sum() + } +} + +/// This is the animation used for some of the types like shadows and filters, where the +/// interpolation happens with the zero value if one of the sides is not present. +/// +/// https://drafts.csswg.org/web-animations-1/#animating-shadow-lists +pub mod with_zero { + use crate::values::animated::ToAnimatedZero; + use crate::values::{ + animated::{Animate, Procedure}, + distance::{ComputeSquaredDistance, SquaredDistance}, + }; + use itertools::{EitherOrBoth, Itertools}; + use std::iter::FromIterator; + + #[allow(missing_docs)] + pub fn animate(left: &[T], right: &[T], procedure: Procedure) -> Result + where + T: Animate + Clone + ToAnimatedZero, + C: FromIterator, + { + if procedure == Procedure::Add { + return Ok(left.iter().chain(right.iter()).cloned().collect()); + } + left.iter() + .zip_longest(right.iter()) + .map(|it| match it { + EitherOrBoth::Both(left, right) => left.animate(right, procedure), + EitherOrBoth::Left(left) => left.animate(&left.to_animated_zero()?, procedure), + EitherOrBoth::Right(right) => right.to_animated_zero()?.animate(right, procedure), + }) + .collect() + } + + #[allow(missing_docs)] + pub fn squared_distance(left: &[T], right: &[T]) -> Result + where + T: ToAnimatedZero + ComputeSquaredDistance, + { + left.iter() + .zip_longest(right.iter()) + .map(|it| match it { + EitherOrBoth::Both(left, right) => left.compute_squared_distance(right), + EitherOrBoth::Left(item) | EitherOrBoth::Right(item) => { + item.to_animated_zero()?.compute_squared_distance(item) + }, + }) + .sum() + } +} + +/// https://drafts.csswg.org/web-animations-1/#repeatable-list +pub mod repeatable_list { + use crate::values::{ + animated::{Animate, Procedure}, + distance::{ComputeSquaredDistance, SquaredDistance}, + }; + use std::iter::FromIterator; + + #[allow(missing_docs)] + pub fn animate(left: &[T], right: &[T], procedure: Procedure) -> Result + where + T: Animate, + C: FromIterator, + { + use num_integer::lcm; + // If the length of either list is zero, the least common multiple is undefined. + if left.is_empty() || right.is_empty() { + return Err(()); + } + let len = lcm(left.len(), right.len()); + left.iter() + .cycle() + .zip(right.iter().cycle()) + .take(len) + .map(|(left, right)| left.animate(right, procedure)) + .collect() + } + + #[allow(missing_docs)] + pub fn squared_distance(left: &[T], right: &[T]) -> Result + where + T: ComputeSquaredDistance, + { + use num_integer::lcm; + if left.is_empty() || right.is_empty() { + return Err(()); + } + let len = lcm(left.len(), right.len()); + left.iter() + .cycle() + .zip(right.iter().cycle()) + .take(len) + .map(|(left, right)| left.compute_squared_distance(right)) + .sum() + } +} -- cgit v1.2.3