--- 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);