mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
style: Allow inheritance when computing anonymous box styles
This is used a lot by Gecko, not still for servo though.
This commit is contained in:
parent
3563ecb770
commit
5a43c7e3cd
4 changed files with 56 additions and 31 deletions
|
@ -738,8 +738,8 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
|
|||
self.borrow_layout_data().unwrap()
|
||||
.style_data
|
||||
.precomputed
|
||||
.non_eagerly_cascaded_pseudo_elements
|
||||
.get(&PseudoElement::DetailsContent)
|
||||
.computed_values_for(&PseudoElement::DetailsContent,
|
||||
Some(&*self.style()))
|
||||
.map(|style| {
|
||||
let display = if element.get_attr(&ns!(), &atom!("open")).is_some() {
|
||||
style.get_box().display
|
||||
|
@ -768,6 +768,22 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
|
|||
/// Unlike the version on TNode, this handles pseudo-elements.
|
||||
#[inline]
|
||||
fn style(&self) -> Ref<Arc<ServoComputedValues>> {
|
||||
// Precompute anonymous-box pseudo-element style if not cached.
|
||||
match self.get_pseudo_element_type() {
|
||||
PseudoElementType::DetailsContent(_) => {
|
||||
if self.borrow_layout_data().unwrap()
|
||||
.style_data.per_pseudo.get(&PseudoElement::DetailsContent).is_none() {
|
||||
let mut data = self.mutate_layout_data().unwrap();
|
||||
let new_style = data.style_data
|
||||
.precomputed
|
||||
.computed_values_for(&PseudoElement::DetailsContent,
|
||||
data.style_data.style.as_ref());
|
||||
data.style_data.per_pseudo.insert(PseudoElement::DetailsContent, new_style.unwrap());
|
||||
}
|
||||
}
|
||||
_ => {},
|
||||
};
|
||||
|
||||
Ref::map(self.borrow_layout_data().unwrap(), |data| {
|
||||
let style = match self.get_pseudo_element_type() {
|
||||
PseudoElementType::Before(_)
|
||||
|
@ -777,10 +793,7 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
|
|||
PseudoElementType::DetailsSummary(_)
|
||||
=> data.style_data.per_pseudo.get(&PseudoElement::DetailsSummary),
|
||||
PseudoElementType::DetailsContent(_)
|
||||
=> data.style_data
|
||||
.precomputed
|
||||
.non_eagerly_cascaded_pseudo_elements
|
||||
.get(&PseudoElement::DetailsContent),
|
||||
=> data.style_data.per_pseudo.get(&PseudoElement::DetailsContent),
|
||||
PseudoElementType::Normal
|
||||
=> data.style_data.style.as_ref(),
|
||||
};
|
||||
|
@ -791,7 +804,9 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
|
|||
#[inline]
|
||||
fn selected_style(&self) -> Ref<Arc<ServoComputedValues>> {
|
||||
Ref::map(self.borrow_layout_data().unwrap(), |data| {
|
||||
data.style_data.per_pseudo.get(&PseudoElement::Selection).unwrap_or(data.style_data.style.as_ref().unwrap())
|
||||
data.style_data.per_pseudo
|
||||
.get(&PseudoElement::Selection)
|
||||
.unwrap_or(data.style_data.style.as_ref().unwrap())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -814,7 +829,6 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
|
|||
PseudoElementType::DetailsContent(_) => {
|
||||
data.style_data.per_pseudo.remove(&PseudoElement::DetailsContent);
|
||||
}
|
||||
|
||||
PseudoElementType::Normal => {
|
||||
data.style_data.style = None;
|
||||
}
|
||||
|
|
|
@ -65,4 +65,3 @@ pub enum ReflowGoal {
|
|||
/// We're reflowing in order to satisfy a script query. No display list will be created.
|
||||
ForScriptQuery,
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,10 @@ pub struct PrivateStyleData<Impl: SelectorImpl, ConcreteComputedValues: Computed
|
|||
/// The results of CSS styling for this node.
|
||||
pub style: Option<Arc<ConcreteComputedValues>>,
|
||||
|
||||
/// Precomputed data needed to avoid doing the cascade for some
|
||||
/// Shared rules data needed to avoid doing the cascade for some
|
||||
/// pseudo-elements like "-servo-details-content"
|
||||
///
|
||||
/// TODO: Move to TLS to avoid this extra pointer?
|
||||
pub precomputed: Arc<PrecomputedStyleData<Impl, ConcreteComputedValues>>,
|
||||
|
||||
/// The results of CSS styling for each pseudo-element (if any).
|
||||
|
|
|
@ -86,12 +86,13 @@ lazy_static! {
|
|||
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct PrecomputedStyleData<Impl: SelectorImpl, Computed: ComputedValues> {
|
||||
/// Computed values for a given non-eagerly cascaded pseudo-element. These
|
||||
/// are eagerly computed once, and then just looked up in the table,
|
||||
/// since they only appear in rules of the form *|*::pseudo-element
|
||||
pub non_eagerly_cascaded_pseudo_elements: HashMap<Impl::PseudoElement,
|
||||
Arc<Computed>,
|
||||
BuildHasherDefault<::fnv::FnvHasher>>,
|
||||
/// Applicable declarations for a given non-eagerly cascaded pseudo-element.
|
||||
/// These are eagerly computed once, and then used to resolve the new
|
||||
/// computed values on the fly on layout.
|
||||
non_eagerly_cascaded_pseudo_elements: HashMap<Impl::PseudoElement,
|
||||
Vec<DeclarationBlock>,
|
||||
BuildHasherDefault<::fnv::FnvHasher>>,
|
||||
_phantom: ::std::marker::PhantomData<Computed>,
|
||||
}
|
||||
|
||||
impl<Impl, Computed> PrecomputedStyleData<Impl, Computed>
|
||||
|
@ -99,6 +100,22 @@ impl<Impl, Computed> PrecomputedStyleData<Impl, Computed>
|
|||
fn new() -> Self {
|
||||
PrecomputedStyleData {
|
||||
non_eagerly_cascaded_pseudo_elements: HashMap::with_hasher(Default::default()),
|
||||
_phantom: ::std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn computed_values_for(&self,
|
||||
pseudo: &Impl::PseudoElement,
|
||||
parent: Option<&Arc<Computed>>) -> Option<Arc<Computed>> {
|
||||
if let Some(declarations) = self.non_eagerly_cascaded_pseudo_elements.get(pseudo) {
|
||||
let (computed, _) =
|
||||
properties::cascade::<Computed>(Size2D::zero(),
|
||||
&declarations, false,
|
||||
parent.map(|p| &**p), None,
|
||||
box StdoutErrorReporter);
|
||||
Some(Arc::new(computed))
|
||||
} else {
|
||||
parent.map(|p| p.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -256,28 +273,21 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
|
|||
self.rules_source_order = rules_source_order;
|
||||
|
||||
Impl::each_non_eagerly_cascaded_pseudo_element(|pseudo| {
|
||||
// TODO: Don't precompute this, and compute it on demand instead
|
||||
// TODO: Don't precompute this, compute it on demand instead and
|
||||
// cache it.
|
||||
//
|
||||
// This is actually kind of hard, because the stylist is shared
|
||||
// between threads.
|
||||
//
|
||||
if let Some(map) = self.pseudos_map.get(&pseudo) {
|
||||
if let Some(map) = self.pseudos_map.remove(&pseudo) {
|
||||
let mut precomputed = Arc::get_mut(&mut self.precomputed)
|
||||
.expect("Stylist was not the single owner of PrecomputedStyleData");
|
||||
|
||||
let mut declarations = vec![];
|
||||
|
||||
map.user_agent.normal.get_universal_rules(&mut declarations);
|
||||
|
||||
map.user_agent.important.get_universal_rules(&mut declarations);
|
||||
|
||||
// NB: Viewport size shouldn't matter since these rules should
|
||||
// be absolute.
|
||||
let (computed, _) =
|
||||
properties::cascade::<Impl::ComputedValues>(Size2D::zero(),
|
||||
&declarations, false,
|
||||
None, None,
|
||||
box StdoutErrorReporter);
|
||||
precomputed.non_eagerly_cascaded_pseudo_elements.insert(pseudo, Arc::new(computed));
|
||||
precomputed.non_eagerly_cascaded_pseudo_elements.insert(pseudo, declarations);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -287,11 +297,11 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
|
|||
}
|
||||
|
||||
pub fn get_non_eagerly_cascaded_pseudo_element_style(&self,
|
||||
pseudo: &Impl::PseudoElement) -> Option<Arc<Impl::ComputedValues>> {
|
||||
pseudo: &Impl::PseudoElement,
|
||||
parent: Option<&Arc<Impl::ComputedValues>>) -> Option<Arc<Impl::ComputedValues>> {
|
||||
debug_assert!(!Impl::is_eagerly_cascaded_pseudo_element(pseudo));
|
||||
self.precomputed
|
||||
.non_eagerly_cascaded_pseudo_elements
|
||||
.get(pseudo).map(|computed| computed.clone())
|
||||
.computed_values_for(pseudo, parent)
|
||||
}
|
||||
|
||||
pub fn compute_restyle_hint<E>(&self, element: &E,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue