From 73ae5ffd94d7b27c62caa4e2fff09226c7a0500d Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Wed, 13 Sep 2017 16:07:41 +0800 Subject: [PATCH] style: Make structs uncacheable if currentcolor is used on properties not using ComplexColor storage. --- .../style/properties/properties.mako.rs | 30 +++++++++++++++++++ components/style/values/specified/color.rs | 30 +++++++++++++++---- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index b106c6af830..fcdca32c074 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -626,6 +626,36 @@ impl LonghandId { LonghandId::Direction ) } + + /// Whether computed values of this property lossily convert any complex + /// colors into RGBA colors. + /// + /// In Gecko, there are some properties still that compute currentcolor + /// down to an RGBA color at computed value time, instead of as + /// `StyleComplexColor`s. For these properties, we must return `false`, + /// so that we correctly avoid caching style data in the rule tree. + pub fn stores_complex_colors_lossily(&self) -> bool { + % if product == "gecko": + matches!(*self, + % for property in data.longhands: + % if property.predefined_type == "RGBAColor": + LonghandId::${property.camel_case} | + % endif + % endfor + LonghandId::BackgroundImage | + LonghandId::BorderImageSource | + LonghandId::BoxShadow | + LonghandId::MaskImage | + LonghandId::MozBorderBottomColors | + LonghandId::MozBorderLeftColors | + LonghandId::MozBorderRightColors | + LonghandId::MozBorderTopColors | + LonghandId::TextShadow + ) + % else: + false + % endif + } } /// An identifier for a given shorthand property. diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index df7b75ad117..9583242805c 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -248,18 +248,36 @@ fn convert_nscolor_to_computedcolor(color: nscolor) -> ComputedColor { impl ToComputedValue for Color { type ComputedValue = ComputedColor; - fn to_computed_value(&self, _context: &Context) -> ComputedColor { + fn to_computed_value(&self, context: &Context) -> ComputedColor { match *self { - Color::CurrentColor => ComputedColor::currentcolor(), + 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() + } Color::Numeric { ref parsed, .. } => ComputedColor::rgba(*parsed), - Color::Complex(ref complex) => *complex, + 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 + } #[cfg(feature = "gecko")] Color::System(system) => - convert_nscolor_to_computedcolor(system.to_computed_value(_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(); + let pres_context = context.device().pres_context(); convert_nscolor_to_computedcolor(match special { Keyword::MozDefaultColor => pres_context.mDefaultColor, Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, @@ -273,7 +291,7 @@ impl ToComputedValue for Color { use dom::TElement; use gecko::wrapper::GeckoElement; use gecko_bindings::bindings::Gecko_GetBody; - let pres_context = _context.device().pres_context(); + let pres_context = context.device().pres_context(); let body = unsafe { Gecko_GetBody(pres_context) }.map(GeckoElement); let data = body.as_ref().and_then(|wrap| wrap.borrow_data()); if let Some(data) = data {