Unify specified Color type between Stylo and Servo.

This commit is contained in:
Xidorn Quan 2017-06-08 10:42:24 +10:00
parent f3610d2724
commit d0d170767d
5 changed files with 82 additions and 96 deletions

View file

@ -4,7 +4,6 @@
//! Element nodes. //! Element nodes.
use cssparser::Color;
use devtools_traits::AttrInfo; use devtools_traits::AttrInfo;
use dom::activation::Activatable; use dom::activation::Activatable;
use dom::attr::{Attr, AttrHelpersForLayout}; use dom::attr::{Attr, AttrHelpersForLayout};
@ -112,7 +111,7 @@ use style::stylearc::Arc;
use style::stylist::ApplicableDeclarationBlock; use style::stylist::ApplicableDeclarationBlock;
use style::thread_state; use style::thread_state;
use style::values::{CSSFloat, Either}; use style::values::{CSSFloat, Either};
use style::values::specified::{self, CSSColor}; use style::values::specified::{self, CSSColor, Color};
use stylesheet_loader::StylesheetOwner; use stylesheet_loader::StylesheetOwner;
// TODO: Update focus state when the top-level browsing context gains or loses system focus, // TODO: Update focus state when the top-level browsing context gains or loses system focus,

View file

@ -7,34 +7,38 @@
use cssparser::{self, Color as CSSParserColor, Parser, RGBA, Token}; use cssparser::{self, Color as CSSParserColor, Parser, RGBA, Token};
use itoa; use itoa;
use parser::{ParserContext, Parse}; use parser::{ParserContext, Parse};
#[cfg(feature = "gecko")]
use properties::longhands::color::SystemColor;
use std::fmt; use std::fmt;
use std::io::Write; use std::io::Write;
use style_traits::ToCss; use style_traits::ToCss;
use super::AllowQuirks; use super::AllowQuirks;
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
#[cfg(not(feature = "gecko"))] pub use self::servo::Color; /// Specified color value
#[cfg(feature = "gecko")] pub use self::gecko::Color; #[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"))] /// A system color
mod servo { #[cfg(feature = "gecko")]
pub use cssparser::Color; System(SystemColor),
use cssparser::Parser; /// A special color keyword value used in Gecko
use parser::{Parse, ParserContext}; #[cfg(feature = "gecko")]
Special(gecko::SpecialColorKeyword),
impl Parse for Color { /// Quirksmode-only rule for inheriting color from the body
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> { #[cfg(feature = "gecko")]
Color::parse(input) InheritFromBodyQuirk,
}
}
} }
no_viewport_percentage!(Color);
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
mod 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; use style_traits::ToCss;
define_css_keyword_enum! { SpecialColorKeyword: define_css_keyword_enum! { SpecialColorKeyword:
@ -44,59 +48,53 @@ mod gecko {
"-moz-activehyperlinktext" => MozActiveHyperlinktext, "-moz-activehyperlinktext" => MozActiveHyperlinktext,
"-moz-visitedhyperlinktext" => MozVisitedHyperlinktext, "-moz-visitedhyperlinktext" => MozVisitedHyperlinktext,
} }
}
/// Color value including non-standard -moz prefixed values. impl From<CSSParserColor> for Color {
#[derive(Clone, Copy, PartialEq, Debug)] fn from(value: CSSParserColor) -> Self {
pub enum Color { match value {
/// The 'currentColor' keyword CSSParserColor::CurrentColor => Color::CurrentColor,
CurrentColor, CSSParserColor::RGBA(x) => Color::RGBA(x),
/// 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<CSSParserColor> for Color {
fn from(value: CSSParserColor) -> Self {
match value {
CSSParserColor::CurrentColor => Color::CurrentColor,
CSSParserColor::RGBA(x) => Color::RGBA(x),
}
} }
} }
}
impl Parse for Color { impl From<RGBA> for Color {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn from(value: RGBA) -> Self {
if let Ok(value) = input.try(CSSParserColor::parse) { Color::RGBA(value)
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) { impl Parse for Color {
Ok(Color::Special(special)) fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
} else { 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(()) Err(())
} }
} }
} }
}
impl ToCss for Color { impl ToCss for Color {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self { match *self {
// Standard values: Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest),
Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), Color::RGBA(rgba) => rgba.to_css(dest),
Color::RGBA(rgba) => rgba.to_css(dest), #[cfg(feature = "gecko")]
Color::System(system) => system.to_css(dest), Color::System(system) => system.to_css(dest),
#[cfg(feature = "gecko")]
// Non-standard values: Color::Special(special) => special.to_css(dest),
Color::Special(special) => special.to_css(dest), #[cfg(feature = "gecko")]
Color::InheritFromBodyQuirk => Ok(()), Color::InheritFromBodyQuirk => Ok(()),
}
} }
} }
} }
@ -245,25 +243,18 @@ impl CSSColor {
impl ToComputedValue for Color { impl ToComputedValue for Color {
type ComputedValue = RGBA; 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 { fn to_computed_value(&self, context: &Context) -> RGBA {
#[cfg(feature = "gecko")]
use gecko::values::convert_nscolor_to_rgba as to_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 { match *self {
Color::RGBA(rgba) => rgba, Color::RGBA(rgba) => rgba,
Color::System(system) => to_rgba(system.to_computed_value(context)),
Color::CurrentColor => context.inherited_style.get_color().clone_color(), 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) => { Color::Special(special) => {
use self::gecko::SpecialColorKeyword as Keyword; use self::gecko::SpecialColorKeyword as Keyword;
let pres_context = unsafe { &*context.device.pres_context };
to_rgba(match special { to_rgba(match special {
Keyword::MozDefaultColor => pres_context.mDefaultColor, Keyword::MozDefaultColor => pres_context.mDefaultColor,
Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor,
@ -272,10 +263,12 @@ impl ToComputedValue for Color {
Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor, Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor,
}) })
} }
#[cfg(feature = "gecko")]
Color::InheritFromBodyQuirk => { Color::InheritFromBodyQuirk => {
use dom::TElement; use dom::TElement;
use gecko::wrapper::GeckoElement; use gecko::wrapper::GeckoElement;
use gecko_bindings::bindings::Gecko_GetBody; use gecko_bindings::bindings::Gecko_GetBody;
let pres_context = unsafe { &*context.device.pres_context };
let body = unsafe { let body = unsafe {
Gecko_GetBody(pres_context) Gecko_GetBody(pres_context)
}; };
@ -301,20 +294,14 @@ impl ToComputedValue for Color {
impl ToComputedValue for CSSColor { impl ToComputedValue for CSSColor {
type ComputedValue = CSSParserColor; type ComputedValue = CSSParserColor;
#[cfg(not(feature = "gecko"))]
#[inline] #[inline]
fn to_computed_value(&self, _context: &Context) -> CSSParserColor { 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 { match self.parsed {
Color::RGBA(rgba) => CSSParserColor::RGBA(rgba), Color::RGBA(rgba) => CSSParserColor::RGBA(rgba),
Color::CurrentColor => CSSParserColor::CurrentColor, Color::CurrentColor => CSSParserColor::CurrentColor,
// Resolve non-standard -moz keywords to RGBA: // 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)),
} }
} }

View file

@ -2,10 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::{Color, RGBA}; use cssparser::RGBA;
use parsing::parse; use parsing::parse;
use style::values::{Auto, Either}; use style::values::{Auto, Either};
use style::values::specified::CSSColor; use style::values::specified::{CSSColor, Color};
use style_traits::ToCss; use style_traits::ToCss;
#[test] #[test]

View file

@ -5,11 +5,11 @@
use properties::parse; use properties::parse;
use style::computed_values::display::T::inline_block; use style::computed_values::display::T::inline_block;
use style::properties::{PropertyDeclaration, Importance, PropertyId}; 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::properties::parse_property_declaration_list;
use style::values::{RGBA, Auto}; use style::values::{RGBA, Auto};
use style::values::CustomIdent; 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::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
use style::values::specified::{NoCalcLength, PositionComponent}; use style::values::specified::{NoCalcLength, PositionComponent};
use style::values::specified::position::Y; use style::values::specified::position::Y;
@ -111,7 +111,7 @@ mod shorthand_serialization {
let line = TextDecorationLine::OVERLINE; let line = TextDecorationLine::OVERLINE;
let style = TextDecorationStyle::dotted; let style = TextDecorationStyle::dotted;
let color = CSSColor { let color = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(128, 0, 128, 255)), parsed: RGBA::new(128, 0, 128, 255).into(),
authored: None authored: None
}; };
@ -230,7 +230,7 @@ mod shorthand_serialization {
properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone())); properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone()));
let blue = CSSColor { let blue = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), parsed: RGBA::new(0, 0, 255, 255).into(),
authored: None authored: None
}; };
@ -263,7 +263,7 @@ mod shorthand_serialization {
properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone())); properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone()));
let blue = CSSColor { let blue = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), parsed: RGBA::new(0, 0, 255, 255).into(),
authored: None authored: None
}; };
@ -333,12 +333,12 @@ mod shorthand_serialization {
let mut properties = Vec::new(); let mut properties = Vec::new();
let red = CSSColor { let red = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), parsed: RGBA::new(255, 0, 0, 255).into(),
authored: None authored: None
}; };
let blue = CSSColor { let blue = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), parsed: RGBA::new(0, 0, 255, 255).into(),
authored: None authored: None
}; };
@ -406,7 +406,7 @@ mod shorthand_serialization {
let width = BorderSideWidth::Length(Length::from_px(4f32)); let width = BorderSideWidth::Length(Length::from_px(4f32));
let style = BorderStyle::solid; let style = BorderStyle::solid;
let color = CSSColor { let color = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), parsed: RGBA::new(255, 0, 0, 255).into(),
authored: None authored: None
}; };
@ -533,7 +533,7 @@ mod shorthand_serialization {
let width = BorderSideWidth::Length(Length::from_px(4f32)); let width = BorderSideWidth::Length(Length::from_px(4f32));
let style = Either::Second(BorderStyle::solid); let style = Either::Second(BorderStyle::solid);
let color = CSSColor { let color = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), parsed: RGBA::new(255, 0, 0, 255).into(),
authored: None authored: None
}; };
@ -552,7 +552,7 @@ mod shorthand_serialization {
let width = BorderSideWidth::Length(Length::from_px(4f32)); let width = BorderSideWidth::Length(Length::from_px(4f32));
let style = Either::First(Auto); let style = Either::First(Auto);
let color = CSSColor { let color = CSSColor {
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), parsed: RGBA::new(255, 0, 0, 255).into(),
authored: None authored: None
}; };
properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineWidth(width));

View file

@ -160,7 +160,7 @@ fn test_parse_stylesheet() {
(PropertyDeclaration::BackgroundColor( (PropertyDeclaration::BackgroundColor(
longhands::background_color::SpecifiedValue { longhands::background_color::SpecifiedValue {
authored: Some("blue".to_owned().into_boxed_str()), 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), Importance::Normal),