aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/css/matching.rs
diff options
context:
space:
mode:
authorBobby Holley <bobbyholley@gmail.com>2015-12-17 16:21:29 -0800
committerBobby Holley <bobbyholley@gmail.com>2015-12-29 11:50:03 -0800
commit47059d2d26f14f71e5b7212fa8bc01608eca11b5 (patch)
treed0693fb9987a7113323c7d6fb5502cb5621d8f15 /components/layout/css/matching.rs
parent89ab368258eb827b0dcc8d6e6deecd3ed3c1de71 (diff)
downloadservo-47059d2d26f14f71e5b7212fa8bc01608eca11b5.tar.gz
servo-47059d2d26f14f71e5b7212fa8bc01608eca11b5.zip
Separate style+layout and layout-specific wrapper functionality.
This patch does a number of things, unfortunately all at once: * Hoists a large subset of the layout wrapper functionality into the style system. * Merges TElementAttributes into the newly-created TElement. * Reorganizes LayoutData by style vs layout, and removes LayoutDataShared. * Simplifies the API for borrowing style/layout data. There's still more to do to make the style system usable standalone, but this is a good start.
Diffstat (limited to 'components/layout/css/matching.rs')
-rw-r--r--components/layout/css/matching.rs179
1 files changed, 86 insertions, 93 deletions
diff --git a/components/layout/css/matching.rs b/components/layout/css/matching.rs
index ae136aea5ff..a9c07848309 100644
--- a/components/layout/css/matching.rs
+++ b/components/layout/css/matching.rs
@@ -8,7 +8,7 @@
use animation;
use context::SharedLayoutContext;
-use data::LayoutDataWrapper;
+use data::PrivateLayoutData;
use incremental::{self, RestyleDamage};
use msg::ParseErrorReporter;
use script::layout_interface::Animation;
@@ -20,18 +20,19 @@ use selectors::{Element};
use smallvec::SmallVec;
use std::borrow::ToOwned;
use std::hash::{Hash, Hasher};
+use std::mem::transmute;
use std::slice::Iter;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use string_cache::{Atom, Namespace};
-use style::node::TElementAttributes;
+use style::data::PrivateStyleData;
+use style::dom::{TElement, TNode};
use style::properties::{ComputedValues, PropertyDeclaration, cascade};
use style::selector_matching::{DeclarationBlock, Stylist};
use util::arc_ptr_eq;
use util::cache::{LRUCache, SimpleHashCache};
use util::opts;
use util::vec::ForgetfulSink;
-use wrapper::{LayoutElement, LayoutNode};
pub struct ApplicableDeclarations {
pub normal: SmallVec<[DeclarationBlock; 16]>,
@@ -160,7 +161,7 @@ pub struct StyleSharingCandidateCache {
cache: LRUCache<StyleSharingCandidate, ()>,
}
-fn create_common_style_affecting_attributes_from_element<'le, E: LayoutElement<'le>>(element: &E)
+fn create_common_style_affecting_attributes_from_element<'le, E: TElement<'le>>(element: &E)
-> CommonStyleAffectingAttributes {
let mut flags = CommonStyleAffectingAttributes::empty();
for attribute_info in &common_style_affecting_attributes() {
@@ -211,17 +212,17 @@ impl StyleSharingCandidate {
/// Attempts to create a style sharing candidate from this node. Returns
/// the style sharing candidate or `None` if this node is ineligible for
/// style sharing.
- fn new<'le, E: LayoutElement<'le>>(element: &E) -> Option<StyleSharingCandidate> {
+ fn new<'le, E: TElement<'le>>(element: &E) -> Option<StyleSharingCandidate> {
let parent_element = match element.parent_element() {
None => return None,
Some(parent_element) => parent_element,
};
let style = unsafe {
- match *element.as_node().borrow_layout_data_unchecked() {
+ match element.as_node().borrow_data_unchecked() {
None => return None,
- Some(ref layout_data_ref) => {
- match layout_data_ref.shared_data.style {
+ Some(data_ref) => {
+ match (*data_ref).style {
None => return None,
Some(ref data) => (*data).clone(),
}
@@ -229,10 +230,10 @@ impl StyleSharingCandidate {
}
};
let parent_style = unsafe {
- match *parent_element.as_node().borrow_layout_data_unchecked() {
+ match parent_element.as_node().borrow_data_unchecked() {
None => return None,
- Some(ref parent_layout_data_ref) => {
- match parent_layout_data_ref.shared_data.style {
+ Some(parent_data_ref) => {
+ match (*parent_data_ref).style {
None => return None,
Some(ref data) => (*data).clone(),
}
@@ -257,7 +258,7 @@ impl StyleSharingCandidate {
})
}
- fn can_share_style_with<'a, E: LayoutElement<'a>>(&self, element: &E) -> bool {
+ fn can_share_style_with<'a, E: TElement<'a>>(&self, element: &E) -> bool {
if *element.get_local_name() != self.local_name {
return false
}
@@ -342,7 +343,7 @@ impl StyleSharingCandidateCache {
self.cache.iter()
}
- pub fn insert_if_possible<'le, E: LayoutElement<'le>>(&mut self, element: &E) {
+ pub fn insert_if_possible<'le, E: TElement<'le>>(&mut self, element: &E) {
match StyleSharingCandidate::new(element) {
None => {}
Some(candidate) => self.cache.insert(candidate, ())
@@ -363,7 +364,7 @@ pub enum StyleSharingResult {
StyleWasShared(usize, RestyleDamage),
}
-pub trait ElementMatchMethods<'le, ConcreteLayoutElement: LayoutElement<'le>> {
+pub trait ElementMatchMethods<'le, ConcreteElement: TElement<'le>> {
fn match_element(&self,
stylist: &Stylist,
parent_bf: Option<&BloomFilter>,
@@ -376,11 +377,11 @@ pub trait ElementMatchMethods<'le, ConcreteLayoutElement: LayoutElement<'le>> {
unsafe fn share_style_if_possible(&self,
style_sharing_candidate_cache:
&mut StyleSharingCandidateCache,
- parent: Option<ConcreteLayoutElement::ConcreteLayoutNode>)
+ parent: Option<ConcreteElement::ConcreteNode>)
-> StyleSharingResult;
}
-pub trait MatchMethods<'ln, ConcreteLayoutNode: LayoutNode<'ln>> {
+pub trait MatchMethods<'ln, ConcreteNode: TNode<'ln>> {
/// Inserts and removes the matching `Descendant` selectors from a bloom
/// filter. This is used to speed up CSS selector matching to remove
/// unnecessary tree climbs for `Descendant` queries.
@@ -396,7 +397,7 @@ pub trait MatchMethods<'ln, ConcreteLayoutNode: LayoutNode<'ln>> {
unsafe fn cascade_node(&self,
layout_context: &SharedLayoutContext,
- parent: Option<ConcreteLayoutNode>,
+ parent: Option<ConcreteNode>,
applicable_declarations: &ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
new_animations_sender: &Mutex<Sender<Animation>>);
@@ -420,15 +421,15 @@ trait PrivateMatchMethods {
-> bool;
}
-trait PrivateElementMatchMethods<'le, ConcreteLayoutElement: LayoutElement<'le>> {
+trait PrivateElementMatchMethods<'le, ConcreteElement: TElement<'le>> {
fn share_style_with_candidate_if_possible(&self,
- parent_node: Option<ConcreteLayoutElement::ConcreteLayoutNode>,
+ parent_node: Option<ConcreteElement::ConcreteNode>,
candidate: &StyleSharingCandidate)
-> Option<Arc<ComputedValues>>;
}
-impl<'ln, ConcreteLayoutNode> PrivateMatchMethods for ConcreteLayoutNode
- where ConcreteLayoutNode: LayoutNode<'ln> {
+impl<'ln, ConcreteNode> PrivateMatchMethods for ConcreteNode
+ where ConcreteNode: TNode<'ln> {
fn cascade_node_pseudo_element(&self,
layout_context: &SharedLayoutContext,
parent_style: Option<&Arc<ComputedValues>>,
@@ -547,11 +548,11 @@ impl<'ln, ConcreteLayoutNode> PrivateMatchMethods for ConcreteLayoutNode
}
}
-impl<'le, ConcreteLayoutElement> PrivateElementMatchMethods<'le, ConcreteLayoutElement>
- for ConcreteLayoutElement
- where ConcreteLayoutElement: LayoutElement<'le> {
+impl<'le, ConcreteElement> PrivateElementMatchMethods<'le, ConcreteElement>
+ for ConcreteElement
+ where ConcreteElement: TElement<'le> {
fn share_style_with_candidate_if_possible(&self,
- parent_node: Option<ConcreteLayoutElement::ConcreteLayoutNode>,
+ parent_node: Option<ConcreteElement::ConcreteNode>,
candidate: &StyleSharingCandidate)
-> Option<Arc<ComputedValues>> {
let parent_node = match parent_node {
@@ -559,13 +560,13 @@ impl<'le, ConcreteLayoutElement> PrivateElementMatchMethods<'le, ConcreteLayoutE
Some(_) | None => return None,
};
- let parent_layout_data: &Option<LayoutDataWrapper> = unsafe {
- &*parent_node.borrow_layout_data_unchecked()
+ let parent_data: Option<&PrivateStyleData> = unsafe {
+ parent_node.borrow_data_unchecked().map(|d| &*d)
};
- match *parent_layout_data {
- Some(ref parent_layout_data_ref) => {
+ match parent_data {
+ Some(parent_data_ref) => {
// Check parent style.
- let parent_style = parent_layout_data_ref.shared_data.style.as_ref().unwrap();
+ let parent_style = (*parent_data_ref).style.as_ref().unwrap();
if !arc_ptr_eq(parent_style, &candidate.parent_style) {
return None
}
@@ -584,9 +585,9 @@ impl<'le, ConcreteLayoutElement> PrivateElementMatchMethods<'le, ConcreteLayoutE
}
}
-impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
- for ConcreteLayoutElement
- where ConcreteLayoutElement: LayoutElement<'le> {
+impl<'le, ConcreteElement> ElementMatchMethods<'le, ConcreteElement>
+ for ConcreteElement
+ where ConcreteElement: TElement<'le> {
fn match_element(&self,
stylist: &Stylist,
parent_bf: Option<&BloomFilter>,
@@ -619,7 +620,7 @@ impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
unsafe fn share_style_if_possible(&self,
style_sharing_candidate_cache:
&mut StyleSharingCandidateCache,
- parent: Option<ConcreteLayoutElement::ConcreteLayoutNode>)
+ parent: Option<ConcreteElement::ConcreteNode>)
-> StyleSharingResult {
if opts::get().disable_share_style_cache {
return StyleSharingResult::CannotShare
@@ -637,9 +638,7 @@ impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
Some(shared_style) => {
// Yay, cache hit. Share the style.
let node = self.as_node();
- let mut layout_data_ref = node.mutate_layout_data();
- let shared_data = &mut layout_data_ref.as_mut().unwrap().shared_data;
- let style = &mut shared_data.style;
+ let style = &mut node.mutate_data().unwrap().style;
let damage = incremental::compute_damage(style, &*shared_style);
*style = Some(shared_style);
return StyleSharingResult::StyleWasShared(i, damage)
@@ -652,9 +651,9 @@ impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
}
}
-impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode>
- for ConcreteLayoutNode
- where ConcreteLayoutNode: LayoutNode<'ln> {
+impl<'ln, ConcreteNode> MatchMethods<'ln, ConcreteNode>
+ for ConcreteNode
+ where ConcreteNode: TNode<'ln> {
// The below two functions are copy+paste because I can't figure out how to
// write a function which takes a generic function. I don't think it can
// be done.
@@ -696,7 +695,7 @@ impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode>
unsafe fn cascade_node(&self,
layout_context: &SharedLayoutContext,
- parent: Option<ConcreteLayoutNode>,
+ parent: Option<ConcreteNode>,
applicable_declarations: &ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
new_animations_sender: &Mutex<Sender<Animation>>) {
@@ -708,63 +707,57 @@ impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode>
let parent_style = match parent {
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_style = (*parent_node.borrow_data_unchecked().unwrap()).style.as_ref().unwrap();
Some(parent_style)
}
};
- let mut layout_data_ref = self.mutate_layout_data();
- match *layout_data_ref {
- None => panic!("no layout data"),
- Some(ref mut layout_data) => {
- if self.is_text_node() {
- // Text nodes get a copy of the parent style. This ensures
- // that during fragment construction any non-inherited
- // CSS properties (such as vertical-align) are correctly
- // set on the fragment(s).
- let cloned_parent_style = parent_style.unwrap().clone();
- layout_data.shared_data.style = Some(cloned_parent_style);
- } else {
- let mut damage = self.cascade_node_pseudo_element(
- layout_context,
- parent_style,
- &applicable_declarations.normal,
- &mut layout_data.shared_data.style,
- applicable_declarations_cache,
- new_animations_sender,
- applicable_declarations.normal_shareable,
- true);
- if !applicable_declarations.before.is_empty() {
- damage = damage | self.cascade_node_pseudo_element(
- layout_context,
- Some(layout_data.shared_data.style.as_ref().unwrap()),
- &*applicable_declarations.before,
- &mut layout_data.data.before_style,
- applicable_declarations_cache,
- new_animations_sender,
- false,
- false);
- }
- if !applicable_declarations.after.is_empty() {
- damage = damage | self.cascade_node_pseudo_element(
- layout_context,
- Some(layout_data.shared_data.style.as_ref().unwrap()),
- &*applicable_declarations.after,
- &mut layout_data.data.after_style,
- applicable_declarations_cache,
- new_animations_sender,
- false,
- false);
- }
- layout_data.data.restyle_damage = damage;
- }
+ let mut data_ref = self.mutate_data().unwrap();
+ let mut data = &mut *data_ref;
+ if self.is_text_node() {
+ // Text nodes get a copy of the parent style. This ensures
+ // that during fragment construction any non-inherited
+ // CSS properties (such as vertical-align) are correctly
+ // set on the fragment(s).
+ let cloned_parent_style = parent_style.unwrap().clone();
+ data.style = Some(cloned_parent_style);
+ } else {
+ let mut damage = self.cascade_node_pseudo_element(
+ layout_context,
+ parent_style,
+ &applicable_declarations.normal,
+ &mut data.style,
+ applicable_declarations_cache,
+ new_animations_sender,
+ applicable_declarations.normal_shareable,
+ true);
+ if !applicable_declarations.before.is_empty() {
+ damage = damage | self.cascade_node_pseudo_element(
+ layout_context,
+ Some(data.style.as_ref().unwrap()),
+ &*applicable_declarations.before,
+ &mut data.before_style,
+ applicable_declarations_cache,
+ new_animations_sender,
+ false,
+ false);
}
+ if !applicable_declarations.after.is_empty() {
+ damage = damage | self.cascade_node_pseudo_element(
+ layout_context,
+ Some(data.style.as_ref().unwrap()),
+ &*applicable_declarations.after,
+ &mut data.after_style,
+ applicable_declarations_cache,
+ new_animations_sender,
+ false,
+ false);
+ }
+
+ // FIXME(bholley): This is the only dependency in this file on non-style
+ // stuff.
+ let layout_data: &mut PrivateLayoutData = transmute(data);
+ layout_data.restyle_damage = damage;
}
}
}