style/values/computed/
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//! Computed color values.
6
7use crate::color::AbsoluteColor;
8use crate::values::animated::ToAnimatedZero;
9use crate::values::computed::percentage::Percentage;
10use crate::values::generics::color::{
11    GenericCaretColor, GenericColor, GenericColorMix, GenericColorOrAuto,
12};
13use std::fmt::{self, Write};
14use style_traits::{CssWriter, ToCss};
15
16pub use crate::values::specified::color::{ColorScheme, ForcedColorAdjust, PrintColorAdjust};
17
18/// The computed value of the `color` property.
19pub type ColorPropertyValue = AbsoluteColor;
20
21/// A computed value for `<color>`.
22pub type Color = GenericColor<Percentage>;
23
24/// A computed color-mix().
25pub type ColorMix = GenericColorMix<Color, Percentage>;
26
27impl ToCss for Color {
28    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
29    where
30        W: fmt::Write,
31    {
32        match *self {
33            Self::Absolute(ref c) => c.to_css(dest),
34            Self::ColorFunction(ref color_function) => color_function.to_css(dest),
35            Self::CurrentColor => dest.write_str("currentcolor"),
36            Self::ColorMix(ref m) => m.to_css(dest),
37        }
38    }
39}
40
41impl Color {
42    /// A fully transparent color.
43    pub const TRANSPARENT_BLACK: Self = Self::Absolute(AbsoluteColor::TRANSPARENT_BLACK);
44
45    /// An opaque black color.
46    pub const BLACK: Self = Self::Absolute(AbsoluteColor::BLACK);
47
48    /// An opaque white color.
49    pub const WHITE: Self = Self::Absolute(AbsoluteColor::WHITE);
50
51    /// Create a new computed [`Color`] from a given color-mix, simplifying it to an absolute color
52    /// if possible.
53    pub fn from_color_mix(color_mix: ColorMix) -> Self {
54        if let Some(absolute) = color_mix.mix_to_absolute() {
55            Self::Absolute(absolute)
56        } else {
57            Self::ColorMix(Box::new(color_mix))
58        }
59    }
60
61    /// Combine this complex color with the given foreground color into an
62    /// absolute color.
63    pub fn resolve_to_absolute(&self, current_color: &AbsoluteColor) -> AbsoluteColor {
64        use crate::values::specified::percentage::ToPercentage;
65
66        match *self {
67            Self::Absolute(c) => c,
68            Self::ColorFunction(ref color_function) => {
69                color_function.resolve_to_absolute(current_color)
70            },
71            Self::CurrentColor => *current_color,
72            Self::ColorMix(ref mix) => {
73                let left = mix.left.resolve_to_absolute(current_color);
74                let right = mix.right.resolve_to_absolute(current_color);
75                crate::color::mix::mix(
76                    mix.interpolation,
77                    &left,
78                    mix.left_percentage.to_percentage(),
79                    &right,
80                    mix.right_percentage.to_percentage(),
81                    mix.flags,
82                )
83            },
84        }
85    }
86}
87
88impl ToAnimatedZero for AbsoluteColor {
89    fn to_animated_zero(&self) -> Result<Self, ()> {
90        Ok(Self::TRANSPARENT_BLACK)
91    }
92}
93
94/// auto | <color>
95pub type ColorOrAuto = GenericColorOrAuto<Color>;
96
97/// caret-color
98pub type CaretColor = GenericCaretColor<Color>;