mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #19859 - birtles:individual-transforms, r=emilio
Implement individual CSS transform properties: translate, rotate, scale These are the servo-side changes for [Gecko bug 1207734](https://bugzilla.mozilla.org/show_bug.cgi?id=1207734). - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix [Gecko bug 1207734](https://bugzilla.mozilla.org/show_bug.cgi?id=1207734) - [X] There are tests for these changes on the Gecko side including 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/19859) <!-- Reviewable:end -->
This commit is contained in:
commit
3e27459ad3
17 changed files with 1563 additions and 839 deletions
|
@ -189,6 +189,9 @@ partial interface CSSStyleDeclaration {
|
||||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform-style;
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform-style;
|
||||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backfaceVisibility;
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backfaceVisibility;
|
||||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backface-visibility;
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backface-visibility;
|
||||||
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString rotate;
|
||||||
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString scale;
|
||||||
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString translate;
|
||||||
|
|
||||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString direction;
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString direction;
|
||||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString unicodeBidi;
|
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString unicodeBidi;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3016,20 +3016,53 @@ fn static_assert() {
|
||||||
${impl_copy_animation_value(ident, gecko_ffi_name)}
|
${impl_copy_animation_value(ident, gecko_ffi_name)}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="impl_individual_transform(ident, type, gecko_ffi_name)">
|
||||||
|
pub fn set_${ident}(&mut self, other: values::computed::${type}) {
|
||||||
|
unsafe { self.gecko.${gecko_ffi_name}.clear() };
|
||||||
|
|
||||||
|
if let Some(operation) = other.to_transform_operation() {
|
||||||
|
convert_transform(&[operation], &mut self.gecko.${gecko_ffi_name})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||||
|
unsafe { self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_${ident}(&mut self, other: &Self) {
|
||||||
|
self.copy_${ident}_from(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_${ident}(&self) -> values::computed::${type} {
|
||||||
|
use values::generics::transform::${type};
|
||||||
|
|
||||||
|
if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
|
||||||
|
return ${type}::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let list = unsafe { (*self.gecko.${gecko_ffi_name}.to_safe().get()).mHead.as_ref() };
|
||||||
|
|
||||||
|
let mut transform = clone_transform_from_list(list);
|
||||||
|
debug_assert_eq!(transform.0.len(), 1);
|
||||||
|
${type}::from_transform_operation(&transform.0.pop().unwrap())
|
||||||
|
}
|
||||||
|
</%def>
|
||||||
|
|
||||||
<% skip_box_longhands= """display overflow-y vertical-align
|
<% skip_box_longhands= """display overflow-y vertical-align
|
||||||
animation-name animation-delay animation-duration
|
animation-name animation-delay animation-duration
|
||||||
animation-direction animation-fill-mode animation-play-state
|
animation-direction animation-fill-mode animation-play-state
|
||||||
animation-iteration-count animation-timing-function
|
animation-iteration-count animation-timing-function
|
||||||
transition-duration transition-delay
|
transition-duration transition-delay
|
||||||
transition-timing-function transition-property
|
transition-timing-function transition-property
|
||||||
page-break-before page-break-after
|
page-break-before page-break-after rotate
|
||||||
scroll-snap-points-x scroll-snap-points-y
|
scroll-snap-points-x scroll-snap-points-y
|
||||||
scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate
|
scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate
|
||||||
perspective-origin -moz-binding will-change
|
perspective-origin -moz-binding will-change
|
||||||
overscroll-behavior-x overscroll-behavior-y
|
overscroll-behavior-x overscroll-behavior-y
|
||||||
overflow-clip-box-inline overflow-clip-box-block
|
overflow-clip-box-inline overflow-clip-box-block
|
||||||
perspective-origin -moz-binding will-change
|
perspective-origin -moz-binding will-change
|
||||||
shape-outside contain touch-action""" %>
|
shape-outside contain touch-action translate
|
||||||
|
scale""" %>
|
||||||
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
|
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
|
||||||
|
|
||||||
// We manually-implement the |display| property until we get general
|
// We manually-implement the |display| property until we get general
|
||||||
|
@ -3454,6 +3487,10 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
|
||||||
|
${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')}
|
||||||
|
${impl_individual_transform('scale', 'Scale', 'mSpecifiedScale')}
|
||||||
|
|
||||||
pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
|
pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
|
||||||
use gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
|
use gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
|
||||||
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_OPACITY;
|
use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_OPACITY;
|
||||||
|
|
|
@ -46,7 +46,10 @@ use values::computed::ToComputedValue;
|
||||||
use values::computed::transform::{DirectionVector, Matrix, Matrix3D};
|
use values::computed::transform::{DirectionVector, Matrix, Matrix3D};
|
||||||
use values::computed::transform::TransformOperation as ComputedTransformOperation;
|
use values::computed::transform::TransformOperation as ComputedTransformOperation;
|
||||||
use values::computed::transform::Transform as ComputedTransform;
|
use values::computed::transform::Transform as ComputedTransform;
|
||||||
use values::generics::transform::{self, Transform, TransformOperation};
|
use values::computed::transform::Rotate as ComputedRotate;
|
||||||
|
use values::computed::transform::Translate as ComputedTranslate;
|
||||||
|
use values::computed::transform::Scale as ComputedScale;
|
||||||
|
use values::generics::transform::{self, Rotate, Translate, Scale, Transform, TransformOperation};
|
||||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
#[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings;
|
#[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings;
|
||||||
#[cfg(feature = "gecko")] use values::generics::FontSettingTag as GenericFontSettingTag;
|
#[cfg(feature = "gecko")] use values::generics::FontSettingTag as GenericFontSettingTag;
|
||||||
|
@ -1696,7 +1699,7 @@ pub struct Perspective(f32, f32, f32, f32);
|
||||||
pub struct Quaternion(f64, f64, f64, f64);
|
pub struct Quaternion(f64, f64, f64, f64);
|
||||||
|
|
||||||
/// A decomposed 3d matrix.
|
/// A decomposed 3d matrix.
|
||||||
#[derive(Clone, ComputeSquaredDistance, Copy, Debug)]
|
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||||
pub struct MatrixDecomposed3D {
|
pub struct MatrixDecomposed3D {
|
||||||
/// A translation function.
|
/// A translation function.
|
||||||
|
@ -1739,6 +1742,76 @@ impl Quaternion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Animate for Quaternion {
|
||||||
|
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||||
|
use std::f64;
|
||||||
|
|
||||||
|
let (this_weight, other_weight) = procedure.weights();
|
||||||
|
debug_assert!((this_weight + other_weight - 1.0f64).abs() <= f64::EPSILON ||
|
||||||
|
other_weight == 1.0f64 || other_weight == 0.0f64,
|
||||||
|
"animate should only be used for interpolating or accumulating transforms");
|
||||||
|
|
||||||
|
// We take a specialized code path for accumulation (where other_weight is 1)
|
||||||
|
if other_weight == 1.0 {
|
||||||
|
if this_weight == 0.0 {
|
||||||
|
return Ok(*other);
|
||||||
|
}
|
||||||
|
|
||||||
|
let clamped_w = self.3.min(1.0).max(-1.0);
|
||||||
|
|
||||||
|
// Determine the scale factor.
|
||||||
|
let mut theta = clamped_w.acos();
|
||||||
|
let mut scale = if theta == 0.0 { 0.0 } else { 1.0 / theta.sin() };
|
||||||
|
theta *= this_weight;
|
||||||
|
scale *= theta.sin();
|
||||||
|
|
||||||
|
// Scale the self matrix by this_weight.
|
||||||
|
let mut scaled_self = *self;
|
||||||
|
% for i in range(3):
|
||||||
|
scaled_self.${i} *= scale;
|
||||||
|
% endfor
|
||||||
|
scaled_self.3 = theta.cos();
|
||||||
|
|
||||||
|
// Multiply scaled-self by other.
|
||||||
|
let a = &scaled_self;
|
||||||
|
let b = other;
|
||||||
|
return Ok(Quaternion(
|
||||||
|
a.3 * b.0 + a.0 * b.3 + a.1 * b.2 - a.2 * b.1,
|
||||||
|
a.3 * b.1 - a.0 * b.2 + a.1 * b.3 + a.2 * b.0,
|
||||||
|
a.3 * b.2 + a.0 * b.1 - a.1 * b.0 + a.2 * b.3,
|
||||||
|
a.3 * b.3 - a.0 * b.0 - a.1 * b.1 - a.2 * b.2,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut product = self.0 * other.0 +
|
||||||
|
self.1 * other.1 +
|
||||||
|
self.2 * other.2 +
|
||||||
|
self.3 * other.3;
|
||||||
|
|
||||||
|
// Clamp product to -1.0 <= product <= 1.0
|
||||||
|
product = product.min(1.0);
|
||||||
|
product = product.max(-1.0);
|
||||||
|
|
||||||
|
if product == 1.0 {
|
||||||
|
return Ok(*self);
|
||||||
|
}
|
||||||
|
|
||||||
|
let theta = product.acos();
|
||||||
|
let w = (other_weight * theta).sin() * 1.0 / (1.0 - product * product).sqrt();
|
||||||
|
|
||||||
|
let mut a = *self;
|
||||||
|
let mut b = *other;
|
||||||
|
let mut result = Quaternion(0., 0., 0., 0.,);
|
||||||
|
% for i in range(4):
|
||||||
|
a.${i} *= (other_weight * theta).cos() - product * w;
|
||||||
|
b.${i} *= w;
|
||||||
|
result.${i} = a.${i} + b.${i};
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ComputeSquaredDistance for Quaternion {
|
impl ComputeSquaredDistance for Quaternion {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||||
|
@ -2002,87 +2075,6 @@ impl Animate for Perspective {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animate for MatrixDecomposed3D {
|
|
||||||
/// <https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-3d-matrix-values>
|
|
||||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
|
||||||
use std::f64;
|
|
||||||
|
|
||||||
let (this_weight, other_weight) = procedure.weights();
|
|
||||||
|
|
||||||
debug_assert!((this_weight + other_weight - 1.0f64).abs() <= f64::EPSILON ||
|
|
||||||
other_weight == 1.0f64 || other_weight == 0.0f64,
|
|
||||||
"animate should only be used for interpolating or accumulating transforms");
|
|
||||||
|
|
||||||
let mut sum = *self;
|
|
||||||
|
|
||||||
// Add translate, scale, skew and perspective components.
|
|
||||||
sum.translate = self.translate.animate(&other.translate, procedure)?;
|
|
||||||
sum.scale = self.scale.animate(&other.scale, procedure)?;
|
|
||||||
sum.skew = self.skew.animate(&other.skew, procedure)?;
|
|
||||||
sum.perspective = self.perspective.animate(&other.perspective, procedure)?;
|
|
||||||
|
|
||||||
// Add quaternions using spherical linear interpolation (Slerp).
|
|
||||||
//
|
|
||||||
// We take a specialized code path for accumulation (where other_weight is 1)
|
|
||||||
if other_weight == 1.0 {
|
|
||||||
if this_weight == 0.0 {
|
|
||||||
return Ok(*other)
|
|
||||||
}
|
|
||||||
|
|
||||||
let clamped_w = self.quaternion.3.min(1.0).max(-1.0);
|
|
||||||
|
|
||||||
// Determine the scale factor.
|
|
||||||
let mut theta = clamped_w.acos();
|
|
||||||
let mut scale = if theta == 0.0 { 0.0 } else { 1.0 / theta.sin() };
|
|
||||||
theta *= this_weight;
|
|
||||||
scale *= theta.sin();
|
|
||||||
|
|
||||||
// Scale the self matrix by this_weight.
|
|
||||||
let mut scaled_self = *self;
|
|
||||||
% for i in range(3):
|
|
||||||
scaled_self.quaternion.${i} *= scale;
|
|
||||||
% endfor
|
|
||||||
scaled_self.quaternion.3 = theta.cos();
|
|
||||||
|
|
||||||
// Multiply scaled-self by other.
|
|
||||||
let a = &scaled_self.quaternion;
|
|
||||||
let b = &other.quaternion;
|
|
||||||
sum.quaternion = Quaternion(
|
|
||||||
a.3 * b.0 + a.0 * b.3 + a.1 * b.2 - a.2 * b.1,
|
|
||||||
a.3 * b.1 - a.0 * b.2 + a.1 * b.3 + a.2 * b.0,
|
|
||||||
a.3 * b.2 + a.0 * b.1 - a.1 * b.0 + a.2 * b.3,
|
|
||||||
a.3 * b.3 - a.0 * b.0 - a.1 * b.1 - a.2 * b.2,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let mut product = self.quaternion.0 * other.quaternion.0 +
|
|
||||||
self.quaternion.1 * other.quaternion.1 +
|
|
||||||
self.quaternion.2 * other.quaternion.2 +
|
|
||||||
self.quaternion.3 * other.quaternion.3;
|
|
||||||
|
|
||||||
// Clamp product to -1.0 <= product <= 1.0
|
|
||||||
product = product.min(1.0);
|
|
||||||
product = product.max(-1.0);
|
|
||||||
|
|
||||||
if product == 1.0 {
|
|
||||||
return Ok(sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
let theta = product.acos();
|
|
||||||
let w = (other_weight * theta).sin() * 1.0 / (1.0 - product * product).sqrt();
|
|
||||||
|
|
||||||
let mut a = *self;
|
|
||||||
let mut b = *other;
|
|
||||||
% for i in range(4):
|
|
||||||
a.quaternion.${i} *= (other_weight * theta).cos() - product * w;
|
|
||||||
b.quaternion.${i} *= w;
|
|
||||||
sum.quaternion.${i} = a.quaternion.${i} + b.quaternion.${i};
|
|
||||||
% endfor
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(sum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<MatrixDecomposed3D> for Matrix3D {
|
impl From<MatrixDecomposed3D> for Matrix3D {
|
||||||
/// Recompose a 3D matrix.
|
/// Recompose a 3D matrix.
|
||||||
/// <https://drafts.csswg.org/css-transforms/#recomposing-to-a-3d-matrix>
|
/// <https://drafts.csswg.org/css-transforms/#recomposing-to-a-3d-matrix>
|
||||||
|
@ -2280,6 +2272,129 @@ impl Matrix3D {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://drafts.csswg.org/css-transforms-2/#propdef-rotate>
|
||||||
|
impl ComputedRotate {
|
||||||
|
fn fill_unspecified(rotate: &ComputedRotate) -> Result<(Number, Number, Number, Angle), ()> {
|
||||||
|
// According to the spec:
|
||||||
|
// https://drafts.csswg.org/css-transforms-2/#individual-transforms
|
||||||
|
//
|
||||||
|
// If the axis is unspecified, it defaults to "0 0 1"
|
||||||
|
match *rotate {
|
||||||
|
Rotate::None =>
|
||||||
|
Ok((0., 0., 1., Angle::zero())),
|
||||||
|
Rotate::Rotate3D(rx, ry, rz, angle) => Ok((rx, ry, rz, angle)),
|
||||||
|
Rotate::Rotate(angle) => Ok((0., 0., 1., angle)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Animate for ComputedRotate {
|
||||||
|
#[inline]
|
||||||
|
fn animate(
|
||||||
|
&self,
|
||||||
|
other: &Self,
|
||||||
|
procedure: Procedure,
|
||||||
|
) -> Result<Self, ()> {
|
||||||
|
let from = ComputedRotate::fill_unspecified(self)?;
|
||||||
|
let to = ComputedRotate::fill_unspecified(other)?;
|
||||||
|
|
||||||
|
let (fx, fy, fz, fa) = transform::get_normalized_vector_and_angle(from.0, from.1, from.2, from.3);
|
||||||
|
let (tx, ty, tz, ta) = transform::get_normalized_vector_and_angle(to.0, to.1, to.2, to.3);
|
||||||
|
if (fx, fy, fz) == (tx, ty, tz) {
|
||||||
|
return Ok(Rotate::Rotate3D(fx, fy, fz, fa.animate(&ta, procedure)?));
|
||||||
|
}
|
||||||
|
|
||||||
|
let fv = DirectionVector::new(fx, fy, fz);
|
||||||
|
let tv = DirectionVector::new(tx, ty, tz);
|
||||||
|
let fq = Quaternion::from_direction_and_angle(&fv, fa.radians64());
|
||||||
|
let tq = Quaternion::from_direction_and_angle(&tv, ta.radians64());
|
||||||
|
|
||||||
|
let rq = Quaternion::animate(&fq, &tq, procedure)?;
|
||||||
|
let (x, y, z, angle) =
|
||||||
|
transform::get_normalized_vector_and_angle(rq.0 as f32,
|
||||||
|
rq.1 as f32,
|
||||||
|
rq.2 as f32,
|
||||||
|
rq.3.acos() as f32 *2.0);
|
||||||
|
|
||||||
|
Ok(Rotate::Rotate3D(x, y, z, Angle::from_radians(angle)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://drafts.csswg.org/css-transforms-2/#propdef-translate>
|
||||||
|
impl ComputedTranslate {
|
||||||
|
fn fill_unspecified(translate: &ComputedTranslate)
|
||||||
|
-> Result<(LengthOrPercentage, LengthOrPercentage, Length), ()> {
|
||||||
|
// According to the spec:
|
||||||
|
// https://drafts.csswg.org/css-transforms-2/#individual-transforms
|
||||||
|
//
|
||||||
|
// Unspecified translations default to 0px
|
||||||
|
match *translate {
|
||||||
|
Translate::None => {
|
||||||
|
Ok((LengthOrPercentage::Length(Length::zero()),
|
||||||
|
LengthOrPercentage::Length(Length::zero()),
|
||||||
|
Length::zero()))
|
||||||
|
},
|
||||||
|
Translate::Translate3D(tx, ty, tz) => Ok((tx, ty, tz)),
|
||||||
|
Translate::Translate(tx, ty) => Ok((tx, ty, Length::zero())),
|
||||||
|
Translate::TranslateX(tx) => Ok((tx, LengthOrPercentage::Length(Length::zero()), Length::zero())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Animate for ComputedTranslate {
|
||||||
|
#[inline]
|
||||||
|
fn animate(
|
||||||
|
&self,
|
||||||
|
other: &Self,
|
||||||
|
procedure: Procedure,
|
||||||
|
) -> Result<Self, ()> {
|
||||||
|
let from = ComputedTranslate::fill_unspecified(self)?;
|
||||||
|
let to = ComputedTranslate::fill_unspecified(other)?;
|
||||||
|
|
||||||
|
Ok(Translate::Translate3D(from.0.animate(&to.0, procedure)?,
|
||||||
|
from.1.animate(&to.1, procedure)?,
|
||||||
|
from.2.animate(&to.2, procedure)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://drafts.csswg.org/css-transforms-2/#propdef-scale>
|
||||||
|
impl ComputedScale {
|
||||||
|
fn fill_unspecified(scale: &ComputedScale)
|
||||||
|
-> Result<(Number, Number, Number), ()> {
|
||||||
|
// According to the spec:
|
||||||
|
// https://drafts.csswg.org/css-transforms-2/#individual-transforms
|
||||||
|
//
|
||||||
|
// Unspecified scales default to 1
|
||||||
|
match *scale {
|
||||||
|
Scale::None => Ok((1.0, 1.0, 1.0)),
|
||||||
|
Scale::Scale3D(sx, sy, sz) => Ok((sx, sy, sz)),
|
||||||
|
Scale::Scale(sx, sy) => Ok((sx, sy, 1.)),
|
||||||
|
Scale::ScaleX(sx) => Ok((sx, 1., 1.)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Animate for ComputedScale {
|
||||||
|
#[inline]
|
||||||
|
fn animate(
|
||||||
|
&self,
|
||||||
|
other: &Self,
|
||||||
|
procedure: Procedure,
|
||||||
|
) -> Result<Self, ()> {
|
||||||
|
let from = ComputedScale::fill_unspecified(self)?;
|
||||||
|
let to = ComputedScale::fill_unspecified(other)?;
|
||||||
|
|
||||||
|
if procedure == Procedure::Add {
|
||||||
|
// scale(x1,y1,z1)*scale(x2,y2,z2) = scale(x1*x2, y1*y2, z1*z2)
|
||||||
|
return Ok(Scale::Scale3D(from.0 * to.0, from.1 * to.1, from.2 * to.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Scale::Scale3D(animate_multiplicative_factor(from.0, to.0, procedure)?,
|
||||||
|
animate_multiplicative_factor(from.1, to.1, procedure)?,
|
||||||
|
animate_multiplicative_factor(from.2, to.2, procedure)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-transforms/#interpolation-of-transforms>
|
/// <https://drafts.csswg.org/css-transforms/#interpolation-of-transforms>
|
||||||
impl Animate for ComputedTransform {
|
impl Animate for ComputedTransform {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -390,6 +390,30 @@ ${helpers.predefined_type("transform", "Transform",
|
||||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||||
spec="https://drafts.csswg.org/css-transforms/#propdef-transform")}
|
spec="https://drafts.csswg.org/css-transforms/#propdef-transform")}
|
||||||
|
|
||||||
|
${helpers.predefined_type("rotate", "Rotate",
|
||||||
|
"generics::transform::Rotate::None",
|
||||||
|
animation_value_type="ComputedValue",
|
||||||
|
boxed=True,
|
||||||
|
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||||
|
gecko_pref="layout.css.individual-transform.enabled",
|
||||||
|
spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")}
|
||||||
|
|
||||||
|
${helpers.predefined_type("scale", "Scale",
|
||||||
|
"generics::transform::Scale::None",
|
||||||
|
animation_value_type="ComputedValue",
|
||||||
|
boxed=True,
|
||||||
|
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||||
|
gecko_pref="layout.css.individual-transform.enabled",
|
||||||
|
spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")}
|
||||||
|
|
||||||
|
${helpers.predefined_type("translate", "Translate",
|
||||||
|
"generics::transform::Translate::None",
|
||||||
|
animation_value_type="ComputedValue",
|
||||||
|
boxed=True,
|
||||||
|
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||||
|
gecko_pref="layout.css.individual-transform.enabled",
|
||||||
|
spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")}
|
||||||
|
|
||||||
// CSSOM View Module
|
// CSSOM View Module
|
||||||
// https://www.w3.org/TR/cssom-view-1/
|
// https://www.w3.org/TR/cssom-view-1/
|
||||||
${helpers.single_keyword("scroll-behavior",
|
${helpers.single_keyword("scroll-behavior",
|
||||||
|
|
|
@ -73,7 +73,7 @@ pub use self::svg::MozContextProperties;
|
||||||
pub use self::table::XSpan;
|
pub use self::table::XSpan;
|
||||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing};
|
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing};
|
||||||
pub use self::time::Time;
|
pub use self::time::Time;
|
||||||
pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin};
|
pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate, Translate, Scale};
|
||||||
pub use self::ui::MozForceBrokenImageIcon;
|
pub use self::ui::MozForceBrokenImageIcon;
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
|
|
@ -12,8 +12,11 @@ use values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Perce
|
||||||
use values::computed::{LengthOrNumber, LengthOrPercentageOrNumber};
|
use values::computed::{LengthOrNumber, LengthOrPercentageOrNumber};
|
||||||
use values::generics::transform::{self, Matrix as GenericMatrix, Matrix3D as GenericMatrix3D};
|
use values::generics::transform::{self, Matrix as GenericMatrix, Matrix3D as GenericMatrix3D};
|
||||||
use values::generics::transform::{Transform as GenericTransform, TransformOperation as GenericTransformOperation};
|
use values::generics::transform::{Transform as GenericTransform, TransformOperation as GenericTransformOperation};
|
||||||
|
use values::generics::transform::Rotate as GenericRotate;
|
||||||
|
use values::generics::transform::Scale as GenericScale;
|
||||||
use values::generics::transform::TimingFunction as GenericTimingFunction;
|
use values::generics::transform::TimingFunction as GenericTimingFunction;
|
||||||
use values::generics::transform::TransformOrigin as GenericTransformOrigin;
|
use values::generics::transform::TransformOrigin as GenericTransformOrigin;
|
||||||
|
use values::generics::transform::Translate as GenericTranslate;
|
||||||
|
|
||||||
/// A single operation in a computed CSS `transform`
|
/// A single operation in a computed CSS `transform`
|
||||||
pub type TransformOperation = GenericTransformOperation<
|
pub type TransformOperation = GenericTransformOperation<
|
||||||
|
@ -293,3 +296,77 @@ impl ToAnimatedZero for Transform {
|
||||||
.collect::<Result<Vec<_>, _>>()?))
|
.collect::<Result<Vec<_>, _>>()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A computed CSS `rotate`
|
||||||
|
pub type Rotate = GenericRotate<Number, Angle>;
|
||||||
|
|
||||||
|
impl Rotate {
|
||||||
|
/// Convert TransformOperation to Rotate.
|
||||||
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
||||||
|
match *self {
|
||||||
|
GenericRotate::None => None,
|
||||||
|
GenericRotate::Rotate(angle) => Some(GenericTransformOperation::Rotate(angle)),
|
||||||
|
GenericRotate::Rotate3D(rx, ry, rz, angle) => Some(GenericTransformOperation::Rotate3D(rx, ry, rz, angle)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert Rotate to TransformOperation.
|
||||||
|
pub fn from_transform_operation(operation: &TransformOperation) -> Rotate {
|
||||||
|
match *operation {
|
||||||
|
GenericTransformOperation::Rotate(angle) => GenericRotate::Rotate(angle),
|
||||||
|
GenericTransformOperation::Rotate3D(rx, ry, rz, angle) =>
|
||||||
|
GenericRotate::Rotate3D(rx, ry, rz, angle),
|
||||||
|
_ => unreachable!("Found unexpected value for rotate property"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A computed CSS `translate`
|
||||||
|
pub type Translate = GenericTranslate<LengthOrPercentage, Length>;
|
||||||
|
|
||||||
|
impl Translate {
|
||||||
|
/// Convert TransformOperation to Translate.
|
||||||
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
||||||
|
match *self {
|
||||||
|
GenericTranslate::None => None,
|
||||||
|
GenericTranslate::TranslateX(tx) => Some(GenericTransformOperation::TranslateX(tx)),
|
||||||
|
GenericTranslate::Translate(tx, ty) => Some(GenericTransformOperation::Translate(tx, Some(ty))),
|
||||||
|
GenericTranslate::Translate3D(tx, ty, tz) => Some(GenericTransformOperation::Translate3D(tx, ty, tz)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert Translate to TransformOperation.
|
||||||
|
pub fn from_transform_operation(operation: &TransformOperation) -> Translate {
|
||||||
|
match *operation {
|
||||||
|
GenericTransformOperation::TranslateX(tx) => GenericTranslate::TranslateX(tx),
|
||||||
|
GenericTransformOperation::Translate(tx, Some(ty)) => GenericTranslate::Translate(tx, ty),
|
||||||
|
GenericTransformOperation::Translate3D(tx, ty, tz) => GenericTranslate::Translate3D(tx, ty, tz),
|
||||||
|
_ => unreachable!("Found unexpected value for translate"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A computed CSS `scale`
|
||||||
|
pub type Scale = GenericScale<Number>;
|
||||||
|
|
||||||
|
impl Scale {
|
||||||
|
/// Convert TransformOperation to Scale.
|
||||||
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
||||||
|
match *self {
|
||||||
|
GenericScale::None => None,
|
||||||
|
GenericScale::ScaleX(sx) => Some(GenericTransformOperation::ScaleX(sx)),
|
||||||
|
GenericScale::Scale(sx, sy) => Some(GenericTransformOperation::Scale(sx, Some(sy))),
|
||||||
|
GenericScale::Scale3D(sx, sy, sz) => Some(GenericTransformOperation::Scale3D(sx, sy, sz)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert Scale to TransformOperation.
|
||||||
|
pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
|
||||||
|
match *operation {
|
||||||
|
GenericTransformOperation::ScaleX(sx) => GenericScale::ScaleX(sx),
|
||||||
|
GenericTransformOperation::Scale(sx, Some(sy)) => GenericScale::Scale(sx, sy),
|
||||||
|
GenericTransformOperation::Scale3D(sx, sy, sz) => GenericScale::Scale3D(sx, sy, sz),
|
||||||
|
_ => unreachable!("Found unexpected value for scale"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -668,3 +668,49 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
|
||||||
(vector.x, vector.y, vector.z, angle)
|
(vector.x, vector.y, vector.z, angle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)]
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
|
/// A value of the `Rotate` property
|
||||||
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
|
||||||
|
pub enum Rotate<Number, Angle> {
|
||||||
|
/// 'none'
|
||||||
|
None,
|
||||||
|
/// '<angle>'
|
||||||
|
Rotate(Angle),
|
||||||
|
/// '<number>{3} <angle>'
|
||||||
|
Rotate3D(Number, Number, Number, Angle),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)]
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
|
/// A value of the `Scale` property
|
||||||
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
|
||||||
|
pub enum Scale<Number> {
|
||||||
|
/// 'none'
|
||||||
|
None,
|
||||||
|
/// '<number>'
|
||||||
|
ScaleX(Number),
|
||||||
|
/// '<number>{2}'
|
||||||
|
Scale(Number, Number),
|
||||||
|
/// '<number>{3}'
|
||||||
|
Scale3D(Number, Number, Number),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)]
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
|
/// A value of the `Translate` property
|
||||||
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
|
||||||
|
pub enum Translate<LengthOrPercentage, Length> {
|
||||||
|
/// 'none'
|
||||||
|
None,
|
||||||
|
/// '<length-percentage>'
|
||||||
|
TranslateX(LengthOrPercentage),
|
||||||
|
/// '<length-percentage> <length-percentage>'
|
||||||
|
Translate(LengthOrPercentage, LengthOrPercentage),
|
||||||
|
/// '<length-percentage> <length-percentage> <length>'
|
||||||
|
Translate3D(LengthOrPercentage, LengthOrPercentage, Length),
|
||||||
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub use self::table::XSpan;
|
||||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine};
|
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine};
|
||||||
pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing};
|
pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing};
|
||||||
pub use self::time::Time;
|
pub use self::time::Time;
|
||||||
pub use self::transform::{TimingFunction, Transform, TransformOrigin};
|
pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate, Translate, Scale};
|
||||||
pub use self::ui::MozForceBrokenImageIcon;
|
pub use self::ui::MozForceBrokenImageIcon;
|
||||||
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,10 @@ use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
||||||
use values::generics::transform::{Matrix3D, Transform as GenericTransform};
|
use values::generics::transform::{Matrix3D, Transform as GenericTransform};
|
||||||
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction, Matrix};
|
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction, Matrix};
|
||||||
use values::generics::transform::{TimingKeyword, TransformOrigin as GenericTransformOrigin};
|
use values::generics::transform::{TimingKeyword, TransformOrigin as GenericTransformOrigin};
|
||||||
|
use values::generics::transform::Rotate as GenericRotate;
|
||||||
|
use values::generics::transform::Scale as GenericScale;
|
||||||
use values::generics::transform::TransformOperation as GenericTransformOperation;
|
use values::generics::transform::TransformOperation as GenericTransformOperation;
|
||||||
|
use values::generics::transform::Translate as GenericTranslate;
|
||||||
use values::specified::{self, Angle, Number, Length, Integer};
|
use values::specified::{self, Angle, Number, Length, Integer};
|
||||||
use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber};
|
use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber};
|
||||||
use values::specified::position::{Side, X, Y};
|
use values::specified::position::{Side, X, Y};
|
||||||
|
@ -508,3 +511,85 @@ impl ToComputedValue for TimingFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A specified CSS `rotate`
|
||||||
|
pub type Rotate = GenericRotate<Number, Angle>;
|
||||||
|
|
||||||
|
impl Parse for Rotate {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
|
return Ok(GenericRotate::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(rx) = input.try(|i| Number::parse(context, i)) {
|
||||||
|
// 'rotate: <number>{3} <angle>'
|
||||||
|
let ry = Number::parse(context, input)?;
|
||||||
|
let rz = Number::parse(context, input)?;
|
||||||
|
let angle = specified::Angle::parse(context, input)?;
|
||||||
|
return Ok(GenericRotate::Rotate3D(rx, ry, rz, angle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'rotate: <angle>'
|
||||||
|
let angle = specified::Angle::parse(context, input)?;
|
||||||
|
Ok(GenericRotate::Rotate(angle))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A specified CSS `translate`
|
||||||
|
pub type Translate = GenericTranslate<LengthOrPercentage, Length>;
|
||||||
|
|
||||||
|
impl Parse for Translate {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
|
return Ok(GenericTranslate::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tx = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
|
if let Ok(ty) = input.try(|i| specified::LengthOrPercentage::parse(context, i)) {
|
||||||
|
if let Ok(tz) = input.try(|i| specified::Length::parse(context, i)) {
|
||||||
|
// 'translate: <length-percentage> <length-percentage> <length>'
|
||||||
|
return Ok(GenericTranslate::Translate3D(tx, ty, tz));
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate: <length-percentage> <length-percentage>'
|
||||||
|
return Ok(GenericTranslate::Translate(tx, ty));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'translate: <length-percentage> '
|
||||||
|
Ok(GenericTranslate::TranslateX(tx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A specified CSS `scale`
|
||||||
|
pub type Scale = GenericScale<Number>;
|
||||||
|
|
||||||
|
impl Parse for Scale {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
|
return Ok(GenericScale::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sx = Number::parse(context, input)?;
|
||||||
|
if let Ok(sy) = input.try(|i| Number::parse(context, i)) {
|
||||||
|
if let Ok(sz) = input.try(|i| Number::parse(context, i)) {
|
||||||
|
// 'scale: <number> <number> <number>'
|
||||||
|
return Ok(GenericScale::Scale3D(sx, sy, sz));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'scale: <number> <number>'
|
||||||
|
return Ok(GenericScale::Scale(sx, sy));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'scale: <number>'
|
||||||
|
Ok(GenericScale::ScaleX(sx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
[rotate-interpolation.html]
|
[rotate-interpolation.html]
|
||||||
["100deg" and "180deg" are valid rotate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "100deg" and "180deg" at progress -1]
|
[Animation between "100deg" and "180deg" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -20,9 +17,6 @@
|
||||||
[Animation between "100deg" and "180deg" at progress 2]
|
[Animation between "100deg" and "180deg" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["45deg" and "-1 1 0 60deg" are valid rotate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "45deg" and "-1 1 0 60deg" at progress -1]
|
[Animation between "45deg" and "-1 1 0 60deg" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -41,9 +35,6 @@
|
||||||
[Animation between "45deg" and "-1 1 0 60deg" at progress 2]
|
[Animation between "45deg" and "-1 1 0 60deg" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["none" and "7 -8 9 400grad" are valid rotate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "none" and "7 -8 9 400grad" at progress -1]
|
[Animation between "none" and "7 -8 9 400grad" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -62,9 +53,6 @@
|
||||||
[Animation between "none" and "7 -8 9 400grad" at progress 2]
|
[Animation between "none" and "7 -8 9 400grad" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["none" and "none" are valid rotate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "none" and "none" at progress -1]
|
[Animation between "none" and "none" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
[scale-interpolation.html]
|
[scale-interpolation.html]
|
||||||
["2 30 400" and "10 110 1200" are valid scale values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "2 30 400" and "10 110 1200" at progress -1]
|
[Animation between "2 30 400" and "10 110 1200" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -20,9 +17,6 @@
|
||||||
[Animation between "2 30 400" and "10 110 1200" at progress 2]
|
[Animation between "2 30 400" and "10 110 1200" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["26 17 9" and "2" are valid scale values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "26 17 9" and "2" at progress -1]
|
[Animation between "26 17 9" and "2" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -41,9 +35,6 @@
|
||||||
[Animation between "26 17 9" and "2" at progress 2]
|
[Animation between "26 17 9" and "2" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["none" and "4 3 2" are valid scale values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "none" and "4 3 2" at progress -1]
|
[Animation between "none" and "4 3 2" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -62,9 +53,6 @@
|
||||||
[Animation between "none" and "4 3 2" at progress 2]
|
[Animation between "none" and "4 3 2" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["none" and "none" are valid scale values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "none" and "none" at progress -1]
|
[Animation between "none" and "none" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
[translate-interpolation.html]
|
[translate-interpolation.html]
|
||||||
["220px 240px 260px" and "300px 400px 500px" are valid translate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "220px 240px 260px" and "300px 400px 500px" at progress -1]
|
[Animation between "220px 240px 260px" and "300px 400px 500px" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -20,9 +17,6 @@
|
||||||
[Animation between "220px 240px 260px" and "300px 400px 500px" at progress 2]
|
[Animation between "220px 240px 260px" and "300px 400px 500px" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["480px 400px 320px" and "240% 160%" are valid translate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "480px 400px 320px" and "240% 160%" at progress -1]
|
[Animation between "480px 400px 320px" and "240% 160%" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -41,9 +35,6 @@
|
||||||
[Animation between "480px 400px 320px" and "240% 160%" at progress 2]
|
[Animation between "480px 400px 320px" and "240% 160%" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["none" and "8px 80% 800px" are valid translate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "none" and "8px 80% 800px" at progress -1]
|
[Animation between "none" and "8px 80% 800px" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -62,9 +53,6 @@
|
||||||
[Animation between "none" and "8px 80% 800px" at progress 2]
|
[Animation between "none" and "8px 80% 800px" at progress 2]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
["none" and "none" are valid translate values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Animation between "none" and "none" at progress -1]
|
[Animation between "none" and "none" at progress -1]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
[rotate-parsing-invalid.html]
|
|
||||||
[e.style['rotate'\] = "100px" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['rotate'\] = "100 400deg" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['rotate'\] = "100 200 400deg" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['rotate'\] = "100 200 300 500 400deg" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
[scale-parsing-invalid.html]
|
|
||||||
[e.style['scale'\] = "100px" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['scale'\] = "100 200 300 400" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
[translate-parsing-invalid.html]
|
|
||||||
[e.style['translate'\] = "100deg" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['translate'\] = "100px 200px 300%" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['translate'\] = "100px 200px calc(30px + 30%)" should not set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -5,9 +5,3 @@
|
||||||
[Serialization should round-trip after setting e.style['translate'\] = "1px 2px 0"]
|
[Serialization should round-trip after setting e.style['translate'\] = "1px 2px 0"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[e.style['translate'\] = "0" should set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[e.style['translate'\] = "1px 2px 0" should set the property value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue