mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Refactor style to be completely backend-independent
This commit refactors the style crate to be completely independent of the actual implementation and pseudo-elements supported. This also adds a gecko backend which introduces parsing for the anonymous box pseudo-elements[1], although there's still no way of querying them. https://mxr.mozilla.org/mozilla-central/source/layout/style/nsCSSAnonBoxList.h
This commit is contained in:
parent
a164176876
commit
dd503dfacb
41 changed files with 767 additions and 310 deletions
|
@ -9,13 +9,14 @@ use context::SharedStyleContext;
|
|||
use data::PrivateStyleData;
|
||||
use dom::{TElement, TNode, TRestyleDamage};
|
||||
use properties::{ComputedValues, PropertyDeclaration, cascade};
|
||||
use selector_impl::{NonTSPseudoClass, PseudoElement};
|
||||
use selector_impl::SelectorImplExt;
|
||||
use selector_matching::{DeclarationBlock, Stylist};
|
||||
use selectors::Element;
|
||||
use selectors::bloom::BloomFilter;
|
||||
use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes};
|
||||
use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::slice::Iter;
|
||||
use std::sync::mpsc::Sender;
|
||||
|
@ -51,23 +52,27 @@ fn create_common_style_affecting_attributes_from_element<'le, E: TElement<'le>>(
|
|||
flags
|
||||
}
|
||||
|
||||
pub struct ApplicableDeclarations {
|
||||
pub struct ApplicableDeclarations<Impl: SelectorImplExt> {
|
||||
pub normal: SmallVec<[DeclarationBlock; 16]>,
|
||||
pub before: Vec<DeclarationBlock>,
|
||||
pub after: Vec<DeclarationBlock>,
|
||||
pub per_pseudo: HashMap<Impl::PseudoElement, Vec<DeclarationBlock>>,
|
||||
|
||||
/// Whether the `normal` declarations are shareable with other nodes.
|
||||
pub normal_shareable: bool,
|
||||
}
|
||||
|
||||
impl ApplicableDeclarations {
|
||||
pub fn new() -> ApplicableDeclarations {
|
||||
ApplicableDeclarations {
|
||||
impl<Impl: SelectorImplExt> ApplicableDeclarations<Impl> {
|
||||
pub fn new() -> ApplicableDeclarations<Impl> {
|
||||
let mut applicable_declarations = ApplicableDeclarations {
|
||||
normal: SmallVec::new(),
|
||||
before: Vec::new(),
|
||||
after: Vec::new(),
|
||||
per_pseudo: HashMap::new(),
|
||||
normal_shareable: false,
|
||||
}
|
||||
};
|
||||
|
||||
Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
||||
applicable_declarations.per_pseudo.insert(pseudo, vec![]);
|
||||
});
|
||||
|
||||
applicable_declarations
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +251,7 @@ impl StyleSharingCandidate {
|
|||
local_name: element.get_local_name().clone(),
|
||||
class: element.get_attr(&ns!(), &atom!("class"))
|
||||
.map(|string| string.to_owned()),
|
||||
link: element.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink),
|
||||
link: element.is_link(),
|
||||
namespace: (*element.get_namespace()).clone(),
|
||||
common_style_affecting_attributes:
|
||||
create_common_style_affecting_attributes_from_element::<'le, E>(&element)
|
||||
|
@ -314,7 +319,7 @@ impl StyleSharingCandidate {
|
|||
}
|
||||
}
|
||||
|
||||
if element.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink) != self.link {
|
||||
if element.is_link() != self.link {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -359,9 +364,10 @@ pub enum StyleSharingResult<ConcreteRestyleDamage: TRestyleDamage> {
|
|||
StyleWasShared(usize, ConcreteRestyleDamage),
|
||||
}
|
||||
|
||||
trait PrivateMatchMethods<'ln>: TNode<'ln> {
|
||||
trait PrivateMatchMethods<'ln>: TNode<'ln>
|
||||
where <Self::ConcreteElement as Element>::Impl: SelectorImplExt {
|
||||
fn cascade_node_pseudo_element(&self,
|
||||
context: &SharedStyleContext,
|
||||
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
|
||||
parent_style: Option<&Arc<ComputedValues>>,
|
||||
applicable_declarations: &[DeclarationBlock],
|
||||
style: &mut Option<Arc<ComputedValues>>,
|
||||
|
@ -434,7 +440,7 @@ trait PrivateMatchMethods<'ln>: TNode<'ln> {
|
|||
}
|
||||
|
||||
fn update_animations_for_cascade(&self,
|
||||
context: &SharedStyleContext,
|
||||
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
|
||||
style: &mut Option<Arc<ComputedValues>>)
|
||||
-> bool {
|
||||
let style = match *style {
|
||||
|
@ -478,7 +484,8 @@ trait PrivateMatchMethods<'ln>: TNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ln, N: TNode<'ln>> PrivateMatchMethods<'ln> for N {}
|
||||
impl<'ln, N: TNode<'ln>> PrivateMatchMethods<'ln> for N
|
||||
where <N::ConcreteElement as Element>::Impl: SelectorImplExt {}
|
||||
|
||||
trait PrivateElementMatchMethods<'le>: TElement<'le> {
|
||||
fn share_style_with_candidate_if_possible(&self,
|
||||
|
@ -490,7 +497,7 @@ trait PrivateElementMatchMethods<'le>: TElement<'le> {
|
|||
Some(_) | None => return None,
|
||||
};
|
||||
|
||||
let parent_data: Option<&PrivateStyleData> = unsafe {
|
||||
let parent_data: Option<&PrivateStyleData<_>> = unsafe {
|
||||
parent_node.borrow_data_unchecked().map(|d| &*d)
|
||||
};
|
||||
|
||||
|
@ -512,11 +519,12 @@ trait PrivateElementMatchMethods<'le>: TElement<'le> {
|
|||
|
||||
impl<'le, E: TElement<'le>> PrivateElementMatchMethods<'le> for E {}
|
||||
|
||||
pub trait ElementMatchMethods<'le> : TElement<'le> {
|
||||
pub trait ElementMatchMethods<'le> : TElement<'le>
|
||||
where Self::Impl: SelectorImplExt {
|
||||
fn match_element(&self,
|
||||
stylist: &Stylist,
|
||||
stylist: &Stylist<Self::Impl>,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
applicable_declarations: &mut ApplicableDeclarations)
|
||||
applicable_declarations: &mut ApplicableDeclarations<Self::Impl>)
|
||||
-> bool {
|
||||
let style_attribute = self.style_attribute().as_ref();
|
||||
|
||||
|
@ -526,20 +534,16 @@ pub trait ElementMatchMethods<'le> : TElement<'le> {
|
|||
style_attribute,
|
||||
None,
|
||||
&mut applicable_declarations.normal);
|
||||
stylist.push_applicable_declarations(self,
|
||||
parent_bf,
|
||||
None,
|
||||
Some(PseudoElement::Before),
|
||||
&mut applicable_declarations.before);
|
||||
stylist.push_applicable_declarations(self,
|
||||
parent_bf,
|
||||
None,
|
||||
Some(PseudoElement::After),
|
||||
&mut applicable_declarations.after);
|
||||
Self::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
||||
stylist.push_applicable_declarations(self,
|
||||
parent_bf,
|
||||
None,
|
||||
Some(pseudo.clone()),
|
||||
applicable_declarations.per_pseudo.entry(pseudo).or_insert(vec![]));
|
||||
});
|
||||
|
||||
applicable_declarations.normal_shareable &&
|
||||
applicable_declarations.before.is_empty() &&
|
||||
applicable_declarations.after.is_empty()
|
||||
applicable_declarations.per_pseudo.values().all(|v| v.is_empty())
|
||||
}
|
||||
|
||||
/// Attempts to share a style with another node. This method is unsafe because it depends on
|
||||
|
@ -580,7 +584,8 @@ pub trait ElementMatchMethods<'le> : TElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'le, E: TElement<'le>> ElementMatchMethods<'le> for E {}
|
||||
impl<'le, E: TElement<'le>> ElementMatchMethods<'le> for E
|
||||
where E::Impl: SelectorImplExt {}
|
||||
|
||||
pub trait MatchMethods<'ln> : TNode<'ln> {
|
||||
// The below two functions are copy+paste because I can't figure out how to
|
||||
|
@ -632,11 +637,12 @@ pub trait MatchMethods<'ln> : TNode<'ln> {
|
|||
}
|
||||
|
||||
unsafe fn cascade_node(&self,
|
||||
context: &SharedStyleContext,
|
||||
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
|
||||
parent: Option<Self>,
|
||||
applicable_declarations: &ApplicableDeclarations,
|
||||
applicable_declarations: &ApplicableDeclarations<<Self::ConcreteElement as Element>::Impl>,
|
||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
|
||||
new_animations_sender: &Mutex<Sender<Animation>>) {
|
||||
new_animations_sender: &Mutex<Sender<Animation>>)
|
||||
where <Self::ConcreteElement as Element>::Impl: SelectorImplExt {
|
||||
// Get our parent's style. This must be unsafe so that we don't touch the parent's
|
||||
// borrow flags.
|
||||
//
|
||||
|
@ -673,28 +679,24 @@ pub trait MatchMethods<'ln> : TNode<'ln> {
|
|||
new_animations_sender,
|
||||
applicable_declarations.normal_shareable,
|
||||
true);
|
||||
if !applicable_declarations.before.is_empty() {
|
||||
damage = damage | self.cascade_node_pseudo_element(
|
||||
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(
|
||||
context,
|
||||
Some(data.style.as_ref().unwrap()),
|
||||
&*applicable_declarations.after,
|
||||
&mut data.after_style,
|
||||
applicable_declarations_cache,
|
||||
new_animations_sender,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
<Self::ConcreteElement as Element>::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
||||
let applicable_declarations_for_this_pseudo =
|
||||
applicable_declarations.per_pseudo.get(&pseudo).unwrap();
|
||||
|
||||
|
||||
if !applicable_declarations_for_this_pseudo.is_empty() {
|
||||
damage = damage | self.cascade_node_pseudo_element(
|
||||
context,
|
||||
Some(data.style.as_ref().unwrap()),
|
||||
&*applicable_declarations_for_this_pseudo,
|
||||
data.per_pseudo.entry(pseudo).or_insert(None),
|
||||
applicable_declarations_cache,
|
||||
new_animations_sender,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// This method needs to borrow the data as mutable, so make sure data_ref goes out of
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue