layout: Add a new cascading mode that inherits all properties, even

non-inheritable ones.

This works like the `modify_style_for_*` functions and will allow us to
easily migrate from them to real cascading.
This commit is contained in:
Patrick Walton 2016-10-24 18:00:06 -07:00
parent 93e41ba4aa
commit fb2d1e1020
6 changed files with 86 additions and 43 deletions

View file

@ -265,9 +265,10 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
.current_styles().pseudos.contains_key(&style_pseudo) { .current_styles().pseudos.contains_key(&style_pseudo) {
let mut data = self.get_style_data().unwrap().borrow_mut(); let mut data = self.get_style_data().unwrap().borrow_mut();
let new_style = let new_style =
context.stylist context.stylist.precomputed_values_for_pseudo(
.precomputed_values_for_pseudo(&style_pseudo, &style_pseudo,
Some(&data.current_styles().primary)); Some(&data.current_styles().primary),
false);
data.current_pseudos_mut() data.current_pseudos_mut()
.insert(style_pseudo.clone(), new_style.unwrap()); .insert(style_pseudo.clone(), new_style.unwrap());
} }

View file

@ -9,7 +9,7 @@ use context::SharedStyleContext;
use dom::{OpaqueNode, UnsafeNode}; use dom::{OpaqueNode, UnsafeNode};
use euclid::point::Point2D; use euclid::point::Point2D;
use keyframes::{KeyframesStep, KeyframesStepValue}; use keyframes::{KeyframesStep, KeyframesStepValue};
use properties::{self, ComputedValues, Importance}; use properties::{self, CascadeFlags, ComputedValues, Importance};
use properties::animated_properties::{AnimatedProperty, TransitionProperty}; use properties::animated_properties::{AnimatedProperty, TransitionProperty};
use properties::longhands::animation_direction::computed_value::AnimationDirection; use properties::longhands::animation_direction::computed_value::AnimationDirection;
use properties::longhands::animation_iteration_count::computed_value::AnimationIterationCount; use properties::longhands::animation_iteration_count::computed_value::AnimationIterationCount;
@ -397,11 +397,11 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
}; };
let (computed, _) = properties::cascade(context.viewport_size, let (computed, _) = properties::cascade(context.viewport_size,
&[declaration_block], &[declaration_block],
false,
Some(previous_style), Some(previous_style),
None, None,
None, None,
context.error_reporter.clone()); context.error_reporter.clone(),
CascadeFlags::empty());
computed computed
} }
} }

View file

@ -13,7 +13,7 @@ use cascade_info::CascadeInfo;
use context::{SharedStyleContext, StyleContext}; use context::{SharedStyleContext, StyleContext};
use data::{NodeStyles, PseudoStyles}; use data::{NodeStyles, PseudoStyles};
use dom::{NodeInfo, TElement, TNode, TRestyleDamage, UnsafeNode}; use dom::{NodeInfo, TElement, TNode, TRestyleDamage, UnsafeNode};
use properties::{ComputedValues, cascade}; use properties::{CascadeFlags, ComputedValues, SHAREABLE, cascade};
use properties::longhands::display::computed_value as display; use properties::longhands::display::computed_value as display;
use selector_impl::{PseudoElement, TheSelectorImpl}; use selector_impl::{PseudoElement, TheSelectorImpl};
use selector_matching::{ApplicableDeclarationBlock, Stylist}; use selector_matching::{ApplicableDeclarationBlock, Stylist};
@ -489,6 +489,8 @@ pub enum StyleSharingResult<ConcreteRestyleDamage: TRestyleDamage> {
// Callers need to pass several boolean flags to cascade_node_pseudo_element. // Callers need to pass several boolean flags to cascade_node_pseudo_element.
// We encapsulate them in this struct to avoid mixing them up. // We encapsulate them in this struct to avoid mixing them up.
//
// FIXME(pcwalton): Unify with `CascadeFlags`, perhaps?
struct CascadeBooleans { struct CascadeBooleans {
shareable: bool, shareable: bool,
cacheable: bool, cacheable: bool,
@ -523,6 +525,11 @@ trait PrivateMatchMethods: TNode {
cacheable = cacheable && !has_style_attribute; cacheable = cacheable && !has_style_attribute;
let mut cascade_info = CascadeInfo::new(); let mut cascade_info = CascadeInfo::new();
let mut cascade_flags = CascadeFlags::empty();
if booleans.shareable {
cascade_flags.insert(SHAREABLE)
}
let (this_style, is_cacheable) = match parent_style { let (this_style, is_cacheable) = match parent_style {
Some(ref parent_style) => { Some(ref parent_style) => {
let cache_entry = applicable_declarations_cache.find(applicable_declarations); let cache_entry = applicable_declarations_cache.find(applicable_declarations);
@ -533,20 +540,20 @@ trait PrivateMatchMethods: TNode {
cascade(shared_context.viewport_size, cascade(shared_context.viewport_size,
applicable_declarations, applicable_declarations,
booleans.shareable,
Some(&***parent_style), Some(&***parent_style),
cached_computed_values, cached_computed_values,
Some(&mut cascade_info), Some(&mut cascade_info),
shared_context.error_reporter.clone()) shared_context.error_reporter.clone(),
cascade_flags)
} }
None => { None => {
cascade(shared_context.viewport_size, cascade(shared_context.viewport_size,
applicable_declarations, applicable_declarations,
booleans.shareable,
None, None,
None, None,
Some(&mut cascade_info), Some(&mut cascade_info),
shared_context.error_reporter.clone()) shared_context.error_reporter.clone(),
cascade_flags)
} }
}; };
cascade_info.finish(self); cascade_info.finish(self);

View file

@ -1524,6 +1524,17 @@ static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
% endfor % endfor
]; ];
bitflags! {
pub flags CascadeFlags: u8 {
/// Whether the `ComputedValues` structure to be constructed should be considered
/// shareable.
const SHAREABLE = 0x01,
/// Whether to inherit all styles from the parent. If this flag is not present,
/// non-inherited styles are reset to their initial values.
const INHERIT_ALL = 0x02,
}
}
/// Performs the CSS cascade, computing new styles for an element from its parent style and /// Performs the CSS cascade, computing new styles for an element from its parent style and
/// optionally a cached related style. The arguments are: /// optionally a cached related style. The arguments are:
/// ///
@ -1531,9 +1542,6 @@ static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
/// ///
/// * `applicable_declarations`: The list of CSS rules that matched. /// * `applicable_declarations`: The list of CSS rules that matched.
/// ///
/// * `shareable`: Whether the `ComputedValues` structure to be constructed should be considered
/// shareable.
///
/// * `parent_style`: The parent style, if applicable; if `None`, this is the root node. /// * `parent_style`: The parent style, if applicable; if `None`, this is the root node.
/// ///
/// * `cached_style`: If present, cascading is short-circuited for everything but inherited /// * `cached_style`: If present, cascading is short-circuited for everything but inherited
@ -1541,14 +1549,16 @@ static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
/// this that it is safe to only provide inherited declarations. If `parent_style` is `None`, /// this that it is safe to only provide inherited declarations. If `parent_style` is `None`,
/// this is ignored. /// this is ignored.
/// ///
/// * `flags`: Various flags.
///
/// Returns the computed values and a boolean indicating whether the result is cacheable. /// Returns the computed values and a boolean indicating whether the result is cacheable.
pub fn cascade(viewport_size: Size2D<Au>, pub fn cascade(viewport_size: Size2D<Au>,
applicable_declarations: &[ApplicableDeclarationBlock], applicable_declarations: &[ApplicableDeclarationBlock],
shareable: bool,
parent_style: Option<<&ComputedValues>, parent_style: Option<<&ComputedValues>,
cached_style: Option<<&ComputedValues>, cached_style: Option<<&ComputedValues>,
mut cascade_info: Option<<&mut CascadeInfo>, mut cascade_info: Option<<&mut CascadeInfo>,
mut error_reporter: StdBox<ParseErrorReporter + Send>) mut error_reporter: StdBox<ParseErrorReporter + Send>,
flags: CascadeFlags)
-> (ComputedValues, bool) { -> (ComputedValues, bool) {
let initial_values = ComputedValues::initial_values(); let initial_values = ComputedValues::initial_values();
let (is_root_element, inherited_style) = match parent_style { let (is_root_element, inherited_style) = match parent_style {
@ -1582,7 +1592,7 @@ pub fn cascade(viewport_size: Size2D<Au>,
if let (Some(cached_style), Some(parent_style)) = (cached_style, parent_style) { if let (Some(cached_style), Some(parent_style)) = (cached_style, parent_style) {
let style = cascade_with_cached_declarations(viewport_size, let style = cascade_with_cached_declarations(viewport_size,
&applicable_declarations, &applicable_declarations,
shareable, flags.contains(SHAREABLE),
parent_style, parent_style,
cached_style, cached_style,
custom_properties, custom_properties,
@ -1591,24 +1601,35 @@ pub fn cascade(viewport_size: Size2D<Au>,
return (style, false) return (style, false)
} }
let starting_style = if !flags.contains(INHERIT_ALL) {
ComputedValues::new(custom_properties,
flags.contains(SHAREABLE),
WritingMode::empty(),
inherited_style.root_font_size(),
% for style_struct in data.active_style_structs():
% if style_struct.inherited:
inherited_style.clone_${style_struct.name_lower}(),
% else:
initial_values.clone_${style_struct.name_lower}(),
% endif
% endfor
)
} else {
ComputedValues::new(custom_properties,
flags.contains(SHAREABLE),
WritingMode::empty(),
inherited_style.root_font_size(),
% for style_struct in data.active_style_structs():
inherited_style.clone_${style_struct.name_lower}(),
% endfor
)
};
let mut context = computed::Context { let mut context = computed::Context {
is_root_element: is_root_element, is_root_element: is_root_element,
viewport_size: viewport_size, viewport_size: viewport_size,
inherited_style: inherited_style, inherited_style: inherited_style,
style: ComputedValues::new( style: starting_style,
custom_properties,
shareable,
WritingMode::empty(),
inherited_style.root_font_size(),
% for style_struct in data.active_style_structs():
% if style_struct.inherited:
inherited_style
% else:
initial_values
% endif
.clone_${style_struct.name_lower}(),
% endfor
),
}; };
// Set computed values, overwriting earlier declarations for the same property. // Set computed values, overwriting earlier declarations for the same property.

View file

@ -10,7 +10,8 @@ use error_reporting::StdoutErrorReporter;
use keyframes::KeyframesAnimation; use keyframes::KeyframesAnimation;
use media_queries::{Device, MediaType}; use media_queries::{Device, MediaType};
use parking_lot::{RwLock, RwLockReadGuard}; use parking_lot::{RwLock, RwLockReadGuard};
use properties::{self, PropertyDeclaration, PropertyDeclarationBlock, ComputedValues, Importance}; use properties::{self, CascadeFlags, ComputedValues, INHERIT_ALL, Importance};
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
use quickersort::sort_by; use quickersort::sort_by;
use restyle_hints::{RestyleHint, DependencySet}; use restyle_hints::{RestyleHint, DependencySet};
use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement}; use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement};
@ -252,19 +253,30 @@ impl Stylist {
/// Computes the style for a given "precomputed" pseudo-element, taking the /// Computes the style for a given "precomputed" pseudo-element, taking the
/// universal rules and applying them. /// universal rules and applying them.
///
/// If `inherit_all` is true, then all properties are inherited from the parent; otherwise,
/// non-inherited properties are reset to their initial values. The flow constructor uses this
/// flag when constructing anonymous flows.
pub fn precomputed_values_for_pseudo(&self, pub fn precomputed_values_for_pseudo(&self,
pseudo: &PseudoElement, pseudo: &PseudoElement,
parent: Option<&Arc<ComputedValues>>) parent: Option<&Arc<ComputedValues>>,
inherit_all: bool)
-> Option<Arc<ComputedValues>> { -> Option<Arc<ComputedValues>> {
debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_precomputed()); debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_precomputed());
if let Some(declarations) = self.precomputed_pseudo_element_decls.get(pseudo) { if let Some(declarations) = self.precomputed_pseudo_element_decls.get(pseudo) {
let mut flags = CascadeFlags::empty();
if inherit_all {
flags.insert(INHERIT_ALL)
}
let (computed, _) = let (computed, _) =
properties::cascade(self.device.au_viewport_size(), properties::cascade(self.device.au_viewport_size(),
&declarations, false, &declarations,
parent.map(|p| &**p), parent.map(|p| &**p),
None, None,
None, None,
Box::new(StdoutErrorReporter)); Box::new(StdoutErrorReporter),
flags);
Some(Arc::new(computed)) Some(Arc::new(computed))
} else { } else {
parent.map(|p| p.clone()) parent.map(|p| p.clone())
@ -325,10 +337,12 @@ impl Stylist {
let (computed, _) = let (computed, _) =
properties::cascade(self.device.au_viewport_size(), properties::cascade(self.device.au_viewport_size(),
&declarations, false, &declarations,
Some(&**parent), None, None, Some(&**parent),
Box::new(StdoutErrorReporter)); None,
None,
Box::new(StdoutErrorReporter),
CascadeFlags::empty());
Some(Arc::new(computed)) Some(Arc::new(computed))
} }

View file

@ -37,7 +37,7 @@ use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI}; use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use style::parallel; use style::parallel;
use style::parser::{ParserContext, ParserContextExtraData}; use style::parser::{ParserContext, ParserContextExtraData};
use style::properties::{ComputedValues, Importance, PropertyDeclaration}; use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock}; use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock};
use style::properties::{cascade, parse_one_declaration}; use style::properties::{cascade, parse_one_declaration};
use style::selector_impl::PseudoElementCascadeType; use style::selector_impl::PseudoElementCascadeType;
@ -143,11 +143,11 @@ pub extern "C" fn Servo_RestyleWithAddedDeclaration(declarations: RawServoDeclar
// FIXME (bug 1303229): Use the actual viewport size here // FIXME (bug 1303229): Use the actual viewport size here
let (computed, _) = cascade(Size2D::new(Au(0), Au(0)), let (computed, _) = cascade(Size2D::new(Au(0), Au(0)),
&[declaration_block], &[declaration_block],
false,
Some(previous_style), Some(previous_style),
None, None,
None, None,
Box::new(StdoutErrorReporter)); Box::new(StdoutErrorReporter),
CascadeFlags::empty());
Arc::new(computed).into_strong() Arc::new(computed).into_strong()
} }
@ -282,7 +282,7 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null); let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null);
let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent); let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent, false);
new_computed.map_or(Strong::null(), |c| c.into_strong()) new_computed.map_or(Strong::null(), |c| c.into_strong())
} }