Skip to content

Commit

Permalink
Auto merge of #16863 - birtles:additive-animation, r=hiro
Browse files Browse the repository at this point in the history
Additive animation

Pull request for [Mozilla bug 1329878](https://bugzilla.mozilla.org/show_bug.cgi?id=1329878).

---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix [Mozilla bug 1329878](https://bugzilla.mozilla.org/show_bug.cgi?id=1329878).
- [X] There are tests for these changes in web-platform-tests

<!-- 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/16863)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed May 15, 2017
2 parents 8366b4d + 5539728 commit 94e977e
Show file tree
Hide file tree
Showing 8 changed files with 361 additions and 218 deletions.
18 changes: 12 additions & 6 deletions components/style/properties/helpers.mako.rs
Expand Up @@ -113,8 +113,13 @@
% if delegate_animate:
use properties::animated_properties::Animatable;
impl Animatable for T {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
self.0.interpolate(&other.0, progress).map(T)
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(T)
}

fn add(&self, other: &Self) -> Result<Self, ()> {
self.0.add(&other.0).map(T)
}

#[inline]
Expand Down Expand Up @@ -976,16 +981,17 @@
<%def name="impl_animatable_for_option_tuple(value_for_none)">
impl Animatable for T {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
match (self, other) {
(&T(Some(ref this)), &T(Some(ref other))) => {
Ok(T(this.interpolate(other, progress).ok()))
Ok(T(this.add_weighted(other, self_portion, other_portion).ok()))
},
(&T(Some(ref this)), &T(None)) => {
Ok(T(this.interpolate(&${value_for_none}, progress).ok()))
Ok(T(this.add_weighted(&${value_for_none}, self_portion, other_portion).ok()))
},
(&T(None), &T(Some(ref other))) => {
Ok(T(${value_for_none}.interpolate(other, progress).ok()))
Ok(T(${value_for_none}.add_weighted(other, self_portion, other_portion).ok()))
},
(&T(None), &T(None)) => {
Ok(T(None))
Expand Down
486 changes: 296 additions & 190 deletions components/style/properties/helpers/animated_properties.mako.rs

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions components/style/properties/longhand/background.mako.rs
Expand Up @@ -190,13 +190,16 @@ ${helpers.single_keyword("background-origin",
impl RepeatableListAnimatable for T {}

impl Animatable for T {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
use properties::longhands::background_size::single_value::computed_value::ExplicitSize;
match (self, other) {
(&T::Explicit(ref me), &T::Explicit(ref other)) => {
Ok(T::Explicit(ExplicitSize {
width: try!(me.width.interpolate(&other.width, time)),
height: try!(me.height.interpolate(&other.height, time)),
width: try!(me.width.add_weighted(&other.width,
self_portion, other_portion)),
height: try!(me.height.add_weighted(&other.height,
self_portion, other_portion)),
}))
}
_ => Err(()),
Expand Down
11 changes: 7 additions & 4 deletions components/style/properties/longhand/box.mako.rs
Expand Up @@ -2198,11 +2198,14 @@ ${helpers.single_keyword("transform-style",

impl Animatable for T {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
Ok(T {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
depth: try!(self.depth.interpolate(&other.depth, time)),
horizontal: try!(self.horizontal.add_weighted(&other.horizontal,
self_portion, other_portion)),
vertical: try!(self.vertical.add_weighted(&other.vertical,
self_portion, other_portion)),
depth: try!(self.depth.add_weighted(&other.depth, self_portion, other_portion)),
})
}

Expand Down
6 changes: 4 additions & 2 deletions components/style/properties/longhand/font.mako.rs
Expand Up @@ -1073,10 +1073,12 @@ ${helpers.single_keyword_system("font-variant-caps",
}

impl Animatable for T {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
match (*self, *other) {
(T::Number(ref number), T::Number(ref other)) =>
Ok(T::Number(try!(number.interpolate(other, time)))),
Ok(T::Number(try!(number.add_weighted(other,
self_portion, other_portion)))),
_ => Err(()),
}
}
Expand Down
9 changes: 6 additions & 3 deletions components/style/properties/longhand/inherited_table.mako.rs
Expand Up @@ -42,10 +42,13 @@ ${helpers.single_keyword("caption-side", "top bottom",
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
impl Animatable for T {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
Ok(T {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
horizontal: try!(self.horizontal.add_weighted(&other.horizontal,
self_portion, other_portion)),
vertical: try!(self.vertical.add_weighted(&other.vertical,
self_portion, other_portion)),
})
}

Expand Down
3 changes: 2 additions & 1 deletion components/style/values/mod.rs
Expand Up @@ -129,7 +129,8 @@ macro_rules! define_keyword_type {

impl Animatable for $name {
#[inline]
fn interpolate(&self, _other: &Self, _progress: f64) -> Result<Self, ()> {
fn add_weighted(&self, _other: &Self, _self_progress: f64, _other_progress: f64)
-> Result<Self, ()> {
Ok($name)
}
}
Expand Down
37 changes: 28 additions & 9 deletions ports/geckolib/glue.rs
Expand Up @@ -62,6 +62,7 @@ use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet};
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, nsCSSFontFaceRule};
use style::gecko_bindings::structs::CompositeOperation;
use style::gecko_bindings::structs::Loader;
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
use style::gecko_bindings::structs::ServoElementSnapshotTable;
Expand Down Expand Up @@ -325,12 +326,16 @@ pub extern "C" fn Servo_AnimationCompose(raw_value_map: RawServoAnimationValueMa
let property: TransitionProperty = css_property.into();
let value_map = AnimationValueMap::from_ffi_mut(raw_value_map);

let need_underlying_value = segment.mFromValue.mServo.mRawPtr.is_null() ||
segment.mToValue.mServo.mRawPtr.is_null() ||
segment.mFromComposite != CompositeOperation::Replace ||
segment.mToComposite != CompositeOperation::Replace;

// If either of the segment endpoints are null, get the underlying value to
// use from the current value in the values map (set by a lower-priority
// effect), or, if there is no current value, look up the cached base value
// for this property.
let underlying_value = if segment.mFromValue.mServo.mRawPtr.is_null() ||
segment.mToValue.mServo.mRawPtr.is_null() {
let underlying_value = if need_underlying_value {
let previous_composed_value = value_map.get(&property).cloned();
previous_composed_value.or_else(|| {
let raw_base_style = unsafe { Gecko_AnimationGetBaseStyle(base_values, css_property) };
Expand All @@ -340,26 +345,40 @@ pub extern "C" fn Servo_AnimationCompose(raw_value_map: RawServoAnimationValueMa
None
};

if (segment.mFromValue.mServo.mRawPtr.is_null() ||
segment.mToValue.mServo.mRawPtr.is_null()) &&
underlying_value.is_none() {
warn!("Underlying value should be valid in the case where either 'from' value or 'to' value is null");
if need_underlying_value && underlying_value.is_none() {
warn!("Underlying value should be valid when we expect to use it");
return;
}

// Declare for making derefenced raw pointer alive outside the if block.
// Temporaries used in the following if-block whose lifetimes we need to prlong.
let raw_from_value;
let from_composite_result;
let from_value = if !segment.mFromValue.mServo.mRawPtr.is_null() {
raw_from_value = unsafe { &*segment.mFromValue.mServo.mRawPtr };
AnimationValue::as_arc(&raw_from_value).as_ref()
match segment.mFromComposite {
CompositeOperation::Add => {
let value_to_composite = AnimationValue::as_arc(&raw_from_value).as_ref();
from_composite_result = underlying_value.as_ref().unwrap().add(value_to_composite);
from_composite_result.as_ref().unwrap_or(value_to_composite)
}
_ => { AnimationValue::as_arc(&raw_from_value) }
}
} else {
underlying_value.as_ref().unwrap()
};

let raw_to_value;
let to_composite_result;
let to_value = if !segment.mToValue.mServo.mRawPtr.is_null() {
raw_to_value = unsafe { &*segment.mToValue.mServo.mRawPtr };
AnimationValue::as_arc(&raw_to_value).as_ref()
match segment.mToComposite {
CompositeOperation::Add => {
let value_to_composite = AnimationValue::as_arc(&raw_to_value).as_ref();
to_composite_result = underlying_value.as_ref().unwrap().add(value_to_composite);
to_composite_result.as_ref().unwrap_or(value_to_composite)
}
_ => { AnimationValue::as_arc(&raw_to_value) }
}
} else {
underlying_value.as_ref().unwrap()
};
Expand Down

0 comments on commit 94e977e

Please sign in to comment.