From 5f74a15f385b4777549513a4d59bf01803ef2470 Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Tue, 5 Jun 2018 11:49:51 +1000 Subject: [PATCH] style: Extract {animated,computed}::Color common parts. Extract the common parts of `animated::Color` and `computed::Color` out into `generics::color::Color` that is generic over the type of RGBA color. Bug: 1465307 Reviewed-by: xidorn MozReview-Commit-ID: EymSr7aqnAP --- .../sugar/style_complex_color.rs | 14 +-- components/style/values/animated/color.rs | 68 ++++-------- components/style/values/computed/color.rs | 100 ++---------------- components/style/values/computed/mod.rs | 2 +- components/style/values/generics/color.rs | 76 +++++++++++++ components/style/values/generics/mod.rs | 1 + components/style/values/specified/color.rs | 7 +- 7 files changed, 122 insertions(+), 146 deletions(-) create mode 100644 components/style/values/generics/color.rs diff --git a/components/style/gecko_bindings/sugar/style_complex_color.rs b/components/style/gecko_bindings/sugar/style_complex_color.rs index 3a37f9cb0fdd..90e93b72fd08 100644 --- a/components/style/gecko_bindings/sugar/style_complex_color.rs +++ b/components/style/gecko_bindings/sugar/style_complex_color.rs @@ -9,8 +9,8 @@ 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`. @@ -48,9 +48,9 @@ impl From for StyleComplexColor { impl From 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 { @@ -69,16 +69,16 @@ impl From for ComputedColor { 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, diff --git a/components/style/values/animated/color.rs b/components/style/values/animated/color.rs index 98f3f425d223..6a82896d62b7 100644 --- a/components/style/values/animated/color.rs +++ b/components/style/values/animated/color.rs @@ -6,7 +6,7 @@ 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. /// @@ -102,30 +102,15 @@ impl Animate for ComplexColorRatios { } } -#[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 ``. +pub type Color = GenericColor; 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() }, @@ -134,9 +119,9 @@ impl Color { 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, } } } @@ -144,28 +129,26 @@ impl Color { impl Animate for Color { #[inline] fn animate(&self, other: &Self, procedure: Procedure) -> Result { + 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, @@ -173,8 +156,8 @@ impl Animate for Color { }, ), - // 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., @@ -197,13 +180,7 @@ impl Animate for Color { 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) } }) } @@ -212,12 +189,13 @@ impl Animate for Color { impl ComputeSquaredDistance for Color { #[inline] fn compute_squared_distance(&self, other: &Self) -> Result { + 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.) diff --git a/components/style/values/computed/color.rs b/components/style/values/computed/color.rs index d5fff0867592..5effffe59661 100644 --- a/components/style/values/computed/color.rs +++ b/components/style/values/computed/color.rs @@ -8,39 +8,8 @@ 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; @@ -48,41 +17,24 @@ pub type RGBAColor = RGBA; /// The computed value of the `color` property. pub type ColorPropertyValue = RGBA; -impl Color { - /// Returns a numeric color representing the given RGBA value. - pub fn rgba(color: RGBA) -> Color { - Color::Numeric(color) - } +/// A computed value for ``. +pub type Color = GenericColor; +impl 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, @@ -117,51 +69,19 @@ impl Color { } } -impl From for Color { - fn from(color: RGBA) -> Color { - Color::Numeric(color) - } -} - impl ToCss for Color { fn to_css(&self, dest: &mut CssWriter) -> 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; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index fc1d617a02ec..e742c4e49f16 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -45,7 +45,7 @@ pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, 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}; diff --git a/components/style/values/generics/color.rs b/components/style/values/generics/color.rs new file mode 100644 index 000000000000..693803ad5fdf --- /dev/null +++ b/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 { + /// 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 Color { + /// 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 From for Color { + fn from(color: RGBA) -> Self { + Self::rgba(color) + } +} diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index c3b29c937696..e6c1befea9f8 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -17,6 +17,7 @@ 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; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 0670e8126ec4..c05f0ddce0ef 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -18,6 +18,7 @@ use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError, StyleParse 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 @@ -384,9 +385,9 @@ impl ToComputedValue for Color { 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), } } }