mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
layout: Implement CSS transitions per CSS-TRANSITIONS § 2.
Transition events are not yet supported, and the only animatable properties are `top`, `right`, `bottom`, and `left`. However, all other features of transitions are supported. There are no automated tests at present because I'm not sure how best to test it, but three manual tests are included.
This commit is contained in:
parent
c1cc31b9d6
commit
66dd8c8a6c
31 changed files with 1603 additions and 224 deletions
|
@ -6,29 +6,33 @@
|
|||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use animation;
|
||||
use context::SharedLayoutContext;
|
||||
use css::node_style::StyledNode;
|
||||
use incremental::{self, RestyleDamage};
|
||||
use data::{LayoutDataAccess, LayoutDataWrapper};
|
||||
use incremental::{self, RestyleDamage};
|
||||
use opaque_node::OpaqueNodeMethods;
|
||||
use wrapper::{LayoutElement, LayoutNode, TLayoutNode};
|
||||
|
||||
use script::dom::node::NodeTypeId;
|
||||
use script::layout_interface::Animation;
|
||||
use selectors::bloom::BloomFilter;
|
||||
use util::cache::{LRUCache, SimpleHashCache};
|
||||
use util::smallvec::{SmallVec, SmallVec16};
|
||||
use util::arc_ptr_eq;
|
||||
use std::borrow::ToOwned;
|
||||
use std::mem;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::slice::Iter;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use selectors::parser::PseudoElement;
|
||||
use style::selector_matching::{Stylist, DeclarationBlock};
|
||||
use style::node::{TElement, TNode};
|
||||
use style::properties::{ComputedValues, cascade};
|
||||
use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes};
|
||||
use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
|
||||
use selectors::parser::PseudoElement;
|
||||
use std::borrow::ToOwned;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
use std::slice::Iter;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use style::node::{TElement, TNode};
|
||||
use style::properties::{ComputedValues, cascade};
|
||||
use style::selector_matching::{Stylist, DeclarationBlock};
|
||||
use util::arc_ptr_eq;
|
||||
use util::cache::{LRUCache, SimpleHashCache};
|
||||
use util::smallvec::{SmallVec, SmallVec16};
|
||||
|
||||
pub struct ApplicableDeclarations {
|
||||
pub normal: SmallVec16<DeclarationBlock>,
|
||||
|
@ -399,7 +403,8 @@ pub trait MatchMethods {
|
|||
layout_context: &SharedLayoutContext,
|
||||
parent: Option<LayoutNode>,
|
||||
applicable_declarations: &ApplicableDeclarations,
|
||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache);
|
||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
|
||||
new_animations_sender: &Sender<Animation>);
|
||||
}
|
||||
|
||||
trait PrivateMatchMethods {
|
||||
|
@ -408,8 +413,9 @@ trait PrivateMatchMethods {
|
|||
parent_style: Option<&Arc<ComputedValues>>,
|
||||
applicable_declarations: &[DeclarationBlock],
|
||||
style: &mut Option<Arc<ComputedValues>>,
|
||||
applicable_declarations_cache: &mut
|
||||
ApplicableDeclarationsCache,
|
||||
applicable_declarations_cache:
|
||||
&mut ApplicableDeclarationsCache,
|
||||
new_animations_sender: &Sender<Animation>,
|
||||
shareable: bool)
|
||||
-> RestyleDamage;
|
||||
|
||||
|
@ -425,11 +431,12 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
|||
parent_style: Option<&Arc<ComputedValues>>,
|
||||
applicable_declarations: &[DeclarationBlock],
|
||||
style: &mut Option<Arc<ComputedValues>>,
|
||||
applicable_declarations_cache: &mut
|
||||
ApplicableDeclarationsCache,
|
||||
applicable_declarations_cache:
|
||||
&mut ApplicableDeclarationsCache,
|
||||
new_animations_sender: &Sender<Animation>,
|
||||
shareable: bool)
|
||||
-> RestyleDamage {
|
||||
let this_style;
|
||||
let mut this_style;
|
||||
let cacheable;
|
||||
match parent_style {
|
||||
Some(ref parent_style) => {
|
||||
|
@ -444,7 +451,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
|||
Some(&***parent_style),
|
||||
cached_computed_values);
|
||||
cacheable = is_cacheable;
|
||||
this_style = Arc::new(the_style);
|
||||
this_style = the_style
|
||||
}
|
||||
None => {
|
||||
let (the_style, is_cacheable) = cascade(layout_context.screen_size,
|
||||
|
@ -453,22 +460,39 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
|||
None,
|
||||
None);
|
||||
cacheable = is_cacheable;
|
||||
this_style = Arc::new(the_style);
|
||||
this_style = the_style
|
||||
}
|
||||
};
|
||||
|
||||
// Trigger transitions if necessary. This will reset `this_style` back to its old value if
|
||||
// it did trigger a transition.
|
||||
match *style {
|
||||
None => {
|
||||
// This is a newly-created node; we've nothing to transition from!
|
||||
}
|
||||
Some(ref style) => {
|
||||
let node = OpaqueNodeMethods::from_layout_node(self);
|
||||
animation::start_transitions_if_applicable(new_animations_sender,
|
||||
node,
|
||||
&**style,
|
||||
&mut this_style);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate style difference.
|
||||
let this_style = Arc::new(this_style);
|
||||
let damage = incremental::compute_damage(style, &*this_style);
|
||||
|
||||
// Cache the resolved style if it was cacheable.
|
||||
if cacheable {
|
||||
applicable_declarations_cache.insert(applicable_declarations.to_vec(), this_style.clone());
|
||||
}
|
||||
|
||||
// Calculate style difference and write.
|
||||
let damage = incremental::compute_damage(style, &*this_style);
|
||||
// Write in the final style and return the damage done to our caller.
|
||||
*style = Some(this_style);
|
||||
damage
|
||||
}
|
||||
|
||||
|
||||
fn share_style_with_candidate_if_possible(&self,
|
||||
parent_node: Option<LayoutNode>,
|
||||
candidate: &StyleSharingCandidate)
|
||||
|
@ -615,7 +639,8 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
layout_context: &SharedLayoutContext,
|
||||
parent: Option<LayoutNode>,
|
||||
applicable_declarations: &ApplicableDeclarations,
|
||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache) {
|
||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
|
||||
new_animations_sender: &Sender<Animation>) {
|
||||
// Get our parent's style. This must be unsafe so that we don't touch the parent's
|
||||
// borrow flags.
|
||||
//
|
||||
|
@ -625,8 +650,12 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
None => None,
|
||||
Some(parent_node) => {
|
||||
let parent_layout_data_ref = parent_node.borrow_layout_data_unchecked();
|
||||
let parent_layout_data = (&*parent_layout_data_ref).as_ref().expect("no parent data!?");
|
||||
let parent_style = parent_layout_data.shared_data.style.as_ref().expect("parent hasn't been styled yet!");
|
||||
let parent_layout_data = (&*parent_layout_data_ref).as_ref()
|
||||
.expect("no parent data!?");
|
||||
let parent_style = parent_layout_data.shared_data
|
||||
.style
|
||||
.as_ref()
|
||||
.expect("parent hasn't been styled yet!");
|
||||
Some(parent_style)
|
||||
}
|
||||
};
|
||||
|
@ -651,6 +680,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
applicable_declarations.normal.as_slice(),
|
||||
&mut layout_data.shared_data.style,
|
||||
applicable_declarations_cache,
|
||||
new_animations_sender,
|
||||
applicable_declarations.normal_shareable);
|
||||
if applicable_declarations.before.len() > 0 {
|
||||
damage = damage | self.cascade_node_pseudo_element(
|
||||
|
@ -659,6 +689,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
&*applicable_declarations.before,
|
||||
&mut layout_data.data.before_style,
|
||||
applicable_declarations_cache,
|
||||
new_animations_sender,
|
||||
false);
|
||||
}
|
||||
if applicable_declarations.after.len() > 0 {
|
||||
|
@ -668,6 +699,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
&*applicable_declarations.after,
|
||||
&mut layout_data.data.after_style,
|
||||
applicable_declarations_cache,
|
||||
new_animations_sender,
|
||||
false);
|
||||
}
|
||||
layout_data.data.restyle_damage = damage;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue