mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Auto merge of #16554 - BorisChiou:stylo/animation/compute_distance, r=emilio
stylo: Bug 1332633 - Implement ComputeDistance trait. These patches implement ComputeDistance trait, so we can use it for SMIL animation and for testing test_transitions_per_property.html, which uses nsDOMWindowUtils::ComputeAnimationDistance() to get the the distance between two AnimationValues. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix Bug 1332633. - [X] These changes do not require tests because we have test cases in Gecko. (If Servo wants to use this feature, we can add more tests in Servo in the future.) <!-- 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/16554) <!-- Reviewable:end -->
This commit is contained in:
commit
350d9c6c47
9 changed files with 750 additions and 12 deletions
|
@ -1753,6 +1753,13 @@ extern "C" {
|
|||
RawServoAnimationValueBorrowed)
|
||||
-> bool;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_AnimationValues_ComputeDistance(from:
|
||||
RawServoAnimationValueBorrowed,
|
||||
to:
|
||||
RawServoAnimationValueBorrowed)
|
||||
-> f64;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_AnimationValue_Serialize(value:
|
||||
RawServoAnimationValueBorrowed,
|
||||
|
|
|
@ -95,6 +95,19 @@
|
|||
self.0.interpolate(&other.0, progress).map(T)
|
||||
}
|
||||
}
|
||||
|
||||
use properties::animated_properties::ComputeDistance;
|
||||
impl ComputeDistance for T {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_distance(&other.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_squared_distance(&other.0)
|
||||
}
|
||||
}
|
||||
% endif
|
||||
}
|
||||
|
||||
|
@ -785,3 +798,41 @@
|
|||
}
|
||||
}
|
||||
</%def>
|
||||
|
||||
/// Macro for defining ComputeDistance trait for tuple struct which has Option<T>,
|
||||
/// e.g. struct T(pub Option<Au>).
|
||||
<%def name="impl_compute_distance_for_option_tuple(value_for_none)">
|
||||
impl ComputeDistance for T {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
(&T(Some(ref this)), &T(Some(ref other))) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(&T(Some(ref value)), &T(None)) |
|
||||
(&T(None), &T(Some(ref value)))=> {
|
||||
value.compute_distance(&${value_for_none})
|
||||
},
|
||||
(&T(None), &T(None)) => {
|
||||
Ok(0.0)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
(&T(Some(ref this)), &T(Some(ref other))) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
(&T(Some(ref value)), &T(None)) |
|
||||
(&T(None), &T(Some(ref value))) => {
|
||||
value.compute_squared_distance(&${value_for_none})
|
||||
},
|
||||
(&T(None), &T(None)) => {
|
||||
Ok(0.0)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
|
|
@ -10,7 +10,7 @@ use euclid::{Point2D, Size2D};
|
|||
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
|
||||
use properties::{CSSWideKeyword, PropertyDeclaration};
|
||||
use properties::longhands;
|
||||
use properties::longhands::background_size::computed_value::T as BackgroundSize;
|
||||
use properties::longhands::background_size::computed_value::T as BackgroundSizeList;
|
||||
use properties::longhands::font_weight::computed_value::T as FontWeight;
|
||||
use properties::longhands::line_height::computed_value::T as LineHeight;
|
||||
use properties::longhands::text_shadow::computed_value::T as TextShadowList;
|
||||
|
@ -696,14 +696,14 @@ impl Interpolate for VerticalAlign {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl Interpolate for BackgroundSize {
|
||||
|
||||
impl Interpolate for BackgroundSizeList {
|
||||
#[inline]
|
||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||
self.0.interpolate(&other.0, progress).map(BackgroundSize)
|
||||
self.0.interpolate(&other.0, progress).map(BackgroundSizeList)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-color
|
||||
impl Interpolate for RGBA {
|
||||
#[inline]
|
||||
|
@ -2032,3 +2032,614 @@ impl<T, U> Interpolate for Either<T, U>
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// We support ComputeDistance for an API in gecko to test the transition per property.
|
||||
impl ComputeDistance for AnimationValue {
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
% for prop in data.longhands:
|
||||
% if prop.animatable:
|
||||
% if prop.animation_type == "normal":
|
||||
(&AnimationValue::${prop.camel_case}(ref from),
|
||||
&AnimationValue::${prop.camel_case}(ref to)) => {
|
||||
from.compute_distance(to)
|
||||
},
|
||||
% else:
|
||||
(&AnimationValue::${prop.camel_case}(ref _from),
|
||||
&AnimationValue::${prop.camel_case}(ref _to)) => {
|
||||
Err(())
|
||||
},
|
||||
% endif
|
||||
% endif
|
||||
% endfor
|
||||
_ => {
|
||||
panic!("Expected compute_distance of computed values of the same \
|
||||
property, got: {:?}, {:?}", self, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait used to implement [compute_distance].
|
||||
/// In order to compute the Euclidean distance of a list, we need to compute squared distance
|
||||
/// for each element, so the vector can sum it and then get its squared root as the distance.
|
||||
pub trait ComputeDistance: Sized {
|
||||
/// Compute distance between a value and another for a given property.
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()>;
|
||||
|
||||
/// Compute squared distance between a value and another for a given property.
|
||||
/// This is used for list or if there are many components in a property value.
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.compute_distance(other).map(|d| d * d)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ComputeDistance> ComputeDistance for Vec<T> {
|
||||
#[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, ()> {
|
||||
if self.len() != other.len() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut squared_dist = 0.0f64;
|
||||
for (this, other) in self.iter().zip(other) {
|
||||
let diff = try!(this.compute_squared_distance(other));
|
||||
squared_dist += diff;
|
||||
}
|
||||
Ok(squared_dist)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for Au {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_distance(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for Auto {
|
||||
#[inline]
|
||||
fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for Normal {
|
||||
#[inline]
|
||||
fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
impl <T> ComputeDistance for Option<T>
|
||||
where T: ComputeDistance,
|
||||
{
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
(&Some(ref this), &Some(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
(&Some(ref this), &Some(ref other)) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for f32 {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
Ok((*self - *other).abs() as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for f64 {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
Ok((*self - *other).abs())
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for i32 {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
Ok((*self - *other).abs() as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for Visibility {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
if *self == *other {
|
||||
Ok(0.0)
|
||||
} else {
|
||||
Ok(1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.w3.org/TR/smil-animation/#animateColorElement says we should use Euclidean RGB-cube distance.
|
||||
impl ComputeDistance for RGBA {
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for CSSParserColor {
|
||||
#[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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for CalcLengthOrPercentage {
|
||||
#[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, ()> {
|
||||
let length_diff = (self.length().0 - other.length().0) as f64;
|
||||
let percentage_diff = (self.percentage() - other.percentage()) as f64;
|
||||
Ok(length_diff * length_diff + percentage_diff * percentage_diff)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LengthOrPercentage::Length(ref this),
|
||||
LengthOrPercentage::Length(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(LengthOrPercentage::Percentage(ref this),
|
||||
LengthOrPercentage::Percentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(this, other) => {
|
||||
let this: CalcLengthOrPercentage = From::from(this);
|
||||
let other: CalcLengthOrPercentage = From::from(other);
|
||||
this.compute_distance(&other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LengthOrPercentage::Length(ref this),
|
||||
LengthOrPercentage::Length(ref other)) => {
|
||||
let diff = (this.0 - other.0) as f64;
|
||||
Ok(diff * diff)
|
||||
},
|
||||
(LengthOrPercentage::Percentage(ref this),
|
||||
LengthOrPercentage::Percentage(ref other)) => {
|
||||
let diff = (this - other) as f64;
|
||||
Ok(diff * diff)
|
||||
},
|
||||
(this, other) => {
|
||||
let this: CalcLengthOrPercentage = From::from(this);
|
||||
let other: CalcLengthOrPercentage = From::from(other);
|
||||
let length_diff = (this.length().0 - other.length().0) as f64;
|
||||
let percentage_diff = (this.percentage() - other.percentage()) as f64;
|
||||
Ok(length_diff * length_diff + percentage_diff * percentage_diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for LengthOrPercentageOrAuto {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LengthOrPercentageOrAuto::Length(ref this),
|
||||
LengthOrPercentageOrAuto::Length(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(LengthOrPercentageOrAuto::Percentage(ref this),
|
||||
LengthOrPercentageOrAuto::Percentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(this, other) => {
|
||||
// If one of the element is Auto, Option<> will be None, and the returned distance is Err(())
|
||||
let this: Option<CalcLengthOrPercentage> = From::from(this);
|
||||
let other: Option<CalcLengthOrPercentage> = From::from(other);
|
||||
this.compute_distance(&other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LengthOrPercentageOrAuto::Length(ref this),
|
||||
LengthOrPercentageOrAuto::Length(ref other)) => {
|
||||
let diff = (this.0 - other.0) as f64;
|
||||
Ok(diff * diff)
|
||||
},
|
||||
(LengthOrPercentageOrAuto::Percentage(ref this),
|
||||
LengthOrPercentageOrAuto::Percentage(ref other)) => {
|
||||
let diff = (this - other) as f64;
|
||||
Ok(diff * diff)
|
||||
},
|
||||
(this, other) => {
|
||||
let this: Option<CalcLengthOrPercentage> = From::from(this);
|
||||
let other: Option<CalcLengthOrPercentage> = From::from(other);
|
||||
if this.is_none() || other.is_none() {
|
||||
Err(())
|
||||
} else {
|
||||
let length_diff = (this.unwrap().length().0 - other.unwrap().length().0) as f64;
|
||||
let percentage_diff = (this.unwrap().percentage() - other.unwrap().percentage()) as f64;
|
||||
Ok(length_diff * length_diff + percentage_diff * percentage_diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for LengthOrPercentageOrNone {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LengthOrPercentageOrNone::Length(ref this),
|
||||
LengthOrPercentageOrNone::Length(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(LengthOrPercentageOrNone::Percentage(ref this),
|
||||
LengthOrPercentageOrNone::Percentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for LengthOrNone {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(Either::First(ref length), Either::First(ref other)) => {
|
||||
length.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for MinLength {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(MinLength::LengthOrPercentage(ref this),
|
||||
MinLength::LengthOrPercentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for MaxLength {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(MaxLength::LengthOrPercentage(ref this),
|
||||
MaxLength::LengthOrPercentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for VerticalAlign {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(VerticalAlign::LengthOrPercentage(ref this),
|
||||
VerticalAlign::LengthOrPercentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for BorderRadiusSize {
|
||||
#[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, ()> {
|
||||
Ok(try!(self.0.width.compute_squared_distance(&other.0.width)) +
|
||||
try!(self.0.height.compute_squared_distance(&other.0.height)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for BackgroundSizeList {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_distance(&other.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_squared_distance(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for LineHeight {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LineHeight::Length(ref this),
|
||||
LineHeight::Length(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(LineHeight::Number(ref this),
|
||||
LineHeight::Number(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for FontWeight {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
let a = (*self as u32) as f64;
|
||||
let b = (*other as u32) as f64;
|
||||
a.compute_distance(&b)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for Position {
|
||||
#[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, ()> {
|
||||
Ok(try!(self.horizontal.compute_squared_distance(&other.horizontal)) +
|
||||
try!(self.vertical.compute_squared_distance(&other.vertical)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for HorizontalPosition {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_distance(&other.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_squared_distance(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for VerticalPosition {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_distance(&other.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
self.0.compute_squared_distance(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for ClipRect {
|
||||
#[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, ()> {
|
||||
let list = [ try!(self.top.compute_distance(&other.top)),
|
||||
try!(self.right.compute_distance(&other.right)),
|
||||
try!(self.bottom.compute_distance(&other.bottom)),
|
||||
try!(self.left.compute_distance(&other.left)) ];
|
||||
Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for TextShadow {
|
||||
#[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, ()> {
|
||||
let list = [ try!(self.offset_x.compute_distance(&other.offset_x)),
|
||||
try!(self.offset_y.compute_distance(&other.offset_y)),
|
||||
try!(self.blur_radius.compute_distance(&other.blur_radius)),
|
||||
try!(self.color.compute_distance(&other.color)) ];
|
||||
Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for TextShadowList {
|
||||
#[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, ()> {
|
||||
let zero = TextShadow {
|
||||
offset_x: Au(0),
|
||||
offset_y: Au(0),
|
||||
blur_radius: Au(0),
|
||||
color: CSSParserColor::RGBA(RGBA::transparent()),
|
||||
};
|
||||
|
||||
let max_len = cmp::max(self.0.len(), other.0.len());
|
||||
let mut diff_squared = 0.0f64;
|
||||
for i in 0..max_len {
|
||||
diff_squared += match (self.0.get(i), other.0.get(i)) {
|
||||
(Some(shadow), Some(other)) => {
|
||||
try!(shadow.compute_squared_distance(other))
|
||||
},
|
||||
(Some(shadow), None) |
|
||||
(None, Some(shadow)) => {
|
||||
try!(shadow.compute_squared_distance(&zero))
|
||||
},
|
||||
(None, None) => unreachable!(),
|
||||
};
|
||||
}
|
||||
Ok(diff_squared)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for BoxShadow {
|
||||
#[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, ()> {
|
||||
if self.inset != other.inset {
|
||||
return Err(());
|
||||
}
|
||||
let list = [ try!(self.offset_x.compute_distance(&other.offset_x)),
|
||||
try!(self.offset_y.compute_distance(&other.offset_y)),
|
||||
try!(self.color.compute_distance(&other.color)),
|
||||
try!(self.spread_radius.compute_distance(&other.spread_radius)),
|
||||
try!(self.blur_radius.compute_distance(&other.blur_radius)) ];
|
||||
Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for BoxShadowList {
|
||||
#[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, ()> {
|
||||
// The inset value must change
|
||||
let mut zero = BoxShadow {
|
||||
offset_x: Au(0),
|
||||
offset_y: Au(0),
|
||||
spread_radius: Au(0),
|
||||
blur_radius: Au(0),
|
||||
color: CSSParserColor::RGBA(RGBA::transparent()),
|
||||
inset: false,
|
||||
};
|
||||
|
||||
let max_len = cmp::max(self.0.len(), other.0.len());
|
||||
let mut diff_squared = 0.0f64;
|
||||
for i in 0..max_len {
|
||||
diff_squared += match (self.0.get(i), other.0.get(i)) {
|
||||
(Some(shadow), Some(other)) => {
|
||||
try!(shadow.compute_squared_distance(other))
|
||||
},
|
||||
(Some(shadow), None) |
|
||||
(None, Some(shadow)) => {
|
||||
zero.inset = shadow.inset;
|
||||
try!(shadow.compute_squared_distance(&zero))
|
||||
}
|
||||
(None, None) => unreachable!(),
|
||||
};
|
||||
}
|
||||
Ok(diff_squared)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for TransformList {
|
||||
#[inline]
|
||||
fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> ComputeDistance for Either<T, U>
|
||||
where T: ComputeDistance, U: ComputeDistance
|
||||
{
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
(&Either::First(ref this), &Either::First(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(&Either::Second(ref this), &Either::Second(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (self, other) {
|
||||
(&Either::First(ref this), &Either::First(ref other)) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
(&Either::Second(ref this), &Either::Second(ref other)) => {
|
||||
this.compute_squared_distance(other)
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -334,7 +334,7 @@ ${helpers.single_keyword("background-origin",
|
|||
#[allow(missing_docs)]
|
||||
pub mod computed_value {
|
||||
use values::computed::LengthOrPercentageOrAuto;
|
||||
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -367,6 +367,24 @@ ${helpers.single_keyword("background-origin",
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for T {
|
||||
#[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, ()> {
|
||||
match (self, other) {
|
||||
(&T::Explicit(ref me), &T::Explicit(ref other)) => {
|
||||
Ok(try!(me.width.compute_squared_distance(&other.width)) +
|
||||
try!(me.height.compute_squared_distance(&other.height)))
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for computed_value::T {
|
||||
|
|
|
@ -2197,7 +2197,7 @@ ${helpers.single_keyword("transform-style",
|
|||
use values::specified::{NoCalcLength, LengthOrPercentage, Percentage};
|
||||
|
||||
pub mod computed_value {
|
||||
use properties::animated_properties::Interpolate;
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate};
|
||||
use values::computed::{Length, LengthOrPercentage};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
@ -2209,6 +2209,7 @@ ${helpers.single_keyword("transform-style",
|
|||
}
|
||||
|
||||
impl Interpolate for T {
|
||||
#[inline]
|
||||
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
|
||||
Ok(T {
|
||||
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
|
||||
|
@ -2217,6 +2218,20 @@ ${helpers.single_keyword("transform-style",
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for T {
|
||||
#[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, ()> {
|
||||
Ok(try!(self.horizontal.compute_squared_distance(&other.horizontal)) +
|
||||
try!(self.vertical.compute_squared_distance(&other.vertical)) +
|
||||
try!(self.depth.compute_squared_distance(&other.depth)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasViewportPercentage for SpecifiedValue {
|
||||
|
|
|
@ -818,7 +818,7 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use properties::animated_properties::Interpolate;
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::CSSFloat;
|
||||
|
@ -850,6 +850,17 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeDistance for T {
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(T::Number(ref number), T::Number(ref other)) =>
|
||||
number.compute_distance(other),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -439,13 +439,14 @@ ${helpers.single_keyword("text-align-last",
|
|||
|
||||
pub mod computed_value {
|
||||
use app_units::Au;
|
||||
use properties::animated_properties::Interpolate;
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct T(pub Option<Au>);
|
||||
|
||||
${helpers.impl_interpolate_for_option_tuple('Au(0)')}
|
||||
${helpers.impl_compute_distance_for_option_tuple('Au(0)')}
|
||||
}
|
||||
|
||||
impl ToCss for computed_value::T {
|
||||
|
@ -523,13 +524,14 @@ ${helpers.single_keyword("text-align-last",
|
|||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use properties::animated_properties::Interpolate;
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate};
|
||||
use values::computed::LengthOrPercentage;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct T(pub Option<LengthOrPercentage>);
|
||||
|
||||
${helpers.impl_interpolate_for_option_tuple('LengthOrPercentage::zero()')}
|
||||
${helpers.impl_compute_distance_for_option_tuple('LengthOrPercentage::zero()')}
|
||||
}
|
||||
|
||||
impl ToCss for computed_value::T {
|
||||
|
|
|
@ -121,7 +121,7 @@ ${helpers.single_keyword("mask-mode",
|
|||
pub use properties::longhands::background_position_x::single_value::parse;
|
||||
pub use properties::longhands::background_position_x::single_value::SpecifiedValue;
|
||||
pub use properties::longhands::background_position_x::single_value::computed_value;
|
||||
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
|
||||
use properties::longhands::mask_position_x::computed_value::T as MaskPositionX;
|
||||
|
||||
impl Interpolate for MaskPositionX {
|
||||
|
@ -132,6 +132,13 @@ ${helpers.single_keyword("mask-mode",
|
|||
}
|
||||
|
||||
impl RepeatableListInterpolate for MaskPositionX {}
|
||||
|
||||
impl ComputeDistance for MaskPositionX {
|
||||
#[inline]
|
||||
fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
</%helpers:vector_longhand>
|
||||
|
||||
<%helpers:vector_longhand name="mask-position-y" products="gecko" animation_type="normal" extra_prefixes="webkit"
|
||||
|
@ -142,7 +149,7 @@ ${helpers.single_keyword("mask-mode",
|
|||
pub use properties::longhands::background_position_y::single_value::parse;
|
||||
pub use properties::longhands::background_position_y::single_value::SpecifiedValue;
|
||||
pub use properties::longhands::background_position_y::single_value::computed_value;
|
||||
use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
|
||||
use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
|
||||
use properties::longhands::mask_position_y::computed_value::T as MaskPositionY;
|
||||
|
||||
impl Interpolate for MaskPositionY {
|
||||
|
@ -153,6 +160,13 @@ ${helpers.single_keyword("mask-mode",
|
|||
}
|
||||
|
||||
impl RepeatableListInterpolate for MaskPositionY {}
|
||||
|
||||
impl ComputeDistance for MaskPositionY {
|
||||
#[inline]
|
||||
fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
</%helpers:vector_longhand>
|
||||
|
||||
${helpers.single_keyword("mask-clip",
|
||||
|
|
|
@ -74,7 +74,7 @@ use style::parser::{LengthParsingMode, ParserContext};
|
|||
use style::properties::{CascadeFlags, ComputedValues, Importance, ParsedDeclaration};
|
||||
use style::properties::{PropertyDeclarationBlock, PropertyId};
|
||||
use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
|
||||
use style::properties::animated_properties::{AnimationValue, Interpolate, TransitionProperty};
|
||||
use style::properties::animated_properties::{AnimationValue, ComputeDistance, Interpolate, TransitionProperty};
|
||||
use style::properties::parse_one_declaration;
|
||||
use style::restyle_hints::{self, RestyleHint};
|
||||
use style::rule_tree::StyleSource;
|
||||
|
@ -265,6 +265,15 @@ pub extern "C" fn Servo_AnimationValues_IsInterpolable(from: RawServoAnimationVa
|
|||
from_value.interpolate(to_value, 0.5).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_AnimationValues_ComputeDistance(from: RawServoAnimationValueBorrowed,
|
||||
to: RawServoAnimationValueBorrowed)
|
||||
-> f64 {
|
||||
let from_value = AnimationValue::as_arc(&from);
|
||||
let to_value = AnimationValue::as_arc(&to);
|
||||
from_value.compute_distance(to_value).unwrap_or(0.0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_AnimationValueMap_Push(value_map: RawServoAnimationValueMapBorrowed,
|
||||
property: nsCSSPropertyID,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue