зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #14879 - Stylo: Store animation properties into gecko's struct (from hiikezoe:animation-properties); r=heycam
<!-- Please describe your changes on the following line: --> This is the counter part of https://bugzilla.mozilla.org/show_bug.cgi?id=1328786 All patches get reviewed by r=@heycam. --- <!-- 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 <!-- Either: --> - [X] These changes do not require tests because it's for stylo. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 43a537a1ba8d62a39e062a21df9d5c771631411b
This commit is contained in:
Родитель
63fc85cd4b
Коммит
acccadb9f2
|
@ -9,6 +9,7 @@ mod ns_css_shadow_array;
|
|||
mod ns_style_auto_array;
|
||||
pub mod ns_style_coord;
|
||||
mod ns_t_array;
|
||||
mod ns_timing_function;
|
||||
pub mod ownership;
|
||||
pub mod refptr;
|
||||
mod style_complex_color;
|
||||
|
|
|
@ -4,10 +4,25 @@
|
|||
|
||||
//! Rust helpers for Gecko's `nsStyleAutoArray`.
|
||||
|
||||
use gecko_bindings::bindings::Gecko_EnsureStyleAnimationArrayLength;
|
||||
use gecko_bindings::structs::nsStyleAutoArray;
|
||||
use std::iter::{once, Chain, Once, IntoIterator};
|
||||
use std::ops::Index;
|
||||
use std::slice::{Iter, IterMut};
|
||||
|
||||
impl<T> Index<usize> for nsStyleAutoArray<T> {
|
||||
type Output = T;
|
||||
fn index(&self, index: usize) -> &T {
|
||||
if index > self.len() {
|
||||
panic!("out of range")
|
||||
}
|
||||
match index {
|
||||
0 => &self.mFirstElement,
|
||||
_ => &self.mOtherElements[index - 1],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> nsStyleAutoArray<T> {
|
||||
/// Mutably iterate over the array elements.
|
||||
pub fn iter_mut(&mut self) -> Chain<Once<&mut T>, IterMut<T>> {
|
||||
|
@ -26,6 +41,14 @@ impl<T> nsStyleAutoArray<T> {
|
|||
pub fn len(&self) -> usize {
|
||||
1 + self.mOtherElements.len()
|
||||
}
|
||||
|
||||
/// Ensures that the array has length at least the given length.
|
||||
pub fn ensure_len(&mut self, len: usize) {
|
||||
unsafe {
|
||||
Gecko_EnsureStyleAnimationArrayLength(self as *mut nsStyleAutoArray<T> as *mut _,
|
||||
len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray<T> {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::point::TypedPoint2D;
|
||||
use gecko_bindings::structs::{nsTimingFunction, nsTimingFunction_Type};
|
||||
use properties::longhands::transition_timing_function::single_value::computed_value::StartEnd;
|
||||
use properties::longhands::transition_timing_function::single_value::computed_value::T as TransitionTimingFunction;
|
||||
use std::mem;
|
||||
|
||||
impl From<TransitionTimingFunction> for nsTimingFunction {
|
||||
fn from(function: TransitionTimingFunction) -> nsTimingFunction {
|
||||
let mut tf: nsTimingFunction = unsafe { mem::zeroed() };
|
||||
|
||||
match function {
|
||||
TransitionTimingFunction::Steps(steps, StartEnd::Start) => {
|
||||
tf.mType = nsTimingFunction_Type::StepStart;
|
||||
unsafe {
|
||||
tf.__bindgen_anon_1.__bindgen_anon_1.as_mut().mSteps = steps;
|
||||
}
|
||||
},
|
||||
TransitionTimingFunction::Steps(steps, StartEnd::End) => {
|
||||
tf.mType = nsTimingFunction_Type::StepEnd;
|
||||
unsafe {
|
||||
tf.__bindgen_anon_1.__bindgen_anon_1.as_mut().mSteps = steps;
|
||||
}
|
||||
},
|
||||
TransitionTimingFunction::CubicBezier(p1, p2) => {
|
||||
tf.mType = nsTimingFunction_Type::CubicBezier;
|
||||
let ref mut gecko_cubic_bezier =
|
||||
unsafe { tf.__bindgen_anon_1.mFunc.as_mut() };
|
||||
gecko_cubic_bezier.mX1 = p1.x;
|
||||
gecko_cubic_bezier.mY1 = p1.y;
|
||||
gecko_cubic_bezier.mX2 = p2.x;
|
||||
gecko_cubic_bezier.mY2 = p2.y;
|
||||
},
|
||||
// FIXME: we need to add more types once TransitionTimingFunction
|
||||
// has more types.
|
||||
}
|
||||
tf
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nsTimingFunction> for TransitionTimingFunction {
|
||||
fn from(function: nsTimingFunction) -> TransitionTimingFunction {
|
||||
match function.mType {
|
||||
nsTimingFunction_Type::StepStart => {
|
||||
TransitionTimingFunction::Steps(unsafe { function.__bindgen_anon_1.__bindgen_anon_1.as_ref().mSteps },
|
||||
StartEnd::Start)
|
||||
},
|
||||
nsTimingFunction_Type::StepEnd => {
|
||||
TransitionTimingFunction::Steps(unsafe { function.__bindgen_anon_1.__bindgen_anon_1.as_ref().mSteps },
|
||||
StartEnd::End)
|
||||
},
|
||||
// FIXME: As above, we need to fix here.
|
||||
nsTimingFunction_Type::Ease |
|
||||
nsTimingFunction_Type::Linear |
|
||||
nsTimingFunction_Type::EaseIn |
|
||||
nsTimingFunction_Type::EaseOut |
|
||||
nsTimingFunction_Type::EaseInOut |
|
||||
nsTimingFunction_Type::CubicBezier => {
|
||||
TransitionTimingFunction::CubicBezier(
|
||||
TypedPoint2D::new(unsafe { function.__bindgen_anon_1.mFunc.as_ref().mX1 },
|
||||
unsafe { function.__bindgen_anon_1.mFunc.as_ref().mY1 }),
|
||||
TypedPoint2D::new(unsafe { function.__bindgen_anon_1.mFunc.as_ref().mX2 },
|
||||
unsafe { function.__bindgen_anon_1.mFunc.as_ref().mY2 }))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,12 +60,12 @@ class Keyword(object):
|
|||
|
||||
def gecko_constant(self, value):
|
||||
moz_stripped = value.replace("-moz-", '') if self.gecko_strip_moz_prefix else value
|
||||
parts = moz_stripped.split('-')
|
||||
mapped = self.consts_map.get(value)
|
||||
if self.gecko_enum_prefix:
|
||||
parts = [p.title() for p in parts]
|
||||
parts = moz_stripped.split('-')
|
||||
parts = mapped if mapped else [p.title() for p in parts]
|
||||
return self.gecko_enum_prefix + "::" + "".join(parts)
|
||||
else:
|
||||
mapped = self.consts_map.get(value)
|
||||
suffix = mapped if mapped else moz_stripped.replace("-", "_")
|
||||
return self.gecko_constant_prefix + "_" + suffix.upper()
|
||||
|
||||
|
|
|
@ -452,12 +452,6 @@ impl Debug for ${style_struct.gecko_struct_name} {
|
|||
force_stub += ["font-variant"]
|
||||
# These have unusual representations in gecko.
|
||||
force_stub += ["list-style-type"]
|
||||
# In a nsTArray, have to be done manually, but probably not too much work
|
||||
# (the "filling them", not the "making them work")
|
||||
force_stub += ["animation-name", "animation-duration",
|
||||
"animation-timing-function", "animation-iteration-count",
|
||||
"animation-direction", "animation-play-state",
|
||||
"animation-fill-mode", "animation-delay"]
|
||||
|
||||
# These are part of shorthands so we must include them in stylo builds,
|
||||
# but we haven't implemented the stylo glue for the longhand
|
||||
|
@ -1023,7 +1017,81 @@ fn static_assert() {
|
|||
|
||||
</%self:impl_trait>
|
||||
|
||||
<%def name="impl_copy_animation_value(ident, gecko_ffi_name)">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn copy_animation_${ident}_from(&mut self, other: &Self) {
|
||||
unsafe { self.gecko.mAnimations.ensure_len(other.gecko.mAnimations.len()) };
|
||||
self.gecko.mAnimation${gecko_ffi_name}Count = other.gecko.mAnimation${gecko_ffi_name}Count;
|
||||
for (index, animation) in self.gecko.mAnimations.iter_mut().enumerate() {
|
||||
animation.m${gecko_ffi_name} = other.gecko.mAnimations[index].m${gecko_ffi_name};
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_animation_count(ident, gecko_ffi_name)">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn animation_${ident}_count(&self) -> usize {
|
||||
self.gecko.mAnimation${gecko_ffi_name}Count as usize
|
||||
}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_animation_time_value(ident, gecko_ffi_name)">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_animation_${ident}(&mut self, v: longhands::animation_${ident}::computed_value::T) {
|
||||
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
||||
self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32;
|
||||
for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
|
||||
gecko.m${gecko_ffi_name} = servo.seconds() * 1000.;
|
||||
}
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn animation_${ident}_at(&self, index: usize)
|
||||
-> longhands::animation_${ident}::computed_value::SingleComputedValue {
|
||||
use values::specified::Time;
|
||||
Time(self.gecko.mAnimations[index].m${gecko_ffi_name} / 1000.)
|
||||
}
|
||||
${impl_animation_count(ident, gecko_ffi_name)}
|
||||
${impl_copy_animation_value(ident, gecko_ffi_name)}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_animation_keyword(ident, gecko_ffi_name, keyword, cast_type='u8')">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_animation_${ident}(&mut self, v: longhands::animation_${ident}::computed_value::T) {
|
||||
use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword;
|
||||
use gecko_bindings::structs;
|
||||
|
||||
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
||||
self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32;
|
||||
|
||||
for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
|
||||
let result = match servo {
|
||||
% for value in keyword.gecko_values():
|
||||
Keyword::${to_rust_ident(value)} =>
|
||||
structs::${keyword.gecko_constant(value)} ${keyword.maybe_cast(cast_type)},
|
||||
% endfor
|
||||
};
|
||||
gecko.m${gecko_ffi_name} = result;
|
||||
}
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn animation_${ident}_at(&self, index: usize)
|
||||
-> longhands::animation_${ident}::computed_value::SingleComputedValue {
|
||||
use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword;
|
||||
match self.gecko.mAnimations[index].m${gecko_ffi_name} ${keyword.maybe_cast("u32")} {
|
||||
% for value in keyword.gecko_values():
|
||||
structs::${keyword.gecko_constant(value)} => Keyword::${to_rust_ident(value)},
|
||||
% endfor
|
||||
x => panic!("Found unexpected value for animation-${ident}: {:?}", x),
|
||||
}
|
||||
}
|
||||
${impl_animation_count(ident, gecko_ffi_name)}
|
||||
${impl_copy_animation_value(ident, gecko_ffi_name)}
|
||||
</%def>
|
||||
|
||||
<% skip_box_longhands= """display overflow-y vertical-align
|
||||
animation-name animation-delay animation-duration
|
||||
animation-direction animation-fill-mode animation-play-state
|
||||
animation-iteration-count animation-timing-function
|
||||
-moz-binding page-break-before page-break-after
|
||||
scroll-snap-points-x scroll-snap-points-y transform
|
||||
scroll-snap-type-y perspective-origin transform-origin""" %>
|
||||
|
@ -1294,6 +1362,88 @@ fn static_assert() {
|
|||
unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); }
|
||||
}
|
||||
|
||||
pub fn set_animation_name(&mut self, v: longhands::animation_name::computed_value::T) {
|
||||
use nsstring::nsCString;
|
||||
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
||||
self.gecko.mAnimationNameCount = v.0.len() as u32;
|
||||
for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
|
||||
gecko.mName.assign_utf8(&nsCString::from(servo.0.to_string()));
|
||||
}
|
||||
}
|
||||
pub fn animation_name_at(&self, index: usize)
|
||||
-> longhands::animation_name::computed_value::SingleComputedValue {
|
||||
use Atom;
|
||||
use properties::longhands::animation_name::single_value::SpecifiedValue as AnimationName;
|
||||
// XXX: Is there any effective ways?
|
||||
AnimationName(Atom::from(String::from_utf16_lossy(&self.gecko.mAnimations[index].mName[..])))
|
||||
}
|
||||
pub fn copy_animation_name_from(&mut self, other: &Self) {
|
||||
unsafe { self.gecko.mAnimations.ensure_len(other.gecko.mAnimations.len()) };
|
||||
self.gecko.mAnimationNameCount = other.gecko.mAnimationNameCount;
|
||||
for (index, animation) in self.gecko.mAnimations.iter_mut().enumerate() {
|
||||
animation.mName.assign(&other.gecko.mAnimations[index].mName);
|
||||
}
|
||||
}
|
||||
${impl_animation_count('name', 'Name')}
|
||||
|
||||
${impl_animation_time_value('delay', 'Delay')}
|
||||
${impl_animation_time_value('duration', 'Duration')}
|
||||
|
||||
${impl_animation_keyword('direction', 'Direction',
|
||||
data.longhands_by_name["animation-direction"].keyword)}
|
||||
${impl_animation_keyword('fill_mode', 'FillMode',
|
||||
data.longhands_by_name["animation-fill-mode"].keyword)}
|
||||
${impl_animation_keyword('play_state', 'PlayState',
|
||||
data.longhands_by_name["animation-play-state"].keyword)}
|
||||
|
||||
pub fn set_animation_iteration_count(&mut self, v: longhands::animation_iteration_count::computed_value::T) {
|
||||
use std::f32;
|
||||
use properties::longhands::animation_iteration_count::single_value::SpecifiedValue as AnimationIterationCount;
|
||||
|
||||
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
||||
self.gecko.mAnimationIterationCountCount = v.0.len() as u32;
|
||||
for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
|
||||
match servo {
|
||||
AnimationIterationCount::Number(n) => gecko.mIterationCount = n,
|
||||
AnimationIterationCount::Infinite => gecko.mIterationCount = f32::INFINITY,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn animation_iteration_count_at(&self, index: usize)
|
||||
-> longhands::animation_iteration_count::computed_value::SingleComputedValue {
|
||||
use properties::longhands::animation_iteration_count::single_value::computed_value::T
|
||||
as AnimationIterationCount;
|
||||
|
||||
if self.gecko.mAnimations[index].mIterationCount.is_infinite() {
|
||||
AnimationIterationCount::Infinite
|
||||
} else {
|
||||
AnimationIterationCount::Number(self.gecko.mAnimations[index].mIterationCount)
|
||||
}
|
||||
}
|
||||
${impl_animation_count('iteration_count', 'IterationCount')}
|
||||
${impl_copy_animation_value('iteration_count', 'IterationCount')}
|
||||
|
||||
pub fn set_animation_timing_function(&mut self, v: longhands::animation_timing_function::computed_value::T) {
|
||||
unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
|
||||
|
||||
self.gecko.mAnimationTimingFunctionCount = v.0.len() as u32;
|
||||
for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
|
||||
gecko.mTimingFunction = servo.into();
|
||||
}
|
||||
}
|
||||
${impl_animation_count('timing_function', 'TimingFunction')}
|
||||
pub fn animation_timing_function_at(&self, index: usize)
|
||||
-> longhands::animation_timing_function::computed_value::SingleComputedValue {
|
||||
self.gecko.mAnimations[index].mTimingFunction.into()
|
||||
}
|
||||
pub fn copy_animation_timing_function_from(&mut self, other: &Self) {
|
||||
unsafe { self.gecko.mAnimations.ensure_len(other.gecko.mAnimations.len()) };
|
||||
self.gecko.mAnimationTimingFunctionCount = other.gecko.mAnimationTimingFunctionCount;
|
||||
for (index, animation) in self.gecko.mAnimations.iter_mut().enumerate() {
|
||||
animation.mTimingFunction = other.gecko.mAnimations[index].mTimingFunction;
|
||||
}
|
||||
}
|
||||
|
||||
<% scroll_snap_type_keyword = Keyword("scroll-snap-type", "none mandatory proximity") %>
|
||||
|
||||
${impl_keyword('scroll_snap_type_y', 'mScrollSnapTypeY', scroll_snap_type_keyword, need_clone=False)}
|
||||
|
|
|
@ -891,11 +891,14 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
</%helpers:vector_longhand>
|
||||
|
||||
<% animation_direction_custom_consts = { "alternate-reverse": "Alternate_reverse" } %>
|
||||
${helpers.single_keyword("animation-direction",
|
||||
"normal reverse alternate alternate-reverse",
|
||||
need_index=True,
|
||||
animatable=False,
|
||||
vector=True,
|
||||
gecko_enum_prefix="PlaybackDirection",
|
||||
custom_consts=animation_direction_custom_consts,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-direction",
|
||||
allowed_in_keyframe_block=False)}
|
||||
|
||||
|
@ -915,6 +918,7 @@ ${helpers.single_keyword("animation-fill-mode",
|
|||
need_index=True,
|
||||
animatable=False,
|
||||
vector=True,
|
||||
gecko_enum_prefix="FillMode",
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode",
|
||||
allowed_in_keyframe_block=False)}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче