mirror of
https://github.com/servo/servo.git
synced 2025-06-28 19:13:41 +01:00
Unify specified Color type between Stylo and Servo.
This commit is contained in:
parent
f3610d2724
commit
d0d170767d
5 changed files with 82 additions and 96 deletions
|
@ -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,
|
||||||
|
|
|
@ -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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue