Skip to content

Commit

Permalink
Unify specified Color type between Stylo and Servo.
Browse files Browse the repository at this point in the history
  • Loading branch information
upsuper committed Jun 8, 2017
1 parent f3610d2 commit d0d1707
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 95 deletions.
3 changes: 1 addition & 2 deletions components/script/dom/element.rs
Expand Up @@ -4,7 +4,6 @@

//! Element nodes.

use cssparser::Color;
use devtools_traits::AttrInfo;
use dom::activation::Activatable;
use dom::attr::{Attr, AttrHelpersForLayout};
Expand Down Expand Up @@ -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,
Expand Down
147 changes: 67 additions & 80 deletions components/style/values/specified/color.rs
Expand Up @@ -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;

#[cfg(not(feature = "gecko"))]
mod servo {
pub use cssparser::Color;
use cssparser::Parser;
use parser::{Parse, ParserContext};
/// 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),

impl Parse for Color {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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:
Expand All @@ -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,
impl From<CSSParserColor> for Color {
fn from(value: CSSParserColor) -> Self {
match value {
CSSParserColor::CurrentColor => Color::CurrentColor,
CSSParserColor::RGBA(x) => Color::RGBA(x),
}
}
}

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 From<RGBA> for Color {
fn from(value: RGBA) -> Self {
Color::RGBA(value)
}
}

impl Parse for Color {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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 Parse for Color {
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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<W>(&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<W>(&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(()),
}
}
}
Expand Down Expand Up @@ -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,
Expand All @@ -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)
};
Expand All @@ -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)),
}
}

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/style/parsing/ui.rs
Expand Up @@ -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]
Expand Down
20 changes: 10 additions & 10 deletions tests/unit/style/properties/serialization.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
};

Expand Down Expand Up @@ -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
};

Expand Down Expand Up @@ -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
};

Expand Down Expand Up @@ -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
};

Expand Down Expand Up @@ -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
};

Expand Down Expand Up @@ -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
};

Expand All @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/style/stylesheets.rs
Expand Up @@ -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),
Expand Down

0 comments on commit d0d1707

Please sign in to comment.