Bug 1465307 - P3: Extract {animated,computed}::Color common parts. r=xidorn
authorDan Glastonbury <dan.glastonbury@gmail.com>
Tue, 05 Jun 2018 11:49:51 +1000
changeset 421717 85784a996d8bba9332f523544ef27bd19fb16a9a
parent 421716 31c82145a8e705b626438523f62c18e9c74fce55
child 421718 b34fa444062517697f98d9152c27ffd06ddf8708
push id104092
push userccoroiu@mozilla.com
push dateThu, 07 Jun 2018 10:01:21 +0000
treeherdermozilla-inbound@f6d91bbd77c6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs1465307
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1465307 - P3: Extract {animated,computed}::Color common parts. r=xidorn Extract the common parts of `animated::Color` and `computed::Color` out into `generics::color::Color<T>` that is generic over the type of RGBA color. MozReview-Commit-ID: EymSr7aqnAP
servo/components/style/gecko_bindings/sugar/style_complex_color.rs
servo/components/style/values/animated/color.rs
servo/components/style/values/computed/color.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/generics/color.rs
servo/components/style/values/generics/mod.rs
servo/components/style/values/specified/color.rs
--- a/servo/components/style/gecko_bindings/sugar/style_complex_color.rs
+++ b/servo/components/style/gecko_bindings/sugar/style_complex_color.rs
@@ -4,18 +4,18 @@
 
 //! Rust helpers to interact with Gecko's StyleComplexColor.
 
 use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
 use gecko_bindings::structs::StyleComplexColor;
 use gecko_bindings::structs::StyleComplexColor_Tag as Tag;
 use values::{Auto, Either};
 use values::computed::{Color as ComputedColor, RGBAColor as ComputedRGBA};
-use values::computed::ComplexColorRatios;
 use values::computed::ui::ColorOrAuto;
+use values::generics::color::{Color as GenericColor, ComplexColorRatios};
 
 impl StyleComplexColor {
     /// Create a `StyleComplexColor` value that represents `currentColor`.
     pub fn current_color() -> Self {
         StyleComplexColor {
             mColor: 0,
             mBgRatio: 0.,
             mFgRatio: 1.,
@@ -43,19 +43,19 @@ impl From<ComputedRGBA> for StyleComplex
             mTag: Tag::eNumeric,
         }
     }
 }
 
 impl From<ComputedColor> for StyleComplexColor {
     fn from(other: ComputedColor) -> Self {
         match other {
-            ComputedColor::Numeric(color) => color.into(),
-            ComputedColor::Foreground => Self::current_color(),
-            ComputedColor::Complex(color, ratios) => {
+            GenericColor::Numeric(color) => color.into(),
+            GenericColor::Foreground => Self::current_color(),
+            GenericColor::Complex(color, ratios) => {
                 debug_assert!(ratios != ComplexColorRatios::NUMERIC);
                 debug_assert!(ratios != ComplexColorRatios::FOREGROUND);
                 StyleComplexColor {
                     mColor: convert_rgba_to_nscolor(&color).into(),
                     mBgRatio: ratios.bg,
                     mFgRatio: ratios.fg,
                     mTag: Tag::eComplex,
                 }
@@ -64,26 +64,26 @@ impl From<ComputedColor> for StyleComple
     }
 }
 
 impl From<StyleComplexColor> for ComputedColor {
     fn from(other: StyleComplexColor) -> Self {
         match other.mTag {
             Tag::eNumeric => {
                 debug_assert!(other.mBgRatio == 1. && other.mFgRatio == 0.);
-                ComputedColor::Numeric(convert_nscolor_to_rgba(other.mColor))
+                GenericColor::Numeric(convert_nscolor_to_rgba(other.mColor))
             }
             Tag::eForeground => {
                 debug_assert!(other.mBgRatio == 0. && other.mFgRatio == 1.);
-                ComputedColor::Foreground
+                GenericColor::Foreground
             }
             Tag::eComplex => {
                 debug_assert!(other.mBgRatio != 1. || other.mFgRatio != 0.);
                 debug_assert!(other.mBgRatio != 0. || other.mFgRatio != 1.);
-                ComputedColor::Complex(
+                GenericColor::Complex(
                     convert_nscolor_to_rgba(other.mColor),
                     ComplexColorRatios {
                         bg: other.mBgRatio,
                         fg: other.mFgRatio,
                     },
                 )
             }
             Tag::eAuto => unreachable!("Unsupport StyleComplexColor with tag eAuto"),
--- a/servo/components/style/values/animated/color.rs
+++ b/servo/components/style/values/animated/color.rs
@@ -1,17 +1,17 @@
 /* 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 http://mozilla.org/MPL/2.0/. */
 
 //! Animated types for CSS colors.
 
 use values::animated::{Animate, Procedure, ToAnimatedZero};
 use values::distance::{ComputeSquaredDistance, SquaredDistance};
-use values::computed::ComplexColorRatios;
+use values::generics::color::{Color as GenericColor, ComplexColorRatios};
 
 /// An animated RGBA color.
 ///
 /// Unlike in computed values, each component value may exceed the
 /// range `[0.0, 1.0]`.
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 #[derive(Clone, Copy, Debug, PartialEq, ToAnimatedZero)]
 pub struct RGBA {
@@ -97,89 +97,72 @@ impl Animate for ComplexColorRatios {
     fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
         let bg = self.bg.animate(&other.bg, procedure)?;
         let fg = self.fg.animate(&other.fg, procedure)?;
 
         Ok(ComplexColorRatios { bg, fg })
     }
 }
 
-#[allow(missing_docs)]
-#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum Color {
-    Numeric(RGBA),
-    Foreground,
-    Complex(RGBA, ComplexColorRatios),
-}
+/// An animated value for `<color>`.
+pub type Color = GenericColor<RGBA>;
 
 impl Color {
-    fn currentcolor() -> Self {
-        Color::Foreground
-    }
-
-    /// Returns a transparent intermediate color.
-    pub fn transparent() -> Self {
-        Color::Numeric(RGBA::transparent())
-    }
-
     fn effective_intermediate_rgba(&self) -> RGBA {
         match *self {
-            Color::Numeric(color) => color,
-            Color::Foreground => RGBA::transparent(),
-            Color::Complex(color, ratios) => RGBA {
+            GenericColor::Numeric(color) => color,
+            GenericColor::Foreground => RGBA::transparent(),
+            GenericColor::Complex(color, ratios) => RGBA {
                 alpha: color.alpha * ratios.bg,
                 ..color.clone()
             },
         }
     }
 
     fn effective_ratios(&self) -> ComplexColorRatios {
         match *self {
-            Color::Numeric(..) => ComplexColorRatios::NUMERIC,
-            Color::Foreground => ComplexColorRatios::FOREGROUND,
-            Color::Complex(.., ratios) => ratios,
+            GenericColor::Numeric(..) => ComplexColorRatios::NUMERIC,
+            GenericColor::Foreground => ComplexColorRatios::FOREGROUND,
+            GenericColor::Complex(.., ratios) => ratios,
         }
     }
 }
 
 impl Animate for Color {
     #[inline]
     fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
+        use self::GenericColor::*;
+
         // Common cases are interpolating between two numeric colors,
         // two currentcolors, and a numeric color and a currentcolor.
         let (this_weight, other_weight) = procedure.weights();
 
         Ok(match (*self, *other, procedure) {
             // Any interpolation of currentColor with currentColor returns currentColor.
-            (Color::Foreground, Color::Foreground, Procedure::Interpolate { .. }) => {
-                Color::currentcolor()
-            }
+            (Foreground, Foreground, Procedure::Interpolate { .. }) => Color::currentcolor(),
             // Animating two numeric colors.
-            (Color::Numeric(c1), Color::Numeric(c2), _) => {
-                Color::Numeric(c1.animate(&c2, procedure)?)
-            }
+            (Numeric(c1), Numeric(c2), _) => Numeric(c1.animate(&c2, procedure)?),
             // Combinations of numeric color and currentColor
-            (Color::Foreground, Color::Numeric(color), _) => Color::Complex(
+            (Foreground, Numeric(color), _) => Self::with_ratios(
                 color,
                 ComplexColorRatios {
                     bg: other_weight as f32,
                     fg: this_weight as f32,
                 },
             ),
-            (Color::Numeric(color), Color::Foreground, _) => Color::Complex(
+            (Numeric(color), Foreground, _) => Self::with_ratios(
                 color,
                 ComplexColorRatios {
                     bg: this_weight as f32,
                     fg: other_weight as f32,
                 },
             ),
 
-            // Any other animation of currentColor with currentColor is complex.
-            (Color::Foreground, Color::Foreground, _) => Color::Complex(
+            // Any other animation of currentColor with currentColor.
+            (Foreground, Foreground, _) => Self::with_ratios(
                 RGBA::transparent(),
                 ComplexColorRatios {
                     bg: 0.,
                     fg: (this_weight + other_weight) as f32,
                 },
             ),
 
             // Defer to complex calculations
@@ -192,37 +175,32 @@ impl Animate for Color {
                 // Then we compute the final background ratio, and derive
                 // the final alpha value from the effective alpha value.
                 let self_ratios = self.effective_ratios();
                 let other_ratios = other.effective_ratios();
                 let ratios = self_ratios.animate(&other_ratios, procedure)?;
                 let alpha = color.alpha / ratios.bg;
                 let color = RGBA { alpha, ..color };
 
-                if ratios == ComplexColorRatios::NUMERIC {
-                    Color::Numeric(color)
-                } else if ratios == ComplexColorRatios::FOREGROUND {
-                    Color::Foreground
-                } else {
-                    Color::Complex(color, ratios)
-                }
+                Self::with_ratios(color, ratios)
             }
         })
     }
 }
 
 impl ComputeSquaredDistance for Color {
     #[inline]
     fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+        use self::GenericColor::*;
+
         // All comments from the Animate impl also applies here.
         Ok(match (*self, *other) {
-            (Color::Foreground, Color::Foreground) => SquaredDistance::from_sqrt(0.),
-            (Color::Numeric(c1), Color::Numeric(c2)) => c1.compute_squared_distance(&c2)?,
-            (Color::Foreground, Color::Numeric(color))
-            | (Color::Numeric(color), Color::Foreground) => {
+            (Foreground, Foreground) => SquaredDistance::from_sqrt(0.),
+            (Numeric(c1), Numeric(c2)) => c1.compute_squared_distance(&c2)?,
+            (Foreground, Numeric(color)) | (Numeric(color), Foreground) => {
                 // `computed_squared_distance` is symmetic.
                 color.compute_squared_distance(&RGBA::transparent())?
                     + SquaredDistance::from_sqrt(1.)
             }
             (_, _) => {
                 let self_color = self.effective_intermediate_rgba();
                 let other_color = other.effective_intermediate_rgba();
                 let self_ratios = self.effective_ratios();
--- a/servo/components/style/values/computed/color.rs
+++ b/servo/components/style/values/computed/color.rs
@@ -3,91 +3,43 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Computed color values.
 
 use cssparser::{Color as CSSParserColor, RGBA};
 use std::fmt;
 use style_traits::{CssWriter, ToCss};
 use values::animated::ToAnimatedValue;
-use values::animated::color::{Color as AnimatedColor, RGBA as AnimatedRGBA};
-
-/// Ratios representing the contribution of color and currentcolor to
-/// the final color value.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
-pub struct ComplexColorRatios {
-    /// Numeric color contribution.
-    pub bg: f32,
-    /// Foreground color, aka currentcolor, contribution.
-    pub fg: f32,
-}
-
-impl ComplexColorRatios {
-    /// Ratios representing pure numeric color.
-    pub const NUMERIC: ComplexColorRatios = ComplexColorRatios { bg: 1., fg: 0. };
-    /// Ratios representing pure foreground color.
-    pub const FOREGROUND: ComplexColorRatios = ComplexColorRatios { bg: 0., fg: 1. };
-}
-
-/// This enum represents a combined color from a numeric color and
-/// the current foreground color (currentColor keyword).
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
-pub enum Color {
-    ///  Numeric RGBA color.
-    Numeric(RGBA),
-
-    /// The current foreground color.
-    Foreground,
-
-    /// A linear combination of numeric color and currentColor.
-    /// The formula is: `color * bg_ratio + currentColor * fg_ratio`.
-    Complex(RGBA, ComplexColorRatios),
-}
+use values::animated::color::RGBA as AnimatedRGBA;
+use values::generics::color::Color as GenericColor;
 
 /// Computed value type for the specified RGBAColor.
 pub type RGBAColor = RGBA;
 
 /// The computed value of the `color` property.
 pub type ColorPropertyValue = RGBA;
 
+/// A computed value for `<color>`.
+pub type Color = GenericColor<RGBAColor>;
+
 impl Color {
-    /// Returns a numeric color representing the given RGBA value.
-    pub fn rgba(color: RGBA) -> Color {
-        Color::Numeric(color)
-    }
-
     /// Returns a complex color value representing transparent.
     pub fn transparent() -> Color {
         Color::rgba(RGBA::transparent())
     }
 
-    /// Returns a complex color value representing currentcolor.
-    pub fn currentcolor() -> Color {
-        Color::Foreground
-    }
-
-    /// Whether it is a numeric color (no currentcolor component).
-    pub fn is_numeric(&self) -> bool {
-        matches!(*self, Color::Numeric { .. })
-    }
-
-    /// Whether it is a currentcolor value (no numeric color component).
-    pub fn is_currentcolor(&self) -> bool {
-        matches!(*self, Color::Foreground)
-    }
-
     /// Combine this complex color with the given foreground color into
     /// a numeric RGBA color. It currently uses linear blending.
     pub fn to_rgba(&self, fg_color: RGBA) -> RGBA {
         let (color, ratios) = match *self {
             // Common cases that the complex color is either pure numeric
             // color or pure currentcolor.
-            Color::Numeric(color) => return color,
-            Color::Foreground => return fg_color,
-            Color::Complex(color, ratios) => (color, ratios),
+            GenericColor::Numeric(color) => return color,
+            GenericColor::Foreground => return fg_color,
+            GenericColor::Complex(color, ratios) => (color, ratios),
         };
 
         // For the more complicated case that the alpha value differs,
         // we use the following formula to compute the components:
         // alpha = self_alpha * bg_ratio + fg_alpha * fg_ratio
         // color = (self_color * self_alpha * bg_ratio +
         //          fg_color * fg_alpha * fg_ratio) / alpha
 
@@ -112,61 +64,29 @@ impl Color {
         let inverse_a = 1. / a;
         let r = (p1 * r1 + p2 * r2) * inverse_a;
         let g = (p1 * g1 + p2 * g2) * inverse_a;
         let b = (p1 * b1 + p2 * b2) * inverse_a;
         return RGBA::from_floats(r, g, b, a);
     }
 }
 
-impl From<RGBA> for Color {
-    fn from(color: RGBA) -> Color {
-        Color::Numeric(color)
-    }
-}
-
 impl ToCss for Color {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: fmt::Write,
     {
         match *self {
-            Color::Numeric(color) => color.to_css(dest),
-            Color::Foreground => CSSParserColor::CurrentColor.to_css(dest),
+            GenericColor::Numeric(color) => color.to_css(dest),
+            GenericColor::Foreground => CSSParserColor::CurrentColor.to_css(dest),
             _ => Ok(()),
         }
     }
 }
 
-impl ToAnimatedValue for Color {
-    type AnimatedValue = AnimatedColor;
-
-    #[inline]
-    fn to_animated_value(self) -> Self::AnimatedValue {
-        match self {
-            Color::Numeric(color) => AnimatedColor::Numeric(color.to_animated_value()),
-            Color::Foreground => AnimatedColor::Foreground,
-            Color::Complex(color, ratios) => {
-                AnimatedColor::Complex(color.to_animated_value(), ratios)
-            }
-        }
-    }
-
-    #[inline]
-    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
-        match animated {
-            AnimatedColor::Numeric(color) => Color::Numeric(RGBA::from_animated_value(color)),
-            AnimatedColor::Foreground => Color::Foreground,
-            AnimatedColor::Complex(color, ratios) => {
-                Color::Complex(RGBA::from_animated_value(color), ratios)
-            }
-        }
-    }
-}
-
 impl ToAnimatedValue for RGBA {
     type AnimatedValue = AnimatedRGBA;
 
     #[inline]
     fn to_animated_value(self) -> Self::AnimatedValue {
         AnimatedRGBA::new(
             self.red_f32(),
             self.green_f32(),
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -40,17 +40,17 @@ pub use self::border::{BorderImageRepeat
 pub use self::border::{BorderCornerRadius, BorderRadius, BorderSpacing};
 pub use self::font::{FontSize, FontSizeAdjust, FontStretch, FontSynthesis, FontVariantAlternates, FontWeight};
 pub use self::font::{FontFamily, FontLanguageOverride, FontStyle, FontVariantEastAsian, FontVariationSettings};
 pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric};
 pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XLang, XTextZoom};
 pub use self::box_::{AnimationIterationCount, AnimationName, Contain, Display, TransitionProperty};
 pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective};
 pub use self::box_::{ScrollSnapType, TouchAction, VerticalAlign, WillChange};
-pub use self::color::{Color, ColorPropertyValue, ComplexColorRatios, RGBAColor};
+pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::column::ColumnCount;
 pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
 pub use self::inherited_box::{ImageOrientation, Orientation};
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/generics/color.rs
@@ -0,0 +1,76 @@
+/* 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 http://mozilla.org/MPL/2.0/. */
+
+//! Generic types for color properties.
+
+/// Ratios representing the contribution of color and currentcolor to
+/// the final color value.
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue)]
+pub struct ComplexColorRatios {
+    /// Numeric color contribution.
+    pub bg: f32,
+    /// Foreground color, aka currentcolor, contribution.
+    pub fg: f32,
+}
+
+impl ComplexColorRatios {
+    /// Ratios representing a `Numeric` color.
+    pub const NUMERIC: ComplexColorRatios = ComplexColorRatios { bg: 1., fg: 0. };
+    /// Ratios representing the `Foreground` color.
+    pub const FOREGROUND: ComplexColorRatios = ComplexColorRatios { bg: 0., fg: 1. };
+}
+
+/// This enum represents a combined color from a numeric color and
+/// the current foreground color (currentcolor keyword).
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue)]
+pub enum Color<RGBA> {
+    ///  Numeric RGBA color.
+    Numeric(RGBA),
+
+    /// The current foreground color.
+    Foreground,
+
+    /// A linear combination of numeric color and currentcolor.
+    /// The formula is: `color * ratios.bg + currentcolor * ratios.fg`.
+    Complex(RGBA, ComplexColorRatios),
+}
+
+impl<RGBA> Color<RGBA> {
+    /// Create a color based upon the specified ratios.
+    pub fn with_ratios(color: RGBA, ratios: ComplexColorRatios) -> Self {
+        if ratios == ComplexColorRatios::NUMERIC {
+            Color::Numeric(color)
+        } else if ratios == ComplexColorRatios::FOREGROUND {
+            Color::Foreground
+        } else {
+            Color::Complex(color, ratios)
+        }
+    }
+
+    /// Returns a numeric color representing the given RGBA value.
+    pub fn rgba(color: RGBA) -> Self {
+        Color::Numeric(color)
+    }
+
+    /// Returns a complex color value representing currentcolor.
+    pub fn currentcolor() -> Self {
+        Color::Foreground
+    }
+
+    /// Whether it is a numeric color (no currentcolor component).
+    pub fn is_numeric(&self) -> bool {
+        matches!(*self, Color::Numeric(..))
+    }
+
+    /// Whether it is a currentcolor value (no numeric color component).
+    pub fn is_currentcolor(&self) -> bool {
+        matches!(*self, Color::Foreground)
+    }
+}
+
+impl<RGBA> From<RGBA> for Color<RGBA> {
+    fn from(color: RGBA) -> Self {
+        Self::rgba(color)
+    }
+}
--- a/servo/components/style/values/generics/mod.rs
+++ b/servo/components/style/values/generics/mod.rs
@@ -12,16 +12,17 @@ use style_traits::{KeywordsCollectFn, Pa
 use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};
 use super::CustomIdent;
 
 pub mod background;
 pub mod basic_shape;
 pub mod border;
 #[path = "box.rs"]
 pub mod box_;
+pub mod color;
 pub mod column;
 pub mod counters;
 pub mod effects;
 pub mod flex;
 pub mod font;
 #[cfg(feature = "gecko")]
 pub mod gecko;
 pub mod grid;
--- a/servo/components/style/values/specified/color.rs
+++ b/servo/components/style/values/specified/color.rs
@@ -13,16 +13,17 @@ use parser::{Parse, ParserContext};
 #[cfg(feature = "gecko")]
 use properties::longhands::system_colors::SystemColor;
 use std::fmt::{self, Write};
 use std::io::Write as IoWrite;
 use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError, StyleParseErrorKind};
 use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind};
 use super::AllowQuirks;
 use values::computed::{Color as ComputedColor, Context, ToComputedValue};
+use values::generics::color::Color as GenericColor;
 use values::specified::calc::CalcNode;
 
 /// Specified color value
 #[derive(Clone, Debug, MallocSizeOf, PartialEq)]
 pub enum Color {
     /// The 'currentColor' keyword
     CurrentColor,
     /// A specific RGBA color
@@ -379,19 +380,19 @@ impl ToComputedValue for Color {
                 }
             }
         }
         result
     }
 
     fn from_computed_value(computed: &ComputedColor) -> Self {
         match *computed {
-            ComputedColor::Numeric(color) => Color::rgba(color),
-            ComputedColor::Foreground => Color::currentcolor(),
-            ComputedColor::Complex(..) => Color::Complex(*computed),
+            GenericColor::Numeric(color) => Color::rgba(color),
+            GenericColor::Foreground => Color::currentcolor(),
+            GenericColor::Complex(..) => Color::Complex(*computed),
         }
     }
 }
 
 /// Specified color value, but resolved to just RGBA for computed value
 /// with value from color property at the same context.
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
 pub struct RGBAColor(pub Color);