mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Use animation_value_type in AnimatedProperty.
So that we can remove redundant interpolation code for corresponding computed types.
This commit is contained in:
parent
0ef3a23313
commit
61eb7e055f
2 changed files with 38 additions and 117 deletions
|
@ -294,9 +294,14 @@ impl<'a> From<TransitionProperty> for PropertyDeclarationId<'a> {
|
||||||
pub enum AnimatedProperty {
|
pub enum AnimatedProperty {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
|
<%
|
||||||
|
if prop.is_animatable_with_computed_value:
|
||||||
|
value_type = "longhands::{}::computed_value::T".format(prop.ident)
|
||||||
|
else:
|
||||||
|
value_type = prop.animation_value_type
|
||||||
|
%>
|
||||||
/// ${prop.name}
|
/// ${prop.name}
|
||||||
${prop.camel_case}(longhands::${prop.ident}::computed_value::T,
|
${prop.camel_case}(${value_type}, ${value_type}),
|
||||||
longhands::${prop.ident}::computed_value::T),
|
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
@ -356,6 +361,9 @@ impl AnimatedProperty {
|
||||||
Err(()) => return,
|
Err(()) => return,
|
||||||
};
|
};
|
||||||
% endif
|
% endif
|
||||||
|
% if not prop.is_animatable_with_computed_value:
|
||||||
|
let value: longhands::${prop.ident}::computed_value::T = value.into();
|
||||||
|
% endif
|
||||||
style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value);
|
style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value);
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
|
@ -375,8 +383,8 @@ impl AnimatedProperty {
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
TransitionProperty::${prop.camel_case} => {
|
TransitionProperty::${prop.camel_case} => {
|
||||||
AnimatedProperty::${prop.camel_case}(
|
AnimatedProperty::${prop.camel_case}(
|
||||||
old_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}(),
|
old_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}().into(),
|
||||||
new_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}())
|
new_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}().into())
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -936,96 +944,6 @@ impl Animatable for BackgroundSizeList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-transitions/#animtype-color
|
|
||||||
impl Animatable for RGBA {
|
|
||||||
#[inline]
|
|
||||||
fn add_weighted(&self, other: &RGBA, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
|
||||||
fn clamp(val: f32) -> f32 {
|
|
||||||
val.max(0.).min(1.)
|
|
||||||
}
|
|
||||||
|
|
||||||
let alpha = clamp(try!(self.alpha_f32().add_weighted(&other.alpha_f32(),
|
|
||||||
self_portion, other_portion)));
|
|
||||||
if alpha == 0. {
|
|
||||||
Ok(RGBA::transparent())
|
|
||||||
} else {
|
|
||||||
// NB: We rely on RGBA::from_floats clamping already.
|
|
||||||
let red = try!((self.red_f32() * self.alpha_f32())
|
|
||||||
.add_weighted(&(other.red_f32() * other.alpha_f32()),
|
|
||||||
self_portion, other_portion))
|
|
||||||
* 1. / alpha;
|
|
||||||
let green = try!((self.green_f32() * self.alpha_f32())
|
|
||||||
.add_weighted(&(other.green_f32() * other.alpha_f32()),
|
|
||||||
self_portion, other_portion))
|
|
||||||
* 1. / alpha;
|
|
||||||
let blue = try!((self.blue_f32() * self.alpha_f32())
|
|
||||||
.add_weighted(&(other.blue_f32() * other.alpha_f32()),
|
|
||||||
self_portion, other_portion))
|
|
||||||
* 1. / alpha;
|
|
||||||
Ok(RGBA::from_floats(red, green, blue, alpha))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://www.w3.org/TR/smil-animation/#animateColorElement says we should use Euclidean
|
|
||||||
/// RGB-cube distance.
|
|
||||||
#[inline]
|
|
||||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
|
||||||
self.compute_squared_distance(other).map(|sd| sd.sqrt())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
|
||||||
fn clamp(val: f32) -> f32 {
|
|
||||||
val.max(0.).min(1.)
|
|
||||||
}
|
|
||||||
|
|
||||||
let start_a = clamp(self.alpha_f32());
|
|
||||||
let end_a = clamp(other.alpha_f32());
|
|
||||||
let start = [ start_a,
|
|
||||||
self.red_f32() * start_a,
|
|
||||||
self.green_f32() * start_a,
|
|
||||||
self.blue_f32() * start_a ];
|
|
||||||
let end = [ end_a,
|
|
||||||
other.red_f32() * end_a,
|
|
||||||
other.green_f32() * end_a,
|
|
||||||
other.blue_f32() * end_a ];
|
|
||||||
let diff = start.iter().zip(&end)
|
|
||||||
.fold(0.0f64, |n, (&a, &b)| {
|
|
||||||
let diff = (a - b) as f64;
|
|
||||||
n + diff * diff
|
|
||||||
});
|
|
||||||
Ok(diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-transitions/#animtype-color
|
|
||||||
impl Animatable for CSSParserColor {
|
|
||||||
#[inline]
|
|
||||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
|
||||||
match (*self, *other) {
|
|
||||||
(CSSParserColor::RGBA(ref this), CSSParserColor::RGBA(ref other)) => {
|
|
||||||
this.add_weighted(other, self_portion, other_portion).map(CSSParserColor::RGBA)
|
|
||||||
}
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
|
||||||
self.compute_squared_distance(other).map(|sq| sq.sqrt())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
|
||||||
match (*self, *other) {
|
|
||||||
(CSSParserColor::RGBA(ref this), CSSParserColor::RGBA(ref other)) => {
|
|
||||||
this.compute_squared_distance(other)
|
|
||||||
},
|
|
||||||
_ => Ok(0.0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
|
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
|
||||||
impl Animatable for CalcLengthOrPercentage {
|
impl Animatable for CalcLengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1569,9 +1487,6 @@ impl Animatable for ClipRect {
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
${impl_animatable_for_shadow('BoxShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
|
|
||||||
${impl_animatable_for_shadow('TextShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
|
|
||||||
|
|
||||||
/// Check if it's possible to do a direct numerical interpolation
|
/// Check if it's possible to do a direct numerical interpolation
|
||||||
/// between these two transform lists.
|
/// between these two transform lists.
|
||||||
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
|
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
|
||||||
|
|
|
@ -2,49 +2,55 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::{Color, RGBA};
|
use cssparser::RGBA;
|
||||||
use style::properties::animated_properties::Animatable;
|
use style::properties::animated_properties::{Animatable, IntermediateRGBA};
|
||||||
|
|
||||||
|
fn interpolate_rgba(from: RGBA, to: RGBA, progress: f64) -> RGBA {
|
||||||
|
let from: IntermediateRGBA = from.into();
|
||||||
|
let to: IntermediateRGBA = to.into();
|
||||||
|
from.interpolate(&to, progress).unwrap().into()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgba_color_interepolation_preserves_transparent() {
|
fn test_rgba_color_interepolation_preserves_transparent() {
|
||||||
assert_eq!(Color::RGBA(RGBA::transparent())
|
assert_eq!(interpolate_rgba(RGBA::transparent(),
|
||||||
.interpolate(&Color::RGBA(RGBA::transparent()), 0.5).unwrap(),
|
RGBA::transparent(), 0.5),
|
||||||
Color::RGBA(RGBA::transparent()));
|
RGBA::transparent());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgba_color_interepolation_alpha() {
|
fn test_rgba_color_interepolation_alpha() {
|
||||||
assert_eq!(Color::RGBA(RGBA::new(200, 0, 0, 100))
|
assert_eq!(interpolate_rgba(RGBA::new(200, 0, 0, 100),
|
||||||
.interpolate(&Color::RGBA(RGBA::new(0, 200, 0, 200)), 0.5).unwrap(),
|
RGBA::new(0, 200, 0, 200), 0.5),
|
||||||
Color::RGBA(RGBA::new(67, 133, 0, 150)));
|
RGBA::new(67, 133, 0, 150));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgba_color_interepolation_out_of_range_1() {
|
fn test_rgba_color_interepolation_out_of_range_1() {
|
||||||
// Some cubic-bezier functions produce values that are out of range [0, 1].
|
// Some cubic-bezier functions produce values that are out of range [0, 1].
|
||||||
// Unclamped cases.
|
// Unclamped cases.
|
||||||
assert_eq!(Color::RGBA(RGBA::from_floats(0.3, 0.0, 0.0, 0.4)).interpolate(
|
assert_eq!(interpolate_rgba(RGBA::from_floats(0.3, 0.0, 0.0, 0.4),
|
||||||
&Color::RGBA(RGBA::from_floats(0.0, 1.0, 0.0, 0.6)), -0.5).unwrap(),
|
RGBA::from_floats(0.0, 1.0, 0.0, 0.6), -0.5),
|
||||||
Color::RGBA(RGBA::new(154, 0, 0, 77)));
|
RGBA::new(154, 0, 0, 77));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgba_color_interepolation_out_of_range_2() {
|
fn test_rgba_color_interepolation_out_of_range_2() {
|
||||||
assert_eq!(Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 0.6)).interpolate(
|
assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.6),
|
||||||
&Color::RGBA(RGBA::from_floats(0.0, 0.3, 0.0, 0.4)), 1.5).unwrap(),
|
RGBA::from_floats(0.0, 0.3, 0.0, 0.4), 1.5),
|
||||||
Color::RGBA(RGBA::new(0, 154, 0, 77)));
|
RGBA::new(0, 154, 0, 77));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgba_color_interepolation_out_of_range_clamped_1() {
|
fn test_rgba_color_interepolation_out_of_range_clamped_1() {
|
||||||
assert_eq!(Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 0.8)).interpolate(
|
assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
|
||||||
&Color::RGBA(RGBA::from_floats(0.0, 1.0, 0.0, 0.2)), -0.5).unwrap(),
|
RGBA::from_floats(0.0, 1.0, 0.0, 0.2), -0.5),
|
||||||
Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 1.0)));
|
RGBA::from_floats(1.0, 0.0, 0.0, 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgba_color_interepolation_out_of_range_clamped_2() {
|
fn test_rgba_color_interepolation_out_of_range_clamped_2() {
|
||||||
assert_eq!(Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 0.8)).interpolate(
|
assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
|
||||||
&Color::RGBA(RGBA::from_floats(0.0, 1.0, 0.0, 0.2)), 1.5).unwrap(),
|
RGBA::from_floats(0.0, 1.0, 0.0, 0.2), 1.5),
|
||||||
Color::RGBA(RGBA::from_floats(0.0, 0.0, 0.0, 0.0)));
|
RGBA::from_floats(0.0, 0.0, 0.0, 0.0));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue