From ed4a23eccfd47359df8edd6d0580e2c1859e3ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 19 Mar 2019 21:10:13 +0000 Subject: [PATCH] style: Keep track of whether a style is affected by font metrics. Differential Revision: https://phabricator.services.mozilla.com/D20728 --- .../style/properties/computed_value_flags.rs | 5 ++- .../style/properties/properties.mako.rs | 41 +++++++++++++++---- components/style/style_adjuster.rs | 32 ++++----------- components/style/values/specified/length.rs | 3 ++ 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/components/style/properties/computed_value_flags.rs b/components/style/properties/computed_value_flags.rs index 18fc886c7ae..2f6851d3f43 100644 --- a/components/style/properties/computed_value_flags.rs +++ b/components/style/properties/computed_value_flags.rs @@ -56,10 +56,13 @@ bitflags! { /// Whether the child explicitly inherits any reset property. const INHERITS_RESET_STYLE = 1 << 8; + /// Whether any value on our style is font-metric-dependent. + const DEPENDS_ON_FONT_METRICS = 1 << 9; + /// Whether the style or any of the ancestors has a multicol style. /// /// Only used in Servo. - const CAN_BE_FRAGMENTED = 1 << 9; + const CAN_BE_FRAGMENTED = 1 << 10; } } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a470eb84b08..f57e27eff1e 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -45,6 +45,7 @@ use crate::rule_tree::StrongRuleNode; use crate::Zero; use self::computed_value_flags::*; use crate::str::{CssString, CssStringBorrow, CssStringWriter}; +use std::cell::Cell; pub use self::declaration_block::*; pub use self::cascade::*; @@ -2758,7 +2759,7 @@ pub struct ComputedValuesInner { pub writing_mode: WritingMode, /// A set of flags we use to store misc information regarding this style. - pub flags: ComputedValueFlags, + flags: ComputedValueFlags, /// The rule node representing the ordered list of rules matched for this /// node. Can be None for default values and text nodes. This is @@ -3322,8 +3323,10 @@ pub struct StyleBuilder<'a> { /// /// TODO(emilio): Make private. pub writing_mode: WritingMode, + /// Flags for the computed value. - pub flags: ComputedValueFlags, + pub flags: Cell, + /// The element's style if visited, only computed if there's a relevant link /// for this element. A element's "relevant link" is the element being /// matched if it is a link or the nearest ancestor link. @@ -3365,7 +3368,7 @@ impl<'a> StyleBuilder<'a> { modified_reset: false, custom_properties, writing_mode: inherited_style.writing_mode, - flags, + flags: Cell::new(flags), visited_style: None, % for style_struct in data.active_style_structs(): % if style_struct.inherited: @@ -3404,7 +3407,7 @@ impl<'a> StyleBuilder<'a> { rules: None, custom_properties: style_to_derive_from.custom_properties().cloned(), writing_mode: style_to_derive_from.writing_mode, - flags: style_to_derive_from.flags, + flags: Cell::new(style_to_derive_from.flags), visited_style: None, % for style_struct in data.active_style_structs(): ${style_struct.ident}: StyleStructRef::Borrowed( @@ -3434,14 +3437,14 @@ impl<'a> StyleBuilder<'a> { .get_${property.style_struct.name_lower}(); self.modified_reset = true; - self.flags.insert(ComputedValueFlags::INHERITS_RESET_STYLE); + self.add_flags(ComputedValueFlags::INHERITS_RESET_STYLE); % if property.ident == "content": - self.flags.insert(ComputedValueFlags::INHERITS_CONTENT); + self.add_flags(ComputedValueFlags::INHERITS_CONTENT); % endif % if property.ident == "display": - self.flags.insert(ComputedValueFlags::INHERITS_DISPLAY); + self.add_flags(ComputedValueFlags::INHERITS_DISPLAY); % endif if self.${property.style_struct.ident}.ptr_eq(inherited_struct) { @@ -3628,13 +3631,33 @@ impl<'a> StyleBuilder<'a> { self.modified_reset } + /// Return the current flags. + #[inline] + pub fn flags(&self) -> ComputedValueFlags { + self.flags.get() + } + + /// Add a flag to the current builder. + #[inline] + pub fn add_flags(&self, flag: ComputedValueFlags) { + let flags = self.flags() | flag; + self.flags.set(flags); + } + + /// Removes a flag to the current builder. + #[inline] + pub fn remove_flags(&self, flag: ComputedValueFlags) { + let flags = self.flags() & !flag; + self.flags.set(flags); + } + /// Turns this `StyleBuilder` into a proper `ComputedValues` instance. pub fn build(self) -> Arc { ComputedValues::new( self.pseudo, self.custom_properties, self.writing_mode, - self.flags, + self.flags.get(), self.rules, self.visited_style, % for style_struct in data.active_style_structs(): @@ -3721,7 +3744,7 @@ mod lazy_static_module { writing_mode: WritingMode::empty(), rules: None, visited_style: None, - flags: ComputedValueFlags::empty(), + flags: Cell::new(ComputedValueFlags::empty()), } }; } diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 248d0ad0661..8218e2706a3 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -225,23 +225,17 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { .clone_text_decoration_line() .is_empty() { - self.style - .flags - .insert(ComputedValueFlags::HAS_TEXT_DECORATION_LINES); + self.style.add_flags(ComputedValueFlags::HAS_TEXT_DECORATION_LINES); } if self.style.is_pseudo_element() { - self.style - .flags - .insert(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE); + self.style.add_flags(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE); } #[cfg(feature = "servo")] { if self.style.get_parent_column().is_multicol() { - self.style - .flags - .insert(ComputedValueFlags::CAN_BE_FRAGMENTED); + self.style.add_flags(ComputedValueFlags::CAN_BE_FRAGMENTED); } } } @@ -280,9 +274,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { if writing_mode != WritingMode::HorizontalTb && text_combine_upright == TextCombineUpright::All { - self.style - .flags - .insert(ComputedValueFlags::IS_TEXT_COMBINED); + self.style.add_flags(ComputedValueFlags::IS_TEXT_COMBINED); self.style .mutate_inherited_box() .set_writing_mode(WritingMode::HorizontalTb); @@ -303,9 +295,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { .get_parent_flags() .contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) { - self.style - .flags - .insert(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK); + self.style.add_flags(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK); } } @@ -591,9 +581,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { let self_display = self.style.get_box().clone_display(); // Check whether line break should be suppressed for this element. if self.should_suppress_linebreak(layout_parent_style) { - self.style - .flags - .insert(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK); + self.style.add_flags(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK); // Inlinify the display type if allowed. if !self.skip_item_display_fixup(element) { let inline_display = self_display.inlinify(); @@ -651,14 +639,10 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { } if element.unwrap().is_visited_link() { - self.style - .flags - .insert(ComputedValueFlags::IS_RELEVANT_LINK_VISITED); + self.style.add_flags(ComputedValueFlags::IS_RELEVANT_LINK_VISITED); } else { // Need to remove to handle unvisited link inside visited. - self.style - .flags - .remove(ComputedValueFlags::IS_RELEVANT_LINK_VISITED); + self.style.remove_flags(ComputedValueFlags::IS_RELEVANT_LINK_VISITED); } } diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 9a1d366f7fd..b3a7932dd93 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -9,6 +9,7 @@ use super::{AllowQuirks, Number, Percentage, ToComputedValue}; use crate::font_metrics::FontMetricsQueryResult; 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::{ @@ -158,6 +159,7 @@ impl FontRelativeLength { if context.for_non_inherited_property.is_some() { context.rule_cache_conditions.borrow_mut().set_uncacheable(); } + context.builder.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS); let reference_size = match query_font_metrics(context, base_size) { FontMetricsQueryResult::Available(metrics) => metrics.x_height, // https://drafts.csswg.org/css-values/#ex @@ -174,6 +176,7 @@ impl FontRelativeLength { if context.for_non_inherited_property.is_some() { context.rule_cache_conditions.borrow_mut().set_uncacheable(); } + context.builder.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS); let reference_size = match query_font_metrics(context, base_size) { FontMetricsQueryResult::Available(metrics) => metrics.zero_advance_measure, // https://drafts.csswg.org/css-values/#ch