diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-10-16 04:49:33 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-16 04:49:33 -0500 |
commit | 1e351ef8c478de507c6ee7b65eeff7524d73a4c9 (patch) | |
tree | 0f460841dbe50c97d5259cc92a83ce16d1cb9ea8 | |
parent | a759ded65d965b54c535c74d460f60a782e51487 (diff) | |
parent | 46695336e8c38ae0dd9d3362f0700b2ad724886e (diff) | |
download | servo-1e351ef8c478de507c6ee7b65eeff7524d73a4c9.tar.gz servo-1e351ef8c478de507c6ee7b65eeff7524d73a4c9.zip |
Auto merge of #18891 - heycam:color-refactor, r=upsuper
style: add FFI functions for color parsing
Servo side of https://bugzilla.mozilla.org/show_bug.cgi?id=1408312, reviewed there by Xidorn.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18891)
<!-- Reviewable:end -->
-rw-r--r-- | components/style/values/specified/color.rs | 157 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 66 |
2 files changed, 155 insertions, 68 deletions
diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index bee0daecfea..aae2674803e 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -67,42 +67,7 @@ impl From<RGBA> for Color { impl Parse for Color { fn parse<'i, 't>(_: &ParserContext, 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()) - } - } - } + Color::parse_color(input) } } @@ -244,6 +209,46 @@ impl Color { _ => 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")] @@ -252,53 +257,71 @@ fn convert_nscolor_to_computedcolor(color: nscolor) -> ComputedColor { ComputedColor::rgba(convert_nscolor_to_rgba(color)) } -impl ToComputedValue for Color { - type ComputedValue = ComputedColor; - - fn to_computed_value(&self, context: &Context) -> ComputedColor { +impl Color { + /// Converts this Color into a 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 { Color::CurrentColor => { - if let Some(longhand) = context.for_non_inherited_property { - if longhand.stores_complex_colors_lossily() { - context.rule_cache_conditions.borrow_mut() - .set_uncacheable(); - } - } - ComputedColor::currentcolor() + Some(ComputedColor::currentcolor()) + } + Color::Numeric { ref parsed, .. } => { + Some(ComputedColor::rgba(*parsed)) } - Color::Numeric { ref parsed, .. } => ComputedColor::rgba(*parsed), Color::Complex(ref complex) => { - if complex.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(); - } - } - } - *complex + Some(*complex) } #[cfg(feature = "gecko")] - Color::System(system) => - convert_nscolor_to_computedcolor(system.to_computed_value(context)), + Color::System(system) => { + _context.map(|context| { + convert_nscolor_to_computedcolor( + system.to_computed_value(context) + ) + }) + } #[cfg(feature = "gecko")] Color::Special(special) => { use self::gecko::SpecialColorKeyword as Keyword; - let pres_context = context.device().pres_context(); - convert_nscolor_to_computedcolor(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, + _context.map(|context| { + let pres_context = context.device().pres_context(); + convert_nscolor_to_computedcolor(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, + }) }) } #[cfg(feature = "gecko")] 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 { if computed.is_numeric() { diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 509d869c625..9e7c2f22f2d 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -44,7 +44,7 @@ use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrow use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed}; use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed}; use style::gecko_bindings::bindings::{RawServoSelectorListBorrowed, RawServoSelectorListOwned}; -use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned}; +use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetBorrowedOrNull, RawServoStyleSetOwned}; use style::gecko_bindings::bindings::{RawServoStyleSheetContentsBorrowed, ServoComputedDataBorrowed}; use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoStyleContextBorrowed}; use style::gecko_bindings::bindings::{RawServoSupportsRule, RawServoSupportsRuleBorrowed}; @@ -145,6 +145,7 @@ use style::values::{CustomIdent, KeyframesName}; use style::values::animated::{Animate, Procedure, ToAnimatedZero}; use style::values::computed::{Context, ToComputedValue}; use style::values::distance::ComputeSquaredDistance; +use style::values::specified; use style_traits::{PARSING_MODE_DEFAULT, ToCss}; use super::error_reporter::ErrorReporter; use super::stylesheet_loader::StylesheetLoader; @@ -4206,3 +4207,66 @@ pub unsafe extern "C" fn Servo_SelectorList_Parse( pub unsafe extern "C" fn Servo_SelectorList_Drop(list: RawServoSelectorListOwned) { let _ = list.into_box::<::selectors::SelectorList<SelectorImpl>>(); } + +fn parse_color(value: &str) -> Result<specified::Color, ()> { + let mut input = ParserInput::new(value); + let mut parser = Parser::new(&mut input); + parser.parse_entirely(specified::Color::parse_color).map_err(|_| ()) +} + +#[no_mangle] +pub extern "C" fn Servo_IsValidCSSColor( + value: *const nsAString, +) -> bool { + let value = unsafe { (*value).to_string() }; + parse_color(&value).is_ok() +} + +#[no_mangle] +pub extern "C" fn Servo_ComputeColor( + raw_data: RawServoStyleSetBorrowedOrNull, + current_color: structs::nscolor, + value: *const nsAString, + result_color: *mut structs::nscolor, +) -> bool { + use style::gecko; + + let current_color = gecko::values::convert_nscolor_to_rgba(current_color); + let value = unsafe { (*value).to_string() }; + let result_color = unsafe { result_color.as_mut().unwrap() }; + + match parse_color(&value) { + Ok(specified_color) => { + let computed_color = match raw_data { + Some(raw_data) => { + let data = PerDocumentStyleData::from_ffi(raw_data).borrow(); + let metrics = get_metrics_provider_for_product(); + let mut conditions = Default::default(); + let context = create_context( + &data, + &metrics, + data.stylist.device().default_computed_values(), + /* parent_style = */ None, + /* pseudo = */ None, + /* for_smil_animation = */ false, + &mut conditions, + ); + specified_color.to_computed_color(Some(&context)) + } + None => { + specified_color.to_computed_color(None) + } + }; + + match computed_color { + Some(computed_color) => { + let rgba = computed_color.to_rgba(current_color); + *result_color = gecko::values::convert_rgba_to_nscolor(&rgba); + true + } + None => false, + } + } + Err(_) => false, + } +} |