tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lists.rs (4682B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 //! Lists have various ways of being animated, this module implements them.
      6 //!
      7 //! See https://drafts.csswg.org/web-animations-1/#animating-properties
      8 
      9 /// https://drafts.csswg.org/web-animations-1/#by-computed-value
     10 pub mod by_computed_value {
     11    use crate::values::{
     12        animated::{Animate, Procedure},
     13        distance::{ComputeSquaredDistance, SquaredDistance},
     14    };
     15    use std::iter::FromIterator;
     16 
     17    #[allow(missing_docs)]
     18    pub fn animate<T, C>(left: &[T], right: &[T], procedure: Procedure) -> Result<C, ()>
     19    where
     20        T: Animate,
     21        C: FromIterator<T>,
     22    {
     23        if left.len() != right.len() {
     24            return Err(());
     25        }
     26        left.iter()
     27            .zip(right.iter())
     28            .map(|(left, right)| left.animate(right, procedure))
     29            .collect()
     30    }
     31 
     32    #[allow(missing_docs)]
     33    pub fn squared_distance<T>(left: &[T], right: &[T]) -> Result<SquaredDistance, ()>
     34    where
     35        T: ComputeSquaredDistance,
     36    {
     37        if left.len() != right.len() {
     38            return Err(());
     39        }
     40        left.iter()
     41            .zip(right.iter())
     42            .map(|(left, right)| left.compute_squared_distance(right))
     43            .sum()
     44    }
     45 }
     46 
     47 /// This is the animation used for some of the types like shadows and filters, where the
     48 /// interpolation happens with the zero value if one of the sides is not present.
     49 ///
     50 /// https://drafts.csswg.org/web-animations-1/#animating-shadow-lists
     51 pub mod with_zero {
     52    use crate::values::animated::ToAnimatedZero;
     53    use crate::values::{
     54        animated::{Animate, Procedure},
     55        distance::{ComputeSquaredDistance, SquaredDistance},
     56    };
     57    use itertools::{EitherOrBoth, Itertools};
     58    use std::iter::FromIterator;
     59 
     60    #[allow(missing_docs)]
     61    pub fn animate<T, C>(left: &[T], right: &[T], procedure: Procedure) -> Result<C, ()>
     62    where
     63        T: Animate + Clone + ToAnimatedZero,
     64        C: FromIterator<T>,
     65    {
     66        if procedure == Procedure::Add {
     67            return Ok(left.iter().chain(right.iter()).cloned().collect());
     68        }
     69        left.iter()
     70            .zip_longest(right.iter())
     71            .map(|it| match it {
     72                EitherOrBoth::Both(left, right) => left.animate(right, procedure),
     73                EitherOrBoth::Left(left) => left.animate(&left.to_animated_zero()?, procedure),
     74                EitherOrBoth::Right(right) => right.to_animated_zero()?.animate(right, procedure),
     75            })
     76            .collect()
     77    }
     78 
     79    #[allow(missing_docs)]
     80    pub fn squared_distance<T>(left: &[T], right: &[T]) -> Result<SquaredDistance, ()>
     81    where
     82        T: ToAnimatedZero + ComputeSquaredDistance,
     83    {
     84        left.iter()
     85            .zip_longest(right.iter())
     86            .map(|it| match it {
     87                EitherOrBoth::Both(left, right) => left.compute_squared_distance(right),
     88                EitherOrBoth::Left(item) | EitherOrBoth::Right(item) => {
     89                    item.to_animated_zero()?.compute_squared_distance(item)
     90                },
     91            })
     92            .sum()
     93    }
     94 }
     95 
     96 /// https://drafts.csswg.org/web-animations-1/#repeatable-list
     97 pub mod repeatable_list {
     98    use crate::values::{
     99        animated::{Animate, Procedure},
    100        distance::{ComputeSquaredDistance, SquaredDistance},
    101    };
    102    use std::iter::FromIterator;
    103 
    104    #[allow(missing_docs)]
    105    pub fn animate<T, C>(left: &[T], right: &[T], procedure: Procedure) -> Result<C, ()>
    106    where
    107        T: Animate,
    108        C: FromIterator<T>,
    109    {
    110        use num_integer::lcm;
    111        // If the length of either list is zero, the least common multiple is undefined.
    112        if left.is_empty() || right.is_empty() {
    113            return Err(());
    114        }
    115        let len = lcm(left.len(), right.len());
    116        left.iter()
    117            .cycle()
    118            .zip(right.iter().cycle())
    119            .take(len)
    120            .map(|(left, right)| left.animate(right, procedure))
    121            .collect()
    122    }
    123 
    124    #[allow(missing_docs)]
    125    pub fn squared_distance<T>(left: &[T], right: &[T]) -> Result<SquaredDistance, ()>
    126    where
    127        T: ComputeSquaredDistance,
    128    {
    129        use num_integer::lcm;
    130        if left.is_empty() || right.is_empty() {
    131            return Err(());
    132        }
    133        let len = lcm(left.len(), right.len());
    134        left.iter()
    135            .cycle()
    136            .zip(right.iter().cycle())
    137            .take(len)
    138            .map(|(left, right)| left.compute_squared_distance(right))
    139            .sum()
    140    }
    141 }