mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
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:
parent
93e41ba4aa
commit
fb2d1e1020
6 changed files with 86 additions and 43 deletions
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue