mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Auto merge of #15363 - hiikezoe:transform-animatable, r=heycam,Manishearth
Make transform property animatable for stylo <!-- Please describe your changes on the following line: --> This is the servo side fix for https://bugzilla.mozilla.org/show_bug.cgi?id=1332657 Reviewed by @heycam and @Manishearth. Thanks! --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because this is for stylo. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/15363) <!-- Reviewable:end -->
This commit is contained in:
commit
cd2dbd720b
5 changed files with 994 additions and 884 deletions
|
@ -738,6 +738,35 @@ extern "C" {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_NewCSSValueSharedList(len: u32) -> *mut nsCSSValueSharedList;
|
pub fn Gecko_NewCSSValueSharedList(len: u32) -> *mut nsCSSValueSharedList;
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetArrayItem(css_value: nsCSSValueBorrowedMut,
|
||||||
|
index: i32) -> nsCSSValueBorrowedMut;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetArrayItemConst(css_value: nsCSSValueBorrowed,
|
||||||
|
index: i32) -> nsCSSValueBorrowed;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetAbsoluteLength(css_value: nsCSSValueBorrowed)
|
||||||
|
-> nscoord;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetAngle(css_value: nsCSSValueBorrowed) -> f32;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetKeyword(aCSSValue: nsCSSValueBorrowed)
|
||||||
|
-> nsCSSKeyword;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetNumber(css_value: nsCSSValueBorrowed) -> f32;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetPercentage(css_value: nsCSSValueBorrowed) -> f32;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_CSSValue_GetCalc(aCSSValue: nsCSSValueBorrowed)
|
||||||
|
-> nsStyleCoord_CalcValue;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_CSSValue_SetAbsoluteLength(css_value: nsCSSValueBorrowedMut,
|
pub fn Gecko_CSSValue_SetAbsoluteLength(css_value: nsCSSValueBorrowedMut,
|
||||||
len: nscoord);
|
len: nscoord);
|
||||||
|
@ -766,10 +795,6 @@ extern "C" {
|
||||||
pub fn Gecko_CSSValue_SetFunction(css_value: nsCSSValueBorrowedMut,
|
pub fn Gecko_CSSValue_SetFunction(css_value: nsCSSValueBorrowedMut,
|
||||||
len: i32);
|
len: i32);
|
||||||
}
|
}
|
||||||
extern "C" {
|
|
||||||
pub fn Gecko_CSSValue_GetArrayItem(css_value: nsCSSValueBorrowedMut,
|
|
||||||
index: i32) -> nsCSSValueBorrowedMut;
|
|
||||||
}
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_CSSValue_Drop(css_value: nsCSSValueBorrowedMut);
|
pub fn Gecko_CSSValue_Drop(css_value: nsCSSValueBorrowedMut);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,19 @@
|
||||||
|
|
||||||
//! Little helpers for `nsCSSValue`.
|
//! Little helpers for `nsCSSValue`.
|
||||||
|
|
||||||
|
use app_units::Au;
|
||||||
use gecko_bindings::bindings::Gecko_CSSValue_Drop;
|
use gecko_bindings::bindings::Gecko_CSSValue_Drop;
|
||||||
|
use gecko_bindings::bindings::Gecko_CSSValue_GetAbsoluteLength;
|
||||||
|
use gecko_bindings::bindings::Gecko_CSSValue_GetCalc;
|
||||||
|
use gecko_bindings::bindings::Gecko_CSSValue_GetPercentage;
|
||||||
|
use gecko_bindings::bindings::Gecko_CSSValue_SetAbsoluteLength;
|
||||||
|
use gecko_bindings::bindings::Gecko_CSSValue_SetCalc;
|
||||||
|
use gecko_bindings::bindings::Gecko_CSSValue_SetPercentage;
|
||||||
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsCSSValue_Array};
|
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsCSSValue_Array};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
use values::computed::LengthOrPercentage;
|
||||||
|
|
||||||
impl nsCSSValue {
|
impl nsCSSValue {
|
||||||
/// Create a CSSValue with null unit, useful to be used as a return value.
|
/// Create a CSSValue with null unit, useful to be used as a return value.
|
||||||
|
@ -42,6 +50,37 @@ impl nsCSSValue {
|
||||||
debug_assert!(!array.is_null());
|
debug_assert!(!array.is_null());
|
||||||
&*array
|
&*array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets LengthOrPercentage value to this nsCSSValue.
|
||||||
|
pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) {
|
||||||
|
match lop {
|
||||||
|
LengthOrPercentage::Length(au) => {
|
||||||
|
Gecko_CSSValue_SetAbsoluteLength(self, au.0)
|
||||||
|
}
|
||||||
|
LengthOrPercentage::Percentage(pc) => {
|
||||||
|
Gecko_CSSValue_SetPercentage(self, pc)
|
||||||
|
}
|
||||||
|
LengthOrPercentage::Calc(calc) => {
|
||||||
|
Gecko_CSSValue_SetCalc(self, calc.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns LengthOrPercentage value.
|
||||||
|
pub unsafe fn get_lop(&self) -> LengthOrPercentage {
|
||||||
|
match self.mUnit {
|
||||||
|
nsCSSUnit::eCSSUnit_Pixel => {
|
||||||
|
LengthOrPercentage::Length(Au(Gecko_CSSValue_GetAbsoluteLength(self)))
|
||||||
|
},
|
||||||
|
nsCSSUnit::eCSSUnit_Percent => {
|
||||||
|
LengthOrPercentage::Percentage(Gecko_CSSValue_GetPercentage(self))
|
||||||
|
},
|
||||||
|
nsCSSUnit::eCSSUnit_Calc => {
|
||||||
|
LengthOrPercentage::Calc(Gecko_CSSValue_GetCalc(self).into())
|
||||||
|
},
|
||||||
|
x => panic!("The unit should not be {:?}", x),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for nsCSSValue {
|
impl Drop for nsCSSValue {
|
||||||
|
|
|
@ -1317,7 +1317,7 @@ fn static_assert() {
|
||||||
css_value_setters = {
|
css_value_setters = {
|
||||||
"length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)",
|
"length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)",
|
||||||
"percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s)",
|
"percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s)",
|
||||||
"lop" : "set_lop(%s, %s)",
|
"lop" : "%s.set_lop(%s)",
|
||||||
"angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.0)",
|
"angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.0)",
|
||||||
"number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
|
"number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
|
||||||
}
|
}
|
||||||
|
@ -1341,21 +1341,6 @@ fn static_assert() {
|
||||||
use gecko_bindings::sugar::refptr::RefPtr;
|
use gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use properties::longhands::transform::computed_value::ComputedMatrix;
|
use properties::longhands::transform::computed_value::ComputedMatrix;
|
||||||
use properties::longhands::transform::computed_value::ComputedOperation;
|
use properties::longhands::transform::computed_value::ComputedOperation;
|
||||||
use values::computed::LengthOrPercentage;
|
|
||||||
|
|
||||||
unsafe fn set_lop(value: &mut structs::nsCSSValue, lop: LengthOrPercentage) {
|
|
||||||
match lop {
|
|
||||||
LengthOrPercentage::Length(au) => {
|
|
||||||
bindings::Gecko_CSSValue_SetAbsoluteLength(value, au.0)
|
|
||||||
}
|
|
||||||
LengthOrPercentage::Percentage(pc) => {
|
|
||||||
bindings::Gecko_CSSValue_SetPercentage(value, pc)
|
|
||||||
}
|
|
||||||
LengthOrPercentage::Calc(calc) => {
|
|
||||||
bindings::Gecko_CSSValue_SetCalc(value, calc.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let vec = if let Some(v) = other.0 {
|
let vec = if let Some(v) = other.0 {
|
||||||
v
|
v
|
||||||
|
@ -1396,6 +1381,71 @@ fn static_assert() {
|
||||||
unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); }
|
unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<%def name="computed_operation_arm(name, keyword, items)">
|
||||||
|
<%
|
||||||
|
# %s is substituted with the call to GetArrayItem.
|
||||||
|
css_value_getters = {
|
||||||
|
"length" : "Au(bindings::Gecko_CSSValue_GetAbsoluteLength(%s))",
|
||||||
|
"lop" : "%s.get_lop()",
|
||||||
|
"angle" : "Angle(bindings::Gecko_CSSValue_GetAngle(%s))",
|
||||||
|
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
eCSSKeyword_${keyword} => {
|
||||||
|
ComputedOperation::${name.title()}(
|
||||||
|
% if name == "matrix":
|
||||||
|
ComputedMatrix {
|
||||||
|
% endif
|
||||||
|
% for index, item in enumerate(items):
|
||||||
|
% if name == "matrix":
|
||||||
|
m${index / 4 + 1}${index % 4 + 1}:
|
||||||
|
% endif
|
||||||
|
${css_value_getters[item] % (
|
||||||
|
"bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
|
||||||
|
)},
|
||||||
|
% endfor
|
||||||
|
% if name == "matrix":
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
)
|
||||||
|
},
|
||||||
|
</%def>
|
||||||
|
pub fn clone_transform(&self) -> longhands::transform::computed_value::T {
|
||||||
|
use app_units::Au;
|
||||||
|
use gecko_bindings::structs::nsCSSKeyword::*;
|
||||||
|
use properties::longhands::transform::computed_value;
|
||||||
|
use properties::longhands::transform::computed_value::ComputedMatrix;
|
||||||
|
use properties::longhands::transform::computed_value::ComputedOperation;
|
||||||
|
use values::computed::Angle;
|
||||||
|
|
||||||
|
if self.gecko.mSpecifiedTransform.mRawPtr.is_null() {
|
||||||
|
return computed_value::T(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = vec![];
|
||||||
|
let mut cur = unsafe { (*self.gecko.mSpecifiedTransform.to_safe().get()).mHead };
|
||||||
|
while !cur.is_null() {
|
||||||
|
let gecko_value = unsafe { &(*cur).mValue };
|
||||||
|
let transform_function = unsafe {
|
||||||
|
bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0))
|
||||||
|
};
|
||||||
|
let servo = unsafe {
|
||||||
|
match transform_function {
|
||||||
|
${computed_operation_arm("matrix", "matrix3d", ["number"] * 16)}
|
||||||
|
${computed_operation_arm("skew", "skew", ["angle"] * 2)}
|
||||||
|
${computed_operation_arm("translate", "translate3d", ["lop", "lop", "length"])}
|
||||||
|
${computed_operation_arm("scale", "scale3d", ["number"] * 3)}
|
||||||
|
${computed_operation_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
||||||
|
${computed_operation_arm("perspective", "perspective", ["length"])}
|
||||||
|
_ => panic!("We shouldn't set any other transform function types"),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
result.push(servo);
|
||||||
|
unsafe { cur = (&*cur).mNext };
|
||||||
|
}
|
||||||
|
computed_value::T(Some(result))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_animation_name(&mut self, v: longhands::animation_name::computed_value::T) {
|
pub fn set_animation_name(&mut self, v: longhands::animation_name::computed_value::T) {
|
||||||
use nsstring::nsCString;
|
use nsstring::nsCString;
|
||||||
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
||||||
|
|
|
@ -19,6 +19,9 @@ use properties::longhands::text_shadow::computed_value::T as TextShadowList;
|
||||||
use properties::longhands::text_shadow::computed_value::TextShadow;
|
use properties::longhands::text_shadow::computed_value::TextShadow;
|
||||||
use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
|
use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
|
||||||
use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
|
use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
|
||||||
|
use properties::longhands::transform::computed_value::ComputedMatrix;
|
||||||
|
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
|
||||||
|
use properties::longhands::transform::computed_value::T as TransformList;
|
||||||
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
|
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
|
||||||
use properties::longhands::visibility::computed_value::T as Visibility;
|
use properties::longhands::visibility::computed_value::T as Visibility;
|
||||||
use properties::longhands::z_index::computed_value::T as ZIndex;
|
use properties::longhands::z_index::computed_value::T as ZIndex;
|
||||||
|
@ -27,12 +30,14 @@ use std::cmp;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use super::ComputedValues;
|
use super::ComputedValues;
|
||||||
|
use values::CSSFloat;
|
||||||
use values::Either;
|
use values::Either;
|
||||||
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||||
use values::computed::{BorderRadiusSize, LengthOrNone};
|
use values::computed::{BorderRadiusSize, LengthOrNone};
|
||||||
use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage};
|
use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage};
|
||||||
use values::computed::position::{HorizontalPosition, Position, VerticalPosition};
|
use values::computed::position::{HorizontalPosition, Position, VerticalPosition};
|
||||||
use values::computed::ToComputedValue;
|
use values::computed::ToComputedValue;
|
||||||
|
use values::specified::Angle as SpecifiedAngle;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -852,17 +857,10 @@ impl Interpolate for LengthOrNone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
% if product == "servo":
|
/// Check if it's possible to do a direct numerical interpolation
|
||||||
use properties::longhands::transform::computed_value::ComputedMatrix;
|
/// between these two transform lists.
|
||||||
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
|
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
|
||||||
use properties::longhands::transform::computed_value::T as TransformList;
|
fn can_interpolate_list(from_list: &[TransformOperation],
|
||||||
use values::CSSFloat;
|
|
||||||
use values::specified::Angle as SpecifiedAngle;
|
|
||||||
|
|
||||||
/// Check if it's possible to do a direct numerical interpolation
|
|
||||||
/// between these two transform lists.
|
|
||||||
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
|
|
||||||
fn can_interpolate_list(from_list: &[TransformOperation],
|
|
||||||
to_list: &[TransformOperation]) -> bool {
|
to_list: &[TransformOperation]) -> bool {
|
||||||
// Lists must be equal length
|
// Lists must be equal length
|
||||||
if from_list.len() != to_list.len() {
|
if from_list.len() != to_list.len() {
|
||||||
|
@ -885,12 +883,12 @@ impl Interpolate for LengthOrNone {
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build an equivalent 'identity transform function list' based
|
/// Build an equivalent 'identity transform function list' based
|
||||||
/// on an existing transform list.
|
/// on an existing transform list.
|
||||||
/// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
|
/// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
|
||||||
fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOperation> {
|
fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOperation> {
|
||||||
let mut result = vec!();
|
let mut result = vec!();
|
||||||
|
|
||||||
for operation in list {
|
for operation in list {
|
||||||
|
@ -922,11 +920,11 @@ impl Interpolate for LengthOrNone {
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interpolate two transform lists.
|
/// Interpolate two transform lists.
|
||||||
/// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
|
/// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
|
||||||
fn interpolate_transform_list(from_list: &[TransformOperation],
|
fn interpolate_transform_list(from_list: &[TransformOperation],
|
||||||
to_list: &[TransformOperation],
|
to_list: &[TransformOperation],
|
||||||
progress: f64) -> TransformList {
|
progress: f64) -> TransformList {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
|
@ -997,10 +995,10 @@ impl Interpolate for LengthOrNone {
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformList(Some(result))
|
TransformList(Some(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-transforms/#Rotate3dDefined
|
/// https://drafts.csswg.org/css-transforms/#Rotate3dDefined
|
||||||
fn rotate_to_matrix(x: f32, y: f32, z: f32, a: SpecifiedAngle) -> ComputedMatrix {
|
fn rotate_to_matrix(x: f32, y: f32, z: f32, a: SpecifiedAngle) -> ComputedMatrix {
|
||||||
let half_rad = a.radians() / 2.0;
|
let half_rad = a.radians() / 2.0;
|
||||||
let sc = (half_rad).sin() * (half_rad).cos();
|
let sc = (half_rad).sin() * (half_rad).cos();
|
||||||
let sq = (half_rad).sin().powi(2);
|
let sq = (half_rad).sin().powi(2);
|
||||||
|
@ -1026,31 +1024,31 @@ impl Interpolate for LengthOrNone {
|
||||||
m43: 0.0,
|
m43: 0.0,
|
||||||
m44: 1.0
|
m44: 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 2d matrix for interpolation.
|
/// A 2d matrix for interpolation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub struct InnerMatrix2D {
|
pub struct InnerMatrix2D {
|
||||||
pub m11: CSSFloat, pub m12: CSSFloat,
|
pub m11: CSSFloat, pub m12: CSSFloat,
|
||||||
pub m21: CSSFloat, pub m22: CSSFloat,
|
pub m21: CSSFloat, pub m22: CSSFloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 2d translation function.
|
/// A 2d translation function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Translate2D(f32, f32);
|
pub struct Translate2D(f32, f32);
|
||||||
|
|
||||||
/// A 2d scale function.
|
/// A 2d scale function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Scale2D(f32, f32);
|
pub struct Scale2D(f32, f32);
|
||||||
|
|
||||||
/// A decomposed 2d matrix.
|
/// A decomposed 2d matrix.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct MatrixDecomposed2D {
|
pub struct MatrixDecomposed2D {
|
||||||
/// The translation function.
|
/// The translation function.
|
||||||
pub translate: Translate2D,
|
pub translate: Translate2D,
|
||||||
/// The scale function.
|
/// The scale function.
|
||||||
|
@ -1059,9 +1057,9 @@ impl Interpolate for LengthOrNone {
|
||||||
pub angle: f32,
|
pub angle: f32,
|
||||||
/// The inner matrix.
|
/// The inner matrix.
|
||||||
pub matrix: InnerMatrix2D,
|
pub matrix: InnerMatrix2D,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for InnerMatrix2D {
|
impl Interpolate for InnerMatrix2D {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(InnerMatrix2D {
|
Ok(InnerMatrix2D {
|
||||||
m11: try!(self.m11.interpolate(&other.m11, progress)),
|
m11: try!(self.m11.interpolate(&other.m11, progress)),
|
||||||
|
@ -1070,27 +1068,27 @@ impl Interpolate for LengthOrNone {
|
||||||
m22: try!(self.m22.interpolate(&other.m22, progress)),
|
m22: try!(self.m22.interpolate(&other.m22, progress)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Translate2D {
|
impl Interpolate for Translate2D {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(Translate2D(
|
Ok(Translate2D(
|
||||||
try!(self.0.interpolate(&other.0, progress)),
|
try!(self.0.interpolate(&other.0, progress)),
|
||||||
try!(self.1.interpolate(&other.1, progress))
|
try!(self.1.interpolate(&other.1, progress))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Scale2D {
|
impl Interpolate for Scale2D {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(Scale2D(
|
Ok(Scale2D(
|
||||||
try!(self.0.interpolate(&other.0, progress)),
|
try!(self.0.interpolate(&other.0, progress)),
|
||||||
try!(self.1.interpolate(&other.1, progress))
|
try!(self.1.interpolate(&other.1, progress))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for MatrixDecomposed2D {
|
impl Interpolate for MatrixDecomposed2D {
|
||||||
/// https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-2d-matrix-values
|
/// https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-2d-matrix-values
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
// If x-axis of one is flipped, and y-axis of the other,
|
// If x-axis of one is flipped, and y-axis of the other,
|
||||||
|
@ -1134,9 +1132,9 @@ impl Interpolate for LengthOrNone {
|
||||||
matrix: matrix,
|
matrix: matrix,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for ComputedMatrix {
|
impl Interpolate for ComputedMatrix {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
if self.is_3d() || other.is_3d() {
|
if self.is_3d() || other.is_3d() {
|
||||||
let decomposed_from = decompose_3d_matrix(*self);
|
let decomposed_from = decompose_3d_matrix(*self);
|
||||||
|
@ -1158,9 +1156,9 @@ impl Interpolate for LengthOrNone {
|
||||||
Ok(ComputedMatrix::from(interpolated))
|
Ok(ComputedMatrix::from(interpolated))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ComputedMatrix> for MatrixDecomposed2D {
|
impl From<ComputedMatrix> for MatrixDecomposed2D {
|
||||||
/// Decompose a 2D matrix.
|
/// Decompose a 2D matrix.
|
||||||
/// https://drafts.csswg.org/css-transforms/#decomposing-a-2d-matrix
|
/// https://drafts.csswg.org/css-transforms/#decomposing-a-2d-matrix
|
||||||
fn from(matrix: ComputedMatrix) -> MatrixDecomposed2D {
|
fn from(matrix: ComputedMatrix) -> MatrixDecomposed2D {
|
||||||
|
@ -1222,9 +1220,9 @@ impl Interpolate for LengthOrNone {
|
||||||
matrix: m,
|
matrix: m,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MatrixDecomposed2D> for ComputedMatrix {
|
impl From<MatrixDecomposed2D> for ComputedMatrix {
|
||||||
/// Recompose a 2D matrix.
|
/// Recompose a 2D matrix.
|
||||||
/// https://drafts.csswg.org/css-transforms/#recomposing-to-a-2d-matrix
|
/// https://drafts.csswg.org/css-transforms/#recomposing-to-a-2d-matrix
|
||||||
fn from(decomposed: MatrixDecomposed2D) -> ComputedMatrix {
|
fn from(decomposed: MatrixDecomposed2D) -> ComputedMatrix {
|
||||||
|
@ -1259,37 +1257,37 @@ impl Interpolate for LengthOrNone {
|
||||||
computed_matrix.m22 *= decomposed.scale.1;
|
computed_matrix.m22 *= decomposed.scale.1;
|
||||||
computed_matrix
|
computed_matrix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 3d translation.
|
/// A 3d translation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Translate3D(f32, f32, f32);
|
pub struct Translate3D(f32, f32, f32);
|
||||||
|
|
||||||
/// A 3d scale function.
|
/// A 3d scale function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Scale3D(f32, f32, f32);
|
pub struct Scale3D(f32, f32, f32);
|
||||||
|
|
||||||
/// A 3d skew function.
|
/// A 3d skew function.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Skew(f32, f32, f32);
|
pub struct Skew(f32, f32, f32);
|
||||||
|
|
||||||
/// A 3d perspective transformation.
|
/// A 3d perspective transformation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Perspective(f32, f32, f32, f32);
|
pub struct Perspective(f32, f32, f32, f32);
|
||||||
|
|
||||||
/// A quaternion used to represent a rotation.
|
/// A quaternion used to represent a rotation.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Quaternion(f32, f32, f32, f32);
|
pub struct Quaternion(f32, f32, f32, f32);
|
||||||
|
|
||||||
/// A decomposed 3d matrix.
|
/// A decomposed 3d matrix.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct MatrixDecomposed3D {
|
pub struct MatrixDecomposed3D {
|
||||||
/// A translation function.
|
/// A translation function.
|
||||||
pub translate: Translate3D,
|
pub translate: Translate3D,
|
||||||
/// A scale function.
|
/// A scale function.
|
||||||
|
@ -1300,11 +1298,11 @@ impl Interpolate for LengthOrNone {
|
||||||
pub perspective: Perspective,
|
pub perspective: Perspective,
|
||||||
/// The quaternion used to represent the rotation.
|
/// The quaternion used to represent the rotation.
|
||||||
pub quaternion: Quaternion,
|
pub quaternion: Quaternion,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decompose a 3D matrix.
|
/// Decompose a 3D matrix.
|
||||||
/// https://drafts.csswg.org/css-transforms/#decomposing-a-3d-matrix
|
/// https://drafts.csswg.org/css-transforms/#decomposing-a-3d-matrix
|
||||||
fn decompose_3d_matrix(mut matrix: ComputedMatrix) -> Result<MatrixDecomposed3D, ()> {
|
fn decompose_3d_matrix(mut matrix: ComputedMatrix) -> Result<MatrixDecomposed3D, ()> {
|
||||||
// Normalize the matrix.
|
// Normalize the matrix.
|
||||||
if matrix.m44 == 0.0 {
|
if matrix.m44 == 0.0 {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -1445,32 +1443,32 @@ impl Interpolate for LengthOrNone {
|
||||||
perspective: perspective,
|
perspective: perspective,
|
||||||
quaternion: quaternion
|
quaternion: quaternion
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine 2 point.
|
// Combine 2 point.
|
||||||
fn combine(a: [f32; 3], b: [f32; 3], ascl: f32, bscl: f32) -> [f32; 3] {
|
fn combine(a: [f32; 3], b: [f32; 3], ascl: f32, bscl: f32) -> [f32; 3] {
|
||||||
[
|
[
|
||||||
(ascl * a[0]) + (bscl * b[0]),
|
(ascl * a[0]) + (bscl * b[0]),
|
||||||
(ascl * a[1]) + (bscl * b[1]),
|
(ascl * a[1]) + (bscl * b[1]),
|
||||||
(ascl * a[2]) + (bscl * b[2])
|
(ascl * a[2]) + (bscl * b[2])
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dot product.
|
// Dot product.
|
||||||
fn dot(a: [f32; 3], b: [f32; 3]) -> f32 {
|
fn dot(a: [f32; 3], b: [f32; 3]) -> f32 {
|
||||||
a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
|
a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross product.
|
// Cross product.
|
||||||
fn cross(row1: [f32; 3], row2: [f32; 3]) -> [f32; 3] {
|
fn cross(row1: [f32; 3], row2: [f32; 3]) -> [f32; 3] {
|
||||||
[
|
[
|
||||||
row1[1] * row2[2] - row1[2] * row2[1],
|
row1[1] * row2[2] - row1[2] * row2[1],
|
||||||
row1[2] * row2[0] - row1[0] * row2[2],
|
row1[2] * row2[0] - row1[0] * row2[2],
|
||||||
row1[0] * row2[1] - row1[1] * row2[0]
|
row1[0] * row2[1] - row1[1] * row2[0]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Translate3D {
|
impl Interpolate for Translate3D {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(Translate3D(
|
Ok(Translate3D(
|
||||||
try!(self.0.interpolate(&other.0, progress)),
|
try!(self.0.interpolate(&other.0, progress)),
|
||||||
|
@ -1478,9 +1476,9 @@ impl Interpolate for LengthOrNone {
|
||||||
try!(self.2.interpolate(&other.2, progress))
|
try!(self.2.interpolate(&other.2, progress))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Scale3D {
|
impl Interpolate for Scale3D {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(Scale3D(
|
Ok(Scale3D(
|
||||||
try!(self.0.interpolate(&other.0, progress)),
|
try!(self.0.interpolate(&other.0, progress)),
|
||||||
|
@ -1488,9 +1486,9 @@ impl Interpolate for LengthOrNone {
|
||||||
try!(self.2.interpolate(&other.2, progress))
|
try!(self.2.interpolate(&other.2, progress))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Skew {
|
impl Interpolate for Skew {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(Skew(
|
Ok(Skew(
|
||||||
try!(self.0.interpolate(&other.0, progress)),
|
try!(self.0.interpolate(&other.0, progress)),
|
||||||
|
@ -1498,9 +1496,9 @@ impl Interpolate for LengthOrNone {
|
||||||
try!(self.2.interpolate(&other.2, progress))
|
try!(self.2.interpolate(&other.2, progress))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Perspective {
|
impl Interpolate for Perspective {
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
Ok(Perspective(
|
Ok(Perspective(
|
||||||
try!(self.0.interpolate(&other.0, progress)),
|
try!(self.0.interpolate(&other.0, progress)),
|
||||||
|
@ -1509,9 +1507,9 @@ impl Interpolate for LengthOrNone {
|
||||||
try!(self.3.interpolate(&other.3, progress))
|
try!(self.3.interpolate(&other.3, progress))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for MatrixDecomposed3D {
|
impl Interpolate for MatrixDecomposed3D {
|
||||||
/// https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-3d-matrix-values
|
/// https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-3d-matrix-values
|
||||||
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
|
||||||
let mut interpolated = *self;
|
let mut interpolated = *self;
|
||||||
|
@ -1549,9 +1547,9 @@ impl Interpolate for LengthOrNone {
|
||||||
|
|
||||||
Ok(interpolated)
|
Ok(interpolated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MatrixDecomposed3D> for ComputedMatrix {
|
impl From<MatrixDecomposed3D> for ComputedMatrix {
|
||||||
/// 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
|
||||||
fn from(decomposed: MatrixDecomposed3D) -> ComputedMatrix {
|
fn from(decomposed: MatrixDecomposed3D) -> ComputedMatrix {
|
||||||
|
@ -1618,10 +1616,10 @@ impl Interpolate for LengthOrNone {
|
||||||
|
|
||||||
matrix
|
matrix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplication of two 4x4 matrices.
|
// Multiplication of two 4x4 matrices.
|
||||||
fn multiply(a: ComputedMatrix, b: ComputedMatrix) -> ComputedMatrix {
|
fn multiply(a: ComputedMatrix, b: ComputedMatrix) -> ComputedMatrix {
|
||||||
let mut a_clone = a;
|
let mut a_clone = a;
|
||||||
% for i in range(1, 5):
|
% for i in range(1, 5):
|
||||||
% for j in range(1, 5):
|
% for j in range(1, 5):
|
||||||
|
@ -1632,9 +1630,9 @@ impl Interpolate for LengthOrNone {
|
||||||
% endfor
|
% endfor
|
||||||
% endfor
|
% endfor
|
||||||
a_clone
|
a_clone
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedMatrix {
|
impl ComputedMatrix {
|
||||||
fn is_3d(&self) -> bool {
|
fn is_3d(&self) -> bool {
|
||||||
self.m13 != 0.0 || self.m14 != 0.0 ||
|
self.m13 != 0.0 || self.m14 != 0.0 ||
|
||||||
self.m23 != 0.0 || self.m24 != 0.0 ||
|
self.m23 != 0.0 || self.m24 != 0.0 ||
|
||||||
|
@ -1746,10 +1744,10 @@ impl Interpolate for LengthOrNone {
|
||||||
|
|
||||||
Some(x)
|
Some(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
|
/// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
|
||||||
impl Interpolate for TransformList {
|
impl Interpolate for TransformList {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn interpolate(&self, other: &TransformList, progress: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &TransformList, progress: f64) -> Result<Self, ()> {
|
||||||
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
|
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
|
||||||
|
@ -1776,7 +1774,5 @@ impl Interpolate for LengthOrNone {
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
% endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1051,7 +1051,7 @@ ${helpers.single_keyword("animation-fill-mode",
|
||||||
|
|
||||||
|
|
||||||
<%helpers:longhand name="transform" products="gecko servo" extra_prefixes="webkit"
|
<%helpers:longhand name="transform" products="gecko servo" extra_prefixes="webkit"
|
||||||
animatable="${product == 'servo'}"
|
animatable="True"
|
||||||
spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
|
spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue