diff --git a/components/style/lib.rs b/components/style/lib.rs index 33862461aa9..aa855b8b55b 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -120,6 +120,8 @@ pub mod attr; pub mod author_styles; pub mod bezier; pub mod bloom; +#[path="properties/computed_value_flags.rs"] +pub mod computed_value_flags; pub mod context; pub mod counter_style; pub mod custom_properties; diff --git a/components/style/matching.rs b/components/style/matching.rs index 7ec94d35346..42921f052c4 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -7,6 +7,7 @@ #![allow(unsafe_code)] #![deny(missing_docs)] +use crate::computed_value_flags::ComputedValueFlags; use crate::context::{ElementCascadeInputs, QuirksMode, SelectorFlagsMap}; use crate::context::{SharedStyleContext, StyleContext}; use crate::data::ElementData; @@ -705,7 +706,7 @@ pub trait MatchMethods: TElement { let new_primary_style = data.styles.primary.as_ref().unwrap(); let mut cascade_requirement = ChildCascadeRequirement::CanSkipCascade; - if self.is_root() && !self.is_in_native_anonymous_subtree() { + if new_primary_style.flags.contains(ComputedValueFlags::IS_ROOT_ELEMENT_STYLE) { let device = context.shared.stylist.device(); let new_font_size = new_primary_style.get_font().clone_font_size(); diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 461bc0c1fce..50029da8479 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -263,8 +263,11 @@ where builder.build() }; + + let is_root_element = + pseudo.is_none() && element.map_or(false, |e| e.is_root()); + let mut context = computed::Context { - is_root_element: pseudo.is_none() && element.map_or(false, |e| e.is_root()), // We'd really like to own the rules here to avoid refcount traffic, but // animation's usage of `apply_declarations` make this tricky. See bug // 1375525. @@ -275,6 +278,7 @@ where pseudo, Some(rules.clone()), custom_properties, + is_root_element, ), cached_system_font: None, in_media_query: false, diff --git a/components/style/properties/computed_value_flags.rs b/components/style/properties/computed_value_flags.rs index a86f8a4da3a..170c4151411 100644 --- a/components/style/properties/computed_value_flags.rs +++ b/components/style/properties/computed_value_flags.rs @@ -11,6 +11,7 @@ bitflags! { /// anonymous boxes, see StyleBuilder::for_inheritance and its callsites. /// If we ever want to add some flags that shouldn't inherit for them, /// we might want to add a function to handle this. + #[repr(C)] pub struct ComputedValueFlags: u16 { /// Whether the style or any of the ancestors has a text-decoration-line /// property that should get propagated to descendants. @@ -63,6 +64,9 @@ bitflags! { /// /// Only used in Servo. const CAN_BE_FRAGMENTED = 1 << 10; + + /// Whether this style is the style of the document element. + const IS_ROOT_ELEMENT_STYLE = 1 << 11; } } @@ -97,22 +101,3 @@ impl ComputedValueFlags { self & Self::maybe_inherited_flags() } } - -/// Asserts that the relevant servo and Gecko representations match. -#[cfg(feature = "gecko")] -#[inline] -pub fn assert_match() { - use crate::gecko_bindings::structs; - macro_rules! assert_bit { - ($rust:ident, $cpp:ident) => { - debug_assert_eq!(ComputedValueFlags::$rust.bits, structs::$cpp); - } - } - - assert_bit!(HAS_TEXT_DECORATION_LINES, ComputedStyleBit_HasTextDecorationLines); - assert_bit!(IS_IN_PSEUDO_ELEMENT_SUBTREE, ComputedStyleBit_HasPseudoElementData); - assert_bit!(SHOULD_SUPPRESS_LINEBREAK, ComputedStyleBit_SuppressLineBreak); - assert_bit!(IS_TEXT_COMBINED, ComputedStyleBit_IsTextCombined); - assert_bit!(IS_RELEVANT_LINK_VISITED, ComputedStyleBit_RelevantLinkVisited); - assert_bit!(DEPENDS_ON_FONT_METRICS, ComputedStyleBit_DependsOnFontMetrics); -} diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 8f384296cbb..84dc8436940 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -12,6 +12,7 @@ use crate::Atom; use app_units::Au; +use crate::computed_value_flags::*; use crate::custom_properties::CustomPropertiesMap; use crate::gecko_bindings::bindings; % for style_struct in data.style_structs: @@ -39,7 +40,6 @@ use crate::gecko_bindings::structs::mozilla::PseudoStyleType; use crate::gecko::values::round_border_to_device_pixels; use crate::logical_geometry::WritingMode; use crate::media_queries::Device; -use crate::properties::computed_value_flags::*; use crate::properties::longhands; use crate::rule_tree::StrongRuleNode; use crate::selector_parser::PseudoElement; diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index d04d6d43d2e..ff5d5b5bf56 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -28,6 +28,7 @@ use crate::context::QuirksMode; #[cfg(feature = "servo")] use crate::computed_values; use crate::logical_geometry::WritingMode; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; +use crate::computed_value_flags::*; use crate::media_queries::Device; use crate::parser::ParserContext; use crate::properties::longhands::system_font::SystemFont; @@ -45,7 +46,6 @@ use crate::values::computed::NonNegativeLength; use crate::values::serialize_atom_name; use crate::rule_tree::StrongRuleNode; use crate::Zero; -use self::computed_value_flags::*; use crate::str::{CssString, CssStringBorrow, CssStringWriter}; use std::cell::Cell; @@ -58,8 +58,6 @@ pub use self::cascade::*; import os.path %> -#[path="${repr(os.path.join(os.path.dirname(__file__), 'computed_value_flags.rs'))[1:-1]}"] -pub mod computed_value_flags; #[path="${repr(os.path.join(os.path.dirname(__file__), 'declaration_block.rs'))[1:-1]}"] pub mod declaration_block; #[path="${repr(os.path.join(os.path.dirname(__file__), 'cascade.rs'))[1:-1]}"] @@ -3436,6 +3434,9 @@ pub struct StyleBuilder<'a> { /// `StyleAdjuster` did any work. modified_reset: bool, + /// Whether this is the style for the root element. + pub is_root_element: bool, + /// The writing mode flags. /// /// TODO(emilio): Make private. @@ -3462,6 +3463,7 @@ impl<'a> StyleBuilder<'a> { pseudo: Option<<&'a PseudoElement>, rules: Option, custom_properties: Option>, + is_root_element: bool, ) -> Self { debug_assert_eq!(parent_style.is_some(), parent_style_ignoring_first_line.is_some()); #[cfg(feature = "gecko")] @@ -3483,6 +3485,7 @@ impl<'a> StyleBuilder<'a> { pseudo, rules, modified_reset: false, + is_root_element, custom_properties, writing_mode: inherited_style.writing_mode, flags: Cell::new(flags), @@ -3521,6 +3524,7 @@ impl<'a> StyleBuilder<'a> { reset_style, pseudo: None, modified_reset: false, + is_root_element: false, rules: None, custom_properties: style_to_derive_from.custom_properties().cloned(), writing_mode: style_to_derive_from.writing_mode, @@ -3648,6 +3652,7 @@ impl<'a> StyleBuilder<'a> { pseudo, /* rules = */ None, parent.and_then(|p| p.custom_properties().cloned()), + /* is_root_element = */ false, ); ret.visited_style = visited_style; ret @@ -3830,9 +3835,9 @@ pub use self::lazy_static_module::INITIAL_SERVO_VALUES; #[allow(missing_docs)] mod lazy_static_module { use crate::logical_geometry::WritingMode; + use create::computed_value_flags::ComputedValueFlags; use servo_arc::Arc; use super::{ComputedValues, ComputedValuesInner, longhands, style_structs}; - use super::computed_value_flags::ComputedValueFlags; lazy_static! { /// The initial values for all style structs as defined by the specification. diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 2a897bbe151..b7c1decc390 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -5,8 +5,8 @@ //! A struct to encapsulate all the style fixups and flags propagations //! a computed style needs in order for it to adhere to the CSS spec. +use crate::computed_value_flags::ComputedValueFlags; use crate::dom::TElement; -use crate::properties::computed_value_flags::ComputedValueFlags; use crate::properties::longhands::display::computed_value::T as Display; use crate::properties::longhands::float::computed_value::T as Float; use crate::properties::longhands::overflow_x::computed_value::T as Overflow; @@ -189,8 +189,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { }; } - let is_root = self.style.pseudo.is_none() && element.map_or(false, |e| e.is_root()); - blockify_if!(is_root); + blockify_if!(self.style.is_root_element); if !self.skip_item_display_fixup(element) { let parent_display = layout_parent_style.get_box().clone_display(); blockify_if!(parent_display.is_item_container()); @@ -213,7 +212,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { } let display = self.style.get_box().clone_display(); - let blockified_display = display.equivalent_block_display(is_root); + let blockified_display = display.equivalent_block_display(self.style.is_root_element); if display != blockified_display { self.style .mutate_box() @@ -222,7 +221,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { } /// Compute a few common flags for both text and element's style. - pub fn set_bits(&mut self) { + fn set_bits(&mut self) { let display = self.style.get_box().clone_display(); if !display.is_contents() && @@ -241,6 +240,10 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { .add_flags(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE); } + if self.style.is_root_element { + self.style.add_flags(ComputedValueFlags::IS_ROOT_ELEMENT_STYLE); + } + #[cfg(feature = "servo-layout-2013")] { if self.style.get_parent_column().is_multicol() { @@ -257,6 +260,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// Note that this, for Gecko, comes through Servo_ComputedValues_Inherit. #[cfg(feature = "gecko")] pub fn adjust_for_text(&mut self) { + debug_assert!(!self.style.is_root_element); self.adjust_for_text_combine_upright(); self.adjust_for_text_in_ruby(); self.set_bits(); diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index 180de3ff281..f3f2c6b41b7 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -110,7 +110,7 @@ fn eager_pseudo_is_definitely_not_generated( pseudo: &PseudoElement, style: &ComputedValues, ) -> bool { - use crate::properties::computed_value_flags::ComputedValueFlags; + use crate::computed_value_flags::ComputedValueFlags; if !pseudo.is_before_or_after() { return false; diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index 7d0881e3336..cd875eefb69 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -733,7 +733,6 @@ impl MaybeNew for ViewportConstraints { let mut conditions = RuleCacheConditions::default(); let context = Context { - is_root_element: false, // Note: DEVICE-ADAPT ยง 5. states that relative length values are // resolved against initial values builder: StyleBuilder::for_inheritance(device, None, None), diff --git a/components/style/traversal.rs b/components/style/traversal.rs index f73a533b718..254d40f0393 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -775,7 +775,7 @@ fn note_children( child_hint |= RestyleHint::RECASCADE_SELF | RestyleHint::RECASCADE_DESCENDANTS; }, ChildCascadeRequirement::MustCascadeChildrenIfInheritResetStyle => { - use crate::properties::computed_value_flags::ComputedValueFlags; + use crate::computed_value_flags::ComputedValueFlags; if child_data .styles .primary() diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 87c430fb265..da5c84aed39 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -126,9 +126,6 @@ pub mod url; /// A `Context` is all the data a specified value could ever need to compute /// itself and be transformed to a computed value. pub struct Context<'a> { - /// Whether the current element is the root element. - pub is_root_element: bool, - /// Values accessed through this need to be in the properties "computed /// early": color, text-decoration, font-size, display, position, float, /// border-*-style, outline-style, font-family, writing-mode... @@ -187,7 +184,6 @@ impl<'a> Context<'a> { let provider = get_metrics_provider_for_product(); let context = Context { - is_root_element: false, builder: StyleBuilder::for_inheritance(device, None, None), font_metrics_provider: &provider, cached_system_font: None, @@ -201,11 +197,6 @@ impl<'a> Context<'a> { f(&context) } - /// Whether the current element is the root element. - pub fn is_root_element(&self) -> bool { - self.is_root_element - } - /// The current device. pub fn device(&self) -> &Device { self.builder.device diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 3ac1f0a9762..71153c4e015 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -7,9 +7,9 @@ //! [length]: https://drafts.csswg.org/css-values/#lengths use super::{AllowQuirks, Number, Percentage, ToComputedValue}; +use crate::computed_value_flags::ComputedValueFlags; use crate::font_metrics::{FontMetrics, FontMetricsOrientation}; use crate::parser::{Parse, ParserContext}; -use crate::properties::computed_value_flags::ComputedValueFlags; use crate::values::computed::{self, CSSPixelLength, Context}; use crate::values::generics::length as generics; use crate::values::generics::length::{ @@ -206,7 +206,7 @@ impl FontRelativeLength { // element, the rem units refer to the property's initial // value. // - let reference_size = if context.is_root_element || context.in_media_query { + let reference_size = if context.builder.is_root_element || context.in_media_query { reference_font_size } else { computed::Length::new(context.device().root_font_size().to_f32_px()) diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index b1f5e1f5c3e..16df2fa4b4e 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -596,7 +596,7 @@ impl ToComputedValue for TextAlign { // In that case, the default behavior here will set it to left, // but we want to set it to right -- instead set it to the default (`start`), // which will do the right thing in this case (but not the general case) - if _context.is_root_element { + if _context.builder.is_root_element { return TextAlignKeyword::Start; } let parent = _context