aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/style/animation.rs18
-rw-r--r--components/style/build_gecko.rs1
-rw-r--r--components/style/dom.rs2
-rw-r--r--components/style/gecko/wrapper.rs20
-rw-r--r--components/style/gecko_bindings/bindings.rs6
-rw-r--r--components/style/keyframes.rs2
-rw-r--r--components/style/properties/gecko.mako.rs34
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs49
-rw-r--r--components/style/properties/properties.mako.rs4
-rw-r--r--components/style/properties/shorthand/box.mako.rs4
10 files changed, 103 insertions, 37 deletions
diff --git a/components/style/animation.rs b/components/style/animation.rs
index 2229d485591..16c7dab364d 100644
--- a/components/style/animation.rs
+++ b/components/style/animation.rs
@@ -272,9 +272,13 @@ impl PropertyAnimation {
let timing_function = box_style.transition_timing_function_mod(transition_index);
let duration = box_style.transition_duration_mod(transition_index);
+ if let TransitionProperty::Unsupported(_) = transition_property {
+ return result
+ }
+
if transition_property.is_shorthand() {
return transition_property.longhands().iter().filter_map(|transition_property| {
- PropertyAnimation::from_transition_property(*transition_property,
+ PropertyAnimation::from_transition_property(transition_property,
timing_function,
duration,
old_style,
@@ -284,7 +288,7 @@ impl PropertyAnimation {
if transition_property != TransitionProperty::All {
if let Some(property_animation) =
- PropertyAnimation::from_transition_property(transition_property,
+ PropertyAnimation::from_transition_property(&transition_property,
timing_function,
duration,
old_style,
@@ -296,7 +300,7 @@ impl PropertyAnimation {
TransitionProperty::each(|transition_property| {
if let Some(property_animation) =
- PropertyAnimation::from_transition_property(transition_property,
+ PropertyAnimation::from_transition_property(&transition_property,
timing_function,
duration,
old_style,
@@ -308,15 +312,15 @@ impl PropertyAnimation {
result
}
- fn from_transition_property(transition_property: TransitionProperty,
+ fn from_transition_property(transition_property: &TransitionProperty,
timing_function: TransitionTimingFunction,
duration: Time,
old_style: &ComputedValues,
new_style: &ComputedValues)
-> Option<PropertyAnimation> {
debug_assert!(!transition_property.is_shorthand() &&
- transition_property != TransitionProperty::All);
- let animated_property = AnimatedProperty::from_transition_property(&transition_property,
+ transition_property != &TransitionProperty::All);
+ let animated_property = AnimatedProperty::from_transition_property(transition_property,
old_style,
new_style);
@@ -702,7 +706,7 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
for transition_property in &animation.properties_changed {
debug!("update_style_for_animation: scanning prop {:?} for animation \"{}\"",
transition_property, name);
- match PropertyAnimation::from_transition_property(*transition_property,
+ match PropertyAnimation::from_transition_property(transition_property,
timing_function,
Time::from_seconds(relative_duration as f32),
&from_style,
diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs
index 00aac6d8526..9d170e64105 100644
--- a/components/style/build_gecko.rs
+++ b/components/style/build_gecko.rs
@@ -659,6 +659,7 @@ mod bindings {
"StyleBasicShape",
"StyleBasicShapeType",
"StyleShapeSource",
+ "StyleTransition",
"nsCSSFontFaceRule",
"nsCSSKeyword",
"nsCSSPropertyID",
diff --git a/components/style/dom.rs b/components/style/dom.rs
index ffc9f67ef8d..645db055be7 100644
--- a/components/style/dom.rs
+++ b/components/style/dom.rs
@@ -520,7 +520,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
/// Returns true if we need to update transitions for the specified property on this element.
#[cfg(feature = "gecko")]
fn needs_transitions_update_per_property(&self,
- property: TransitionProperty,
+ property: &TransitionProperty,
combined_duration: f32,
before_change_style: &Arc<ComputedValues>,
after_change_style: &Arc<ComputedValues>,
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 6c72aa0b3d5..948a87d4cf6 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -811,7 +811,7 @@ impl<'le> TElement for GeckoElement<'le> {
continue;
}
- let mut property_check_helper = |property: TransitionProperty| -> bool {
+ let mut property_check_helper = |property: &TransitionProperty| -> bool {
if self.needs_transitions_update_per_property(property,
combined_duration,
before_change_style,
@@ -821,7 +821,9 @@ impl<'le> TElement for GeckoElement<'le> {
}
if let Some(set) = transitions_to_keep.as_mut() {
- set.insert(property);
+ // The TransitionProperty here must be animatable, so cloning it is cheap
+ // because it is an integer-like enum.
+ set.insert(property.clone());
}
false
};
@@ -835,12 +837,12 @@ impl<'le> TElement for GeckoElement<'le> {
});
if is_shorthand {
let shorthand: TransitionProperty = property.into();
- if shorthand.longhands().iter().any(|&p| property_check_helper(p)) {
+ if shorthand.longhands().iter().any(|p| property_check_helper(p)) {
return true;
}
} else {
if animated_properties::nscsspropertyid_is_animatable(property) &&
- property_check_helper(property.into()) {
+ property_check_helper(&property.into()) {
return true;
}
}
@@ -855,7 +857,7 @@ impl<'le> TElement for GeckoElement<'le> {
}
fn needs_transitions_update_per_property(&self,
- property: TransitionProperty,
+ property: &TransitionProperty,
combined_duration: f32,
before_change_style: &Arc<ComputedValues>,
after_change_style: &Arc<ComputedValues>,
@@ -869,17 +871,17 @@ impl<'le> TElement for GeckoElement<'le> {
return false;
}
- if existing_transitions.contains_key(&property) {
+ if existing_transitions.contains_key(property) {
// If there is an existing transition, update only if the end value differs.
// If the end value has not changed, we should leave the currently running
// transition as-is since we don't want to interrupt its timing function.
let after_value =
- Arc::new(AnimationValue::from_computed_values(&property, after_change_style));
- return existing_transitions.get(&property).unwrap() != &after_value;
+ Arc::new(AnimationValue::from_computed_values(property, after_change_style));
+ return existing_transitions.get(property).unwrap() != &after_value;
}
combined_duration > 0.0f32 &&
- AnimatedProperty::from_transition_property(&property,
+ AnimatedProperty::from_transition_property(property,
before_change_style,
after_change_style).does_animate()
}
diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs
index c663df92012..f4d1a515d4b 100644
--- a/components/style/gecko_bindings/bindings.rs
+++ b/components/style/gecko_bindings/bindings.rs
@@ -39,6 +39,7 @@ use gecko_bindings::structs::SheetParsingMode;
use gecko_bindings::structs::StyleBasicShape;
use gecko_bindings::structs::StyleBasicShapeType;
use gecko_bindings::structs::StyleShapeSource;
+use gecko_bindings::structs::StyleTransition;
use gecko_bindings::structs::nsCSSFontFaceRule;
use gecko_bindings::structs::nsCSSKeyword;
use gecko_bindings::structs::nsCSSPropertyID;
@@ -693,6 +694,11 @@ extern "C" {
-> RawServoAnimationValueBorrowedOrNull;
}
extern "C" {
+ pub fn Gecko_StyleTransition_SetUnsupportedProperty(aTransition:
+ *mut StyleTransition,
+ aAtom: *mut nsIAtom);
+}
+extern "C" {
pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
-> *mut nsIAtom;
}
diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs
index d7e3485fc7d..fb8290fedf4 100644
--- a/components/style/keyframes.rs
+++ b/components/style/keyframes.rs
@@ -259,8 +259,8 @@ fn get_animated_properties(keyframes: &[Arc<Locked<Keyframe>>], guard: &SharedRw
if let Some(property) = TransitionProperty::from_declaration(declaration) {
if !seen.has_transition_property_bit(&property) {
- ret.push(property);
seen.set_transition_property_bit(&property);
+ ret.push(property);
}
}
}
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index 57ebd1114ff..fc40dcff52d 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -33,6 +33,7 @@ use gecko_bindings::bindings::Gecko_FontFamilyList_AppendNamed;
use gecko_bindings::bindings::Gecko_FontFamilyList_Clear;
use gecko_bindings::bindings::Gecko_SetCursorArrayLength;
use gecko_bindings::bindings::Gecko_SetCursorImage;
+use gecko_bindings::bindings::Gecko_StyleTransition_SetUnsupportedProperty;
use gecko_bindings::bindings::Gecko_NewCSSShadowArray;
use gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
use gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
@@ -53,6 +54,7 @@ use gecko::values::convert_rgba_to_nscolor;
use gecko::values::GeckoStyleCoordConvertible;
use gecko::values::round_border_to_device_pixels;
use logical_geometry::WritingMode;
+use properties::animated_properties::TransitionProperty;
use properties::longhands;
use properties::{Importance, LonghandId};
use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
@@ -2149,7 +2151,12 @@ fn static_assert() {
unsafe { self.gecko.mTransitions.ensure_len(v.0.len()) };
self.gecko.mTransitionPropertyCount = v.0.len() as u32;
for (servo, gecko) in v.0.into_iter().zip(self.gecko.mTransitions.iter_mut()) {
- gecko.mProperty = servo.into();
+ match servo {
+ TransitionProperty::Unsupported(ref atom) => unsafe {
+ Gecko_StyleTransition_SetUnsupportedProperty(gecko, atom.as_ptr())
+ },
+ _ => gecko.mProperty = (&servo).into(),
+ }
}
} else {
// In gecko |none| is represented by eCSSPropertyExtra_no_properties.
@@ -2172,7 +2179,22 @@ fn static_assert() {
pub fn transition_property_at(&self, index: usize)
-> longhands::transition_property::computed_value::SingleComputedValue {
- self.gecko.mTransitions[index].mProperty.into()
+ use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_no_properties;
+ use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_variable;
+ use gecko_bindings::structs::nsCSSPropertyID::eCSSProperty_UNKNOWN;
+
+ let property = self.gecko.mTransitions[index].mProperty;
+ if property == eCSSProperty_UNKNOWN || property == eCSSPropertyExtra_variable {
+ let atom = self.gecko.mTransitions[index].mUnknownProperty.raw();
+ debug_assert!(!atom.is_null());
+ TransitionProperty::Unsupported(atom.into())
+ } else if property == eCSSPropertyExtra_no_properties {
+ // Actually, we don't expect TransitionProperty::Unsupported also represents "none",
+ // but if the caller wants to convert it, it is fine. Please use it carefully.
+ TransitionProperty::Unsupported(atom!("none"))
+ } else {
+ property.into()
+ }
}
pub fn transition_nscsspropertyid_at(&self, index: usize) -> nsCSSPropertyID {
@@ -2180,6 +2202,8 @@ fn static_assert() {
}
pub fn copy_transition_property_from(&mut self, other: &Self) {
+ use gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_variable;
+ use gecko_bindings::structs::nsCSSPropertyID::eCSSProperty_UNKNOWN;
unsafe { self.gecko.mTransitions.ensure_len(other.gecko.mTransitions.len()) };
let count = other.gecko.mTransitionPropertyCount;
@@ -2187,6 +2211,12 @@ fn static_assert() {
for (index, transition) in self.gecko.mTransitions.iter_mut().enumerate().take(count as usize) {
transition.mProperty = other.gecko.mTransitions[index].mProperty;
+ if transition.mProperty == eCSSProperty_UNKNOWN ||
+ transition.mProperty == eCSSPropertyExtra_variable {
+ let atom = other.gecko.mTransitions[index].mUnknownProperty.raw();
+ debug_assert!(!atom.is_null());
+ unsafe { Gecko_StyleTransition_SetUnsupportedProperty(transition, atom) };
+ }
}
}
${impl_transition_count('property', 'Property')}
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index 8783fc4a44f..cd384da294a 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -7,9 +7,10 @@
<% from data import SYSTEM_FONT_LONGHANDS %>
use app_units::Au;
-use cssparser::{Color as CSSParserColor, Parser, RGBA};
+use cssparser::{Color as CSSParserColor, Parser, RGBA, serialize_identifier};
use euclid::{Point2D, Size2D};
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
+#[cfg(feature = "gecko")] use gecko_string_cache::Atom;
use properties::{CSSWideKeyword, PropertyDeclaration};
use properties::longhands;
use properties::longhands::background_size::computed_value::T as BackgroundSizeList;
@@ -25,6 +26,7 @@ use properties::longhands::transform::computed_value::T as TransformList;
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
use properties::longhands::visibility::computed_value::T as Visibility;
#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
+#[cfg(feature = "servo")] use servo_atoms::Atom;
use std::cmp;
#[cfg(feature = "gecko")] use std::collections::HashMap;
use std::fmt;
@@ -45,7 +47,7 @@ use values::generics::position as generic_position;
/// property.
// NB: This needs to be here because it needs all the longhands generated
// beforehand.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum TransitionProperty {
/// All, any animatable property changing should generate a transition.
@@ -62,24 +64,27 @@ pub enum TransitionProperty {
/// ${prop.name}
${prop.camel_case},
% endfor
+ /// Unrecognized property which could be any non-animatable, custom property, or
+ /// unknown property.
+ Unsupported(Atom)
}
impl TransitionProperty {
/// Iterates over each longhand property.
- pub fn each<F: FnMut(TransitionProperty) -> ()>(mut cb: F) {
+ pub fn each<F: FnMut(&TransitionProperty) -> ()>(mut cb: F) {
% for prop in data.longhands:
% if prop.animatable:
- cb(TransitionProperty::${prop.camel_case});
+ cb(&TransitionProperty::${prop.camel_case});
% endif
% endfor
}
/// Iterates over every property that is not TransitionProperty::All, stopping and returning
/// true when the provided callback returns true for the first time.
- pub fn any<F: FnMut(TransitionProperty) -> bool>(mut cb: F) -> bool {
+ pub fn any<F: FnMut(&TransitionProperty) -> bool>(mut cb: F) -> bool {
% for prop in data.longhands:
% if prop.animatable:
- if cb(TransitionProperty::${prop.camel_case}) {
+ if cb(&TransitionProperty::${prop.camel_case}) {
return true;
}
% endif
@@ -89,7 +94,8 @@ impl TransitionProperty {
/// Parse a transition-property value.
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
- match_ignore_ascii_case! { &try!(input.expect_ident()),
+ let ident = try!(input.expect_ident());
+ match_ignore_ascii_case! { &ident,
"all" => Ok(TransitionProperty::All),
% for prop in data.longhands:
% if prop.animatable:
@@ -99,7 +105,13 @@ impl TransitionProperty {
% for prop in data.shorthands_except_all():
"${prop.name}" => Ok(TransitionProperty::${prop.camel_case}),
% endfor
- _ => Err(())
+ "none" => Err(()),
+ _ => {
+ match CSSWideKeyword::from_ident(&ident) {
+ Some(_) => Err(()),
+ None => Ok(TransitionProperty::Unsupported((&*ident).into()))
+ }
+ }
}
}
@@ -199,6 +211,11 @@ impl ToCss for TransitionProperty {
% for prop in data.shorthands_except_all():
TransitionProperty::${prop.camel_case} => dest.write_str("${prop.name}"),
% endfor
+ #[cfg(feature = "gecko")]
+ TransitionProperty::Unsupported(ref atom) => serialize_identifier(&atom.to_string(),
+ dest),
+ #[cfg(feature = "servo")]
+ TransitionProperty::Unsupported(ref atom) => serialize_identifier(atom, dest),
}
}
}
@@ -206,9 +223,9 @@ impl ToCss for TransitionProperty {
/// Convert to nsCSSPropertyID.
#[cfg(feature = "gecko")]
#[allow(non_upper_case_globals)]
-impl From<TransitionProperty> for nsCSSPropertyID {
- fn from(transition_property: TransitionProperty) -> nsCSSPropertyID {
- match transition_property {
+impl<'a> From< &'a TransitionProperty> for nsCSSPropertyID {
+ fn from(transition_property: &'a TransitionProperty) -> nsCSSPropertyID {
+ match *transition_property {
% for prop in data.longhands:
% if prop.animatable:
TransitionProperty::${prop.camel_case}
@@ -220,6 +237,7 @@ impl From<TransitionProperty> for nsCSSPropertyID {
=> ${helpers.to_nscsspropertyid(prop.ident)},
% endfor
TransitionProperty::All => nsCSSPropertyID::eCSSPropertyExtra_all_properties,
+ _ => panic!("Unconvertable Servo transition property: {:?}", transition_property),
}
}
}
@@ -234,6 +252,9 @@ impl From<nsCSSPropertyID> for TransitionProperty {
% if prop.animatable:
${helpers.to_nscsspropertyid(prop.ident)}
=> TransitionProperty::${prop.camel_case},
+ % else:
+ ${helpers.to_nscsspropertyid(prop.ident)}
+ => TransitionProperty::Unsupported(Atom::from("${prop.ident}")),
% endif
% endfor
% for prop in data.shorthands_except_all():
@@ -241,7 +262,7 @@ impl From<nsCSSPropertyID> for TransitionProperty {
=> TransitionProperty::${prop.camel_case},
% endfor
nsCSSPropertyID::eCSSPropertyExtra_all_properties => TransitionProperty::All,
- _ => panic!("Unsupported Servo transition property: {:?}", property),
+ _ => panic!("Unconvertable nsCSSPropertyID: {:?}", property),
}
}
}
@@ -356,7 +377,7 @@ impl AnimatedProperty {
}
% endif
% endfor
- other => panic!("Can't use TransitionProperty::{:?} here", other),
+ ref other => panic!("Can't use TransitionProperty::{:?} here", other),
}
}
}
@@ -544,7 +565,7 @@ impl AnimationValue {
}
% endif
% endfor
- other => panic!("Can't use TransitionProperty::{:?} here.", other),
+ ref other => panic!("Can't use TransitionProperty::{:?} here.", other),
}
}
}
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 69932549fe2..fa6ed21a33b 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -258,7 +258,7 @@ impl LonghandIdSet {
TransitionProperty::${prop.camel_case} => self.insert(LonghandId::${prop.camel_case}),
% endif
% endfor
- other => unreachable!("Tried to set TransitionProperty::{:?} in a PropertyBitfield", other),
+ ref other => unreachable!("Tried to set TransitionProperty::{:?} in a PropertyBitfield", other),
}
}
@@ -271,7 +271,7 @@ impl LonghandIdSet {
TransitionProperty::${prop.camel_case} => self.contains(LonghandId::${prop.camel_case}),
% endif
% endfor
- other => unreachable!("Tried to get TransitionProperty::{:?} in a PropertyBitfield", other),
+ ref other => unreachable!("Tried to get TransitionProperty::{:?} in a PropertyBitfield", other),
}
}
}
diff --git a/components/style/properties/shorthand/box.mako.rs b/components/style/properties/shorthand/box.mako.rs
index cf98bffa347..0dd320735a8 100644
--- a/components/style/properties/shorthand/box.mako.rs
+++ b/components/style/properties/shorthand/box.mako.rs
@@ -98,10 +98,12 @@ macro_rules! try_parse_one {
loop {
parsed += 1;
- try_parse_one!(input, property, transition_property);
try_parse_one!(context, input, duration, transition_duration);
try_parse_one!(context, input, timing_function, transition_timing_function);
try_parse_one!(context, input, delay, transition_delay);
+ // Must check 'transition-property' after 'transition-timing-function' since
+ // 'transition-property' accepts any keyword.
+ try_parse_one!(input, property, transition_property);
parsed -= 1;
break