style/values/animated/
color.rs

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//! Animated types for CSS colors.
6
7use crate::color::mix::ColorInterpolationMethod;
8use crate::color::AbsoluteColor;
9use crate::values::animated::{Animate, Procedure, ToAnimatedZero};
10use crate::values::computed::Percentage;
11use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
12use crate::values::generics::color::{ColorMixFlags, GenericColor, GenericColorMix};
13
14impl Animate for AbsoluteColor {
15    #[inline]
16    fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
17        let (left_weight, right_weight) = procedure.weights();
18        Ok(crate::color::mix::mix(
19            ColorInterpolationMethod::best_interpolation_between(self, other),
20            self,
21            left_weight as f32,
22            other,
23            right_weight as f32,
24            ColorMixFlags::empty(),
25        ))
26    }
27}
28
29impl ComputeSquaredDistance for AbsoluteColor {
30    #[inline]
31    fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
32        let start = [
33            self.alpha,
34            self.components.0 * self.alpha,
35            self.components.1 * self.alpha,
36            self.components.2 * self.alpha,
37        ];
38        let end = [
39            other.alpha,
40            other.components.0 * other.alpha,
41            other.components.1 * other.alpha,
42            other.components.2 * other.alpha,
43        ];
44        start
45            .iter()
46            .zip(&end)
47            .map(|(this, other)| this.compute_squared_distance(other))
48            .sum()
49    }
50}
51
52/// An animated value for `<color>`.
53pub type Color = GenericColor<Percentage>;
54
55/// An animated value for `<color-mix>`.
56pub type ColorMix = GenericColorMix<Color, Percentage>;
57
58impl Animate for Color {
59    #[inline]
60    fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
61        let (left_weight, right_weight) = procedure.weights();
62        Ok(Self::from_color_mix(ColorMix {
63            interpolation: ColorInterpolationMethod::srgb(),
64            left: self.clone(),
65            left_percentage: Percentage(left_weight as f32),
66            right: other.clone(),
67            right_percentage: Percentage(right_weight as f32),
68            // See https://github.com/w3c/csswg-drafts/issues/7324
69            flags: ColorMixFlags::empty(),
70        }))
71    }
72}
73
74impl ComputeSquaredDistance for Color {
75    #[inline]
76    fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
77        let current_color = AbsoluteColor::TRANSPARENT_BLACK;
78        self.resolve_to_absolute(&current_color)
79            .compute_squared_distance(&other.resolve_to_absolute(&current_color))
80    }
81}
82
83impl ToAnimatedZero for Color {
84    #[inline]
85    fn to_animated_zero(&self) -> Result<Self, ()> {
86        Ok(Color::Absolute(AbsoluteColor::TRANSPARENT_BLACK))
87    }
88}