style: Refactor specified::Color parsing/computation functions.

So they can be called without a context.
This commit is contained in:
Cameron McCormack 2017-10-16 08:51:55 +08:00
parent 086c48210c
commit 1db1c7f544

View file

@ -67,42 +67,7 @@ impl From<RGBA> for Color {
impl Parse for Color { impl Parse for Color {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// Currently we only store authored value for color keywords, Color::parse_color(input)
// because all browsers serialize those values as keywords for
// specified value.
let start = input.state();
let authored = match input.next() {
Ok(&Token::Ident(ref s)) => Some(s.to_lowercase().into_boxed_str()),
_ => None,
};
input.reset(&start);
match input.try(CSSParserColor::parse) {
Ok(value) =>
Ok(match value {
CSSParserColor::CurrentColor => Color::CurrentColor,
CSSParserColor::RGBA(rgba) => Color::Numeric {
parsed: rgba,
authored: authored,
},
}),
Err(e) => {
#[cfg(feature = "gecko")] {
if let Ok(system) = input.try(SystemColor::parse) {
return Ok(Color::System(system));
} else if let Ok(c) = gecko::SpecialColorKeyword::parse(input) {
return Ok(Color::Special(c));
}
}
match e {
BasicParseError { kind: BasicParseErrorKind::UnexpectedToken(t), location } => {
Err(location.new_custom_error(
StyleParseErrorKind::ValueError(ValueParseErrorKind::InvalidColor(t))
))
}
e => Err(e.into())
}
}
}
} }
} }
@ -244,6 +209,46 @@ impl Color {
_ => true, _ => true,
} }
} }
/// Parse a <color> value.
pub fn parse_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
// Currently we only store authored value for color keywords,
// because all browsers serialize those values as keywords for
// specified value.
let start = input.state();
let authored = match input.next() {
Ok(&Token::Ident(ref s)) => Some(s.to_lowercase().into_boxed_str()),
_ => None,
};
input.reset(&start);
match input.try(CSSParserColor::parse) {
Ok(value) =>
Ok(match value {
CSSParserColor::CurrentColor => Color::CurrentColor,
CSSParserColor::RGBA(rgba) => Color::Numeric {
parsed: rgba,
authored: authored,
},
}),
Err(e) => {
#[cfg(feature = "gecko")] {
if let Ok(system) = input.try(SystemColor::parse) {
return Ok(Color::System(system));
} else if let Ok(c) = gecko::SpecialColorKeyword::parse(input) {
return Ok(Color::Special(c));
}
}
match e {
BasicParseError { kind: BasicParseErrorKind::UnexpectedToken(t), location } => {
Err(location.new_custom_error(
StyleParseErrorKind::ValueError(ValueParseErrorKind::InvalidColor(t))
))
}
e => Err(e.into())
}
}
}
}
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -252,53 +257,71 @@ fn convert_nscolor_to_computedcolor(color: nscolor) -> ComputedColor {
ComputedColor::rgba(convert_nscolor_to_rgba(color)) ComputedColor::rgba(convert_nscolor_to_rgba(color))
} }
impl ToComputedValue for Color { impl Color {
type ComputedValue = ComputedColor; /// Converts this Color into a ComputedColor.
///
fn to_computed_value(&self, context: &Context) -> ComputedColor { /// If `context` is `None`, and the specified color requires data from
/// the context to resolve, then `None` is returned.
pub fn to_computed_color(
&self,
_context: Option<&Context>,
) -> Option<ComputedColor> {
match *self { match *self {
Color::CurrentColor => { Color::CurrentColor => {
if let Some(longhand) = context.for_non_inherited_property { Some(ComputedColor::currentcolor())
if longhand.stores_complex_colors_lossily() { }
context.rule_cache_conditions.borrow_mut() Color::Numeric { ref parsed, .. } => {
.set_uncacheable(); Some(ComputedColor::rgba(*parsed))
}
}
ComputedColor::currentcolor()
} }
Color::Numeric { ref parsed, .. } => ComputedColor::rgba(*parsed),
Color::Complex(ref complex) => { Color::Complex(ref complex) => {
if complex.foreground_ratio != 0 { Some(*complex)
if let Some(longhand) = context.for_non_inherited_property {
if longhand.stores_complex_colors_lossily() {
context.rule_cache_conditions.borrow_mut()
.set_uncacheable();
}
}
}
*complex
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
Color::System(system) => Color::System(system) => {
convert_nscolor_to_computedcolor(system.to_computed_value(context)), _context.map(|context| {
convert_nscolor_to_computedcolor(
system.to_computed_value(context)
)
})
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
Color::Special(special) => { Color::Special(special) => {
use self::gecko::SpecialColorKeyword as Keyword; use self::gecko::SpecialColorKeyword as Keyword;
let pres_context = context.device().pres_context(); _context.map(|context| {
convert_nscolor_to_computedcolor(match special { let pres_context = context.device().pres_context();
Keyword::MozDefaultColor => pres_context.mDefaultColor, convert_nscolor_to_computedcolor(match special {
Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, Keyword::MozDefaultColor => pres_context.mDefaultColor,
Keyword::MozHyperlinktext => pres_context.mLinkColor, Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor,
Keyword::MozActiveHyperlinktext => pres_context.mActiveLinkColor, Keyword::MozHyperlinktext => pres_context.mLinkColor,
Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor, Keyword::MozActiveHyperlinktext => pres_context.mActiveLinkColor,
Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor,
})
}) })
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
Color::InheritFromBodyQuirk => { Color::InheritFromBodyQuirk => {
ComputedColor::rgba(context.device().body_text_color()) _context.map(|context| {
ComputedColor::rgba(context.device().body_text_color())
})
}, },
} }
} }
}
impl ToComputedValue for Color {
type ComputedValue = ComputedColor;
fn to_computed_value(&self, context: &Context) -> ComputedColor {
let result = self.to_computed_color(Some(context)).unwrap();
if result.foreground_ratio != 0 {
if let Some(longhand) = context.for_non_inherited_property {
if longhand.stores_complex_colors_lossily() {
context.rule_cache_conditions.borrow_mut().set_uncacheable();
}
}
}
result
}
fn from_computed_value(computed: &ComputedColor) -> Self { fn from_computed_value(computed: &ComputedColor) -> Self {
if computed.is_numeric() { if computed.is_numeric() {