style: Document the keyframes module.

This commit is contained in:
Emilio Cobos Álvarez 2017-01-02 00:31:17 +01:00
parent 3f7f914e16
commit 0b3c1a8924
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -2,6 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
#![deny(missing_docs)]
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser}; use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule}; use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule};
use parking_lot::RwLock; use parking_lot::RwLock;
@ -14,8 +18,8 @@ use std::sync::Arc;
use style_traits::ToCss; use style_traits::ToCss;
use stylesheets::{MemoryHoleReporter, Stylesheet}; use stylesheets::{MemoryHoleReporter, Stylesheet};
/// A number from 0 to 1, indicating the percentage of the animation where /// A number from 0 to 1, indicating the percentage of the animation when this
/// this keyframe should run. /// keyframe should run.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct KeyframePercentage(pub f32); pub struct KeyframePercentage(pub f32);
@ -37,6 +41,7 @@ impl ToCss for KeyframePercentage {
} }
impl KeyframePercentage { impl KeyframePercentage {
/// Trivially constructs a new `KeyframePercentage`.
#[inline] #[inline]
pub fn new(value: f32) -> KeyframePercentage { pub fn new(value: f32) -> KeyframePercentage {
debug_assert!(value >= 0. && value <= 1.); debug_assert!(value >= 0. && value <= 1.);
@ -67,6 +72,7 @@ impl KeyframePercentage {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct KeyframeSelector(Vec<KeyframePercentage>); pub struct KeyframeSelector(Vec<KeyframePercentage>);
impl KeyframeSelector { impl KeyframeSelector {
/// Return the list of percentages this selector contains.
#[inline] #[inline]
pub fn percentages(&self) -> &[KeyframePercentage] { pub fn percentages(&self) -> &[KeyframePercentage] {
&self.0 &self.0
@ -77,6 +83,7 @@ impl KeyframeSelector {
KeyframeSelector(percentages) KeyframeSelector(percentages)
} }
/// Parse a keyframe selector from CSS input.
pub fn parse(input: &mut Parser) -> Result<Self, ()> { pub fn parse(input: &mut Parser) -> Result<Self, ()> {
input.parse_comma_separated(KeyframePercentage::parse) input.parse_comma_separated(KeyframePercentage::parse)
.map(KeyframeSelector) .map(KeyframeSelector)
@ -87,12 +94,13 @@ impl KeyframeSelector {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Keyframe { pub struct Keyframe {
/// The selector this keyframe was specified from.
pub selector: KeyframeSelector, pub selector: KeyframeSelector,
/// `!important` is not allowed in keyframe declarations, /// The declaration block that was declared inside this keyframe.
/// so the second value of these tuples is always `Importance::Normal`. ///
/// But including them enables `compute_style_for_animation_step` to create a `ApplicableDeclarationBlock` /// Note that `!important` rules in keyframes don't apply, but we keep this
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`. /// `Arc` just for convenience.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub block: Arc<RwLock<PropertyDeclarationBlock>>, pub block: Arc<RwLock<PropertyDeclarationBlock>>,
} }
@ -114,7 +122,10 @@ impl ToCss for Keyframe {
impl Keyframe { impl Keyframe {
pub fn parse(css: &str, parent_stylesheet: &Stylesheet, extra_data: ParserContextExtraData) /// Parse a CSS keyframe.
pub fn parse(css: &str,
parent_stylesheet: &Stylesheet,
extra_data: ParserContextExtraData)
-> Result<Arc<RwLock<Self>>, ()> { -> Result<Arc<RwLock<Self>>, ()> {
let error_reporter = Box::new(MemoryHoleReporter); let error_reporter = Box::new(MemoryHoleReporter);
let context = ParserContext::new_with_extra_data(parent_stylesheet.origin, let context = ParserContext::new_with_extra_data(parent_stylesheet.origin,
@ -133,15 +144,19 @@ impl Keyframe {
/// A keyframes step value. This can be a synthetised keyframes animation, that /// A keyframes step value. This can be a synthetised keyframes animation, that
/// is, one autogenerated from the current computed values, or a list of /// is, one autogenerated from the current computed values, or a list of
/// declarations to apply. /// declarations to apply.
// TODO: Find a better name for this? ///
/// TODO: Find a better name for this?
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum KeyframesStepValue { pub enum KeyframesStepValue {
/// See `Keyframe::declarations`s docs about the presence of `Importance`. /// A step formed by a declaration block specified by the CSS.
Declarations { Declarations {
/// The declaration block per se.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
block: Arc<RwLock<PropertyDeclarationBlock>> block: Arc<RwLock<PropertyDeclarationBlock>>
}, },
/// A synthetic step computed from the current computed values at the time
/// of the animation.
ComputedValues, ComputedValues,
} }
@ -162,7 +177,6 @@ pub struct KeyframesStep {
} }
impl KeyframesStep { impl KeyframesStep {
#[allow(unsafe_code)]
#[inline] #[inline]
fn new(percentage: KeyframePercentage, fn new(percentage: KeyframePercentage,
value: KeyframesStepValue) -> Self { value: KeyframesStepValue) -> Self {
@ -193,6 +207,7 @@ impl KeyframesStep {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct KeyframesAnimation { pub struct KeyframesAnimation {
/// The difference steps of the animation.
pub steps: Vec<KeyframesStep>, pub steps: Vec<KeyframesStep>,
/// The properties that change in this animation. /// The properties that change in this animation.
pub properties_changed: Vec<TransitionProperty>, pub properties_changed: Vec<TransitionProperty>,
@ -204,7 +219,6 @@ pub struct KeyframesAnimation {
/// ///
/// In practice, browsers seem to try to do their best job at it, so we might /// In practice, browsers seem to try to do their best job at it, so we might
/// want to go through all the actual keyframes and deduplicate properties. /// want to go through all the actual keyframes and deduplicate properties.
#[allow(unsafe_code)]
fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> { fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
let mut ret = vec![]; let mut ret = vec![];
// NB: declarations are already deduplicated, so we don't have to check for // NB: declarations are already deduplicated, so we don't have to check for
@ -219,6 +233,13 @@ fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
} }
impl KeyframesAnimation { impl KeyframesAnimation {
/// Create a keyframes animation from a given list of keyframes.
///
/// This will return `None` if the list of keyframes is empty, or there are
/// no animated properties obtained from the keyframes.
///
/// Otherwise, this will compute and sort the steps used for the animation,
/// and return the animation object.
pub fn from_keyframes(keyframes: &[Arc<RwLock<Keyframe>>]) -> Option<Self> { pub fn from_keyframes(keyframes: &[Arc<RwLock<Keyframe>>]) -> Option<Self> {
if keyframes.is_empty() { if keyframes.is_empty() {
return None; return None;
@ -273,6 +294,7 @@ struct KeyframeListParser<'a> {
context: &'a ParserContext<'a>, context: &'a ParserContext<'a>,
} }
/// Parses a keyframe list from CSS input.
pub fn parse_keyframe_list(context: &ParserContext, input: &mut Parser) -> Vec<Arc<RwLock<Keyframe>>> { pub fn parse_keyframe_list(context: &ParserContext, input: &mut Parser) -> Vec<Arc<RwLock<Keyframe>>> {
RuleListParser::new_for_nested_rule(input, KeyframeListParser { context: context }) RuleListParser::new_for_nested_rule(input, KeyframeListParser { context: context })
.filter_map(Result::ok) .filter_map(Result::ok)