mirror of
https://github.com/servo/servo.git
synced 2025-07-23 23:33:43 +01:00
Add some wrapper types to propagate styles out of style resolver.
We'll use these next to propagate information about style reuse to the ElementDataFlags. MozReview-Commit-ID: Dya6vgzydpL
This commit is contained in:
parent
9092e6b4c2
commit
7a7070e075
5 changed files with 118 additions and 57 deletions
|
@ -17,7 +17,9 @@ use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use shared_lock::StylesheetGuards;
|
use shared_lock::StylesheetGuards;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use style_resolver::{PrimaryStyle, ResolvedElementStyles, ResolvedStyle};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -264,6 +266,24 @@ impl ElementData {
|
||||||
self.styles.primary.is_some()
|
self.styles.primary.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns this element's styles as resolved styles to use for sharing.
|
||||||
|
pub fn share_styles(&self) -> ResolvedElementStyles {
|
||||||
|
ResolvedElementStyles {
|
||||||
|
primary: self.share_primary_style(),
|
||||||
|
pseudos: self.styles.pseudos.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns this element's primary style as a resolved style to use for sharing.
|
||||||
|
pub fn share_primary_style(&self) -> PrimaryStyle {
|
||||||
|
PrimaryStyle(ResolvedStyle::new(self.styles.primary().clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets a new set of styles, returning the old ones.
|
||||||
|
pub fn set_styles(&mut self, new_styles: ResolvedElementStyles) -> ElementStyles {
|
||||||
|
mem::replace(&mut self.styles, new_styles.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the kind of restyling that we're going to need to do on this
|
/// Returns the kind of restyling that we're going to need to do on this
|
||||||
/// element, based of the stored restyle hint.
|
/// element, based of the stored restyle hint.
|
||||||
pub fn restyle_kind(
|
pub fn restyle_kind(
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use context::{ElementCascadeInputs, SelectorFlagsMap, SharedStyleContext, StyleContext};
|
use context::{ElementCascadeInputs, SelectorFlagsMap, SharedStyleContext, StyleContext};
|
||||||
use data::{ElementData, ElementStyles};
|
use data::ElementData;
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS};
|
use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS};
|
||||||
use invalidation::element::restyle_hints::{RESTYLE_SMIL, RESTYLE_STYLE_ATTRIBUTE};
|
use invalidation::element::restyle_hints::{RESTYLE_SMIL, RESTYLE_STYLE_ATTRIBUTE};
|
||||||
|
@ -18,6 +18,7 @@ use rule_tree::{CascadeLevel, StrongRuleNode};
|
||||||
use selector_parser::{PseudoElement, RestyleDamage};
|
use selector_parser::{PseudoElement, RestyleDamage};
|
||||||
use selectors::matching::ElementSelectorFlags;
|
use selectors::matching::ElementSelectorFlags;
|
||||||
use servo_arc::{Arc, ArcBorrow};
|
use servo_arc::{Arc, ArcBorrow};
|
||||||
|
use style_resolver::ResolvedElementStyles;
|
||||||
use traversal_flags;
|
use traversal_flags;
|
||||||
|
|
||||||
/// Represents the result of comparing an element's old and new style.
|
/// Represents the result of comparing an element's old and new style.
|
||||||
|
@ -156,7 +157,7 @@ trait PrivateMatchMethods: TElement {
|
||||||
StyleResolverForElement::new(*self, context, RuleInclusion::All, PseudoElementResolution::IfApplicable)
|
StyleResolverForElement::new(*self, context, RuleInclusion::All, PseudoElementResolution::IfApplicable)
|
||||||
.cascade_style_and_visited_with_default_parents(inputs);
|
.cascade_style_and_visited_with_default_parents(inputs);
|
||||||
|
|
||||||
Some(style)
|
Some(style.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
@ -530,26 +531,23 @@ pub trait MatchMethods : TElement {
|
||||||
&self,
|
&self,
|
||||||
context: &mut StyleContext<Self>,
|
context: &mut StyleContext<Self>,
|
||||||
data: &mut ElementData,
|
data: &mut ElementData,
|
||||||
mut new_styles: ElementStyles,
|
mut new_styles: ResolvedElementStyles,
|
||||||
important_rules_changed: bool,
|
important_rules_changed: bool,
|
||||||
) -> ChildCascadeRequirement {
|
) -> ChildCascadeRequirement {
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use dom::TNode;
|
use dom::TNode;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
debug_assert!(new_styles.primary.is_some(), "How did that happen?");
|
|
||||||
|
|
||||||
self.process_animations(
|
self.process_animations(
|
||||||
context,
|
context,
|
||||||
&mut data.styles.primary,
|
&mut data.styles.primary,
|
||||||
&mut new_styles.primary.as_mut().unwrap(),
|
&mut new_styles.primary.0.style,
|
||||||
data.hint,
|
data.hint,
|
||||||
important_rules_changed,
|
important_rules_changed,
|
||||||
);
|
);
|
||||||
|
|
||||||
// First of all, update the styles.
|
// First of all, update the styles.
|
||||||
let old_styles = mem::replace(&mut data.styles, new_styles);
|
let old_styles = data.set_styles(new_styles);
|
||||||
|
|
||||||
// Propagate the "can be fragmented" bit. It would be nice to
|
// Propagate the "can be fragmented" bit. It would be nice to
|
||||||
// encapsulate this better.
|
// encapsulate this better.
|
||||||
|
|
|
@ -49,12 +49,52 @@ struct MatchingResults {
|
||||||
relevant_link_found: bool,
|
relevant_link_found: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The primary style of an element or an element-backed pseudo-element.
|
/// A style returned from the resolver machinery.
|
||||||
pub struct PrimaryStyle {
|
pub struct ResolvedStyle {
|
||||||
/// The style per se.
|
/// The style itself.
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The primary style of an element or an element-backed pseudo-element.
|
||||||
|
pub struct PrimaryStyle(pub ResolvedStyle);
|
||||||
|
|
||||||
|
/// A set of style returned from the resolver machinery.
|
||||||
|
pub struct ResolvedElementStyles {
|
||||||
|
/// Primary style.
|
||||||
|
pub primary: PrimaryStyle,
|
||||||
|
/// Pseudo styles.
|
||||||
|
pub pseudos: EagerPseudoStyles,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResolvedStyle {
|
||||||
|
/// Creates a new ResolvedStyle.
|
||||||
|
pub fn new(style: Arc<ComputedValues>) -> Self {
|
||||||
|
ResolvedStyle { style }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimaryStyle {
|
||||||
|
/// Convenience accessor for the style.
|
||||||
|
pub fn style(&self) -> &ComputedValues {
|
||||||
|
&*self.0.style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ResolvedStyle> for Arc<ComputedValues> {
|
||||||
|
fn from(r: ResolvedStyle) -> Arc<ComputedValues> {
|
||||||
|
r.style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ResolvedElementStyles> for ElementStyles {
|
||||||
|
fn from(r: ResolvedElementStyles) -> ElementStyles {
|
||||||
|
ElementStyles {
|
||||||
|
primary: Some(r.primary.0.into()),
|
||||||
|
pseudos: r.pseudos,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn with_default_parent_styles<E, F, R>(element: E, f: F) -> R
|
fn with_default_parent_styles<E, F, R>(element: E, f: F) -> R
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
|
@ -140,8 +180,8 @@ where
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
PrimaryStyle {
|
PrimaryStyle(
|
||||||
style: self.cascade_style_and_visited(
|
self.cascade_style_and_visited(
|
||||||
CascadeInputs {
|
CascadeInputs {
|
||||||
rules: Some(primary_results.rule_node),
|
rules: Some(primary_results.rule_node),
|
||||||
visited_rules,
|
visited_rules,
|
||||||
|
@ -149,8 +189,8 @@ where
|
||||||
parent_style,
|
parent_style,
|
||||||
layout_parent_style,
|
layout_parent_style,
|
||||||
/* pseudo = */ None,
|
/* pseudo = */ None,
|
||||||
),
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve the style of a given element, and all its eager pseudo-elements.
|
/// Resolve the style of a given element, and all its eager pseudo-elements.
|
||||||
|
@ -158,7 +198,7 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
parent_style: Option<&ComputedValues>,
|
parent_style: Option<&ComputedValues>,
|
||||||
layout_parent_style: Option<&ComputedValues>,
|
layout_parent_style: Option<&ComputedValues>,
|
||||||
) -> ElementStyles {
|
) -> ResolvedElementStyles {
|
||||||
let primary_style =
|
let primary_style =
|
||||||
self.resolve_primary_style(parent_style, layout_parent_style);
|
self.resolve_primary_style(parent_style, layout_parent_style);
|
||||||
|
|
||||||
|
@ -166,10 +206,10 @@ where
|
||||||
|
|
||||||
if self.element.implemented_pseudo_element().is_none() {
|
if self.element.implemented_pseudo_element().is_none() {
|
||||||
let layout_parent_style_for_pseudo =
|
let layout_parent_style_for_pseudo =
|
||||||
if primary_style.style.is_display_contents() {
|
if primary_style.style().is_display_contents() {
|
||||||
layout_parent_style
|
layout_parent_style
|
||||||
} else {
|
} else {
|
||||||
Some(&*primary_style.style)
|
Some(primary_style.style())
|
||||||
};
|
};
|
||||||
SelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
SelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
|
||||||
let pseudo_style = self.resolve_pseudo_style(
|
let pseudo_style = self.resolve_pseudo_style(
|
||||||
|
@ -188,16 +228,15 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementStyles {
|
ResolvedElementStyles {
|
||||||
// FIXME(emilio): Remove the Option<>.
|
primary: primary_style,
|
||||||
primary: Some(primary_style.style),
|
|
||||||
pseudos: pseudo_styles,
|
pseudos: pseudo_styles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve an element's styles with the default inheritance parent/layout
|
/// Resolve an element's styles with the default inheritance parent/layout
|
||||||
/// parents.
|
/// parents.
|
||||||
pub fn resolve_style_with_default_parents(&mut self) -> ElementStyles {
|
pub fn resolve_style_with_default_parents(&mut self) -> ResolvedElementStyles {
|
||||||
with_default_parent_styles(self.element, |parent_style, layout_parent_style| {
|
with_default_parent_styles(self.element, |parent_style, layout_parent_style| {
|
||||||
self.resolve_style(parent_style, layout_parent_style)
|
self.resolve_style(parent_style, layout_parent_style)
|
||||||
})
|
})
|
||||||
|
@ -207,7 +246,7 @@ where
|
||||||
pub fn cascade_style_and_visited_with_default_parents(
|
pub fn cascade_style_and_visited_with_default_parents(
|
||||||
&mut self,
|
&mut self,
|
||||||
inputs: CascadeInputs,
|
inputs: CascadeInputs,
|
||||||
) -> Arc<ComputedValues> {
|
) -> ResolvedStyle {
|
||||||
with_default_parent_styles(self.element, |parent_style, layout_parent_style| {
|
with_default_parent_styles(self.element, |parent_style, layout_parent_style| {
|
||||||
self.cascade_style_and_visited(
|
self.cascade_style_and_visited(
|
||||||
inputs,
|
inputs,
|
||||||
|
@ -224,7 +263,7 @@ where
|
||||||
parent_style: Option<&ComputedValues>,
|
parent_style: Option<&ComputedValues>,
|
||||||
layout_parent_style: Option<&ComputedValues>,
|
layout_parent_style: Option<&ComputedValues>,
|
||||||
pseudo: Option<&PseudoElement>,
|
pseudo: Option<&PseudoElement>,
|
||||||
) -> Arc<ComputedValues> {
|
) -> ResolvedStyle {
|
||||||
let mut style_if_visited = None;
|
let mut style_if_visited = None;
|
||||||
if parent_style.map_or(false, |s| s.get_visited_style().is_some()) ||
|
if parent_style.map_or(false, |s| s.get_visited_style().is_some()) ||
|
||||||
inputs.visited_rules.is_some() {
|
inputs.visited_rules.is_some() {
|
||||||
|
@ -237,7 +276,9 @@ where
|
||||||
pseudo,
|
pseudo,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
self.cascade_style(
|
|
||||||
|
ResolvedStyle {
|
||||||
|
style: self.cascade_style(
|
||||||
inputs.rules.as_ref(),
|
inputs.rules.as_ref(),
|
||||||
style_if_visited,
|
style_if_visited,
|
||||||
parent_style,
|
parent_style,
|
||||||
|
@ -246,29 +287,30 @@ where
|
||||||
pseudo,
|
pseudo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Cascade the element and pseudo-element styles with the default parents.
|
/// Cascade the element and pseudo-element styles with the default parents.
|
||||||
pub fn cascade_styles_with_default_parents(
|
pub fn cascade_styles_with_default_parents(
|
||||||
&mut self,
|
&mut self,
|
||||||
inputs: ElementCascadeInputs,
|
inputs: ElementCascadeInputs,
|
||||||
) -> ElementStyles {
|
) -> ResolvedElementStyles {
|
||||||
with_default_parent_styles(self.element, move |parent_style, layout_parent_style| {
|
with_default_parent_styles(self.element, move |parent_style, layout_parent_style| {
|
||||||
let primary_style = PrimaryStyle {
|
let primary_style = PrimaryStyle(
|
||||||
style: self.cascade_style_and_visited(
|
self.cascade_style_and_visited(
|
||||||
inputs.primary,
|
inputs.primary,
|
||||||
parent_style,
|
parent_style,
|
||||||
layout_parent_style,
|
layout_parent_style,
|
||||||
/* pseudo = */ None,
|
/* pseudo = */ None,
|
||||||
),
|
)
|
||||||
};
|
);
|
||||||
|
|
||||||
let mut pseudo_styles = EagerPseudoStyles::default();
|
let mut pseudo_styles = EagerPseudoStyles::default();
|
||||||
if let Some(mut pseudo_array) = inputs.pseudos.into_array() {
|
if let Some(mut pseudo_array) = inputs.pseudos.into_array() {
|
||||||
let layout_parent_style_for_pseudo =
|
let layout_parent_style_for_pseudo =
|
||||||
if primary_style.style.is_display_contents() {
|
if primary_style.style().is_display_contents() {
|
||||||
layout_parent_style
|
layout_parent_style
|
||||||
} else {
|
} else {
|
||||||
Some(&*primary_style.style)
|
Some(primary_style.style())
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, inputs) in pseudo_array.iter_mut().enumerate() {
|
for (i, inputs) in pseudo_array.iter_mut().enumerate() {
|
||||||
|
@ -278,23 +320,23 @@ where
|
||||||
let style =
|
let style =
|
||||||
self.cascade_style_and_visited(
|
self.cascade_style_and_visited(
|
||||||
inputs,
|
inputs,
|
||||||
Some(&*primary_style.style),
|
Some(&*primary_style.style()),
|
||||||
layout_parent_style_for_pseudo,
|
layout_parent_style_for_pseudo,
|
||||||
Some(&pseudo),
|
Some(&pseudo),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !matches!(self.pseudo_resolution, PseudoElementResolution::Force) &&
|
if !matches!(self.pseudo_resolution, PseudoElementResolution::Force) &&
|
||||||
eager_pseudo_is_definitely_not_generated(&pseudo, &style) {
|
eager_pseudo_is_definitely_not_generated(&pseudo, &style.style) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pseudo_styles.set(&pseudo, style);
|
pseudo_styles.set(&pseudo, style.style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementStyles {
|
ResolvedElementStyles {
|
||||||
primary: Some(primary_style.style),
|
primary: primary_style,
|
||||||
pseudos: pseudo_styles,
|
pseudos: pseudo_styles,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -307,7 +349,7 @@ where
|
||||||
layout_parent_style: Option<&ComputedValues>,
|
layout_parent_style: Option<&ComputedValues>,
|
||||||
) -> Option<Arc<ComputedValues>> {
|
) -> Option<Arc<ComputedValues>> {
|
||||||
let rules = self.match_pseudo(
|
let rules = self.match_pseudo(
|
||||||
&originating_element_style.style,
|
originating_element_style.style(),
|
||||||
pseudo,
|
pseudo,
|
||||||
VisitedHandlingMode::AllLinksUnvisited
|
VisitedHandlingMode::AllLinksUnvisited
|
||||||
);
|
);
|
||||||
|
@ -317,9 +359,9 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut visited_rules = None;
|
let mut visited_rules = None;
|
||||||
if originating_element_style.style.get_visited_style().is_some() {
|
if originating_element_style.style().get_visited_style().is_some() {
|
||||||
visited_rules = self.match_pseudo(
|
visited_rules = self.match_pseudo(
|
||||||
&originating_element_style.style,
|
originating_element_style.style(),
|
||||||
pseudo,
|
pseudo,
|
||||||
VisitedHandlingMode::RelevantLinkVisited,
|
VisitedHandlingMode::RelevantLinkVisited,
|
||||||
);
|
);
|
||||||
|
@ -330,10 +372,10 @@ where
|
||||||
rules: Some(rules),
|
rules: Some(rules),
|
||||||
visited_rules
|
visited_rules
|
||||||
},
|
},
|
||||||
Some(&originating_element_style.style),
|
Some(originating_element_style.style()),
|
||||||
layout_parent_style,
|
layout_parent_style,
|
||||||
Some(pseudo),
|
Some(pseudo),
|
||||||
))
|
).style)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_primary(
|
fn match_primary(
|
||||||
|
|
|
@ -419,9 +419,9 @@ where
|
||||||
layout_parent_style.as_ref().map(|s| &**s)
|
layout_parent_style.as_ref().map(|s| &**s)
|
||||||
);
|
);
|
||||||
|
|
||||||
let is_display_contents = primary_style.style.is_display_contents();
|
let is_display_contents = primary_style.style().is_display_contents();
|
||||||
|
|
||||||
style = Some(primary_style.style);
|
style = Some(primary_style.0.into());
|
||||||
if !is_display_contents {
|
if !is_display_contents {
|
||||||
layout_parent_style = style.clone();
|
layout_parent_style = style.clone();
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ where
|
||||||
.resolve_style(
|
.resolve_style(
|
||||||
style.as_ref().map(|s| &**s),
|
style.as_ref().map(|s| &**s),
|
||||||
layout_parent_style.as_ref().map(|s| &**s)
|
layout_parent_style.as_ref().map(|s| &**s)
|
||||||
)
|
).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the style for a single node.
|
/// Calculates the style for a single node.
|
||||||
|
@ -657,8 +657,7 @@ where
|
||||||
match target.share_style_if_possible(context) {
|
match target.share_style_if_possible(context) {
|
||||||
Some(shareable_element) => {
|
Some(shareable_element) => {
|
||||||
context.thread_local.statistics.styles_shared += 1;
|
context.thread_local.statistics.styles_shared += 1;
|
||||||
let shareable_data = shareable_element.borrow_data().unwrap();
|
shareable_element.borrow_data().unwrap().share_styles()
|
||||||
shareable_data.styles.clone()
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
context.thread_local.statistics.elements_matched += 1;
|
context.thread_local.statistics.elements_matched += 1;
|
||||||
|
@ -679,7 +678,7 @@ where
|
||||||
.sharing_cache
|
.sharing_cache
|
||||||
.insert_if_possible(
|
.insert_if_possible(
|
||||||
&element,
|
&element,
|
||||||
new_styles.primary(),
|
new_styles.primary.style(),
|
||||||
&mut target,
|
&mut target,
|
||||||
context.thread_local.bloom_filter.matching_depth(),
|
context.thread_local.bloom_filter.matching_depth(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -727,9 +727,11 @@ pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawSe
|
||||||
};
|
};
|
||||||
|
|
||||||
// Actually `PseudoElementResolution` doesn't matter.
|
// Actually `PseudoElementResolution` doesn't matter.
|
||||||
|
let style: Arc<ComputedValues> =
|
||||||
StyleResolverForElement::new(element, &mut context, RuleInclusion::All, PseudoElementResolution::IfApplicable)
|
StyleResolverForElement::new(element, &mut context, RuleInclusion::All, PseudoElementResolution::IfApplicable)
|
||||||
.cascade_style_and_visited_with_default_parents(inputs)
|
.cascade_style_and_visited_with_default_parents(inputs)
|
||||||
.into()
|
.into();
|
||||||
|
style.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue