style: Add a style flag for the root element style.

This is needed to make the root element not a containing block in presence of
filters or what not.

Differential Revision: https://phabricator.services.mozilla.com/D61167
This commit is contained in:
Emilio Cobos Álvarez 2020-01-31 14:51:06 +00:00
parent f426b644ca
commit 16fd7cad0c
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
13 changed files with 37 additions and 46 deletions

View file

@ -120,6 +120,8 @@ pub mod attr;
pub mod author_styles; pub mod author_styles;
pub mod bezier; pub mod bezier;
pub mod bloom; pub mod bloom;
#[path="properties/computed_value_flags.rs"]
pub mod computed_value_flags;
pub mod context; pub mod context;
pub mod counter_style; pub mod counter_style;
pub mod custom_properties; pub mod custom_properties;

View file

@ -7,6 +7,7 @@
#![allow(unsafe_code)] #![allow(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
use crate::computed_value_flags::ComputedValueFlags;
use crate::context::{ElementCascadeInputs, QuirksMode, SelectorFlagsMap}; use crate::context::{ElementCascadeInputs, QuirksMode, SelectorFlagsMap};
use crate::context::{SharedStyleContext, StyleContext}; use crate::context::{SharedStyleContext, StyleContext};
use crate::data::ElementData; use crate::data::ElementData;
@ -705,7 +706,7 @@ pub trait MatchMethods: TElement {
let new_primary_style = data.styles.primary.as_ref().unwrap(); let new_primary_style = data.styles.primary.as_ref().unwrap();
let mut cascade_requirement = ChildCascadeRequirement::CanSkipCascade; 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 device = context.shared.stylist.device();
let new_font_size = new_primary_style.get_font().clone_font_size(); let new_font_size = new_primary_style.get_font().clone_font_size();

View file

@ -263,8 +263,11 @@ where
builder.build() builder.build()
}; };
let is_root_element =
pseudo.is_none() && element.map_or(false, |e| e.is_root());
let mut context = computed::Context { 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 // 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 // animation's usage of `apply_declarations` make this tricky. See bug
// 1375525. // 1375525.
@ -275,6 +278,7 @@ where
pseudo, pseudo,
Some(rules.clone()), Some(rules.clone()),
custom_properties, custom_properties,
is_root_element,
), ),
cached_system_font: None, cached_system_font: None,
in_media_query: false, in_media_query: false,

View file

@ -11,6 +11,7 @@ bitflags! {
/// anonymous boxes, see StyleBuilder::for_inheritance and its callsites. /// anonymous boxes, see StyleBuilder::for_inheritance and its callsites.
/// If we ever want to add some flags that shouldn't inherit for them, /// If we ever want to add some flags that shouldn't inherit for them,
/// we might want to add a function to handle this. /// we might want to add a function to handle this.
#[repr(C)]
pub struct ComputedValueFlags: u16 { pub struct ComputedValueFlags: u16 {
/// Whether the style or any of the ancestors has a text-decoration-line /// Whether the style or any of the ancestors has a text-decoration-line
/// property that should get propagated to descendants. /// property that should get propagated to descendants.
@ -63,6 +64,9 @@ bitflags! {
/// ///
/// Only used in Servo. /// Only used in Servo.
const CAN_BE_FRAGMENTED = 1 << 10; 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() 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);
}

View file

@ -12,6 +12,7 @@
use crate::Atom; use crate::Atom;
use app_units::Au; use app_units::Au;
use crate::computed_value_flags::*;
use crate::custom_properties::CustomPropertiesMap; use crate::custom_properties::CustomPropertiesMap;
use crate::gecko_bindings::bindings; use crate::gecko_bindings::bindings;
% for style_struct in data.style_structs: % 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::gecko::values::round_border_to_device_pixels;
use crate::logical_geometry::WritingMode; use crate::logical_geometry::WritingMode;
use crate::media_queries::Device; use crate::media_queries::Device;
use crate::properties::computed_value_flags::*;
use crate::properties::longhands; use crate::properties::longhands;
use crate::rule_tree::StrongRuleNode; use crate::rule_tree::StrongRuleNode;
use crate::selector_parser::PseudoElement; use crate::selector_parser::PseudoElement;

View file

@ -28,6 +28,7 @@ use crate::context::QuirksMode;
#[cfg(feature = "servo")] use crate::computed_values; #[cfg(feature = "servo")] use crate::computed_values;
use crate::logical_geometry::WritingMode; use crate::logical_geometry::WritingMode;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use crate::computed_value_flags::*;
use crate::media_queries::Device; use crate::media_queries::Device;
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::properties::longhands::system_font::SystemFont; use crate::properties::longhands::system_font::SystemFont;
@ -45,7 +46,6 @@ use crate::values::computed::NonNegativeLength;
use crate::values::serialize_atom_name; use crate::values::serialize_atom_name;
use crate::rule_tree::StrongRuleNode; use crate::rule_tree::StrongRuleNode;
use crate::Zero; use crate::Zero;
use self::computed_value_flags::*;
use crate::str::{CssString, CssStringBorrow, CssStringWriter}; use crate::str::{CssString, CssStringBorrow, CssStringWriter};
use std::cell::Cell; use std::cell::Cell;
@ -58,8 +58,6 @@ pub use self::cascade::*;
import os.path 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]}"] #[path="${repr(os.path.join(os.path.dirname(__file__), 'declaration_block.rs'))[1:-1]}"]
pub mod declaration_block; pub mod declaration_block;
#[path="${repr(os.path.join(os.path.dirname(__file__), 'cascade.rs'))[1:-1]}"] #[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. /// `StyleAdjuster` did any work.
modified_reset: bool, modified_reset: bool,
/// Whether this is the style for the root element.
pub is_root_element: bool,
/// The writing mode flags. /// The writing mode flags.
/// ///
/// TODO(emilio): Make private. /// TODO(emilio): Make private.
@ -3462,6 +3463,7 @@ impl<'a> StyleBuilder<'a> {
pseudo: Option<<&'a PseudoElement>, pseudo: Option<<&'a PseudoElement>,
rules: Option<StrongRuleNode>, rules: Option<StrongRuleNode>,
custom_properties: Option<Arc<crate::custom_properties::CustomPropertiesMap>>, custom_properties: Option<Arc<crate::custom_properties::CustomPropertiesMap>>,
is_root_element: bool,
) -> Self { ) -> Self {
debug_assert_eq!(parent_style.is_some(), parent_style_ignoring_first_line.is_some()); debug_assert_eq!(parent_style.is_some(), parent_style_ignoring_first_line.is_some());
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -3483,6 +3485,7 @@ impl<'a> StyleBuilder<'a> {
pseudo, pseudo,
rules, rules,
modified_reset: false, modified_reset: false,
is_root_element,
custom_properties, custom_properties,
writing_mode: inherited_style.writing_mode, writing_mode: inherited_style.writing_mode,
flags: Cell::new(flags), flags: Cell::new(flags),
@ -3521,6 +3524,7 @@ impl<'a> StyleBuilder<'a> {
reset_style, reset_style,
pseudo: None, pseudo: None,
modified_reset: false, modified_reset: false,
is_root_element: false,
rules: None, rules: None,
custom_properties: style_to_derive_from.custom_properties().cloned(), custom_properties: style_to_derive_from.custom_properties().cloned(),
writing_mode: style_to_derive_from.writing_mode, writing_mode: style_to_derive_from.writing_mode,
@ -3648,6 +3652,7 @@ impl<'a> StyleBuilder<'a> {
pseudo, pseudo,
/* rules = */ None, /* rules = */ None,
parent.and_then(|p| p.custom_properties().cloned()), parent.and_then(|p| p.custom_properties().cloned()),
/* is_root_element = */ false,
); );
ret.visited_style = visited_style; ret.visited_style = visited_style;
ret ret
@ -3830,9 +3835,9 @@ pub use self::lazy_static_module::INITIAL_SERVO_VALUES;
#[allow(missing_docs)] #[allow(missing_docs)]
mod lazy_static_module { mod lazy_static_module {
use crate::logical_geometry::WritingMode; use crate::logical_geometry::WritingMode;
use create::computed_value_flags::ComputedValueFlags;
use servo_arc::Arc; use servo_arc::Arc;
use super::{ComputedValues, ComputedValuesInner, longhands, style_structs}; use super::{ComputedValues, ComputedValuesInner, longhands, style_structs};
use super::computed_value_flags::ComputedValueFlags;
lazy_static! { lazy_static! {
/// The initial values for all style structs as defined by the specification. /// The initial values for all style structs as defined by the specification.

View file

@ -5,8 +5,8 @@
//! A struct to encapsulate all the style fixups and flags propagations //! 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. //! 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::dom::TElement;
use crate::properties::computed_value_flags::ComputedValueFlags;
use crate::properties::longhands::display::computed_value::T as Display; use crate::properties::longhands::display::computed_value::T as Display;
use crate::properties::longhands::float::computed_value::T as Float; use crate::properties::longhands::float::computed_value::T as Float;
use crate::properties::longhands::overflow_x::computed_value::T as Overflow; 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!(self.style.is_root_element);
blockify_if!(is_root);
if !self.skip_item_display_fixup(element) { if !self.skip_item_display_fixup(element) {
let parent_display = layout_parent_style.get_box().clone_display(); let parent_display = layout_parent_style.get_box().clone_display();
blockify_if!(parent_display.is_item_container()); 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 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 { if display != blockified_display {
self.style self.style
.mutate_box() .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. /// 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(); let display = self.style.get_box().clone_display();
if !display.is_contents() && if !display.is_contents() &&
@ -241,6 +240,10 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
.add_flags(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE); .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")] #[cfg(feature = "servo-layout-2013")]
{ {
if self.style.get_parent_column().is_multicol() { 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. /// Note that this, for Gecko, comes through Servo_ComputedValues_Inherit.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn adjust_for_text(&mut self) { pub fn adjust_for_text(&mut self) {
debug_assert!(!self.style.is_root_element);
self.adjust_for_text_combine_upright(); self.adjust_for_text_combine_upright();
self.adjust_for_text_in_ruby(); self.adjust_for_text_in_ruby();
self.set_bits(); self.set_bits();

View file

@ -110,7 +110,7 @@ fn eager_pseudo_is_definitely_not_generated(
pseudo: &PseudoElement, pseudo: &PseudoElement,
style: &ComputedValues, style: &ComputedValues,
) -> bool { ) -> bool {
use crate::properties::computed_value_flags::ComputedValueFlags; use crate::computed_value_flags::ComputedValueFlags;
if !pseudo.is_before_or_after() { if !pseudo.is_before_or_after() {
return false; return false;

View file

@ -733,7 +733,6 @@ impl MaybeNew for ViewportConstraints {
let mut conditions = RuleCacheConditions::default(); let mut conditions = RuleCacheConditions::default();
let context = Context { let context = Context {
is_root_element: false,
// Note: DEVICE-ADAPT § 5. states that relative length values are // Note: DEVICE-ADAPT § 5. states that relative length values are
// resolved against initial values // resolved against initial values
builder: StyleBuilder::for_inheritance(device, None, None), builder: StyleBuilder::for_inheritance(device, None, None),

View file

@ -775,7 +775,7 @@ fn note_children<E, D, F>(
child_hint |= RestyleHint::RECASCADE_SELF | RestyleHint::RECASCADE_DESCENDANTS; child_hint |= RestyleHint::RECASCADE_SELF | RestyleHint::RECASCADE_DESCENDANTS;
}, },
ChildCascadeRequirement::MustCascadeChildrenIfInheritResetStyle => { ChildCascadeRequirement::MustCascadeChildrenIfInheritResetStyle => {
use crate::properties::computed_value_flags::ComputedValueFlags; use crate::computed_value_flags::ComputedValueFlags;
if child_data if child_data
.styles .styles
.primary() .primary()

View file

@ -126,9 +126,6 @@ pub mod url;
/// A `Context` is all the data a specified value could ever need to compute /// A `Context` is all the data a specified value could ever need to compute
/// itself and be transformed to a computed value. /// itself and be transformed to a computed value.
pub struct Context<'a> { 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 /// Values accessed through this need to be in the properties "computed
/// early": color, text-decoration, font-size, display, position, float, /// early": color, text-decoration, font-size, display, position, float,
/// border-*-style, outline-style, font-family, writing-mode... /// border-*-style, outline-style, font-family, writing-mode...
@ -187,7 +184,6 @@ impl<'a> Context<'a> {
let provider = get_metrics_provider_for_product(); let provider = get_metrics_provider_for_product();
let context = Context { let context = Context {
is_root_element: false,
builder: StyleBuilder::for_inheritance(device, None, None), builder: StyleBuilder::for_inheritance(device, None, None),
font_metrics_provider: &provider, font_metrics_provider: &provider,
cached_system_font: None, cached_system_font: None,
@ -201,11 +197,6 @@ impl<'a> Context<'a> {
f(&context) f(&context)
} }
/// Whether the current element is the root element.
pub fn is_root_element(&self) -> bool {
self.is_root_element
}
/// The current device. /// The current device.
pub fn device(&self) -> &Device { pub fn device(&self) -> &Device {
self.builder.device self.builder.device

View file

@ -7,9 +7,9 @@
//! [length]: https://drafts.csswg.org/css-values/#lengths //! [length]: https://drafts.csswg.org/css-values/#lengths
use super::{AllowQuirks, Number, Percentage, ToComputedValue}; use super::{AllowQuirks, Number, Percentage, ToComputedValue};
use crate::computed_value_flags::ComputedValueFlags;
use crate::font_metrics::{FontMetrics, FontMetricsOrientation}; use crate::font_metrics::{FontMetrics, FontMetricsOrientation};
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::properties::computed_value_flags::ComputedValueFlags;
use crate::values::computed::{self, CSSPixelLength, Context}; use crate::values::computed::{self, CSSPixelLength, Context};
use crate::values::generics::length as generics; use crate::values::generics::length as generics;
use crate::values::generics::length::{ use crate::values::generics::length::{
@ -206,7 +206,7 @@ impl FontRelativeLength {
// element, the rem units refer to the property's initial // element, the rem units refer to the property's initial
// value. // 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 reference_font_size
} else { } else {
computed::Length::new(context.device().root_font_size().to_f32_px()) computed::Length::new(context.device().root_font_size().to_f32_px())

View file

@ -596,7 +596,7 @@ impl ToComputedValue for TextAlign {
// In that case, the default behavior here will set it to left, // 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`), // 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) // 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; return TextAlignKeyword::Start;
} }
let parent = _context let parent = _context