From a9998e899b41f4a8495e1b2df1f01aeb6cc1d8d1 Mon Sep 17 00:00:00 2001 From: Tiaan Louw Date: Tue, 14 Feb 2023 15:13:10 +0000 Subject: [PATCH] style: Move AbsoluteColor to common color module Differential Revision: https://phabricator.services.mozilla.com/D169607 --- components/style/color/mod.rs | 283 +++++++++++++++++++++ components/style/values/animated/color.rs | 19 +- components/style/values/generics/color.rs | 10 +- components/style/values/specified/color.rs | 274 +------------------- 4 files changed, 299 insertions(+), 287 deletions(-) diff --git a/components/style/color/mod.rs b/components/style/color/mod.rs index 5a702fb8ff6..6f47299683e 100644 --- a/components/style/color/mod.rs +++ b/components/style/color/mod.rs @@ -7,6 +7,9 @@ /// cbindgen:ignore pub mod convert; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; + /// The 3 components that make up a color. (Does not include the alpha component) #[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] pub struct ColorComponents(pub f32, pub f32, pub f32); @@ -17,3 +20,283 @@ impl ColorComponents { Self(f(self.0), f(self.1), f(self.2)) } } + +/// A color space representation in the CSS specification. +/// +/// https://w3c.github.io/csswg-drafts/css-color-4/#color-type +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)] +#[repr(u8)] +pub enum ColorSpace { + /// A color specified in the Lab color format, e.g. + /// "lab(29.2345% 39.3825 20.0664)". + /// https://w3c.github.io/csswg-drafts/css-color-4/#lab-colors + Lab, + /// A color specified in the Lch color format, e.g. + /// "lch(29.2345% 44.2 27)". + /// https://w3c.github.io/csswg-drafts/css-color-4/#lch-colors + Lch, + /// A color specified in the Oklab color format, e.g. + /// "oklab(40.101% 0.1147 0.0453)". + /// https://w3c.github.io/csswg-drafts/css-color-4/#lab-colors + Oklab, + /// A color specified in the Oklch color format, e.g. + /// "oklch(40.101% 0.12332 21.555)". + /// https://w3c.github.io/csswg-drafts/css-color-4/#lch-colors + Oklch, + /// A color specified with the color(..) function and the "srgb" color + /// space, e.g. "color(srgb 0.691 0.139 0.259)". + Srgb, + /// A color specified with the color(..) function and the "srgb-linear" + /// color space, e.g. "color(srgb-linear 0.435 0.017 0.055)". + SrgbLinear, + /// A color specified with the color(..) function and the "display-p3" + /// color space, e.g. "color(display-p3 0.84 0.19 0.72)". + DisplayP3, + /// A color specified with the color(..) function and the "a98-rgb" color + /// space, e.g. "color(a98-rgb 0.44091 0.49971 0.37408)". + A98Rgb, + /// A color specified with the color(..) function and the "prophoto-rgb" + /// color space, e.g. "color(prophoto-rgb 0.36589 0.41717 0.31333)". + ProphotoRgb, + /// A color specified with the color(..) function and the "rec2020" color + /// space, e.g. "color(rec2020 0.42210 0.47580 0.35605)". + Rec2020, + /// A color specified with the color(..) function and the "xyz-d50" color + /// space, e.g. "color(xyz-d50 0.2005 0.14089 0.4472)". + XyzD50, + /// A color specified with the color(..) function and the "xyz-d65" or "xyz" + /// color space, e.g. "color(xyz-d65 0.21661 0.14602 0.59452)". + XyzD65, +} + +bitflags! { + /// Flags used when serializing colors. + #[derive(Default, MallocSizeOf, ToShmem)] + #[repr(C)] + pub struct SerializationFlags : u8 { + /// If set, serializes sRGB colors into `color(srgb ...)` instead of + /// `rgba(...)`. + const AS_COLOR_FUNCTION = 0x01; + } +} + +/// An absolutely specified color, using either rgb(), rgba(), lab(), lch(), +/// oklab(), oklch() or color(). +#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] +#[repr(C)] +pub struct AbsoluteColor { + /// The 3 components that make up colors in any color space. + pub components: ColorComponents, + /// The alpha component of the color. + pub alpha: f32, + /// The current color space that the components represent. + pub color_space: ColorSpace, + /// Extra flags used durring serialization of this color. + pub flags: SerializationFlags, +} + +macro_rules! color_components_as { + ($c:expr, $t:ty) => {{ + // This macro is not an inline function, because we can't use the + // generic type ($t) in a constant expression as per: + // https://github.com/rust-lang/rust/issues/76560 + const_assert_eq!(std::mem::size_of::<$t>(), std::mem::size_of::<[f32; 4]>()); + const_assert_eq!(std::mem::align_of::<$t>(), std::mem::align_of::<[f32; 4]>()); + const_assert!(std::mem::size_of::() >= std::mem::size_of::<$t>()); + const_assert_eq!( + std::mem::align_of::(), + std::mem::align_of::<$t>() + ); + + std::mem::transmute::<&ColorComponents, &$t>(&$c.components) + }}; +} + +impl AbsoluteColor { + /// Create a new [AbsoluteColor] with the given [ColorSpace] and components. + pub fn new(color_space: ColorSpace, components: ColorComponents, alpha: f32) -> Self { + Self { + components, + alpha, + color_space, + flags: SerializationFlags::empty(), + } + } + + /// Return the alpha component. + #[inline] + pub fn alpha(&self) -> f32 { + self.alpha + } + + /// Convert this color to the specified color space. + pub fn to_color_space(&self, color_space: ColorSpace) -> Self { + use ColorSpace::*; + + if self.color_space == color_space { + return self.clone(); + } + + let (xyz, white_point) = match self.color_space { + Lab => convert::to_xyz::(&self.components), + Lch => convert::to_xyz::(&self.components), + Oklab => convert::to_xyz::(&self.components), + Oklch => convert::to_xyz::(&self.components), + Srgb => convert::to_xyz::(&self.components), + SrgbLinear => convert::to_xyz::(&self.components), + DisplayP3 => convert::to_xyz::(&self.components), + A98Rgb => convert::to_xyz::(&self.components), + ProphotoRgb => convert::to_xyz::(&self.components), + Rec2020 => convert::to_xyz::(&self.components), + XyzD50 => convert::to_xyz::(&self.components), + XyzD65 => convert::to_xyz::(&self.components), + }; + + let result = match color_space { + Lab => convert::from_xyz::(&xyz, white_point), + Lch => convert::from_xyz::(&xyz, white_point), + Oklab => convert::from_xyz::(&xyz, white_point), + Oklch => convert::from_xyz::(&xyz, white_point), + Srgb => convert::from_xyz::(&xyz, white_point), + SrgbLinear => convert::from_xyz::(&xyz, white_point), + DisplayP3 => convert::from_xyz::(&xyz, white_point), + A98Rgb => convert::from_xyz::(&xyz, white_point), + ProphotoRgb => convert::from_xyz::(&xyz, white_point), + Rec2020 => convert::from_xyz::(&xyz, white_point), + XyzD50 => convert::from_xyz::(&xyz, white_point), + XyzD65 => convert::from_xyz::(&xyz, white_point), + }; + + Self::new(color_space, result, self.alpha) + } +} + +impl From for ColorSpace { + fn from(value: cssparser::PredefinedColorSpace) -> Self { + match value { + cssparser::PredefinedColorSpace::Srgb => ColorSpace::Srgb, + cssparser::PredefinedColorSpace::SrgbLinear => ColorSpace::SrgbLinear, + cssparser::PredefinedColorSpace::DisplayP3 => ColorSpace::DisplayP3, + cssparser::PredefinedColorSpace::A98Rgb => ColorSpace::A98Rgb, + cssparser::PredefinedColorSpace::ProphotoRgb => ColorSpace::ProphotoRgb, + cssparser::PredefinedColorSpace::Rec2020 => ColorSpace::Rec2020, + cssparser::PredefinedColorSpace::XyzD50 => ColorSpace::XyzD50, + cssparser::PredefinedColorSpace::XyzD65 => ColorSpace::XyzD65, + } + } +} + +impl From for AbsoluteColor { + fn from(f: cssparser::AbsoluteColor) -> Self { + match f { + cssparser::AbsoluteColor::Rgba(rgba) => Self::from_rgba(rgba), + + cssparser::AbsoluteColor::Lab(lab) => Self::new( + ColorSpace::Lab, + ColorComponents(lab.lightness, lab.a, lab.b), + lab.alpha, + ), + + cssparser::AbsoluteColor::Lch(lch) => Self::new( + ColorSpace::Lch, + ColorComponents(lch.lightness, lch.chroma, lch.hue), + lch.alpha, + ), + + cssparser::AbsoluteColor::Oklab(oklab) => Self::new( + ColorSpace::Oklab, + ColorComponents(oklab.lightness, oklab.a, oklab.b), + oklab.alpha, + ), + + cssparser::AbsoluteColor::Oklch(oklch) => Self::new( + ColorSpace::Oklch, + ColorComponents(oklch.lightness, oklch.chroma, oklch.hue), + oklch.alpha, + ), + + cssparser::AbsoluteColor::ColorFunction(c) => { + let mut result = AbsoluteColor::new( + c.color_space.into(), + ColorComponents(c.c1, c.c2, c.c3), + c.alpha, + ); + + if matches!(c.color_space, cssparser::PredefinedColorSpace::Srgb) { + result.flags |= SerializationFlags::AS_COLOR_FUNCTION; + } + + result + }, + } + } +} + +impl ToCss for AbsoluteColor { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + match self.color_space { + ColorSpace::Srgb if !self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION) => { + cssparser::ToCss::to_css( + &cssparser::RGBA::from_floats( + self.components.0, + self.components.1, + self.components.2, + self.alpha(), + ), + dest, + ) + }, + ColorSpace::Lab => cssparser::ToCss::to_css( + unsafe { color_components_as!(self, cssparser::Lab) }, + dest, + ), + ColorSpace::Lch => cssparser::ToCss::to_css( + unsafe { color_components_as!(self, cssparser::Lch) }, + dest, + ), + ColorSpace::Oklab => cssparser::ToCss::to_css( + unsafe { color_components_as!(self, cssparser::Oklab) }, + dest, + ), + ColorSpace::Oklch => cssparser::ToCss::to_css( + unsafe { color_components_as!(self, cssparser::Oklch) }, + dest, + ), + _ => { + let color_space = match self.color_space { + ColorSpace::Lab | ColorSpace::Lch | ColorSpace::Oklab | ColorSpace::Oklch => { + unreachable!("Handle these in the wrapping match case!!") + }, + ColorSpace::Srgb => { + debug_assert!( + self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION), + "The case without this flag should be handled in the wrapping match case!!" + ); + + cssparser::PredefinedColorSpace::Srgb + }, + ColorSpace::SrgbLinear => cssparser::PredefinedColorSpace::SrgbLinear, + ColorSpace::DisplayP3 => cssparser::PredefinedColorSpace::DisplayP3, + ColorSpace::A98Rgb => cssparser::PredefinedColorSpace::A98Rgb, + ColorSpace::ProphotoRgb => cssparser::PredefinedColorSpace::ProphotoRgb, + ColorSpace::Rec2020 => cssparser::PredefinedColorSpace::Rec2020, + ColorSpace::XyzD50 => cssparser::PredefinedColorSpace::XyzD50, + ColorSpace::XyzD65 => cssparser::PredefinedColorSpace::XyzD65, + }; + + let color_function = cssparser::ColorFunction { + color_space, + c1: self.components.0, + c2: self.components.1, + c3: self.components.2, + alpha: self.alpha, + }; + let color = cssparser::AbsoluteColor::ColorFunction(color_function); + cssparser::ToCss::to_css(&color, dest) + }, + } + } +} diff --git a/components/style/values/animated/color.rs b/components/style/values/animated/color.rs index efc940b92f6..843a042f092 100644 --- a/components/style/values/animated/color.rs +++ b/components/style/values/animated/color.rs @@ -8,7 +8,8 @@ use crate::values::animated::{Animate, Procedure, ToAnimatedZero}; use crate::values::computed::Percentage; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::generics::color::{ - ColorInterpolationMethod, ColorSpace, GenericColor, GenericColorMix, HueInterpolationMethod, + ColorInterpolationMethod, GenericColor, GenericColorMix, HueInterpolationMethod, + InterpolationColorSpace, }; use euclid::default::{Transform3D, Vector3D}; use std::f32::consts::PI; @@ -133,14 +134,14 @@ impl Color { } let mix_function = match interpolation.space { - ColorSpace::Srgb => Self::mix_in::, - ColorSpace::LinearSrgb => Self::mix_in::, - ColorSpace::Xyz => Self::mix_in::, - ColorSpace::XyzD50 => Self::mix_in::, - ColorSpace::Lab => Self::mix_in::, - ColorSpace::Hwb => Self::mix_in::, - ColorSpace::Hsl => Self::mix_in::, - ColorSpace::Lch => Self::mix_in::, + InterpolationColorSpace::Srgb => Self::mix_in::, + InterpolationColorSpace::LinearSrgb => Self::mix_in::, + InterpolationColorSpace::Xyz => Self::mix_in::, + InterpolationColorSpace::XyzD50 => Self::mix_in::, + InterpolationColorSpace::Lab => Self::mix_in::, + InterpolationColorSpace::Hwb => Self::mix_in::, + InterpolationColorSpace::Hsl => Self::mix_in::, + InterpolationColorSpace::Lch => Self::mix_in::, }; mix_function( left_color, diff --git a/components/style/values/generics/color.rs b/components/style/values/generics/color.rs index 439be95ca44..b4b7cbe8477 100644 --- a/components/style/values/generics/color.rs +++ b/components/style/values/generics/color.rs @@ -42,7 +42,7 @@ pub enum GenericColor { ToShmem, )] #[repr(u8)] -pub enum ColorSpace { +pub enum InterpolationColorSpace { /// The sRGB color space. Srgb, /// The linear-sRGB color space. @@ -63,7 +63,7 @@ pub enum ColorSpace { // TODO: Oklab, Lch } -impl ColorSpace { +impl InterpolationColorSpace { /// Returns whether this is a ``. pub fn is_polar(self) -> bool { match self { @@ -120,7 +120,7 @@ pub enum HueInterpolationMethod { #[repr(C)] pub struct ColorInterpolationMethod { /// The color-space the interpolation should be done in. - pub space: ColorSpace, + pub space: InterpolationColorSpace, /// The hue interpolation method. pub hue: HueInterpolationMethod, } @@ -129,7 +129,7 @@ impl ColorInterpolationMethod { /// Returns the srgb interpolation method. pub fn srgb() -> Self { Self { - space: ColorSpace::Srgb, + space: InterpolationColorSpace::Srgb, hue: HueInterpolationMethod::Shorter, } } @@ -141,7 +141,7 @@ impl Parse for ColorInterpolationMethod { input: &mut Parser<'i, 't>, ) -> Result> { input.expect_ident_matching("in")?; - let space = ColorSpace::parse(input)?; + let space = InterpolationColorSpace::parse(input)?; // https://drafts.csswg.org/css-color-4/#hue-interpolation // Unless otherwise specified, if no specific hue interpolation // algorithm is selected by the host syntax, the default is shorter. diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 725abbe5c88..f0ef6027184 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -5,7 +5,7 @@ //! Specified color values. use super::AllowQuirks; -use crate::color::ColorComponents; +use crate::color::{AbsoluteColor, ColorComponents, ColorSpace}; use crate::media_queries::Device; use crate::parser::{Parse, ParserContext}; use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue}; @@ -107,101 +107,7 @@ impl ColorMix { } } -/// A color space representation in the CSS specification. -/// -/// https://w3c.github.io/csswg-drafts/css-color-4/#color-type -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)] -#[repr(u8)] -pub enum ColorSpace { - /// A color specified in the Lab color format, e.g. - /// "lab(29.2345% 39.3825 20.0664)". - /// https://w3c.github.io/csswg-drafts/css-color-4/#lab-colors - Lab, - /// A color specified in the Lch color format, e.g. - /// "lch(29.2345% 44.2 27)". - /// https://w3c.github.io/csswg-drafts/css-color-4/#lch-colors - Lch, - /// A color specified in the Oklab color format, e.g. - /// "oklab(40.101% 0.1147 0.0453)". - /// https://w3c.github.io/csswg-drafts/css-color-4/#lab-colors - Oklab, - /// A color specified in the Oklch color format, e.g. - /// "oklch(40.101% 0.12332 21.555)". - /// https://w3c.github.io/csswg-drafts/css-color-4/#lch-colors - Oklch, - /// A color specified with the color(..) function and the "srgb" color - /// space, e.g. "color(srgb 0.691 0.139 0.259)". - Srgb, - /// A color specified with the color(..) function and the "srgb-linear" - /// color space, e.g. "color(srgb-linear 0.435 0.017 0.055)". - SrgbLinear, - /// A color specified with the color(..) function and the "display-p3" - /// color space, e.g. "color(display-p3 0.84 0.19 0.72)". - DisplayP3, - /// A color specified with the color(..) function and the "a98-rgb" color - /// space, e.g. "color(a98-rgb 0.44091 0.49971 0.37408)". - A98Rgb, - /// A color specified with the color(..) function and the "prophoto-rgb" - /// color space, e.g. "color(prophoto-rgb 0.36589 0.41717 0.31333)". - ProphotoRgb, - /// A color specified with the color(..) function and the "rec2020" color - /// space, e.g. "color(rec2020 0.42210 0.47580 0.35605)". - Rec2020, - /// A color specified with the color(..) function and the "xyz-d50" color - /// space, e.g. "color(xyz-d50 0.2005 0.14089 0.4472)". - XyzD50, - /// A color specified with the color(..) function and the "xyz-d65" or "xyz" - /// color space, e.g. "color(xyz-d65 0.21661 0.14602 0.59452)". - XyzD65, -} - -bitflags! { - #[derive(Default, MallocSizeOf, ToShmem)] - #[repr(C)] - struct SerializationFlags : u8 { - const AS_COLOR_FUNCTION = 0x01; - } -} - -/// An absolutely specified color, using either rgb(), rgba(), lab(), lch(), -/// oklab(), oklch() or color(). -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] -#[repr(C)] -pub struct AbsoluteColor { - components: ColorComponents, - alpha: f32, - color_space: ColorSpace, - flags: SerializationFlags, -} - -macro_rules! color_components_as { - ($c:expr, $t:ty) => {{ - // This macro is not an inline function, because we can't use the - // generic type ($t) in a constant expression as per: - // https://github.com/rust-lang/rust/issues/76560 - const_assert_eq!(std::mem::size_of::<$t>(), std::mem::size_of::<[f32; 4]>()); - const_assert_eq!(std::mem::align_of::<$t>(), std::mem::align_of::<[f32; 4]>()); - const_assert!(std::mem::size_of::() >= std::mem::size_of::<$t>()); - const_assert_eq!( - std::mem::align_of::(), - std::mem::align_of::<$t>() - ); - - std::mem::transmute::<&ColorComponents, &$t>(&$c.components) - }}; -} - impl AbsoluteColor { - /// Create a new [AbsoluteColor] with the given [ColorSpace] and components. - pub fn new(color_space: ColorSpace, components: ColorComponents, alpha: f32) -> Self { - Self { - components, - alpha, - color_space, - flags: SerializationFlags::empty(), - } - } - /// Convenience function to create a color in the sRGB color space. pub fn from_rgba(rgba: RGBA) -> Self { let red = rgba.red as f32 / 255.0; @@ -215,12 +121,6 @@ impl AbsoluteColor { ) } - /// Return the alpha component. - #[inline] - pub fn alpha(&self) -> f32 { - self.alpha - } - /// Convert the color to sRGB color space and return it in the RGBA struct. pub fn to_rgba(&self) -> RGBA { let rgba = self.to_color_space(ColorSpace::Srgb); @@ -231,178 +131,6 @@ impl AbsoluteColor { RGBA::new(red, green, blue, rgba.alpha) } - - /// Convert this color to the specified color space. - pub fn to_color_space(&self, color_space: ColorSpace) -> Self { - use crate::color::convert; - use ColorSpace::*; - - if self.color_space == color_space { - return self.clone(); - } - - let (xyz, white_point) = match self.color_space { - Lab => convert::to_xyz::(&self.components), - Lch => convert::to_xyz::(&self.components), - Oklab => convert::to_xyz::(&self.components), - Oklch => convert::to_xyz::(&self.components), - Srgb => convert::to_xyz::(&self.components), - SrgbLinear => convert::to_xyz::(&self.components), - DisplayP3 => convert::to_xyz::(&self.components), - A98Rgb => convert::to_xyz::(&self.components), - ProphotoRgb => convert::to_xyz::(&self.components), - Rec2020 => convert::to_xyz::(&self.components), - XyzD50 => convert::to_xyz::(&self.components), - XyzD65 => convert::to_xyz::(&self.components), - }; - - let result = match color_space { - Lab => convert::from_xyz::(&xyz, white_point), - Lch => convert::from_xyz::(&xyz, white_point), - Oklab => convert::from_xyz::(&xyz, white_point), - Oklch => convert::from_xyz::(&xyz, white_point), - Srgb => convert::from_xyz::(&xyz, white_point), - SrgbLinear => convert::from_xyz::(&xyz, white_point), - DisplayP3 => convert::from_xyz::(&xyz, white_point), - A98Rgb => convert::from_xyz::(&xyz, white_point), - ProphotoRgb => convert::from_xyz::(&xyz, white_point), - Rec2020 => convert::from_xyz::(&xyz, white_point), - XyzD50 => convert::from_xyz::(&xyz, white_point), - XyzD65 => convert::from_xyz::(&xyz, white_point), - }; - - Self::new(color_space, result, self.alpha) - } -} - -impl From for ColorSpace { - fn from(value: cssparser::PredefinedColorSpace) -> Self { - match value { - cssparser::PredefinedColorSpace::Srgb => ColorSpace::Srgb, - cssparser::PredefinedColorSpace::SrgbLinear => ColorSpace::SrgbLinear, - cssparser::PredefinedColorSpace::DisplayP3 => ColorSpace::DisplayP3, - cssparser::PredefinedColorSpace::A98Rgb => ColorSpace::A98Rgb, - cssparser::PredefinedColorSpace::ProphotoRgb => ColorSpace::ProphotoRgb, - cssparser::PredefinedColorSpace::Rec2020 => ColorSpace::Rec2020, - cssparser::PredefinedColorSpace::XyzD50 => ColorSpace::XyzD50, - cssparser::PredefinedColorSpace::XyzD65 => ColorSpace::XyzD65, - } - } -} - -impl From for AbsoluteColor { - fn from(f: cssparser::AbsoluteColor) -> Self { - match f { - cssparser::AbsoluteColor::Rgba(rgba) => Self::from_rgba(rgba), - - cssparser::AbsoluteColor::Lab(lab) => Self::new( - ColorSpace::Lab, - ColorComponents(lab.lightness, lab.a, lab.b), - lab.alpha, - ), - - cssparser::AbsoluteColor::Lch(lch) => Self::new( - ColorSpace::Lch, - ColorComponents(lch.lightness, lch.chroma, lch.hue), - lch.alpha, - ), - - cssparser::AbsoluteColor::Oklab(oklab) => Self::new( - ColorSpace::Oklab, - ColorComponents(oklab.lightness, oklab.a, oklab.b), - oklab.alpha, - ), - - cssparser::AbsoluteColor::Oklch(oklch) => Self::new( - ColorSpace::Oklch, - ColorComponents(oklch.lightness, oklch.chroma, oklch.hue), - oklch.alpha, - ), - - cssparser::AbsoluteColor::ColorFunction(c) => { - let mut result = AbsoluteColor::new( - c.color_space.into(), - ColorComponents(c.c1, c.c2, c.c3), - c.alpha, - ); - - if matches!(c.color_space, cssparser::PredefinedColorSpace::Srgb) { - result.flags |= SerializationFlags::AS_COLOR_FUNCTION; - } - - result - }, - } - } -} - -impl ToCss for AbsoluteColor { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - match self.color_space { - ColorSpace::Srgb if !self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION) => { - cssparser::ToCss::to_css( - &cssparser::RGBA::from_floats( - self.components.0, - self.components.1, - self.components.2, - self.alpha(), - ), - dest, - ) - }, - ColorSpace::Lab => cssparser::ToCss::to_css( - unsafe { color_components_as!(self, cssparser::Lab) }, - dest, - ), - ColorSpace::Lch => cssparser::ToCss::to_css( - unsafe { color_components_as!(self, cssparser::Lch) }, - dest, - ), - ColorSpace::Oklab => cssparser::ToCss::to_css( - unsafe { color_components_as!(self, cssparser::Oklab) }, - dest, - ), - ColorSpace::Oklch => cssparser::ToCss::to_css( - unsafe { color_components_as!(self, cssparser::Oklch) }, - dest, - ), - _ => { - let color_space = match self.color_space { - ColorSpace::Lab | ColorSpace::Lch | ColorSpace::Oklab | ColorSpace::Oklch => { - unreachable!("Handle these in the wrapping match case!!") - }, - ColorSpace::Srgb => { - debug_assert!( - self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION), - "The case without this flag should be handled in the wrapping match case!!" - ); - - cssparser::PredefinedColorSpace::Srgb - }, - ColorSpace::SrgbLinear => cssparser::PredefinedColorSpace::SrgbLinear, - ColorSpace::DisplayP3 => cssparser::PredefinedColorSpace::DisplayP3, - ColorSpace::A98Rgb => cssparser::PredefinedColorSpace::A98Rgb, - ColorSpace::ProphotoRgb => cssparser::PredefinedColorSpace::ProphotoRgb, - ColorSpace::Rec2020 => cssparser::PredefinedColorSpace::Rec2020, - ColorSpace::XyzD50 => cssparser::PredefinedColorSpace::XyzD50, - ColorSpace::XyzD65 => cssparser::PredefinedColorSpace::XyzD65, - }; - - let color_function = cssparser::ColorFunction { - color_space, - c1: self.components.0, - c2: self.components.1, - c3: self.components.2, - alpha: self.alpha, - }; - let color = cssparser::AbsoluteColor::ColorFunction(color_function); - cssparser::ToCss::to_css(&color, dest) - }, - } - } } /// Container holding an absolute color and the text specified by an author.