From 6e1b36b32f8a20740f9d7f0cf8c46a10a4c94541 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:18 +1000 Subject: [PATCH 01/10] Remove unused CSSRGBA. --- components/style/values/specified/mod.rs | 19 --------- components/style/values/specified/mod.rs.rej | 44 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 components/style/values/specified/mod.rs.rej diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 59ff135c303..8e5159f3188 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -233,25 +233,6 @@ impl CSSColor { } } -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub struct CSSRGBA { - pub parsed: cssparser::RGBA, - pub authored: Option>, -} - -no_viewport_percentage!(CSSRGBA); - -impl ToCss for CSSRGBA { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match self.authored { - Some(ref s) => dest.write_str(s), - None => self.parsed.to_css(dest), - } - } -} - /// Parse an `` value, handling `calc()` correctly. pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result { match try!(input.next()) { diff --git a/components/style/values/specified/mod.rs.rej b/components/style/values/specified/mod.rs.rej new file mode 100644 index 00000000000..0136e286c72 --- /dev/null +++ b/components/style/values/specified/mod.rs.rej @@ -0,0 +1,44 @@ +--- components/style/values/specified/mod.rs ++++ components/style/values/specified/mod.rs +@@ -4,40 +4,38 @@ + + //! Specified values. + //! + //! TODO(emilio): Enhance docs. + + use Namespace; + use context::QuirksMode; + use cssparser::{self, Parser, Token, serialize_identifier}; +-use itoa; + use parser::{ParserContext, Parse}; + use self::grid::TrackSizeOrRepeat; + use self::url::SpecifiedUrl; + use std::ascii::AsciiExt; + use std::f32; + use std::fmt; +-use std::io::Write; + use style_traits::ToCss; + use style_traits::values::specified::AllowedNumericType; + use super::{Auto, CSSFloat, CSSInteger, Either, None_}; + use super::computed::{self, Context}; + use super::computed::{Shadow as ComputedShadow, ToComputedValue}; + use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; + use super::generics::grid::TrackList as GenericTrackList; + use values::computed::ComputedValueAsSpecified; + use values::specified::calc::CalcNode; + + #[cfg(feature = "gecko")] + pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems}; + pub use self::background::BackgroundSize; + pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; + pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth}; +-pub use self::color::Color; ++pub use self::color::{CSSColor, Color}; + pub use self::rect::LengthOrNumberRect; + pub use super::generics::grid::GridLine; + pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient}; + pub use self::image::{GradientItem, GradientKind, Image, ImageRect, ImageLayer}; + pub use self::length::AbsoluteLength; + pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage}; + pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto}; + pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength}; From a7dda6115896c173277c044527d277a45168b08e Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:19 +1000 Subject: [PATCH 02/10] Move specified color types into specified::color mod. --- components/style/values/specified/color.rs | 151 ++++++++++++++++++++- components/style/values/specified/mod.rs | 145 +------------------- 2 files changed, 151 insertions(+), 145 deletions(-) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 0599563a494..f4d16f6f5ca 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -2,7 +2,15 @@ * 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/. */ -//! Non-standard CSS color values +//! Specified color values. + +use cssparser::{self, Parser, Token}; +use itoa; +use parser::{ParserContext, Parse}; +use std::fmt; +use std::io::Write; +use style_traits::ToCss; +use super::AllowQuirks; #[cfg(not(feature = "gecko"))] pub use self::servo::Color; #[cfg(feature = "gecko")] pub use self::gecko::Color; @@ -101,3 +109,144 @@ mod gecko { } } } + +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[allow(missing_docs)] +pub struct CSSColor { + pub parsed: Color, + pub authored: Option>, +} + +impl Parse for CSSColor { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + Self::parse_quirky(context, input, AllowQuirks::No) + } +} + +impl CSSColor { + /// Parse a color, with quirks. + /// + /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk + pub fn parse_quirky(context: &ParserContext, + input: &mut Parser, + allow_quirks: AllowQuirks) + -> Result { + let start_position = input.position(); + let authored = match input.next() { + Ok(Token::Ident(s)) => Some(s.into_owned().into_boxed_str()), + _ => None, + }; + input.reset(start_position); + if let Ok(parsed) = input.try(|i| Parse::parse(context, i)) { + return Ok(CSSColor { + parsed: parsed, + authored: authored, + }); + } + if !allow_quirks.allowed(context.quirks_mode) { + return Err(()); + } + let (number, dimension) = match input.next()? { + Token::Number(number) => { + (number, None) + }, + Token::Dimension(number, dimension) => { + (number, Some(dimension)) + }, + Token::Ident(ident) => { + if ident.len() != 3 && ident.len() != 6 { + return Err(()); + } + return cssparser::Color::parse_hash(ident.as_bytes()).map(|color| { + Self { + parsed: color.into(), + authored: None + } + }); + } + _ => { + return Err(()); + }, + }; + let value = number.int_value.ok_or(())?; + if value < 0 { + return Err(()); + } + let length = if value <= 9 { + 1 + } else if value <= 99 { + 2 + } else if value <= 999 { + 3 + } else if value <= 9999 { + 4 + } else if value <= 99999 { + 5 + } else if value <= 999999 { + 6 + } else { + return Err(()) + }; + let total = length + dimension.as_ref().map_or(0, |d| d.len()); + if total > 6 { + return Err(()); + } + let mut serialization = [b'0'; 6]; + let space_padding = 6 - total; + let mut written = space_padding; + written += itoa::write(&mut serialization[written..], value).unwrap(); + if let Some(dimension) = dimension { + written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap(); + } + debug_assert!(written == 6); + Ok(CSSColor { + parsed: cssparser::Color::parse_hash(&serialization).map(From::from)?, + authored: None, + }) + } + + /// Returns false if the color is completely transparent, and + /// true otherwise. + pub fn is_non_transparent(&self) -> bool { + match self.parsed { + Color::RGBA(rgba) if rgba.alpha == 0 => false, + _ => true, + } + } +} + +no_viewport_percentage!(CSSColor); + +impl ToCss for CSSColor { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match self.authored { + Some(ref s) => dest.write_str(s), + None => self.parsed.to_css(dest), + } + } +} + +impl From for CSSColor { + fn from(color: Color) -> Self { + CSSColor { + parsed: color, + authored: None, + } + } +} + +impl CSSColor { + #[inline] + /// Returns currentcolor value. + pub fn currentcolor() -> CSSColor { + Color::CurrentColor.into() + } + + #[inline] + /// Returns transparent value. + pub fn transparent() -> CSSColor { + // We should probably set authored to "transparent", but maybe it doesn't matter. + Color::RGBA(cssparser::RGBA::transparent()).into() + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 8e5159f3188..7be15aba77c 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -9,14 +9,12 @@ use Namespace; use context::QuirksMode; use cssparser::{self, Parser, Token, serialize_identifier}; -use itoa; use parser::{ParserContext, Parse}; use self::grid::TrackSizeOrRepeat; use self::url::SpecifiedUrl; use std::ascii::AsciiExt; use std::f32; use std::fmt; -use std::io::Write; use style_traits::ToCss; use style_traits::values::specified::AllowedNumericType; use super::{Auto, CSSFloat, CSSInteger, Either, None_}; @@ -33,7 +31,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify pub use self::background::BackgroundSize; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth}; -pub use self::color::Color; +pub use self::color::{CSSColor, Color}; pub use self::rect::LengthOrNumberRect; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -92,147 +90,6 @@ impl ComputedValueAsSpecified for SpecifiedUrl {} no_viewport_percentage!(SpecifiedUrl); } -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub struct CSSColor { - pub parsed: Color, - pub authored: Option>, -} - -impl Parse for CSSColor { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - Self::parse_quirky(context, input, AllowQuirks::No) - } -} - -impl CSSColor { - /// Parse a color, with quirks. - /// - /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk - pub fn parse_quirky(context: &ParserContext, - input: &mut Parser, - allow_quirks: AllowQuirks) - -> Result { - let start_position = input.position(); - let authored = match input.next() { - Ok(Token::Ident(s)) => Some(s.into_owned().into_boxed_str()), - _ => None, - }; - input.reset(start_position); - if let Ok(parsed) = input.try(|i| Parse::parse(context, i)) { - return Ok(CSSColor { - parsed: parsed, - authored: authored, - }); - } - if !allow_quirks.allowed(context.quirks_mode) { - return Err(()); - } - let (number, dimension) = match input.next()? { - Token::Number(number) => { - (number, None) - }, - Token::Dimension(number, dimension) => { - (number, Some(dimension)) - }, - Token::Ident(ident) => { - if ident.len() != 3 && ident.len() != 6 { - return Err(()); - } - return cssparser::Color::parse_hash(ident.as_bytes()).map(|color| { - Self { - parsed: color.into(), - authored: None - } - }); - } - _ => { - return Err(()); - }, - }; - let value = number.int_value.ok_or(())?; - if value < 0 { - return Err(()); - } - let length = if value <= 9 { - 1 - } else if value <= 99 { - 2 - } else if value <= 999 { - 3 - } else if value <= 9999 { - 4 - } else if value <= 99999 { - 5 - } else if value <= 999999 { - 6 - } else { - return Err(()) - }; - let total = length + dimension.as_ref().map_or(0, |d| d.len()); - if total > 6 { - return Err(()); - } - let mut serialization = [b'0'; 6]; - let space_padding = 6 - total; - let mut written = space_padding; - written += itoa::write(&mut serialization[written..], value).unwrap(); - if let Some(dimension) = dimension { - written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap(); - } - debug_assert!(written == 6); - Ok(CSSColor { - parsed: cssparser::Color::parse_hash(&serialization).map(From::from)?, - authored: None, - }) - } - - /// Returns false if the color is completely transparent, and - /// true otherwise. - pub fn is_non_transparent(&self) -> bool { - match self.parsed { - Color::RGBA(rgba) if rgba.alpha == 0 => false, - _ => true, - } - } -} - -no_viewport_percentage!(CSSColor); - -impl ToCss for CSSColor { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match self.authored { - Some(ref s) => dest.write_str(s), - None => self.parsed.to_css(dest), - } - } -} - -impl From for CSSColor { - fn from(color: Color) -> Self { - CSSColor { - parsed: color, - authored: None, - } - } -} - -impl CSSColor { - #[inline] - /// Returns currentcolor value. - pub fn currentcolor() -> CSSColor { - Color::CurrentColor.into() - } - - #[inline] - /// Returns transparent value. - pub fn transparent() -> CSSColor { - // We should probably set authored to "transparent", but maybe it doesn't matter. - Color::RGBA(cssparser::RGBA::transparent()).into() - } -} - /// Parse an `` value, handling `calc()` correctly. pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result { match try!(input.next()) { From b7d8fd0ff5334ae92fd5de0dead7862fd6418b4b Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:21 +1000 Subject: [PATCH 03/10] Move ToComputedValue impl of color types into specified::color. --- components/style/values/computed/mod.rs | 80 --------------------- components/style/values/specified/color.rs | 83 +++++++++++++++++++++- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 1547cf29424..9c9e23887a8 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -360,86 +360,6 @@ impl ToCss for Time { } } -impl ToComputedValue for specified::Color { - type ComputedValue = RGBA; - - #[cfg(not(feature = "gecko"))] - fn to_computed_value(&self, context: &Context) -> RGBA { - match *self { - specified::Color::RGBA(rgba) => rgba, - specified::Color::CurrentColor => context.inherited_style.get_color().clone_color(), - } - } - - #[cfg(feature = "gecko")] - fn to_computed_value(&self, context: &Context) -> RGBA { - use gecko::values::convert_nscolor_to_rgba as to_rgba; - // It's safe to access the nsPresContext immutably during style computation. - let pres_context = unsafe { &*context.device.pres_context }; - match *self { - specified::Color::RGBA(rgba) => rgba, - specified::Color::System(system) => to_rgba(system.to_computed_value(context)), - specified::Color::CurrentColor => context.inherited_style.get_color().clone_color(), - specified::Color::MozDefaultColor => to_rgba(pres_context.mDefaultColor), - specified::Color::MozDefaultBackgroundColor => to_rgba(pres_context.mBackgroundColor), - specified::Color::MozHyperlinktext => to_rgba(pres_context.mLinkColor), - specified::Color::MozActiveHyperlinktext => to_rgba(pres_context.mActiveLinkColor), - specified::Color::MozVisitedHyperlinktext => to_rgba(pres_context.mVisitedLinkColor), - specified::Color::InheritFromBodyQuirk => { - use dom::TElement; - use gecko::wrapper::GeckoElement; - use gecko_bindings::bindings::Gecko_GetBody; - let body = unsafe { - Gecko_GetBody(pres_context) - }; - if let Some(body) = body { - let wrap = GeckoElement(body); - let borrow = wrap.borrow_data(); - borrow.as_ref().unwrap() - .styles().primary.values() - .get_color() - .clone_color() - } else { - to_rgba(pres_context.mDefaultColor) - } - }, - } - } - - fn from_computed_value(computed: &RGBA) -> Self { - specified::Color::RGBA(*computed) - } -} - -impl ToComputedValue for specified::CSSColor { - type ComputedValue = CSSColor; - - #[cfg(not(feature = "gecko"))] - #[inline] - fn to_computed_value(&self, _context: &Context) -> CSSColor { - self.parsed - } - - #[cfg(feature = "gecko")] - #[inline] - fn to_computed_value(&self, context: &Context) -> CSSColor { - match self.parsed { - specified::Color::RGBA(rgba) => CSSColor::RGBA(rgba), - specified::Color::CurrentColor => CSSColor::CurrentColor, - // Resolve non-standard -moz keywords to RGBA: - non_standard => CSSColor::RGBA(non_standard.to_computed_value(context)), - } - } - - #[inline] - fn from_computed_value(computed: &CSSColor) -> Self { - (match *computed { - CSSColor::RGBA(rgba) => specified::Color::RGBA(rgba), - CSSColor::CurrentColor => specified::Color::CurrentColor, - }).into() - } -} - #[cfg(feature = "gecko")] impl ToComputedValue for specified::JustifyItems { type ComputedValue = JustifyItems; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index f4d16f6f5ca..4d2443e5081 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -4,13 +4,14 @@ //! Specified color values. -use cssparser::{self, Parser, Token}; +use cssparser::{self, Color as CSSParserColor, Parser, RGBA, Token}; use itoa; use parser::{ParserContext, Parse}; use std::fmt; use std::io::Write; use style_traits::ToCss; use super::AllowQuirks; +use values::computed::{Context, ToComputedValue}; #[cfg(not(feature = "gecko"))] pub use self::servo::Color; #[cfg(feature = "gecko")] pub use self::gecko::Color; @@ -250,3 +251,83 @@ impl CSSColor { Color::RGBA(cssparser::RGBA::transparent()).into() } } + +impl ToComputedValue for Color { + type ComputedValue = RGBA; + + #[cfg(not(feature = "gecko"))] + fn to_computed_value(&self, context: &Context) -> RGBA { + match *self { + Color::RGBA(rgba) => rgba, + Color::CurrentColor => context.inherited_style.get_color().clone_color(), + } + } + + #[cfg(feature = "gecko")] + fn to_computed_value(&self, context: &Context) -> RGBA { + use gecko::values::convert_nscolor_to_rgba as to_rgba; + // It's safe to access the nsPresContext immutably during style computation. + let pres_context = unsafe { &*context.device.pres_context }; + match *self { + Color::RGBA(rgba) => rgba, + Color::System(system) => to_rgba(system.to_computed_value(context)), + Color::CurrentColor => context.inherited_style.get_color().clone_color(), + Color::MozDefaultColor => to_rgba(pres_context.mDefaultColor), + Color::MozDefaultBackgroundColor => to_rgba(pres_context.mBackgroundColor), + Color::MozHyperlinktext => to_rgba(pres_context.mLinkColor), + Color::MozActiveHyperlinktext => to_rgba(pres_context.mActiveLinkColor), + Color::MozVisitedHyperlinktext => to_rgba(pres_context.mVisitedLinkColor), + Color::InheritFromBodyQuirk => { + use dom::TElement; + use gecko::wrapper::GeckoElement; + use gecko_bindings::bindings::Gecko_GetBody; + let body = unsafe { + Gecko_GetBody(pres_context) + }; + if let Some(body) = body { + let wrap = GeckoElement(body); + let borrow = wrap.borrow_data(); + borrow.as_ref().unwrap() + .styles().primary.values() + .get_color() + .clone_color() + } else { + to_rgba(pres_context.mDefaultColor) + } + }, + } + } + + fn from_computed_value(computed: &RGBA) -> Self { + Color::RGBA(*computed) + } +} + +impl ToComputedValue for CSSColor { + type ComputedValue = CSSParserColor; + + #[cfg(not(feature = "gecko"))] + #[inline] + fn to_computed_value(&self, _context: &Context) -> CSSParserColor { + self.parsed + } + + #[cfg(feature = "gecko")] + #[inline] + fn to_computed_value(&self, context: &Context) -> CSSParserColor { + match self.parsed { + Color::RGBA(rgba) => CSSParserColor::RGBA(rgba), + Color::CurrentColor => CSSParserColor::CurrentColor, + // Resolve non-standard -moz keywords to RGBA: + non_standard => CSSParserColor::RGBA(non_standard.to_computed_value(context)), + } + } + + #[inline] + fn from_computed_value(computed: &CSSParserColor) -> Self { + (match *computed { + CSSParserColor::RGBA(rgba) => Color::RGBA(rgba), + CSSParserColor::CurrentColor => Color::CurrentColor, + }).into() + } +} From f3610d2724a19d1451a78e53ec5f27aa267ed3b1 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:22 +1000 Subject: [PATCH 04/10] Factor out Gecko-specific color keywords. --- components/style/values/specified/color.rs | 53 ++++++++++------------ 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 4d2443e5081..3a3b45651ec 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -37,6 +37,14 @@ mod gecko { use std::fmt; use style_traits::ToCss; + define_css_keyword_enum! { SpecialColorKeyword: + "-moz-default-color" => MozDefaultColor, + "-moz-default-background-color" => MozDefaultBackgroundColor, + "-moz-hyperlinktext" => MozHyperlinktext, + "-moz-activehyperlinktext" => MozActiveHyperlinktext, + "-moz-visitedhyperlinktext" => MozVisitedHyperlinktext, + } + /// Color value including non-standard -moz prefixed values. #[derive(Clone, Copy, PartialEq, Debug)] pub enum Color { @@ -46,16 +54,8 @@ mod gecko { RGBA(RGBA), /// A system color System(SystemColor), - /// -moz-default-color - MozDefaultColor, - /// -moz-default-background-color - MozDefaultBackgroundColor, - /// -moz-hyperlinktext - MozHyperlinktext, - /// -moz-activehyperlinktext - MozActiveHyperlinktext, - /// -moz-visitedhyperlinktext - MozVisitedHyperlinktext, + /// A special color keyword value used in Gecko + Special(SpecialColorKeyword), /// Quirksmode-only rule for inheriting color from the body InheritFromBodyQuirk, } @@ -77,16 +77,10 @@ mod gecko { Ok(value.into()) } else if let Ok(system) = input.try(SystemColor::parse) { Ok(Color::System(system)) + } else if let Ok(special) = input.try(SpecialColorKeyword::parse) { + Ok(Color::Special(special)) } else { - let ident = input.expect_ident()?; - match_ignore_ascii_case! { &ident, - "-moz-default-color" => Ok(Color::MozDefaultColor), - "-moz-default-background-color" => Ok(Color::MozDefaultBackgroundColor), - "-moz-hyperlinktext" => Ok(Color::MozHyperlinktext), - "-moz-activehyperlinktext" => Ok(Color::MozActiveHyperlinktext), - "-moz-visitedhyperlinktext" => Ok(Color::MozVisitedHyperlinktext), - _ => Err(()) - } + Err(()) } } } @@ -100,11 +94,7 @@ mod gecko { Color::System(system) => system.to_css(dest), // Non-standard values: - Color::MozDefaultColor => dest.write_str("-moz-default-color"), - Color::MozDefaultBackgroundColor => dest.write_str("-moz-default-background-color"), - Color::MozHyperlinktext => dest.write_str("-moz-hyperlinktext"), - Color::MozActiveHyperlinktext => dest.write_str("-moz-activehyperlinktext"), - Color::MozVisitedHyperlinktext => dest.write_str("-moz-visitedhyperlinktext"), + Color::Special(special) => special.to_css(dest), Color::InheritFromBodyQuirk => Ok(()), } } @@ -272,11 +262,16 @@ impl ToComputedValue for Color { Color::RGBA(rgba) => rgba, Color::System(system) => to_rgba(system.to_computed_value(context)), Color::CurrentColor => context.inherited_style.get_color().clone_color(), - Color::MozDefaultColor => to_rgba(pres_context.mDefaultColor), - Color::MozDefaultBackgroundColor => to_rgba(pres_context.mBackgroundColor), - Color::MozHyperlinktext => to_rgba(pres_context.mLinkColor), - Color::MozActiveHyperlinktext => to_rgba(pres_context.mActiveLinkColor), - Color::MozVisitedHyperlinktext => to_rgba(pres_context.mVisitedLinkColor), + Color::Special(special) => { + use self::gecko::SpecialColorKeyword as Keyword; + to_rgba(match special { + Keyword::MozDefaultColor => pres_context.mDefaultColor, + Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, + Keyword::MozHyperlinktext => pres_context.mLinkColor, + Keyword::MozActiveHyperlinktext => pres_context.mActiveLinkColor, + Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor, + }) + } Color::InheritFromBodyQuirk => { use dom::TElement; use gecko::wrapper::GeckoElement; From d0d170767dbd871839a4cdcdf5271c8fb8c5332c Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:24 +1000 Subject: [PATCH 05/10] Unify specified Color type between Stylo and Servo. --- components/script/dom/element.rs | 3 +- components/style/values/specified/color.rs | 149 +++++++++---------- tests/unit/style/parsing/ui.rs | 4 +- tests/unit/style/properties/serialization.rs | 20 +-- tests/unit/style/stylesheets.rs | 2 +- 5 files changed, 82 insertions(+), 96 deletions(-) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index c0d4b6b700a..5353fd7e9ab 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -4,7 +4,6 @@ //! Element nodes. -use cssparser::Color; use devtools_traits::AttrInfo; use dom::activation::Activatable; use dom::attr::{Attr, AttrHelpersForLayout}; @@ -112,7 +111,7 @@ use style::stylearc::Arc; use style::stylist::ApplicableDeclarationBlock; use style::thread_state; use style::values::{CSSFloat, Either}; -use style::values::specified::{self, CSSColor}; +use style::values::specified::{self, CSSColor, Color}; use stylesheet_loader::StylesheetOwner; // TODO: Update focus state when the top-level browsing context gains or loses system focus, diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 3a3b45651ec..538506bfce9 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -7,34 +7,38 @@ use cssparser::{self, Color as CSSParserColor, Parser, RGBA, Token}; use itoa; use parser::{ParserContext, Parse}; +#[cfg(feature = "gecko")] +use properties::longhands::color::SystemColor; use std::fmt; use std::io::Write; use style_traits::ToCss; use super::AllowQuirks; use values::computed::{Context, ToComputedValue}; -#[cfg(not(feature = "gecko"))] pub use self::servo::Color; -#[cfg(feature = "gecko")] pub use self::gecko::Color; +/// Specified color value +#[derive(Clone, Copy, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum Color { + /// The 'currentColor' keyword + CurrentColor, + /// A specific RGBA color + RGBA(RGBA), -#[cfg(not(feature = "gecko"))] -mod servo { - pub use cssparser::Color; - use cssparser::Parser; - use parser::{Parse, ParserContext}; - - impl Parse for Color { - fn parse(_: &ParserContext, input: &mut Parser) -> Result { - Color::parse(input) - } - } + /// A system color + #[cfg(feature = "gecko")] + System(SystemColor), + /// A special color keyword value used in Gecko + #[cfg(feature = "gecko")] + Special(gecko::SpecialColorKeyword), + /// Quirksmode-only rule for inheriting color from the body + #[cfg(feature = "gecko")] + InheritFromBodyQuirk, } +no_viewport_percentage!(Color); + #[cfg(feature = "gecko")] mod gecko { - use cssparser::{Color as CSSParserColor, Parser, RGBA}; - use parser::{Parse, ParserContext}; - use properties::longhands::color::SystemColor; - use std::fmt; use style_traits::ToCss; define_css_keyword_enum! { SpecialColorKeyword: @@ -44,59 +48,53 @@ mod gecko { "-moz-activehyperlinktext" => MozActiveHyperlinktext, "-moz-visitedhyperlinktext" => MozVisitedHyperlinktext, } +} - /// Color value including non-standard -moz prefixed values. - #[derive(Clone, Copy, PartialEq, Debug)] - pub enum Color { - /// The 'currentColor' keyword - CurrentColor, - /// A specific RGBA color - RGBA(RGBA), - /// A system color - System(SystemColor), - /// A special color keyword value used in Gecko - Special(SpecialColorKeyword), - /// Quirksmode-only rule for inheriting color from the body - InheritFromBodyQuirk, - } - - no_viewport_percentage!(Color); - - impl From for Color { - fn from(value: CSSParserColor) -> Self { - match value { - CSSParserColor::CurrentColor => Color::CurrentColor, - CSSParserColor::RGBA(x) => Color::RGBA(x), - } +impl From for Color { + fn from(value: CSSParserColor) -> Self { + match value { + CSSParserColor::CurrentColor => Color::CurrentColor, + CSSParserColor::RGBA(x) => Color::RGBA(x), } } +} - impl Parse for Color { - fn parse(_: &ParserContext, input: &mut Parser) -> Result { - if let Ok(value) = input.try(CSSParserColor::parse) { - Ok(value.into()) - } else if let Ok(system) = input.try(SystemColor::parse) { - Ok(Color::System(system)) - } else if let Ok(special) = input.try(SpecialColorKeyword::parse) { - Ok(Color::Special(special)) - } else { +impl From for Color { + fn from(value: RGBA) -> Self { + Color::RGBA(value) + } +} + +impl Parse for Color { + fn parse(_: &ParserContext, input: &mut Parser) -> Result { + if let Ok(value) = input.try(CSSParserColor::parse) { + Ok(value.into()) + } else { + #[cfg(feature = "gecko")] { + if let Ok(system) = input.try(SystemColor::parse) { + Ok(Color::System(system)) + } else { + gecko::SpecialColorKeyword::parse(input).map(Color::Special) + } + } + #[cfg(not(feature = "gecko"))] { Err(()) } } } +} - impl ToCss for Color { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - // Standard values: - Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), - Color::RGBA(rgba) => rgba.to_css(dest), - Color::System(system) => system.to_css(dest), - - // Non-standard values: - Color::Special(special) => special.to_css(dest), - Color::InheritFromBodyQuirk => Ok(()), - } +impl ToCss for Color { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), + Color::RGBA(rgba) => rgba.to_css(dest), + #[cfg(feature = "gecko")] + Color::System(system) => system.to_css(dest), + #[cfg(feature = "gecko")] + Color::Special(special) => special.to_css(dest), + #[cfg(feature = "gecko")] + Color::InheritFromBodyQuirk => Ok(()), } } } @@ -245,25 +243,18 @@ impl CSSColor { impl ToComputedValue for Color { type ComputedValue = RGBA; - #[cfg(not(feature = "gecko"))] - fn to_computed_value(&self, context: &Context) -> RGBA { - match *self { - Color::RGBA(rgba) => rgba, - Color::CurrentColor => context.inherited_style.get_color().clone_color(), - } - } - - #[cfg(feature = "gecko")] fn to_computed_value(&self, context: &Context) -> RGBA { + #[cfg(feature = "gecko")] use gecko::values::convert_nscolor_to_rgba as to_rgba; - // It's safe to access the nsPresContext immutably during style computation. - let pres_context = unsafe { &*context.device.pres_context }; match *self { Color::RGBA(rgba) => rgba, - Color::System(system) => to_rgba(system.to_computed_value(context)), Color::CurrentColor => context.inherited_style.get_color().clone_color(), + #[cfg(feature = "gecko")] + Color::System(system) => to_rgba(system.to_computed_value(context)), + #[cfg(feature = "gecko")] Color::Special(special) => { use self::gecko::SpecialColorKeyword as Keyword; + let pres_context = unsafe { &*context.device.pres_context }; to_rgba(match special { Keyword::MozDefaultColor => pres_context.mDefaultColor, Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, @@ -272,10 +263,12 @@ impl ToComputedValue for Color { Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor, }) } + #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => { use dom::TElement; use gecko::wrapper::GeckoElement; use gecko_bindings::bindings::Gecko_GetBody; + let pres_context = unsafe { &*context.device.pres_context }; let body = unsafe { Gecko_GetBody(pres_context) }; @@ -301,20 +294,14 @@ impl ToComputedValue for Color { impl ToComputedValue for CSSColor { type ComputedValue = CSSParserColor; - #[cfg(not(feature = "gecko"))] #[inline] fn to_computed_value(&self, _context: &Context) -> CSSParserColor { - self.parsed - } - - #[cfg(feature = "gecko")] - #[inline] - fn to_computed_value(&self, context: &Context) -> CSSParserColor { match self.parsed { Color::RGBA(rgba) => CSSParserColor::RGBA(rgba), Color::CurrentColor => CSSParserColor::CurrentColor, // Resolve non-standard -moz keywords to RGBA: - non_standard => CSSParserColor::RGBA(non_standard.to_computed_value(context)), + #[cfg(feature = "gecko")] + non_standard => CSSParserColor::RGBA(non_standard.to_computed_value(_context)), } } diff --git a/tests/unit/style/parsing/ui.rs b/tests/unit/style/parsing/ui.rs index 9347b1fbc01..35985a1001e 100644 --- a/tests/unit/style/parsing/ui.rs +++ b/tests/unit/style/parsing/ui.rs @@ -2,10 +2,10 @@ * 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/. */ -use cssparser::{Color, RGBA}; +use cssparser::RGBA; use parsing::parse; use style::values::{Auto, Either}; -use style::values::specified::CSSColor; +use style::values::specified::{CSSColor, Color}; use style_traits::ToCss; #[test] diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index e8009794a5a..f3e666ec65f 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -5,11 +5,11 @@ use properties::parse; use style::computed_values::display::T::inline_block; use style::properties::{PropertyDeclaration, Importance, PropertyId}; -use style::properties::longhands::outline_color::computed_value::T as ComputedColor; use style::properties::parse_property_declaration_list; use style::values::{RGBA, Auto}; use style::values::CustomIdent; -use style::values::specified::{BorderStyle, BorderSideWidth, CSSColor, Length, LengthOrPercentage}; +use style::values::specified::{BorderStyle, BorderSideWidth, CSSColor}; +use style::values::specified::{Length, LengthOrPercentage}; use style::values::specified::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent}; use style::values::specified::{NoCalcLength, PositionComponent}; use style::values::specified::position::Y; @@ -111,7 +111,7 @@ mod shorthand_serialization { let line = TextDecorationLine::OVERLINE; let style = TextDecorationStyle::dotted; let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(128, 0, 128, 255)), + parsed: RGBA::new(128, 0, 128, 255).into(), authored: None }; @@ -230,7 +230,7 @@ mod shorthand_serialization { properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone())); let blue = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), + parsed: RGBA::new(0, 0, 255, 255).into(), authored: None }; @@ -263,7 +263,7 @@ mod shorthand_serialization { properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone())); let blue = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), + parsed: RGBA::new(0, 0, 255, 255).into(), authored: None }; @@ -333,12 +333,12 @@ mod shorthand_serialization { let mut properties = Vec::new(); let red = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), + parsed: RGBA::new(255, 0, 0, 255).into(), authored: None }; let blue = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), + parsed: RGBA::new(0, 0, 255, 255).into(), authored: None }; @@ -406,7 +406,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = BorderStyle::solid; let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), + parsed: RGBA::new(255, 0, 0, 255).into(), authored: None }; @@ -533,7 +533,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = Either::Second(BorderStyle::solid); let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), + parsed: RGBA::new(255, 0, 0, 255).into(), authored: None }; @@ -552,7 +552,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = Either::First(Auto); let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), + parsed: RGBA::new(255, 0, 0, 255).into(), authored: None }; properties.push(PropertyDeclaration::OutlineWidth(width)); diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 686a3979a9a..9b9c08c5b1f 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -160,7 +160,7 @@ fn test_parse_stylesheet() { (PropertyDeclaration::BackgroundColor( longhands::background_color::SpecifiedValue { authored: Some("blue".to_owned().into_boxed_str()), - parsed: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 255, 255)), + parsed: cssparser::RGBA::new(0, 0, 255, 255).into(), } ), Importance::Normal), From bf77f81ed639af0e9b305f6672db696f8a144ff4 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:26 +1000 Subject: [PATCH 06/10] Create RGBAColor for colors compute to RGBA. --- components/layout/display_list_builder.rs | 33 +++++------- components/style/gecko/conversions.rs | 15 +----- components/style/properties/gecko.mako.rs | 44 ++++++++------- .../helpers/animated_properties.mako.rs | 4 +- .../style/properties/longhand/border.mako.rs | 10 ++-- .../style/properties/longhand/svg.mako.rs | 12 ++--- components/style/values/computed/color.rs | 10 ++++ components/style/values/computed/image.rs | 8 +-- components/style/values/computed/mod.rs | 8 +-- components/style/values/specified/color.rs | 53 +++++++++++++++++++ components/style/values/specified/image.rs | 16 +++--- components/style/values/specified/mod.rs | 13 ++--- 12 files changed, 135 insertions(+), 91 deletions(-) create mode 100644 components/style/values/computed/color.rs diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 6794d144a47..4a7f2814cbf 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -422,8 +422,7 @@ pub trait FragmentDisplayListBuilding { bounds: &Rect, stops: &[GradientItem], direction: &LineDirection, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::Gradient; fn convert_radial_gradient(&self, @@ -431,8 +430,7 @@ pub trait FragmentDisplayListBuilding { stops: &[GradientItem], shape: &EndingShape, center: &Position, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::RadialGradient; /// Adds the display items necessary to paint the background linear gradient of this fragment @@ -634,8 +632,7 @@ fn build_border_radius_for_inner_rect(outer_rect: &Rect, } fn convert_gradient_stops(gradient_items: &[GradientItem], - total_length: Au, - style: &ServoComputedValues) -> Vec { + total_length: Au) -> Vec { // Determine the position of each stop per CSS-IMAGES ยง 3.4. // Only keep the color stops, discard the color interpolation hints. @@ -722,7 +719,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem], }; stops.push(GradientStop { offset: offset, - color: style.resolve_color(stop.color).to_gfx_color() + color: stop.color.to_gfx_color() }) } stops @@ -1192,8 +1189,7 @@ impl FragmentDisplayListBuilding for Fragment { bounds: &Rect, stops: &[GradientItem], direction: &LineDirection, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::Gradient { let angle = match *direction { LineDirection::Angle(angle) => angle.radians(), @@ -1234,7 +1230,7 @@ impl FragmentDisplayListBuilding for Fragment { let length = Au::from_f32_px( (delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); - let mut stops = convert_gradient_stops(stops, length, style); + let mut stops = convert_gradient_stops(stops, length); // Only clamped gradients need to be fixed because in repeating gradients // there is no "first" or "last" stop because they repeat infinitly in @@ -1258,8 +1254,7 @@ impl FragmentDisplayListBuilding for Fragment { stops: &[GradientItem], shape: &EndingShape, center: &Position, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::RadialGradient { let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width), center.vertical.to_used_value(bounds.size.height)); @@ -1278,7 +1273,7 @@ impl FragmentDisplayListBuilding for Fragment { }, }; - let mut stops = convert_gradient_stops(stops, radius.width, style); + let mut stops = convert_gradient_stops(stops, radius.width); // Repeating gradients have no last stops that can be ignored. So // fixup is not necessary but may actually break the gradient. if !repeating { @@ -1322,8 +1317,7 @@ impl FragmentDisplayListBuilding for Fragment { let gradient = self.convert_linear_gradient(&bounds, &gradient.items[..], angle_or_corner, - gradient.repeating, - style); + gradient.repeating); DisplayItem::Gradient(box GradientDisplayItem { base: base, gradient: gradient, @@ -1334,8 +1328,7 @@ impl FragmentDisplayListBuilding for Fragment { &gradient.items[..], shape, center, - gradient.repeating, - style); + gradient.repeating); DisplayItem::RadialGradient(box RadialGradientDisplayItem { base: base, gradient: gradient, @@ -1459,8 +1452,7 @@ impl FragmentDisplayListBuilding for Fragment { let grad = self.convert_linear_gradient(&bounds, &gradient.items[..], &angle_or_corner, - gradient.repeating, - style); + gradient.repeating); state.add_display_item(DisplayItem::Border(box BorderDisplayItem { base: base, @@ -1478,8 +1470,7 @@ impl FragmentDisplayListBuilding for Fragment { &gradient.items[..], shape, center, - gradient.repeating, - style); + gradient.repeating); state.add_display_item(DisplayItem::Border(box BorderDisplayItem { base: base, border_widths: border.to_physical(style.writing_mode), diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 9f222690404..4266c61826a 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -183,7 +183,6 @@ impl nsStyleImage { } fn set_gradient(&mut self, gradient: Gradient) { - use cssparser::Color as CSSColor; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_CIRCULAR, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL}; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER}; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE}; @@ -321,19 +320,7 @@ impl nsStyleImage { match *item { GradientItem::ColorStop(ref stop) => { - gecko_stop.mColor = match stop.color { - CSSColor::CurrentColor => { - // TODO(emilio): gecko just stores an nscolor, - // and it doesn't seem to support currentColor - // as value in a gradient. - // - // Double-check it and either remove - // currentColor for servo or see how gecko - // handles this. - 0 - }, - CSSColor::RGBA(ref rgba) => convert_rgba_to_nscolor(rgba), - }; + gecko_stop.mColor = convert_rgba_to_nscolor(&stop.color); gecko_stop.mIsInterpolationHint = false; coord.set(stop.position); }, diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 3c0b57c9fe0..fb8a0ea8970 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -11,7 +11,6 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> use app_units::Au; -use cssparser::Color; use custom_properties::ComputedValuesMap; use gecko_bindings::bindings; % for style_struct in data.style_structs: @@ -316,18 +315,6 @@ def set_gecko_property(ffi_name, expr): } -/// Convert a Servo color into an nscolor; with currentColor as 0 -/// -/// Call sites will need to be updated after https://bugzilla.mozilla.org/show_bug.cgi?id=760345 -fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { - match color { - Color::RGBA(rgba) => { - convert_rgba_to_nscolor(&rgba) - }, - Color::CurrentColor => 0, - } -} - <%def name="impl_color_setter(ident, gecko_ffi_name, complex_color=True)"> #[allow(unreachable_code)] #[allow(non_snake_case)] @@ -335,7 +322,11 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { % if complex_color: let result = v.into(); % else: - let result = color_to_nscolor_zero_currentcolor(v); + let result = match color { + Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba), + // FIXME handle currentcolor + Color::CurrentColor => 0, + }; % endif ${set_gecko_property(gecko_ffi_name, "result")} } @@ -416,6 +407,20 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { % endif +<%def name="impl_rgba_color(ident, gecko_ffi_name, need_clone=False)"> + #[allow(non_snake_case)] + pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { + ${set_gecko_property(gecko_ffi_name, "convert_rgba_to_nscolor(&v)")} + } + <%call expr="impl_simple_copy(ident, gecko_ffi_name)"> + % if need_clone: + #[allow(non_snake_case)] + pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { + convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)}) + } + % endif + + <%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { @@ -444,14 +449,14 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { SVGPaintKind::Color(color) => { paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color; unsafe { - *paint.mPaint.mColor.as_mut() = color_to_nscolor_zero_currentcolor(color); + *paint.mPaint.mColor.as_mut() = convert_rgba_to_nscolor(&color); } } } if let Some(fallback) = fallback { paint.mFallbackType = nsStyleSVGFallbackType::eStyleSVGFallbackType_Color; - paint.mFallbackColor = color_to_nscolor_zero_currentcolor(fallback); + paint.mFallbackColor = convert_rgba_to_nscolor(&fallback); } } @@ -472,7 +477,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { use self::structs::nsStyleSVGFallbackType; let ref paint = ${get_gecko_property(gecko_ffi_name)}; let fallback = if let nsStyleSVGFallbackType::eStyleSVGFallbackType_Color = paint.mFallbackType { - Some(Color::RGBA(convert_nscolor_to_rgba(paint.mFallbackColor))) + Some(convert_nscolor_to_rgba(paint.mFallbackColor)) } else { None }; @@ -485,7 +490,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { SVGPaintKind::None } nsStyleSVGPaintType::eStyleSVGPaintType_Color => { - unsafe { SVGPaintKind::Color(Color::RGBA(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref()))) } + unsafe { SVGPaintKind::Color(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref())) } } }; SVGPaint { @@ -717,6 +722,7 @@ impl Debug for ${style_struct.gecko_struct_name} { "Integer": impl_simple, "Opacity": impl_simple, "CSSColor": impl_color, + "RGBAColor": impl_rgba_color, "SVGPaint": impl_svg_paint, "UrlOrNone": impl_css_url, } @@ -948,7 +954,7 @@ fn static_assert() { structs::Side::eSide${to_camel_case(side.ident)}); } for color in colors { - let c = color_to_nscolor_zero_currentcolor(*color); + let c = convert_rgba_to_nscolor(color); unsafe { bindings::Gecko_AppendMozBorderColors(&mut self.gecko, structs::Side::eSide${to_camel_case(side.ident)}, diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 4ba7e6b505a..ce3b406d4f4 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -2823,9 +2823,9 @@ impl From for CSSParserColor { } /// Animatable SVGPaint -pub type IntermediateSVGPaint = SVGPaint; +pub type IntermediateSVGPaint = SVGPaint; /// Animatable SVGPaintKind -pub type IntermediateSVGPaintKind = SVGPaintKind; +pub type IntermediateSVGPaintKind = SVGPaintKind; impl From<::values::computed::SVGPaint> for IntermediateSVGPaint { fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint { diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index 693d1f32551..142825cabda 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -66,21 +66,21 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style', ignored_when_colors_disabled="True"> use std::fmt; use style_traits::ToCss; - use values::specified::CSSColor; + use values::specified::RGBAColor; no_viewport_percentage!(SpecifiedValue); pub mod computed_value { - use values::computed::CSSColor; + use cssparser::RGBA; #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - pub struct T(pub Option>); + pub struct T(pub Option>); } #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { None, - Colors(Vec), + Colors(Vec), } impl ToCss for computed_value::T { @@ -168,7 +168,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style', } let mut result = Vec::new(); - while let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + while let Ok(value) = input.try(|i| RGBAColor::parse(context, i)) { result.push(value); } diff --git a/components/style/properties/longhand/svg.mako.rs b/components/style/properties/longhand/svg.mako.rs index c9704795b8a..9021121f370 100644 --- a/components/style/properties/longhand/svg.mako.rs +++ b/components/style/properties/longhand/svg.mako.rs @@ -20,8 +20,8 @@ ${helpers.single_keyword("vector-effect", "none non-scaling-stroke", // Section 13 - Gradients and Patterns ${helpers.predefined_type( - "stop-color", "CSSColor", - "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))", + "stop-color", "RGBAColor", + "RGBA::new(0, 0, 0, 255)", products="gecko", animation_value_type="none", spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")} @@ -34,8 +34,8 @@ ${helpers.predefined_type("stop-opacity", "Opacity", "1.0", // Section 15 - Filter Effects ${helpers.predefined_type( - "flood-color", "CSSColor", - "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))", + "flood-color", "RGBAColor", + "RGBA::new(0, 0, 0, 255)", products="gecko", animation_value_type="none", spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")} @@ -45,8 +45,8 @@ ${helpers.predefined_type("flood-opacity", "Opacity", spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty")} ${helpers.predefined_type( - "lighting-color", "CSSColor", - "CSSParserColor::RGBA(RGBA::new(255, 255, 255, 255))", + "lighting-color", "RGBAColor", + "RGBA::new(255, 255, 255, 255)", products="gecko", animation_value_type="none", spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")} diff --git a/components/style/values/computed/color.rs b/components/style/values/computed/color.rs new file mode 100644 index 00000000000..b77f55d0453 --- /dev/null +++ b/components/style/values/computed/color.rs @@ -0,0 +1,10 @@ +/* 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/. */ + +//! Computed color values. + +use cssparser::RGBA; + +/// Computed value type for the specified RGBAColor. +pub type RGBAColor = RGBA; diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs index 5f51dd22f85..3718be2fbd3 100644 --- a/components/style/values/computed/image.rs +++ b/components/style/values/computed/image.rs @@ -7,7 +7,7 @@ //! //! [image]: https://drafts.csswg.org/css-images/#image-values -use cssparser::Color as CSSColor; +use cssparser::RGBA; use std::f32::consts::PI; use std::fmt; use style_traits::ToCss; @@ -35,7 +35,7 @@ pub type Gradient = GenericGradient< Length, LengthOrPercentage, Position, - CSSColor, + RGBA, >; /// A computed gradient kind. @@ -60,10 +60,10 @@ pub enum LineDirection { pub type EndingShape = GenericEndingShape; /// A computed gradient item. -pub type GradientItem = GenericGradientItem; +pub type GradientItem = GenericGradientItem; /// A computed color stop. -pub type ColorStop = GenericColorStop; +pub type ColorStop = GenericColorStop; /// Computed values for ImageRect. pub type ImageRect = GenericImageRect; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 9c9e23887a8..b5bb04a8963 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -28,6 +28,7 @@ pub use properties::animated_properties::TransitionProperty; pub use self::background::BackgroundSize; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; pub use self::border::{BorderRadius, BorderCornerRadius}; +pub use self::color::RGBAColor; pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -48,6 +49,7 @@ pub use self::transform::{TimingFunction, TransformOrigin}; pub mod background; pub mod basic_shape; pub mod border; +pub mod color; pub mod image; #[cfg(feature = "gecko")] pub mod gecko; @@ -479,9 +481,9 @@ impl IntegerOrAuto { } /// Computed SVG Paint value -pub type SVGPaint = ::values::generics::SVGPaint; +pub type SVGPaint = ::values::generics::SVGPaint; /// Computed SVG Paint Kind value -pub type SVGPaintKind = ::values::generics::SVGPaintKind; +pub type SVGPaintKind = ::values::generics::SVGPaintKind; impl Default for SVGPaint { fn default() -> Self { @@ -497,7 +499,7 @@ impl SVGPaint { pub fn black() -> Self { let rgba = RGBA::from_floats(0., 0., 0., 1.); SVGPaint { - kind: ::values::generics::SVGPaintKind::Color(CSSColor::RGBA(rgba)), + kind: ::values::generics::SVGPaintKind::Color(rgba), fallback: None, } } diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 538506bfce9..64ef534a337 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -313,3 +313,56 @@ impl ToComputedValue for CSSColor { }).into() } } + +/// Specified color value, but resolved to just RGBA for computed value +/// with value from color property at the same context. +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct RGBAColor(pub CSSColor); + +no_viewport_percentage!(RGBAColor); + +impl Parse for RGBAColor { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + CSSColor::parse(context, input).map(RGBAColor) + } +} + +impl ToCss for RGBAColor { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.0.to_css(dest) + } +} + +impl ToComputedValue for RGBAColor { + type ComputedValue = RGBA; + + fn to_computed_value(&self, context: &Context) -> RGBA { + match self.0.to_computed_value(context) { + CSSParserColor::RGBA(rgba) => rgba, + CSSParserColor::CurrentColor => context.style.get_color().clone_color(), + } + } + + fn from_computed_value(computed: &RGBA) -> Self { + RGBAColor(CSSColor { + parsed: Color::RGBA(*computed), + authored: None, + }) + } +} + +impl From for RGBAColor { + fn from(color: Color) -> RGBAColor { + RGBAColor(CSSColor { + parsed: color, + authored: None, + }) + } +} + +impl From for RGBAColor { + fn from(color: CSSColor) -> RGBAColor { + RGBAColor(color) + } +} diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 4564bc0993f..a4441bcda67 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -25,7 +25,7 @@ use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExten use values::generics::image::PaintWorklet; use values::generics::position::Position as GenericPosition; use values::specified::{Angle, CSSColor, Color, Length, LengthOrPercentage}; -use values::specified::{Number, NumberOrPercentage, Percentage}; +use values::specified::{Number, NumberOrPercentage, Percentage, RGBAColor}; use values::specified::position::{Position, PositionComponent, Side, X, Y}; use values::specified::url::SpecifiedUrl; @@ -43,7 +43,7 @@ pub type Gradient = GenericGradient< Length, LengthOrPercentage, Position, - CSSColor, + RGBAColor, >; /// A specified gradient kind. @@ -72,10 +72,10 @@ pub enum LineDirection { pub type EndingShape = GenericEndingShape; /// A specified gradient item. -pub type GradientItem = GenericGradientItem; +pub type GradientItem = GenericGradientItem; /// A computed color stop. -pub type ColorStop = GenericColorStop; +pub type ColorStop = GenericColorStop; /// Specified values for `moz-image-rect` /// -moz-image-rect(, top, right, bottom, left); @@ -390,7 +390,7 @@ impl Gradient { if color.parsed == Color::CurrentColor { return Err(()); } - Ok((color, p)) + Ok((color.into(), p)) })?; if reverse_stops { p = 1. - p; @@ -405,11 +405,11 @@ impl Gradient { if items.is_empty() { items = vec![ GenericGradientItem::ColorStop(GenericColorStop { - color: CSSColor::transparent(), + color: CSSColor::transparent().into(), position: Some(Percentage(0.).into()), }), GenericGradientItem::ColorStop(GenericColorStop { - color: CSSColor::transparent(), + color: CSSColor::transparent().into(), position: Some(Percentage(1.).into()), }), ]; @@ -674,7 +674,7 @@ impl GradientItem { impl Parse for ColorStop { fn parse(context: &ParserContext, input: &mut Parser) -> Result { Ok(ColorStop { - color: try!(CSSColor::parse(context, input)), + color: try!(RGBAColor::parse(context, input)), position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(), }) } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 7be15aba77c..b157498ff61 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -31,7 +31,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify pub use self::background::BackgroundSize; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth}; -pub use self::color::{CSSColor, Color}; +pub use self::color::{CSSColor, Color, RGBAColor}; pub use self::rect::LengthOrNumberRect; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -799,10 +799,10 @@ impl Shadow { no_viewport_percentage!(SVGPaint); /// Specified SVG Paint value -pub type SVGPaint = ::values::generics::SVGPaint; +pub type SVGPaint = ::values::generics::SVGPaint; /// Specified SVG Paint Kind value -pub type SVGPaintKind = ::values::generics::SVGPaintKind; +pub type SVGPaintKind = ::values::generics::SVGPaintKind; impl ToComputedValue for SVGPaint { type ComputedValue = super::computed::SVGPaint; @@ -829,12 +829,7 @@ impl ToComputedValue for SVGPaintKind { #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - self.convert(|color| { - match color.parsed { - Color::CurrentColor => cssparser::Color::RGBA(context.style().get_color().clone_color()), - _ => color.to_computed_value(context), - } - }) + self.convert(|color| color.to_computed_value(context)) } #[inline] From 7568a196885ed1f1ed2a38aa30d733e66a8e866e Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:27 +1000 Subject: [PATCH 07/10] Merge CSSColor into Color. --- components/script/dom/element.rs | 11 +- components/style/properties/gecko.mako.rs | 21 +- .../properties/longhand/background.mako.rs | 2 +- .../style/properties/longhand/border.mako.rs | 2 +- .../style/properties/longhand/color.mako.rs | 16 +- .../style/properties/longhand/column.mako.rs | 4 +- .../longhand/inherited_text.mako.rs | 10 +- .../style/properties/longhand/outline.mako.rs | 4 +- .../style/properties/longhand/text.mako.rs | 6 +- .../style/properties/properties.mako.rs | 3 +- .../properties/shorthand/background.mako.rs | 6 +- .../style/properties/shorthand/border.mako.rs | 10 +- .../properties/shorthand/outline.mako.rs | 2 +- .../properties/shorthand/serialize.mako.rs | 6 +- .../style/properties/shorthand/text.mako.rs | 2 +- components/style/rule_tree/mod.rs | 3 +- components/style/values/computed/mod.rs | 6 +- components/style/values/specified/color.rs | 239 ++++++++---------- components/style/values/specified/image.rs | 10 +- components/style/values/specified/mod.rs | 8 +- ports/geckolib/glue.rs | 8 +- tests/unit/style/parsing/ui.rs | 8 +- tests/unit/style/properties/serialization.rs | 49 +--- tests/unit/style/stylesheets.rs | 4 +- .../html/cssstyledeclaration-csstext.htm.ini | 5 - 25 files changed, 181 insertions(+), 264 deletions(-) delete mode 100644 tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 5353fd7e9ab..58a1200b915 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -111,7 +111,7 @@ use style::stylearc::Arc; use style::stylist::ApplicableDeclarationBlock; use style::thread_state; use style::values::{CSSFloat, Either}; -use style::values::specified::{self, CSSColor, Color}; +use style::values::specified; use stylesheet_loader::StylesheetOwner; // TODO: Update focus state when the top-level browsing context gains or loses system focus, @@ -420,8 +420,8 @@ impl LayoutElementHelpers for LayoutJS { if let Some(color) = bgcolor { hints.push(from_declaration( shared_lock, - PropertyDeclaration::BackgroundColor( - CSSColor { parsed: Color::RGBA(color), authored: None }))); + PropertyDeclaration::BackgroundColor(color.into()) + )); } let background = if let Some(this) = self.downcast::() { @@ -455,10 +455,7 @@ impl LayoutElementHelpers for LayoutJS { hints.push(from_declaration( shared_lock, PropertyDeclaration::Color( - longhands::color::SpecifiedValue(CSSColor { - parsed: Color::RGBA(color), - authored: None, - }) + longhands::color::SpecifiedValue(color.into()) ) )); } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index fb8a0ea8970..721598b66f9 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -319,16 +319,7 @@ def set_gecko_property(ffi_name, expr): #[allow(unreachable_code)] #[allow(non_snake_case)] pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - % if complex_color: - let result = v.into(); - % else: - let result = match color { - Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba), - // FIXME handle currentcolor - Color::CurrentColor => 0, - }; - % endif - ${set_gecko_property(gecko_ffi_name, "result")} + ${set_gecko_property(gecko_ffi_name, "v.into()")} } @@ -343,11 +334,7 @@ def set_gecko_property(ffi_name, expr): <%def name="impl_color_clone(ident, gecko_ffi_name, complex_color=True)"> #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - % if complex_color: - ${get_gecko_property(gecko_ffi_name)}.into() - % else: - Color::RGBA(convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})) - % endif + ${get_gecko_property(gecko_ffi_name)}.into() } @@ -721,7 +708,7 @@ impl Debug for ${style_struct.gecko_struct_name} { "Number": impl_simple, "Integer": impl_simple, "Opacity": impl_simple, - "CSSColor": impl_color, + "Color": impl_color, "RGBAColor": impl_rgba_color, "SVGPaint": impl_svg_paint, "UrlOrNone": impl_css_url, @@ -742,8 +729,6 @@ impl Debug for ${style_struct.gecko_struct_name} { args.update(cast_type=longhand.cast_type) else: method = predefined_types[longhand.predefined_type] - if longhand.predefined_type in ["CSSColor"]: - args.update(complex_color=longhand.complex_color) method(**args) diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 4937a2569b0..273fc43eac5 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -6,7 +6,7 @@ <% data.new_style_struct("Background", inherited=False) %> -${helpers.predefined_type("background-color", "CSSColor", +${helpers.predefined_type("background-color", "Color", "::cssparser::Color::RGBA(::cssparser::RGBA::transparent())", initial_specified_value="SpecifiedValue::transparent()", spec="https://drafts.csswg.org/css-backgrounds/#background-color", diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index 142825cabda..8c0bf0aa9f2 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -16,7 +16,7 @@ return "https://drafts.csswg.org/css-backgrounds/#border-%s-%s" % (side[0], kind) %> % for side in ALL_SIDES: - ${helpers.predefined_type("border-%s-color" % side[0], "CSSColor", + ${helpers.predefined_type("border-%s-color" % side[0], "Color", "::cssparser::Color::CurrentColor", alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"), spec=maybe_logical_spec(side, "color"), diff --git a/components/style/properties/longhand/color.mako.rs b/components/style/properties/longhand/color.mako.rs index 0728516ab41..bcdd97dedb0 100644 --- a/components/style/properties/longhand/color.mako.rs +++ b/components/style/properties/longhand/color.mako.rs @@ -12,26 +12,30 @@ animation_value_type="IntermediateRGBA" ignored_when_colors_disabled="True" spec="https://drafts.csswg.org/css-color/#color"> - use cssparser::RGBA; - use values::specified::{AllowQuirks, Color, CSSColor}; + use cssparser::{Color as CSSParserColor, RGBA}; + use values::specified::{AllowQuirks, Color}; impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - self.0.parsed.to_computed_value(context) + match self.0.to_computed_value(context) { + CSSParserColor::RGBA(rgba) => rgba, + CSSParserColor::CurrentColor => + context.inherited_style.get_color().clone_color(), + } } #[inline] fn from_computed_value(computed: &computed_value::T) -> Self { - SpecifiedValue(Color::RGBA(*computed).into()) + SpecifiedValue(Color::rgba(*computed).into()) } } #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq, ToCss)] - pub struct SpecifiedValue(pub CSSColor); + pub struct SpecifiedValue(pub Color); no_viewport_percentage!(SpecifiedValue); pub mod computed_value { @@ -43,7 +47,7 @@ RGBA::new(0, 0, 0, 255) // black } pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { - CSSColor::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue) + Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue) } // FIXME(#15973): Add servo support for system colors diff --git a/components/style/properties/longhand/column.mako.rs b/components/style/properties/longhand/column.mako.rs index 2c99a7f1dc3..5b7ea05073d 100644 --- a/components/style/properties/longhand/column.mako.rs +++ b/components/style/properties/longhand/column.mako.rs @@ -51,9 +51,9 @@ ${helpers.predefined_type("column-rule-width", extra_prefixes="moz")} // https://drafts.csswg.org/css-multicol-1/#crc -${helpers.predefined_type("column-rule-color", "CSSColor", +${helpers.predefined_type("column-rule-color", "Color", "::cssparser::Color::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", extra_prefixes="moz", complex_color=True, need_clone=True, ignored_when_colors_disabled=True, diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index 9b4004712ec..2e0b9cd0d39 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -685,9 +685,9 @@ ${helpers.predefined_type("word-spacing", % endif -${helpers.predefined_type("text-emphasis-color", "CSSColor", +${helpers.predefined_type("text-emphasis-color", "Color", "::cssparser::Color::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", complex_color=True, need_clone=True, ignored_when_colors_disabled=True, @@ -705,7 +705,7 @@ ${helpers.predefined_type( // CSS Compatibility // https://compat.spec.whatwg.org ${helpers.predefined_type( - "-webkit-text-fill-color", "CSSColor", + "-webkit-text-fill-color", "Color", "CSSParserColor::CurrentColor", products="gecko", animation_value_type="IntermediateColor", complex_color=True, need_clone=True, @@ -713,9 +713,9 @@ ${helpers.predefined_type( spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")} ${helpers.predefined_type( - "-webkit-text-stroke-color", "CSSColor", + "-webkit-text-stroke-color", "Color", "CSSParserColor::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", complex_color=True, need_clone=True, ignored_when_colors_disabled=True, diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index 1640953e305..51a0aea350e 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -10,8 +10,8 @@ additional_methods=[Method("outline_has_nonzero_width", "bool")]) %> // TODO(pcwalton): `invert` -${helpers.predefined_type("outline-color", "CSSColor", "computed::CSSColor::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", +${helpers.predefined_type("outline-color", "Color", "computed::Color::CurrentColor", + initial_specified_value="specified::Color::currentcolor()", animation_value_type="IntermediateColor", complex_color=True, need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")} diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index d636ed3cb64..04af1b35924 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -278,9 +278,9 @@ ${helpers.single_keyword("text-decoration-style", spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")} ${helpers.predefined_type( - "text-decoration-color", "CSSColor", - "computed::CSSColor::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", + "text-decoration-color", "Color", + "computed::Color::CurrentColor", + initial_specified_value="specified::Color::currentcolor()", complex_color=True, products="gecko", animation_value_type="IntermediateColor", diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a0264d41e8c..d9d95a82024 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -40,7 +40,6 @@ use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraDat #[cfg(feature = "servo")] use values::Either; use values::generics::text::LineHeight; use values::computed; -use values::specified::Color; use cascade_info::CascadeInfo; use rule_tree::{CascadeLevel, StrongRuleNode}; use style_adjuster::StyleAdjuster; @@ -2626,7 +2625,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device, let ignore_colors = !device.use_document_colors(); let default_background_color_decl = if ignore_colors { let color = device.default_background_color(); - Some(PropertyDeclaration::BackgroundColor(Color::RGBA(color).into())) + Some(PropertyDeclaration::BackgroundColor(color.into())) } else { None }; diff --git a/components/style/properties/shorthand/background.mako.rs b/components/style/properties/shorthand/background.mako.rs index 36652a73520..3767d80bed9 100644 --- a/components/style/properties/shorthand/background.mako.rs +++ b/components/style/properties/shorthand/background.mako.rs @@ -15,7 +15,7 @@ use properties::longhands::background_clip; use properties::longhands::background_clip::single_value::computed_value::T as Clip; use properties::longhands::background_origin::single_value::computed_value::T as Origin; - use values::specified::{CSSColor, Position, PositionComponent}; + use values::specified::{Color, Position, PositionComponent}; use parser::Parse; impl From for background_clip::single_value::SpecifiedValue { @@ -50,7 +50,7 @@ % endfor loop { if background_color.is_none() { - if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { background_color = Some(value); continue } @@ -112,7 +112,7 @@ })); Ok(expanded! { - background_color: background_color.unwrap_or(CSSColor::transparent()), + background_color: background_color.unwrap_or(Color::transparent()), background_image: background_image, background_position_x: background_position_x, background_position_y: background_position_y, diff --git a/components/style/properties/shorthand/border.mako.rs b/components/style/properties/shorthand/border.mako.rs index c84549a544f..b5ebe773c66 100644 --- a/components/style/properties/shorthand/border.mako.rs +++ b/components/style/properties/shorthand/border.mako.rs @@ -5,7 +5,7 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> <% from data import to_rust_ident, ALL_SIDES, PHYSICAL_SIDES, maybe_moz_logical_alias %> -${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse", +${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Color::parse", spec="https://drafts.csswg.org/css-backgrounds/#border-color", allow_quirks=True)} @@ -44,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style", pub fn parse_border(context: &ParserContext, input: &mut Parser) - -> Result<(specified::CSSColor, + -> Result<(specified::Color, specified::BorderStyle, specified::BorderSideWidth), ()> { - use values::specified::{CSSColor, BorderStyle, BorderSideWidth}; + use values::specified::{Color, BorderStyle, BorderSideWidth}; let _unused = context; let mut color = None; let mut style = None; @@ -55,7 +55,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) let mut any = false; loop { if color.is_none() { - if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { color = Some(value); any = true; continue @@ -78,7 +78,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) break } if any { - Ok((color.unwrap_or_else(|| CSSColor::currentcolor()), + Ok((color.unwrap_or_else(|| Color::currentcolor()), style.unwrap_or(BorderStyle::none), width.unwrap_or(BorderSideWidth::Medium))) } else { diff --git a/components/style/properties/shorthand/outline.mako.rs b/components/style/properties/shorthand/outline.mako.rs index 8a1ab5900da..649651c02d9 100644 --- a/components/style/properties/shorthand/outline.mako.rs +++ b/components/style/properties/shorthand/outline.mako.rs @@ -18,7 +18,7 @@ let mut any = false; loop { if color.is_none() { - if let Ok(value) = input.try(|i| specified::CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| specified::Color::parse(context, i)) { color = Some(value); any = true; continue diff --git a/components/style/properties/shorthand/serialize.mako.rs b/components/style/properties/shorthand/serialize.mako.rs index f8c1ef9bc3e..a86704a5488 100644 --- a/components/style/properties/shorthand/serialize.mako.rs +++ b/components/style/properties/shorthand/serialize.mako.rs @@ -3,18 +3,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use style_traits::ToCss; -use values::specified::{BorderStyle, Color, CSSColor}; +use values::specified::{BorderStyle, Color}; use std::fmt; fn serialize_directional_border(dest: &mut W, width: &I, style: &BorderStyle, - color: &CSSColor) + color: &Color) -> fmt::Result where W: fmt::Write, I: ToCss { width.to_css(dest)?; dest.write_str(" ")?; style.to_css(dest)?; - if color.parsed != Color::CurrentColor { + if *color != Color::CurrentColor { dest.write_str(" ")?; color.to_css(dest)?; } diff --git a/components/style/properties/shorthand/text.mako.rs b/components/style/properties/shorthand/text.mako.rs index c5e7ba12c5e..111adb4de1b 100644 --- a/components/style/properties/shorthand/text.mako.rs +++ b/components/style/properties/shorthand/text.mako.rs @@ -70,7 +70,7 @@ self.text_decoration_style.to_css(dest)?; } - if self.text_decoration_color.parsed != specified::Color::CurrentColor { + if *self.text_decoration_color != specified::Color::CurrentColor { dest.write_str(" ")?; self.text_decoration_color.to_css(dest)?; } diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 37e7334b9db..c51f6f94ff7 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -912,7 +912,6 @@ impl StrongRuleNode { -> bool where E: ::dom::TElement { - use cssparser::RGBA; use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_BACKGROUND, NS_AUTHOR_SPECIFIED_BORDER}; use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_PADDING, NS_AUTHOR_SPECIFIED_TEXT_SHADOW}; use properties::{CSSWideKeyword, LonghandId, LonghandIdSet}; @@ -1083,7 +1082,7 @@ impl StrongRuleNode { if properties.contains(id) { if !author_colors_allowed { if let PropertyDeclaration::BackgroundColor(ref color) = *declaration { - return color.parsed == Color::RGBA(RGBA::transparent()) + return *color == Color::transparent() } } return true diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index b5bb04a8963..50ad4bbb82d 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -23,7 +23,7 @@ use super::generics::grid::TrackList as GenericTrackList; use super::specified; pub use app_units::Au; -pub use cssparser::Color as CSSColor; +pub use cssparser::Color; pub use properties::animated_properties::TransitionProperty; pub use self::background::BackgroundSize; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; @@ -402,7 +402,7 @@ pub struct Shadow { pub offset_y: Au, pub blur_radius: Au, pub spread_radius: Au, - pub color: CSSColor, + pub color: Color, pub inset: bool, } @@ -584,4 +584,4 @@ impl ClipRectOrAuto { } /// | auto -pub type ColorOrAuto = Either; +pub type ColorOrAuto = Either; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 64ef534a337..d18bd574479 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -4,7 +4,9 @@ //! Specified color values. -use cssparser::{self, Color as CSSParserColor, Parser, RGBA, Token}; +use cssparser::{Color as CSSParserColor, Parser, RGBA, Token}; +#[cfg(feature = "gecko")] +use gecko_bindings::structs::nscolor; use itoa; use parser::{ParserContext, Parse}; #[cfg(feature = "gecko")] @@ -16,13 +18,18 @@ use super::AllowQuirks; use values::computed::{Context, ToComputedValue}; /// Specified color value -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum Color { /// The 'currentColor' keyword CurrentColor, /// A specific RGBA color - RGBA(RGBA), + Numeric { + /// Parsed RGBA color + parsed: RGBA, + /// Authored representation + authored: Option>, + }, /// A system color #[cfg(feature = "gecko")] @@ -50,25 +57,31 @@ mod gecko { } } -impl From for Color { - fn from(value: CSSParserColor) -> Self { - match value { - CSSParserColor::CurrentColor => Color::CurrentColor, - CSSParserColor::RGBA(x) => Color::RGBA(x), - } - } -} - impl From for Color { fn from(value: RGBA) -> Self { - Color::RGBA(value) + Color::rgba(value) } } impl Parse for Color { fn parse(_: &ParserContext, input: &mut Parser) -> Result { + // Currently we only store authored value for color keywords, + // because all browsers serialize those values as keywords for + // specified value. + let start_position = input.position(); + let authored = match input.next() { + Ok(Token::Ident(s)) => Some(s.to_lowercase().into_boxed_str()), + _ => None, + }; + input.reset(start_position); if let Ok(value) = input.try(CSSParserColor::parse) { - Ok(value.into()) + Ok(match value { + CSSParserColor::CurrentColor => Color::CurrentColor, + CSSParserColor::RGBA(rgba) => Color::Numeric { + parsed: rgba, + authored: authored, + }, + }) } else { #[cfg(feature = "gecko")] { if let Ok(system) = input.try(SystemColor::parse) { @@ -88,7 +101,8 @@ impl ToCss for Color { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), - Color::RGBA(rgba) => rgba.to_css(dest), + Color::Numeric { authored: Some(ref authored), .. } => dest.write_str(authored), + Color::Numeric { parsed: ref rgba, .. } => rgba.to_css(dest), #[cfg(feature = "gecko")] Color::System(system) => system.to_css(dest), #[cfg(feature = "gecko")] @@ -99,21 +113,44 @@ impl ToCss for Color { } } -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub struct CSSColor { - pub parsed: Color, - pub authored: Option>, +/// A wrapper of cssparser::Color::parse_hash. +/// +/// That function should never return CurrentColor, so it makes no sense +/// to handle a cssparser::Color here. This should really be done in +/// cssparser directly rather than here. +fn parse_hash_color(value: &[u8]) -> Result { + CSSParserColor::parse_hash(value).map(|color| { + match color { + CSSParserColor::RGBA(rgba) => rgba, + CSSParserColor::CurrentColor => + unreachable!("parse_hash should never return currentcolor"), + } + }) } -impl Parse for CSSColor { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - Self::parse_quirky(context, input, AllowQuirks::No) +impl Color { + /// Returns currentcolor value. + #[inline] + pub fn currentcolor() -> Color { + Color::CurrentColor + } + + /// Returns transparent value. + #[inline] + pub fn transparent() -> Color { + // We should probably set authored to "transparent", but maybe it doesn't matter. + Color::rgba(RGBA::transparent()) + } + + /// Returns a numeric RGBA color value. + #[inline] + pub fn rgba(rgba: RGBA) -> Self { + Color::Numeric { + parsed: rgba, + authored: None, + } } -} -impl CSSColor { /// Parse a color, with quirks. /// /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk @@ -121,21 +158,18 @@ impl CSSColor { input: &mut Parser, allow_quirks: AllowQuirks) -> Result { - let start_position = input.position(); - let authored = match input.next() { - Ok(Token::Ident(s)) => Some(s.into_owned().into_boxed_str()), - _ => None, - }; - input.reset(start_position); - if let Ok(parsed) = input.try(|i| Parse::parse(context, i)) { - return Ok(CSSColor { - parsed: parsed, - authored: authored, - }); - } - if !allow_quirks.allowed(context.quirks_mode) { - return Err(()); - } + input.try(|i| Self::parse(context, i)).or_else(|_| { + if !allow_quirks.allowed(context.quirks_mode) { + return Err(()); + } + Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba)) + }) + } + + /// Parse a value. + /// + /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk + fn parse_quirky_color(input: &mut Parser) -> Result { let (number, dimension) = match input.next()? { Token::Number(number) => { (number, None) @@ -147,12 +181,7 @@ impl CSSColor { if ident.len() != 3 && ident.len() != 6 { return Err(()); } - return cssparser::Color::parse_hash(ident.as_bytes()).map(|color| { - Self { - parsed: color.into(), - authored: None - } - }); + return parse_hash_color(ident.as_bytes()); } _ => { return Err(()); @@ -189,72 +218,38 @@ impl CSSColor { written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap(); } debug_assert!(written == 6); - Ok(CSSColor { - parsed: cssparser::Color::parse_hash(&serialization).map(From::from)?, - authored: None, - }) + parse_hash_color(&serialization) } /// Returns false if the color is completely transparent, and /// true otherwise. pub fn is_non_transparent(&self) -> bool { - match self.parsed { - Color::RGBA(rgba) if rgba.alpha == 0 => false, + match *self { + Color::Numeric { ref parsed, .. } => parsed.alpha != 0, _ => true, } } } -no_viewport_percentage!(CSSColor); - -impl ToCss for CSSColor { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match self.authored { - Some(ref s) => dest.write_str(s), - None => self.parsed.to_css(dest), - } - } -} - -impl From for CSSColor { - fn from(color: Color) -> Self { - CSSColor { - parsed: color, - authored: None, - } - } -} - -impl CSSColor { - #[inline] - /// Returns currentcolor value. - pub fn currentcolor() -> CSSColor { - Color::CurrentColor.into() - } - - #[inline] - /// Returns transparent value. - pub fn transparent() -> CSSColor { - // We should probably set authored to "transparent", but maybe it doesn't matter. - Color::RGBA(cssparser::RGBA::transparent()).into() - } +#[cfg(feature = "gecko")] +fn to_rgba(color: nscolor) -> CSSParserColor { + use gecko::values::convert_nscolor_to_rgba; + CSSParserColor::RGBA(convert_nscolor_to_rgba(color)) } impl ToComputedValue for Color { - type ComputedValue = RGBA; + type ComputedValue = CSSParserColor; - fn to_computed_value(&self, context: &Context) -> RGBA { - #[cfg(feature = "gecko")] - use gecko::values::convert_nscolor_to_rgba as to_rgba; + fn to_computed_value(&self, _context: &Context) -> CSSParserColor { match *self { - Color::RGBA(rgba) => rgba, - Color::CurrentColor => context.inherited_style.get_color().clone_color(), + Color::CurrentColor => CSSParserColor::CurrentColor, + Color::Numeric { ref parsed, .. } => CSSParserColor::RGBA(*parsed), #[cfg(feature = "gecko")] - Color::System(system) => to_rgba(system.to_computed_value(context)), + Color::System(system) => to_rgba(system.to_computed_value(_context)), #[cfg(feature = "gecko")] Color::Special(special) => { use self::gecko::SpecialColorKeyword as Keyword; - let pres_context = unsafe { &*context.device.pres_context }; + let pres_context = unsafe { &*_context.device.pres_context }; to_rgba(match special { Keyword::MozDefaultColor => pres_context.mDefaultColor, Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, @@ -268,17 +263,17 @@ impl ToComputedValue for Color { use dom::TElement; use gecko::wrapper::GeckoElement; use gecko_bindings::bindings::Gecko_GetBody; - let pres_context = unsafe { &*context.device.pres_context }; + let pres_context = unsafe { &*_context.device.pres_context }; let body = unsafe { Gecko_GetBody(pres_context) }; if let Some(body) = body { let wrap = GeckoElement(body); let borrow = wrap.borrow_data(); - borrow.as_ref().unwrap() - .styles().primary.values() - .get_color() - .clone_color() + CSSParserColor::RGBA(borrow.as_ref().unwrap() + .styles().primary.values() + .get_color() + .clone_color()) } else { to_rgba(pres_context.mDefaultColor) } @@ -286,31 +281,11 @@ impl ToComputedValue for Color { } } - fn from_computed_value(computed: &RGBA) -> Self { - Color::RGBA(*computed) - } -} - -impl ToComputedValue for CSSColor { - type ComputedValue = CSSParserColor; - - #[inline] - fn to_computed_value(&self, _context: &Context) -> CSSParserColor { - match self.parsed { - Color::RGBA(rgba) => CSSParserColor::RGBA(rgba), - Color::CurrentColor => CSSParserColor::CurrentColor, - // Resolve non-standard -moz keywords to RGBA: - #[cfg(feature = "gecko")] - non_standard => CSSParserColor::RGBA(non_standard.to_computed_value(_context)), - } - } - - #[inline] fn from_computed_value(computed: &CSSParserColor) -> Self { - (match *computed { - CSSParserColor::RGBA(rgba) => Color::RGBA(rgba), - CSSParserColor::CurrentColor => Color::CurrentColor, - }).into() + match *computed { + CSSParserColor::RGBA(rgba) => Color::rgba(rgba), + CSSParserColor::CurrentColor => Color::currentcolor(), + } } } @@ -318,13 +293,13 @@ impl ToComputedValue for CSSColor { /// with value from color property at the same context. #[derive(Clone, PartialEq, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub struct RGBAColor(pub CSSColor); +pub struct RGBAColor(pub Color); no_viewport_percentage!(RGBAColor); impl Parse for RGBAColor { fn parse(context: &ParserContext, input: &mut Parser) -> Result { - CSSColor::parse(context, input).map(RGBAColor) + Color::parse(context, input).map(RGBAColor) } } @@ -345,24 +320,12 @@ impl ToComputedValue for RGBAColor { } fn from_computed_value(computed: &RGBA) -> Self { - RGBAColor(CSSColor { - parsed: Color::RGBA(*computed), - authored: None, - }) + RGBAColor(Color::rgba(*computed)) } } impl From for RGBAColor { fn from(color: Color) -> RGBAColor { - RGBAColor(CSSColor { - parsed: color, - authored: None, - }) - } -} - -impl From for RGBAColor { - fn from(color: CSSColor) -> RGBAColor { RGBAColor(color) } } diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index a4441bcda67..4284f2f2a43 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -24,7 +24,7 @@ use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRe use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExtent}; use values::generics::image::PaintWorklet; use values::generics::position::Position as GenericPosition; -use values::specified::{Angle, CSSColor, Color, Length, LengthOrPercentage}; +use values::specified::{Angle, Color, Length, LengthOrPercentage}; use values::specified::{Number, NumberOrPercentage, Percentage, RGBAColor}; use values::specified::position::{Position, PositionComponent, Side, X, Y}; use values::specified::url::SpecifiedUrl; @@ -386,8 +386,8 @@ impl Gradient { "to" => 1., _ => return Err(()), }; - let color = CSSColor::parse(context, i)?; - if color.parsed == Color::CurrentColor { + let color = Color::parse(context, i)?; + if color == Color::CurrentColor { return Err(()); } Ok((color.into(), p)) @@ -405,11 +405,11 @@ impl Gradient { if items.is_empty() { items = vec![ GenericGradientItem::ColorStop(GenericColorStop { - color: CSSColor::transparent().into(), + color: Color::transparent().into(), position: Some(Percentage(0.).into()), }), GenericGradientItem::ColorStop(GenericColorStop { - color: CSSColor::transparent().into(), + color: Color::transparent().into(), position: Some(Percentage(1.).into()), }), ]; diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index b157498ff61..c0f9c6c96aa 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -31,7 +31,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify pub use self::background::BackgroundSize; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth}; -pub use self::color::{CSSColor, Color, RGBAColor}; +pub use self::color::{Color, RGBAColor}; pub use self::rect::LengthOrNumberRect; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -681,7 +681,7 @@ pub struct Shadow { pub offset_y: Length, pub blur_radius: Length, pub spread_radius: Length, - pub color: Option, + pub color: Option, pub inset: bool, } @@ -771,7 +771,7 @@ impl Shadow { } } if color.is_none() { - if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { color = Some(value); continue } @@ -997,7 +997,7 @@ impl ClipRectOrAuto { } /// | auto -pub type ColorOrAuto = Either; +pub type ColorOrAuto = Either; /// Whether quirks are allowed in this context. #[derive(Clone, Copy, PartialEq)] diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 6363e38deb1..fa08f50e4db 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -2216,10 +2216,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetCurrentColor(declarations: RawServoDeclarationBlockBorrowed, property: nsCSSPropertyID) { use style::properties::{PropertyDeclaration, LonghandId}; - use style::values::specified::{Color, CSSColor}; + use style::values::specified::Color; let long = get_longhand_from_id!(property); - let cc = CSSColor { parsed: Color::CurrentColor, authored: None }; + let cc = Color::currentcolor(); let prop = match_wrap_declared! { long, BorderTopColor => cc, @@ -2240,11 +2240,11 @@ pub extern "C" fn Servo_DeclarationBlock_SetColorValue(declarations: use style::gecko::values::convert_nscolor_to_rgba; use style::properties::{PropertyDeclaration, LonghandId}; use style::properties::longhands; - use style::values::specified::{Color, CSSColor}; + use style::values::specified::Color; let long = get_longhand_from_id!(property); let rgba = convert_nscolor_to_rgba(value); - let color = CSSColor { parsed: Color::RGBA(rgba), authored: None }; + let color = Color::rgba(rgba); let prop = match_wrap_declared! { long, BorderTopColor => color, diff --git a/tests/unit/style/parsing/ui.rs b/tests/unit/style/parsing/ui.rs index 35985a1001e..14d96656b32 100644 --- a/tests/unit/style/parsing/ui.rs +++ b/tests/unit/style/parsing/ui.rs @@ -5,7 +5,7 @@ use cssparser::RGBA; use parsing::parse; use style::values::{Auto, Either}; -use style::values::specified::{CSSColor, Color}; +use style::values::specified::Color; use style_traits::ToCss; #[test] @@ -33,13 +33,13 @@ fn test_caret_color() { let auto = parse_longhand!(caret_color, "auto"); assert_eq!(auto, Either::Second(Auto)); - let blue_color = CSSColor { - parsed: Color::RGBA(RGBA { + let blue_color = Color::Numeric { + parsed: RGBA { red: 0, green: 0, blue: 255, alpha: 255, - }), + }, authored: Some(String::from("blue").into_boxed_str()), }; diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index f3e666ec65f..9ee2877101a 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -8,7 +8,7 @@ use style::properties::{PropertyDeclaration, Importance, PropertyId}; use style::properties::parse_property_declaration_list; use style::values::{RGBA, Auto}; use style::values::CustomIdent; -use style::values::specified::{BorderStyle, BorderSideWidth, CSSColor}; +use style::values::specified::{BorderStyle, BorderSideWidth, Color}; use style::values::specified::{Length, LengthOrPercentage}; use style::values::specified::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent}; use style::values::specified::{NoCalcLength, PositionComponent}; @@ -110,10 +110,7 @@ mod shorthand_serialization { let line = TextDecorationLine::OVERLINE; let style = TextDecorationStyle::dotted; - let color = CSSColor { - parsed: RGBA::new(128, 0, 128, 255).into(), - authored: None - }; + let color = RGBA::new(128, 0, 128, 255).into(); properties.push(PropertyDeclaration::TextDecorationLine(line)); properties.push(PropertyDeclaration::TextDecorationStyle(style)); @@ -129,7 +126,7 @@ mod shorthand_serialization { let line = TextDecorationLine::UNDERLINE; let style = TextDecorationStyle::solid; - let color = CSSColor::currentcolor(); + let color = Color::currentcolor(); properties.push(PropertyDeclaration::TextDecorationLine(line)); properties.push(PropertyDeclaration::TextDecorationStyle(style)); @@ -229,10 +226,7 @@ mod shorthand_serialization { properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone())); properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone())); - let blue = CSSColor { - parsed: RGBA::new(0, 0, 255, 255).into(), - authored: None - }; + let blue = Color::rgba(RGBA::new(0, 0, 255, 255)); properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderRightColor(blue.clone())); @@ -262,10 +256,7 @@ mod shorthand_serialization { properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone())); properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone())); - let blue = CSSColor { - parsed: RGBA::new(0, 0, 255, 255).into(), - authored: None - }; + let blue = Color::rgba(RGBA::new(0, 0, 255, 255)); properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderRightColor(blue.clone())); @@ -332,15 +323,8 @@ mod shorthand_serialization { fn border_color_should_serialize_correctly() { let mut properties = Vec::new(); - let red = CSSColor { - parsed: RGBA::new(255, 0, 0, 255).into(), - authored: None - }; - - let blue = CSSColor { - parsed: RGBA::new(0, 0, 255, 255).into(), - authored: None - }; + let red = Color::rgba(RGBA::new(255, 0, 0, 255)); + let blue = Color::rgba(RGBA::new(0, 0, 255, 255)); properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderRightColor(red.clone())); @@ -405,10 +389,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = BorderStyle::solid; - let color = CSSColor { - parsed: RGBA::new(255, 0, 0, 255).into(), - authored: None - }; + let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::BorderTopWidth(width)); properties.push(PropertyDeclaration::BorderTopStyle(style)); @@ -418,10 +399,10 @@ mod shorthand_serialization { assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);"); } - fn get_border_property_values() -> (BorderSideWidth, BorderStyle, CSSColor) { + fn get_border_property_values() -> (BorderSideWidth, BorderStyle, Color) { (BorderSideWidth::Length(Length::from_px(4f32)), BorderStyle::solid, - CSSColor::currentcolor()) + Color::currentcolor()) } #[test] @@ -532,10 +513,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = Either::Second(BorderStyle::solid); - let color = CSSColor { - parsed: RGBA::new(255, 0, 0, 255).into(), - authored: None - }; + let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineStyle(style)); @@ -551,10 +529,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = Either::First(Auto); - let color = CSSColor { - parsed: RGBA::new(255, 0, 0, 255).into(), - authored: None - }; + let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineStyle(style)); properties.push(PropertyDeclaration::OutlineColor(color)); diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 9b9c08c5b1f..e8967c54c0c 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -158,9 +158,9 @@ fn test_parse_stylesheet() { )), block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![ (PropertyDeclaration::BackgroundColor( - longhands::background_color::SpecifiedValue { + longhands::background_color::SpecifiedValue::Numeric { authored: Some("blue".to_owned().into_boxed_str()), - parsed: cssparser::RGBA::new(0, 0, 255, 255).into(), + parsed: cssparser::RGBA::new(0, 0, 255, 255), } ), Importance::Normal), diff --git a/tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini b/tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini deleted file mode 100644 index 5f750141b21..00000000000 --- a/tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[cssstyledeclaration-csstext.htm] - type: testharness - [uppercase value] - expected: FAIL - From 742c45f8599272fd77cd342ca81621daa76366b6 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:29 +1000 Subject: [PATCH 08/10] Remove complex_color parameter. --- components/style/properties/data.py | 3 +-- components/style/properties/gecko.mako.rs | 16 ++++++++-------- .../style/properties/longhand/background.mako.rs | 1 - .../style/properties/longhand/column.mako.rs | 3 +-- .../properties/longhand/inherited_text.mako.rs | 9 +++------ .../style/properties/longhand/outline.mako.rs | 2 +- .../style/properties/longhand/text.mako.rs | 1 - 7 files changed, 14 insertions(+), 21 deletions(-) diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 06735ef888b..15d9f2fc89a 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -148,7 +148,7 @@ class Longhand(object): def __init__(self, style_struct, name, spec=None, animation_value_type=None, derived_from=None, keyword=None, predefined_type=None, custom_cascade=False, experimental=False, internal=False, need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False, - allowed_in_keyframe_block=True, complex_color=False, cast_type='u8', + allowed_in_keyframe_block=True, cast_type='u8', has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False, flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False, vector=False): @@ -169,7 +169,6 @@ class Longhand(object): self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case self.depend_on_viewport_size = depend_on_viewport_size self.derived_from = (derived_from or "").split() - self.complex_color = complex_color self.cast_type = cast_type self.logical = arg_to_bool(logical) self.alias = alias.split() if alias else [] diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 721598b66f9..1f64cf99daf 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -315,7 +315,7 @@ def set_gecko_property(ffi_name, expr): } -<%def name="impl_color_setter(ident, gecko_ffi_name, complex_color=True)"> +<%def name="impl_color_setter(ident, gecko_ffi_name)"> #[allow(unreachable_code)] #[allow(non_snake_case)] pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { @@ -323,7 +323,7 @@ def set_gecko_property(ffi_name, expr): } -<%def name="impl_color_copy(ident, gecko_ffi_name, complex_color=True)"> +<%def name="impl_color_copy(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn copy_${ident}_from(&mut self, other: &Self) { let color = ${get_gecko_property(gecko_ffi_name, self_param = "other")}; @@ -331,7 +331,7 @@ def set_gecko_property(ffi_name, expr): } -<%def name="impl_color_clone(ident, gecko_ffi_name, complex_color=True)"> +<%def name="impl_color_clone(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { ${get_gecko_property(gecko_ffi_name)}.into() @@ -386,11 +386,11 @@ def set_gecko_property(ffi_name, expr): % endif -<%def name="impl_color(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> -<%call expr="impl_color_setter(ident, gecko_ffi_name, complex_color)"> -<%call expr="impl_color_copy(ident, gecko_ffi_name, complex_color)"> +<%def name="impl_color(ident, gecko_ffi_name, need_clone=False)"> +<%call expr="impl_color_setter(ident, gecko_ffi_name)"> +<%call expr="impl_color_copy(ident, gecko_ffi_name)"> % if need_clone: - <%call expr="impl_color_clone(ident, gecko_ffi_name, complex_color)"> + <%call expr="impl_color_clone(ident, gecko_ffi_name)"> % endif @@ -408,7 +408,7 @@ def set_gecko_property(ffi_name, expr): % endif -<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> +<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { use values::generics::SVGPaintKind; diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 273fc43eac5..3b2a2e6760f 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -11,7 +11,6 @@ ${helpers.predefined_type("background-color", "Color", initial_specified_value="SpecifiedValue::transparent()", spec="https://drafts.csswg.org/css-backgrounds/#background-color", animation_value_type="IntermediateColor", - complex_color=True, ignored_when_colors_disabled=True, allow_quirks=True)} diff --git a/components/style/properties/longhand/column.mako.rs b/components/style/properties/longhand/column.mako.rs index 5b7ea05073d..56d481b719d 100644 --- a/components/style/properties/longhand/column.mako.rs +++ b/components/style/properties/longhand/column.mako.rs @@ -55,8 +55,7 @@ ${helpers.predefined_type("column-rule-color", "Color", "::cssparser::Color::CurrentColor", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", extra_prefixes="moz", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")} ${helpers.single_keyword("column-span", "none all", diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index 2e0b9cd0d39..a8f055663c2 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -689,8 +689,7 @@ ${helpers.predefined_type("text-emphasis-color", "Color", "::cssparser::Color::CurrentColor", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")} @@ -708,8 +707,7 @@ ${helpers.predefined_type( "-webkit-text-fill-color", "Color", "CSSParserColor::CurrentColor", products="gecko", animation_value_type="IntermediateColor", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")} ${helpers.predefined_type( @@ -717,8 +715,7 @@ ${helpers.predefined_type( "CSSParserColor::CurrentColor", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")} ${helpers.predefined_type("-webkit-text-stroke-width", diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index 51a0aea350e..ec08fa43972 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -12,7 +12,7 @@ // TODO(pcwalton): `invert` ${helpers.predefined_type("outline-color", "Color", "computed::Color::CurrentColor", initial_specified_value="specified::Color::currentcolor()", - animation_value_type="IntermediateColor", complex_color=True, need_clone=True, + animation_value_type="IntermediateColor", need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")} diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index 04af1b35924..c4bbe26c0e5 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -281,7 +281,6 @@ ${helpers.predefined_type( "text-decoration-color", "Color", "computed::Color::CurrentColor", initial_specified_value="specified::Color::currentcolor()", - complex_color=True, products="gecko", animation_value_type="IntermediateColor", ignored_when_colors_disabled=True, From c62935577a36ea98c9d625747cc3e4387ee9941e Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:31 +1000 Subject: [PATCH 09/10] Add separate computed Color value. --- Cargo.lock | 1 - components/layout/Cargo.toml | 1 - components/layout/lib.rs | 1 - components/layout/table_cell.rs | 2 +- components/layout/table_row.rs | 5 +- .../sugar/ns_css_shadow_item.rs | 17 +- .../sugar/style_complex_color.rs | 30 ++- .../helpers/animated_properties.mako.rs | 174 ++++++++++++------ .../properties/longhand/background.mako.rs | 2 +- .../style/properties/longhand/border.mako.rs | 2 +- .../style/properties/longhand/color.mako.rs | 9 +- .../style/properties/longhand/column.mako.rs | 2 +- .../longhand/inherited_text.mako.rs | 6 +- .../style/properties/longhand/outline.mako.rs | 2 +- .../style/properties/longhand/text.mako.rs | 2 +- .../style/properties/properties.mako.rs | 9 +- components/style/values/computed/color.rs | 136 +++++++++++++- components/style/values/computed/mod.rs | 3 +- components/style/values/specified/color.rs | 50 ++--- components/style/values/specified/mod.rs | 8 +- 20 files changed, 317 insertions(+), 145 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38414c4669a..217bc8c7dec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1419,7 +1419,6 @@ dependencies = [ "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "canvas_traits 0.0.1", - "cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index 763ac1288a4..e9679887da6 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -14,7 +14,6 @@ app_units = "0.4.1" atomic_refcell = "0.1" bitflags = "0.7" canvas_traits = {path = "../canvas_traits"} -cssparser = "0.13.7" euclid = "0.13" fnv = "1.0" gfx = {path = "../gfx"} diff --git a/components/layout/lib.rs b/components/layout/lib.rs index 65923c10554..ca85d83e9d1 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -16,7 +16,6 @@ extern crate atomic_refcell; extern crate bitflags; extern crate canvas_traits; extern crate core; -extern crate cssparser; extern crate euclid; extern crate fnv; extern crate gfx; diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 8c54297d4b5..47f74891488 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -9,7 +9,6 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use context::LayoutContext; -use cssparser::Color; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use flow::{self, Flow, FlowClass, IS_ABSOLUTELY_POSITIONED, OpaqueFlow}; @@ -22,6 +21,7 @@ use std::fmt; use style::computed_values::{border_collapse, border_top_style, vertical_align}; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; use style::properties::ServoComputedValues; +use style::values::computed::Color; use table::InternalTable; use table_row::{CollapsedBorder, CollapsedBorderProvenance}; diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 8d074f59c52..2fb61a336de 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -9,7 +9,6 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer}; use context::LayoutContext; -use cssparser::{Color, RGBA}; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState}; use euclid::Point2D; use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; @@ -26,7 +25,7 @@ use style::computed_values::{border_collapse, border_spacing, border_top_style}; use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode}; use style::properties::ServoComputedValues; use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW}; -use style::values::computed::LengthOrPercentageOrAuto; +use style::values::computed::{Color, LengthOrPercentageOrAuto}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt}; use table_cell::{CollapsedBordersForCell, TableCellFlow}; @@ -606,7 +605,7 @@ impl CollapsedBorder { CollapsedBorder { style: border_top_style::T::none, width: Au(0), - color: Color::RGBA(RGBA::transparent()), + color: Color::transparent(), provenance: CollapsedBorderProvenance::FromTable, } } diff --git a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs index 003da073b23..fe818d71330 100644 --- a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs +++ b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs @@ -5,10 +5,9 @@ //! Rust helpers for Gecko's `nsCSSShadowItem`. use app_units::Au; -use cssparser::Color; use gecko::values::{convert_rgba_to_nscolor, convert_nscolor_to_rgba}; use gecko_bindings::structs::nsCSSShadowItem; -use values::computed::Shadow; +use values::computed::{Color, Shadow}; impl nsCSSShadowItem { /// Set this item to the given shadow value. @@ -18,14 +17,14 @@ impl nsCSSShadowItem { self.mRadius = other.blur_radius.0; self.mSpread = other.spread_radius.0; self.mInset = other.inset; - self.mColor = match other.color { - Color::RGBA(rgba) => { - self.mHasColor = true; - convert_rgba_to_nscolor(&rgba) - }, + if other.color.is_currentcolor() { // TODO handle currentColor // https://bugzilla.mozilla.org/show_bug.cgi?id=760345 - Color::CurrentColor => 0, + self.mHasColor = false; + self.mColor = 0; + } else { + self.mHasColor = true; + self.mColor = convert_rgba_to_nscolor(&other.color.color); } } @@ -37,7 +36,7 @@ impl nsCSSShadowItem { blur_radius: Au(self.mRadius), spread_radius: Au(self.mSpread), inset: self.mInset, - color: Color::RGBA(convert_nscolor_to_rgba(self.mColor)), + color: Color::rgba(convert_nscolor_to_rgba(self.mColor)), } } } diff --git a/components/style/gecko_bindings/sugar/style_complex_color.rs b/components/style/gecko_bindings/sugar/style_complex_color.rs index 47d9046e874..6b166384aed 100644 --- a/components/style/gecko_bindings/sugar/style_complex_color.rs +++ b/components/style/gecko_bindings/sugar/style_complex_color.rs @@ -4,10 +4,10 @@ //! Rust helpers to interact with Gecko's StyleComplexColor. -use cssparser; use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; use gecko_bindings::structs::{nscolor, StyleComplexColor}; use values; +use values::computed::Color as ComputedColor; impl From for StyleComplexColor { fn from(other: nscolor) -> Self { @@ -39,13 +39,12 @@ impl StyleComplexColor { } } -impl From for StyleComplexColor { - fn from(other: cssparser::Color) -> Self { - use cssparser::Color; - - match other { - Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba).into(), - Color::CurrentColor => StyleComplexColor::current_color(), +impl From for StyleComplexColor { + fn from(other: ComputedColor) -> Self { + StyleComplexColor { + mColor: convert_rgba_to_nscolor(&other.color).into(), + mForegroundRatio: other.foreground_ratio, + mIsAuto: false, } } } @@ -62,17 +61,12 @@ impl From for values::computed::ColorOrAuto { } } -impl From for cssparser::Color { +impl From for ComputedColor { fn from(other: StyleComplexColor) -> Self { - use cssparser::Color; - - if other.mForegroundRatio == 0 { - Color::RGBA(convert_nscolor_to_rgba(other.mColor)) - } else if other.mForegroundRatio == 255 { - Color::CurrentColor - } else { - // FIXME #13546 handle interpolation values - Color::CurrentColor + debug_assert!(!other.mIsAuto); + ComputedColor { + color: convert_nscolor_to_rgba(other.mColor), + foreground_ratio: other.mForegroundRatio, } } } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index ce3b406d4f4..41501e5ddd8 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -7,7 +7,7 @@ <% from data import SYSTEM_FONT_LONGHANDS %> use app_units::Au; -use cssparser::{Color as CSSParserColor, Parser, RGBA, serialize_identifier}; +use cssparser::{Parser, RGBA, serialize_identifier}; use euclid::{Point2D, Size2D}; #[cfg(feature = "gecko")] use gecko_bindings::bindings::RawServoAnimationValueMap; #[cfg(feature = "gecko")] use gecko_bindings::structs::RawGeckoGfxMatrix4x4; @@ -38,7 +38,7 @@ use values::CSSFloat; use values::{Auto, Either}; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::{BorderCornerRadius, ClipRect}; -use values::computed::{CalcLengthOrPercentage, Context, ComputedValueAsSpecified}; +use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified}; use values::computed::{LengthOrPercentage, MaxLength, MozLength, Shadow, ToComputedValue}; use values::generics::{SVGPaint, SVGPaintKind}; use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; @@ -2721,38 +2721,19 @@ impl Animatable for IntermediateRGBA { } } -impl From> for Either { - fn from(from: Either) -> Either { +impl From> for Either { + fn from(from: Either) -> Either { match from { - Either::First(from) => - match from { - CSSParserColor::RGBA(color) => - Either::First(IntermediateColor::IntermediateRGBA( - IntermediateRGBA::new(color.red_f32(), - color.green_f32(), - color.blue_f32(), - color.alpha_f32()))), - CSSParserColor::CurrentColor => - Either::First(IntermediateColor::CurrentColor), - }, + Either::First(from) => Either::First(from.into()), Either::Second(Auto) => Either::Second(Auto), } } } -impl From> for Either { - fn from(from: Either) -> Either { +impl From> for Either { + fn from(from: Either) -> Either { match from { - Either::First(from) => - match from { - IntermediateColor::IntermediateRGBA(color) => - Either::First(CSSParserColor::RGBA(RGBA::from_floats(color.red, - color.green, - color.blue, - color.alpha))), - IntermediateColor::CurrentColor => - Either::First(CSSParserColor::CurrentColor), - }, + Either::First(from) => Either::First(from.into()), Either::Second(Auto) => Either::Second(Auto), } } @@ -2761,22 +2742,89 @@ impl From> for Either { #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] -pub enum IntermediateColor { - CurrentColor, - IntermediateRGBA(IntermediateRGBA), +pub struct IntermediateColor { + color: IntermediateRGBA, + foreground_ratio: f32, +} + +impl IntermediateColor { + fn currentcolor() -> Self { + IntermediateColor { + color: IntermediateRGBA::transparent(), + foreground_ratio: 1., + } + } + + fn transparent() -> Self { + IntermediateColor { + color: IntermediateRGBA::transparent(), + foreground_ratio: 0., + } + } + + fn is_currentcolor(&self) -> bool { + self.foreground_ratio >= 1. + } + + fn is_numeric(&self) -> bool { + self.foreground_ratio <= 0. + } + + fn effective_intermediate_rgba(&self) -> IntermediateRGBA { + IntermediateRGBA { + alpha: self.color.alpha * (1. - self.foreground_ratio), + .. self.color + } + } } impl Animatable for IntermediateColor { #[inline] fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { - match (*self, *other) { - (IntermediateColor::IntermediateRGBA(ref this), - IntermediateColor::IntermediateRGBA(ref other)) => { - this.add_weighted(other, self_portion, other_portion) - .map(IntermediateColor::IntermediateRGBA) + // Common cases are interpolating between two numeric colors, + // two currentcolors, and a numeric color and a currentcolor. + // + // Note: this algorithm assumes self_portion + other_portion + // equals to one, so it may be broken for additive operation. + // To properly support additive color interpolation, we would + // need two ratio fields in computed color types. + if self.foreground_ratio == other.foreground_ratio { + if self.is_currentcolor() { + Ok(IntermediateColor::currentcolor()) + } else { + Ok(IntermediateColor { + color: self.color.add_weighted(&other.color, self_portion, other_portion)?, + foreground_ratio: self.foreground_ratio, + }) } - // FIXME: Bug 1345709: Implement currentColor animations. - _ => Err(()), + } else if self.is_currentcolor() && other.is_numeric() { + Ok(IntermediateColor { + color: other.color, + foreground_ratio: self_portion as f32, + }) + } else if self.is_numeric() && other.is_currentcolor() { + Ok(IntermediateColor { + color: self.color, + foreground_ratio: other_portion as f32, + }) + } else { + // For interpolating between two complex colors, we need to + // generate colors with effective alpha value. + let self_color = self.effective_intermediate_rgba(); + let other_color = other.effective_intermediate_rgba(); + let color = self_color.add_weighted(&other_color, self_portion, other_portion)?; + // Then we compute the final foreground ratio, and derive + // the final alpha value from the effective alpha value. + let foreground_ratio = self.foreground_ratio + .add_weighted(&other.foreground_ratio, self_portion, other_portion)?; + let alpha = color.alpha / (1. - foreground_ratio); + Ok(IntermediateColor { + color: IntermediateRGBA { + alpha: alpha, + .. color + }, + foreground_ratio: foreground_ratio, + }) } } @@ -2787,37 +2835,41 @@ impl Animatable for IntermediateColor { #[inline] fn compute_squared_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(ref other)) => { - this.compute_squared_distance(other) - }, - _ => Ok(0.0), + // All comments in add_weighted also applies here. + if self.foreground_ratio == other.foreground_ratio { + if self.is_currentcolor() { + Ok(0.) + } else { + self.color.compute_squared_distance(&other.color) + } + } else if self.is_currentcolor() && other.is_numeric() { + Ok(IntermediateRGBA::transparent().compute_squared_distance(&other.color)? + 1.) + } else if self.is_numeric() && other.is_currentcolor() { + Ok(self.color.compute_squared_distance(&IntermediateRGBA::transparent())? + 1.) + } else { + let self_color = self.effective_intermediate_rgba(); + let other_color = other.effective_intermediate_rgba(); + let dist = self_color.compute_squared_distance(&other_color)?; + let ratio_diff = (self.foreground_ratio - other.foreground_ratio) as f64; + Ok(dist + ratio_diff * ratio_diff) } } } -impl From for IntermediateColor { - fn from(color: CSSParserColor) -> IntermediateColor { - match color { - CSSParserColor::RGBA(color) => - IntermediateColor::IntermediateRGBA(IntermediateRGBA::new(color.red_f32(), - color.green_f32(), - color.blue_f32(), - color.alpha_f32())), - CSSParserColor::CurrentColor => IntermediateColor::CurrentColor, +impl From for IntermediateColor { + fn from(color: Color) -> IntermediateColor { + IntermediateColor { + color: color.color.into(), + foreground_ratio: color.foreground_ratio as f32 * (1. / 255.), } } } -impl From for CSSParserColor { - fn from(color: IntermediateColor) -> CSSParserColor { - match color { - IntermediateColor::IntermediateRGBA(color) => - CSSParserColor::RGBA(RGBA::from_floats(color.red, - color.green, - color.blue, - color.alpha)), - IntermediateColor::CurrentColor => CSSParserColor::CurrentColor, +impl From for Color { + fn from(color: IntermediateColor) -> Color { + Color { + color: color.color.into(), + foreground_ratio: (color.foreground_ratio * 255.).round() as u8, } } } @@ -3024,7 +3076,7 @@ impl Animatable for IntermediateShadowList { offset_y: Au(0), blur_radius: Au(0), spread_radius: Au(0), - color: IntermediateColor::IntermediateRGBA(IntermediateRGBA::transparent()), + color: IntermediateColor::transparent(), inset: false, }; diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 3b2a2e6760f..9b799c220b9 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -7,7 +7,7 @@ <% data.new_style_struct("Background", inherited=False) %> ${helpers.predefined_type("background-color", "Color", - "::cssparser::Color::RGBA(::cssparser::RGBA::transparent())", + "computed_value::T::transparent()", initial_specified_value="SpecifiedValue::transparent()", spec="https://drafts.csswg.org/css-backgrounds/#background-color", animation_value_type="IntermediateColor", diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index 8c0bf0aa9f2..0fd7196baf5 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -17,7 +17,7 @@ %> % for side in ALL_SIDES: ${helpers.predefined_type("border-%s-color" % side[0], "Color", - "::cssparser::Color::CurrentColor", + "computed_value::T::currentcolor()", alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"), spec=maybe_logical_spec(side, "color"), animation_value_type="IntermediateColor", diff --git a/components/style/properties/longhand/color.mako.rs b/components/style/properties/longhand/color.mako.rs index bcdd97dedb0..fe5e411801e 100644 --- a/components/style/properties/longhand/color.mako.rs +++ b/components/style/properties/longhand/color.mako.rs @@ -12,7 +12,7 @@ animation_value_type="IntermediateRGBA" ignored_when_colors_disabled="True" spec="https://drafts.csswg.org/css-color/#color"> - use cssparser::{Color as CSSParserColor, RGBA}; + use cssparser::RGBA; use values::specified::{AllowQuirks, Color}; impl ToComputedValue for SpecifiedValue { @@ -20,11 +20,8 @@ #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - match self.0.to_computed_value(context) { - CSSParserColor::RGBA(rgba) => rgba, - CSSParserColor::CurrentColor => - context.inherited_style.get_color().clone_color(), - } + self.0.to_computed_value(context) + .to_rgba(context.inherited_style.get_color().clone_color()) } #[inline] diff --git a/components/style/properties/longhand/column.mako.rs b/components/style/properties/longhand/column.mako.rs index 56d481b719d..440e5d94d81 100644 --- a/components/style/properties/longhand/column.mako.rs +++ b/components/style/properties/longhand/column.mako.rs @@ -52,7 +52,7 @@ ${helpers.predefined_type("column-rule-width", // https://drafts.csswg.org/css-multicol-1/#crc ${helpers.predefined_type("column-rule-color", "Color", - "::cssparser::Color::CurrentColor", + "computed_value::T::currentcolor()", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", extra_prefixes="moz", need_clone=True, ignored_when_colors_disabled=True, diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index a8f055663c2..649caa5cece 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -686,7 +686,7 @@ ${helpers.predefined_type("word-spacing", ${helpers.predefined_type("text-emphasis-color", "Color", - "::cssparser::Color::CurrentColor", + "computed_value::T::currentcolor()", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", need_clone=True, ignored_when_colors_disabled=True, @@ -705,14 +705,14 @@ ${helpers.predefined_type( // https://compat.spec.whatwg.org ${helpers.predefined_type( "-webkit-text-fill-color", "Color", - "CSSParserColor::CurrentColor", + "computed_value::T::currentcolor()", products="gecko", animation_value_type="IntermediateColor", need_clone=True, ignored_when_colors_disabled=True, spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")} ${helpers.predefined_type( "-webkit-text-stroke-color", "Color", - "CSSParserColor::CurrentColor", + "computed_value::T::currentcolor()", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", need_clone=True, ignored_when_colors_disabled=True, diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index ec08fa43972..03ec187135e 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -10,7 +10,7 @@ additional_methods=[Method("outline_has_nonzero_width", "bool")]) %> // TODO(pcwalton): `invert` -${helpers.predefined_type("outline-color", "Color", "computed::Color::CurrentColor", +${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentcolor()", initial_specified_value="specified::Color::currentcolor()", animation_value_type="IntermediateColor", need_clone=True, ignored_when_colors_disabled=True, diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index c4bbe26c0e5..08113b228f2 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -279,7 +279,7 @@ ${helpers.single_keyword("text-decoration-style", ${helpers.predefined_type( "text-decoration-color", "Color", - "computed::Color::CurrentColor", + "computed_value::T::currentcolor()", initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index d9d95a82024..9e8420fa471 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -18,7 +18,7 @@ use std::ops::Deref; use stylearc::{Arc, UniqueArc}; use app_units::Au; -#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA}; +#[cfg(feature = "servo")] use cssparser::RGBA; use cssparser::{Parser, TokenSerializationType, serialize_identifier}; use error_reporting::ParseErrorReporter; #[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D; @@ -1937,11 +1937,8 @@ impl ComputedValues { /// Usage example: /// let top_color = style.resolve_color(style.Border.border_top_color); #[inline] - pub fn resolve_color(&self, color: CSSParserColor) -> RGBA { - match color { - CSSParserColor::RGBA(rgba) => rgba, - CSSParserColor::CurrentColor => self.get_color().color, - } + pub fn resolve_color(&self, color: computed::Color) -> RGBA { + color.to_rgba(self.get_color().color) } /// Get the logical computed inline size. diff --git a/components/style/values/computed/color.rs b/components/style/values/computed/color.rs index b77f55d0453..8c9a863b2c5 100644 --- a/components/style/values/computed/color.rs +++ b/components/style/values/computed/color.rs @@ -4,7 +4,141 @@ //! Computed color values. -use cssparser::RGBA; +use cssparser::{Color as CSSParserColor, RGBA}; +use std::fmt; +use style_traits::ToCss; + +/// This struct represents a combined color from a numeric color and +/// the current foreground color (currentcolor keyword). +/// Conceptually, the formula is "color * (1 - p) + currentcolor * p" +/// where p is foreground_ratio. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct Color { + /// RGBA color. + pub color: RGBA, + /// The ratio of currentcolor in complex color. + pub foreground_ratio: u8, +} + +fn blend_color_component(bg: u8, fg: u8, fg_alpha: u8) -> u8 { + let bg_ratio = (u8::max_value() - fg_alpha) as u32; + let fg_ratio = fg_alpha as u32; + let color = bg as u32 * bg_ratio + fg as u32 * fg_ratio; + // Rounding divide the number by 255 + ((color + 127) / 255) as u8 +} + +impl Color { + /// Returns a numeric color representing the given RGBA value. + pub fn rgba(rgba: RGBA) -> Color { + Color { + color: rgba, + foreground_ratio: 0, + } + } + + /// 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 { + color: RGBA::transparent(), + foreground_ratio: u8::max_value(), + } + } + + /// Whether it is a numeric color (no currentcolor component). + pub fn is_numeric(&self) -> bool { + self.foreground_ratio == 0 + } + + /// Whether it is a currentcolor value (no numeric color component). + pub fn is_currentcolor(&self) -> bool { + self.foreground_ratio == u8::max_value() + } + + /// 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 { + // Common cases that the complex color is either pure numeric + // color or pure currentcolor. + if self.is_numeric() { + return self.color; + } + if self.is_currentcolor() { + return fg_color.clone(); + } + // Common case that alpha channel is equal (usually both are opaque). + let fg_ratio = self.foreground_ratio; + if self.color.alpha == fg_color.alpha { + let r = blend_color_component(self.color.red, fg_color.red, fg_ratio); + let g = blend_color_component(self.color.green, fg_color.green, fg_ratio); + let b = blend_color_component(self.color.blue, fg_color.blue, fg_ratio); + return RGBA::new(r, g, b, fg_color.alpha); + } + + // For the more complicated case that the alpha value differs, + // we use the following formula to compute the components: + // alpha = self_alpha * (1 - fg_ratio) + fg_alpha * fg_ratio + // color = (self_color * self_alpha * (1 - fg_ratio) + + // fg_color * fg_alpha * fg_ratio) / alpha + + let p1 = (1. / 255.) * (255 - fg_ratio) as f32; + let a1 = self.color.alpha_f32(); + let r1 = a1 * self.color.red_f32(); + let g1 = a1 * self.color.green_f32(); + let b1 = a1 * self.color.blue_f32(); + + let p2 = 1. - p1; + let a2 = fg_color.alpha_f32(); + let r2 = a2 * fg_color.red_f32(); + let g2 = a2 * fg_color.green_f32(); + let b2 = a2 * fg_color.blue_f32(); + + let a = p1 * a1 + p2 * a2; + if a == 0.0 { + return RGBA::transparent(); + } + + 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 PartialEq for Color { + fn eq(&self, other: &Color) -> bool { + self.foreground_ratio == other.foreground_ratio && + (self.is_currentcolor() || self.color == other.color) + } +} + +impl From for Color { + fn from(color: RGBA) -> Color { + Color { + color: color, + foreground_ratio: 0, + } + } +} + +impl ToCss for Color { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.is_numeric() { + self.color.to_css(dest) + } else if self.is_currentcolor() { + CSSParserColor::CurrentColor.to_css(dest) + } else { + Ok(()) + } + } +} /// Computed value type for the specified RGBAColor. pub type RGBAColor = RGBA; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 50ad4bbb82d..ff682255d99 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -23,12 +23,11 @@ use super::generics::grid::TrackList as GenericTrackList; use super::specified; pub use app_units::Au; -pub use cssparser::Color; pub use properties::animated_properties::TransitionProperty; pub use self::background::BackgroundSize; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; pub use self::border::{BorderRadius, BorderCornerRadius}; -pub use self::color::RGBAColor; +pub use self::color::{Color, RGBAColor}; pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index d18bd574479..9fb5e849c5c 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -15,7 +15,7 @@ use std::fmt; use std::io::Write; use style_traits::ToCss; use super::AllowQuirks; -use values::computed::{Context, ToComputedValue}; +use values::computed::{Color as ComputedColor, Context, ToComputedValue}; /// Specified color value #[derive(Clone, PartialEq, Debug)] @@ -30,6 +30,8 @@ pub enum Color { /// Authored representation authored: Option>, }, + /// A complex color value from computed value + Complex(ComputedColor), /// A system color #[cfg(feature = "gecko")] @@ -103,6 +105,7 @@ impl ToCss for Color { Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), Color::Numeric { authored: Some(ref authored), .. } => dest.write_str(authored), Color::Numeric { parsed: ref rgba, .. } => rgba.to_css(dest), + Color::Complex(_) => Ok(()), #[cfg(feature = "gecko")] Color::System(system) => system.to_css(dest), #[cfg(feature = "gecko")] @@ -232,25 +235,27 @@ impl Color { } #[cfg(feature = "gecko")] -fn to_rgba(color: nscolor) -> CSSParserColor { +fn convert_nscolor_to_computedcolor(color: nscolor) -> ComputedColor { use gecko::values::convert_nscolor_to_rgba; - CSSParserColor::RGBA(convert_nscolor_to_rgba(color)) + ComputedColor::rgba(convert_nscolor_to_rgba(color)) } impl ToComputedValue for Color { - type ComputedValue = CSSParserColor; + type ComputedValue = ComputedColor; - fn to_computed_value(&self, _context: &Context) -> CSSParserColor { + fn to_computed_value(&self, _context: &Context) -> ComputedColor { match *self { - Color::CurrentColor => CSSParserColor::CurrentColor, - Color::Numeric { ref parsed, .. } => CSSParserColor::RGBA(*parsed), + Color::CurrentColor => ComputedColor::currentcolor(), + Color::Numeric { ref parsed, .. } => ComputedColor::rgba(*parsed), + Color::Complex(ref complex) => *complex, #[cfg(feature = "gecko")] - Color::System(system) => to_rgba(system.to_computed_value(_context)), + Color::System(system) => + convert_nscolor_to_computedcolor(system.to_computed_value(_context)), #[cfg(feature = "gecko")] Color::Special(special) => { use self::gecko::SpecialColorKeyword as Keyword; let pres_context = unsafe { &*_context.device.pres_context }; - to_rgba(match special { + convert_nscolor_to_computedcolor(match special { Keyword::MozDefaultColor => pres_context.mDefaultColor, Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, Keyword::MozHyperlinktext => pres_context.mLinkColor, @@ -270,21 +275,24 @@ impl ToComputedValue for Color { if let Some(body) = body { let wrap = GeckoElement(body); let borrow = wrap.borrow_data(); - CSSParserColor::RGBA(borrow.as_ref().unwrap() - .styles().primary.values() - .get_color() - .clone_color()) + ComputedColor::rgba(borrow.as_ref().unwrap() + .styles().primary.values() + .get_color() + .clone_color()) } else { - to_rgba(pres_context.mDefaultColor) + convert_nscolor_to_computedcolor(pres_context.mDefaultColor) } }, } } - fn from_computed_value(computed: &CSSParserColor) -> Self { - match *computed { - CSSParserColor::RGBA(rgba) => Color::rgba(rgba), - CSSParserColor::CurrentColor => Color::currentcolor(), + fn from_computed_value(computed: &ComputedColor) -> Self { + if computed.is_numeric() { + Color::rgba(computed.color) + } else if computed.is_currentcolor() { + Color::currentcolor() + } else { + Color::Complex(*computed) } } } @@ -313,10 +321,8 @@ impl ToComputedValue for RGBAColor { type ComputedValue = RGBA; fn to_computed_value(&self, context: &Context) -> RGBA { - match self.0.to_computed_value(context) { - CSSParserColor::RGBA(rgba) => rgba, - CSSParserColor::CurrentColor => context.style.get_color().clone_color(), - } + self.0.to_computed_value(context) + .to_rgba(context.style.get_color().clone_color()) } fn from_computed_value(computed: &RGBA) -> Self { diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index c0f9c6c96aa..2ea37db841f 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -8,7 +8,7 @@ use Namespace; use context::QuirksMode; -use cssparser::{self, Parser, Token, serialize_identifier}; +use cssparser::{Parser, Token, serialize_identifier}; use parser::{ParserContext, Parse}; use self::grid::TrackSizeOrRepeat; use self::url::SpecifiedUrl; @@ -695,10 +695,8 @@ impl ToComputedValue for Shadow { offset_y: self.offset_y.to_computed_value(context), blur_radius: self.blur_radius.to_computed_value(context), spread_radius: self.spread_radius.to_computed_value(context), - color: self.color - .as_ref() - .map(|color| color.to_computed_value(context)) - .unwrap_or(cssparser::Color::CurrentColor), + color: self.color.as_ref().unwrap_or(&Color::CurrentColor) + .to_computed_value(context), inset: self.inset, } } From 5c643adb9831ef9c59b96da2eb6349554afa2441 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 8 Jun 2017 10:42:32 +1000 Subject: [PATCH 10/10] Simplify caret-color conversion. --- .../sugar/style_complex_color.rs | 33 +++++++++++-------- components/style/properties/gecko.mako.rs | 22 ++----------- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/components/style/gecko_bindings/sugar/style_complex_color.rs b/components/style/gecko_bindings/sugar/style_complex_color.rs index 6b166384aed..cd0e408b26f 100644 --- a/components/style/gecko_bindings/sugar/style_complex_color.rs +++ b/components/style/gecko_bindings/sugar/style_complex_color.rs @@ -6,7 +6,7 @@ use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; use gecko_bindings::structs::{nscolor, StyleComplexColor}; -use values; +use values::{Auto, Either}; use values::computed::Color as ComputedColor; impl From for StyleComplexColor { @@ -49,18 +49,6 @@ impl From for StyleComplexColor { } } -impl From for values::computed::ColorOrAuto { - fn from(color: StyleComplexColor) -> Self { - use values::{Auto, Either}; - - if color.mIsAuto { - return Either::Second(Auto); - } - - Either::First(color.into()) - } -} - impl From for ComputedColor { fn from(other: StyleComplexColor) -> Self { debug_assert!(!other.mIsAuto); @@ -70,3 +58,22 @@ impl From for ComputedColor { } } } + +impl From> for StyleComplexColor { + fn from(other: Either) -> Self { + match other { + Either::First(color) => color.into(), + Either::Second(_auto) => StyleComplexColor::auto(), + } + } +} + +impl From for Either { + fn from(other: StyleComplexColor) -> Self { + if !other.mIsAuto { + Either::First(other.into()) + } else { + Either::Second(Auto) + } + } +} diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 1f64cf99daf..0df0ee4bde6 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -42,7 +42,7 @@ use gecko_bindings::bindings::Gecko_SetNullImageValue; use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull; use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom}; use gecko_bindings::bindings::RawGeckoPresContextBorrowed; -use gecko_bindings::structs::{self, StyleComplexColor}; +use gecko_bindings::structs; use gecko_bindings::structs::nsCSSPropertyID; use gecko_bindings::structs::nsStyleVariables; use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut}; @@ -4259,25 +4259,7 @@ clip-path } } - pub fn set_caret_color(&mut self, v: longhands::caret_color::computed_value::T){ - use values::Either; - - match v { - Either::First(color) => { - self.gecko.mCaretColor = StyleComplexColor::from(color); - } - Either::Second(_auto) => { - self.gecko.mCaretColor = StyleComplexColor::auto(); - } - } - } - - pub fn copy_caret_color_from(&mut self, other: &Self){ - self.gecko.mCaretColor = other.gecko.mCaretColor; - } - - <%call expr="impl_color_clone('caret_color', 'mCaretColor')"> - + <%call expr="impl_color('caret_color', 'mCaretColor', need_clone=True)"> <%self:impl_trait style_struct_name="Column"