diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2016-03-09 00:33:01 +0100 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2016-03-18 17:09:16 +0100 |
commit | 529164e4a5b0fcca67d5a1fa31f17f87c038eadd (patch) | |
tree | 4d4db27a18480f46ff0d0ae5e968817d0324624b | |
parent | bab28e507090b06272bc9f85627ebaa5cdeddd62 (diff) | |
download | servo-529164e4a5b0fcca67d5a1fa31f17f87c038eadd.tar.gz servo-529164e4a5b0fcca67d5a1fa31f17f87c038eadd.zip |
Refactor the cascade
Converting the specified value of some properties into a computed value
depends on the value of other properties. For example, the `em` unit
of any length depends on the `font-size` property.
Previously, we would do a first pass over applicable declarations
to build up a `values::computed::Context` struct with a number of fields
for each such piece of data from other properties.
This simplies the struct by instead having it contain the
set of computed values (for a given element) that is being populated
and classify properties into "early" and "other",
such that the only dependencies can be from "other" to "early".
We iterate applicable_declarations twice, first cascading "early" properties
then "other".
Unfortunately, it’s not easy to check that this classification is correct.
-rw-r--r-- | components/style/properties.mako.rs | 492 | ||||
-rw-r--r-- | components/style/values.rs | 41 | ||||
-rw-r--r-- | components/style/viewport.rs | 19 |
3 files changed, 213 insertions, 339 deletions
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index a71ad6ebf51..1230ea6f343 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -33,7 +33,7 @@ use selectors::matching::DeclarationBlock; use stylesheets::Origin; use values::AuExtensionMethods; use values::computed::{self, ToComputedValue}; -use values::specified::{Length, BorderStyle}; +use values::specified::BorderStyle; use self::property_bit_field::PropertyBitField; @@ -151,9 +151,8 @@ pub mod longhands { ${caller.body()} #[allow(unused_variables)] pub fn cascade_property(declaration: &PropertyDeclaration, - style: &mut ComputedValues, inherited_style: &ComputedValues, - context: &computed::Context, + context: &mut computed::Context, seen: &mut PropertyBitField, cacheable: &mut bool, error_reporter: &mut Box<ParseErrorReporter + Send>) { @@ -169,7 +168,7 @@ pub mod longhands { } seen.set_${property.ident}(); let computed_value = ::properties::substitute_variables_${property.ident}( - declared_value, &style.custom_properties, |value| match *value { + declared_value, &context.style.custom_properties, |value| match *value { DeclaredValue::Value(ref specified_value) => { specified_value.to_computed_value(&context) } @@ -187,13 +186,12 @@ pub mod longhands { } }, error_reporter ); - Arc::make_mut(&mut style.${THIS_STYLE_STRUCT.ident}).${property.ident} = + Arc::make_mut(&mut context.style.${THIS_STYLE_STRUCT.ident}).${property.ident} = computed_value; % if custom_cascade: cascade_property_custom(&computed_value, declaration, - style, inherited_style, context, seen, @@ -364,11 +362,7 @@ pub mod longhands { #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - if !context.border_${side}_present { - Au(0) - } else { - self.0.to_computed_value(context) - } + self.0.to_computed_value(context) } } </%self:longhand> @@ -428,11 +422,7 @@ pub mod longhands { #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - if !context.outline_style_present { - Au(0) - } else { - self.0.to_computed_value(context) - } + self.0.to_computed_value(context) } } </%self:longhand> @@ -462,7 +452,7 @@ pub mod longhands { experimental_values = set("flex".split()) %> pub use self::computed_value::T as SpecifiedValue; - use values::computed::Context; + use values::computed::{Context, ComputedValueAsSpecified}; pub mod computed_value { #[allow(non_camel_case_types)] @@ -506,47 +496,19 @@ pub mod longhands { } } - impl ToComputedValue for SpecifiedValue { - type ComputedValue = computed_value::T; - - #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { - use self::computed_value::T; - // if context.is_root_element && value == list_item { - // return block - // } - if context.positioned || context.floated || context.is_root_element { - match *self { - T::inline_table => T::table, - T::inline | T::inline_block | - T::table_row_group | T::table_column | - T::table_column_group | T::table_header_group | - T::table_footer_group | T::table_row | T::table_cell | - T::table_caption - => T::block, - _ => *self, - } - } else { - *self - } - } - } + impl ComputedValueAsSpecified for SpecifiedValue {} - fn cascade_property_custom(computed_value: &computed_value::T, + fn cascade_property_custom(_computed_value: &computed_value::T, _declaration: &PropertyDeclaration, - style: &mut ComputedValues, _inherited_style: &ComputedValues, - context: &computed::Context, + context: &mut computed::Context, _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut Box<ParseErrorReporter + Send>) { - Arc::make_mut(&mut style.box_)._servo_display_for_hypothetical_box = - longhands::_servo_display_for_hypothetical_box::derive_from_display( - *computed_value, - &context); - Arc::make_mut(&mut style.inheritedtext)._servo_text_decorations_in_effect = - longhands::_servo_text_decorations_in_effect::derive_from_display(*computed_value, - &context); + Arc::make_mut(&mut context.style.box_)._servo_display_for_hypothetical_box = + longhands::_servo_display_for_hypothetical_box::derive_from_display(&context); + Arc::make_mut(&mut context.style.inheritedtext)._servo_text_decorations_in_effect = + longhands::_servo_text_decorations_in_effect::derive_from_display(&context); } </%self:longhand> @@ -560,7 +522,10 @@ pub mod longhands { #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - if context.positioned { + let positioned = matches!(context.style.box_.position, + longhands::position::SpecifiedValue::absolute | + longhands::position::SpecifiedValue::fixed); + if positioned { SpecifiedValue::none } else { *self @@ -581,14 +546,9 @@ pub mod longhands { } #[inline] - pub fn derive_from_display(computed_value: super::display::computed_value::T, - context: &computed::Context) + pub fn derive_from_display(context: &computed::Context) -> computed_value::T { - if context.is_root_element { - computed_value - } else { - context.display - } + context.style.box_.display } </%self:longhand> @@ -1876,7 +1836,7 @@ pub mod longhands { % for weight in range(100, 901, 100): SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight}, % endfor - SpecifiedValue::Bolder => match context.inherited_font_weight { + SpecifiedValue::Bolder => match context.inherited_style.font.font_weight { computed_value::T::Weight100 => computed_value::T::Weight400, computed_value::T::Weight200 => computed_value::T::Weight400, computed_value::T::Weight300 => computed_value::T::Weight400, @@ -1887,7 +1847,7 @@ pub mod longhands { computed_value::T::Weight800 => computed_value::T::Weight900, computed_value::T::Weight900 => computed_value::T::Weight900, }, - SpecifiedValue::Lighter => match context.inherited_font_weight { + SpecifiedValue::Lighter => match context.inherited_style.font.font_weight { computed_value::T::Weight100 => computed_value::T::Weight100, computed_value::T::Weight200 => computed_value::T::Weight100, computed_value::T::Weight300 => computed_value::T::Weight100, @@ -1909,6 +1869,7 @@ pub mod longhands { use std::fmt; use values::FONT_MEDIUM_PX; use values::computed::Context; + use values::specified::{LengthOrPercentage, Length, Percentage}; impl ToCss for SpecifiedValue { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -1931,8 +1892,25 @@ pub mod longhands { #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - // We already computed this element's font size; no need to compute it again. - return context.font_size + match self.0 { + LengthOrPercentage::Length(Length::FontRelative(value)) => { + value.to_computed_value(context.inherited_style.font.font_size, + context.style.root_font_size) + } + LengthOrPercentage::Length(Length::ServoCharacterWidth(value)) => { + value.to_computed_value(context.inherited_style.font.font_size) + } + LengthOrPercentage::Length(l) => { + l.to_computed_value(&context) + } + LengthOrPercentage::Percentage(Percentage(value)) => { + context.inherited_style.font.font_size.scale_by(value) + } + LengthOrPercentage::Calc(calc) => { + let calc = calc.to_computed_value(&context); + calc.length() + context.inherited_style.font.font_size.scale_by(calc.percentage()) + } + } } } /// <length> | <percentage> | <absolute-size> | <relative-size> @@ -2229,17 +2207,15 @@ pub mod longhands { if !empty { Ok(result) } else { Err(()) } } - fn cascade_property_custom(computed_value: &computed_value::T, + fn cascade_property_custom(_computed_value: &computed_value::T, _declaration: &PropertyDeclaration, - style: &mut ComputedValues, _inherited_style: &ComputedValues, - context: &computed::Context, + context: &mut computed::Context, _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut Box<ParseErrorReporter + Send>) { - Arc::make_mut(&mut style.inheritedtext)._servo_text_decorations_in_effect = + Arc::make_mut(&mut context.style.inheritedtext)._servo_text_decorations_in_effect = longhands::_servo_text_decorations_in_effect::derive_from_text_decoration( - *computed_value, &context); } </%self:longhand> @@ -2284,7 +2260,7 @@ pub mod longhands { fn maybe(flag: bool, context: &computed::Context) -> Option<RGBA> { if flag { - Some(context.color) + Some(context.style.color.color) } else { None } @@ -2293,9 +2269,9 @@ pub mod longhands { fn derive(context: &computed::Context) -> computed_value::T { // Start with no declarations if this is a block; otherwise, start with the // declarations in effect and add in the text decorations that this inline specifies. - let mut result = match context.display { + let mut result = match context.style.box_.display { super::display::computed_value::T::inline => { - context.inherited_text_decorations_in_effect + context.inherited_style.inheritedtext._servo_text_decorations_in_effect } _ => { SpecifiedValue { @@ -2307,27 +2283,25 @@ pub mod longhands { }; if result.underline.is_none() { - result.underline = maybe(context.text_decoration.underline, context) + result.underline = maybe(context.style.text.text_decoration.underline, context) } if result.overline.is_none() { - result.overline = maybe(context.text_decoration.overline, context) + result.overline = maybe(context.style.text.text_decoration.overline, context) } if result.line_through.is_none() { - result.line_through = maybe(context.text_decoration.line_through, context) + result.line_through = maybe(context.style.text.text_decoration.line_through, context) } result } #[inline] - pub fn derive_from_text_decoration(_: super::text_decoration::computed_value::T, - context: &computed::Context) + pub fn derive_from_text_decoration(context: &computed::Context) -> computed_value::T { derive(context) } #[inline] - pub fn derive_from_display(_: super::display::computed_value::T, - context: &computed::Context) + pub fn derive_from_display(context: &computed::Context) -> computed_value::T { derive(context) } @@ -6417,21 +6391,34 @@ lazy_static! { /// Fast path for the function below. Only computes new inherited styles. #[allow(unused_mut)] fn cascade_with_cached_declarations( + viewport_size: Size2D<Au>, applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>], shareable: bool, parent_style: &ComputedValues, cached_style: &ComputedValues, custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, - context: &computed::Context, mut error_reporter: Box<ParseErrorReporter + Send>) -> ComputedValues { - % for style_struct in STYLE_STRUCTS: - % if style_struct.inherited: - let mut style_${style_struct.ident} = parent_style.${style_struct.ident}.clone(); - % else: - let mut style_${style_struct.ident} = cached_style.${style_struct.ident}.clone(); - % endif - % endfor + let mut context = computed::Context { + is_root_element: false, + viewport_size: viewport_size, + inherited_style: parent_style, + style: ComputedValues { + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: + % if style_struct.inherited: + parent_style + % else: + cached_style + % endif + .${style_struct.ident}.clone(), + % endfor + custom_properties: custom_properties, + shareable: shareable, + writing_mode: WritingMode::empty(), + root_font_size: parent_style.root_font_size, + }, + }; let mut seen = PropertyBitField::new(); // Declaration blocks are stored in increasing precedence order, // we want them in decreasing order here. @@ -6452,9 +6439,10 @@ fn cascade_with_cached_declarations( seen.set_${property.ident}(); let computed_value = substitute_variables_${property.ident}( - declared_value, &custom_properties, |value| match *value { + declared_value, &context.style.custom_properties, + |value| match *value { DeclaredValue::Value(ref specified_value) - => specified_value.to_computed_value(context), + => specified_value.to_computed_value(&context), DeclaredValue::Initial => longhands::${property.ident}::get_initial_value(), DeclaredValue::Inherit => { @@ -6469,23 +6457,17 @@ fn cascade_with_cached_declarations( DeclaredValue::WithVariables { .. } => unreachable!() }, &mut error_reporter ); - Arc::make_mut(&mut style_${style_struct.ident}) + Arc::make_mut(&mut context.style.${style_struct.ident}) .${property.ident} = computed_value; % endif % if property.name in DERIVED_LONGHANDS: - % if not style_struct.inherited: - // Use the cached value. - let computed_value = style_${style_struct.ident} - .${property.ident}.clone(); - % endif % for derived in DERIVED_LONGHANDS[property.name]: - Arc::make_mut(&mut style_${derived.style_struct.ident}) + Arc::make_mut(&mut context.style.${derived.style_struct.ident}) .${derived.ident} = longhands::${derived.ident} ::derive_from_${property.ident}( - computed_value, - context); + &context); % endfor % endif } @@ -6503,24 +6485,15 @@ fn cascade_with_cached_declarations( if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || seen.get_font_family() { - compute_font_hash(&mut *Arc::make_mut(&mut style_font)) + compute_font_hash(&mut *Arc::make_mut(&mut context.style.font)) } - ComputedValues { - writing_mode: get_writing_mode(&*style_inheritedbox), - % for style_struct in STYLE_STRUCTS: - ${style_struct.ident}: style_${style_struct.ident}, - % endfor - custom_properties: custom_properties, - shareable: shareable, - root_font_size: parent_style.root_font_size, - } + context.style } type CascadePropertyFn = extern "Rust" fn(declaration: &PropertyDeclaration, - style: &mut ComputedValues, inherited_style: &ComputedValues, - context: &computed::Context, + context: &mut computed::Context, seen: &mut PropertyBitField, cacheable: &mut bool, error_reporter: &mut Box<ParseErrorReporter + Send>); @@ -6595,163 +6568,39 @@ pub fn cascade(viewport_size: Size2D<Au>, let custom_properties = ::custom_properties::finish_cascade( custom_properties, &inherited_style.custom_properties); - let mut context = { - let inherited_font_style = inherited_style.get_font(); - computed::Context { - is_root_element: is_root_element, - viewport_size: viewport_size, - inherited_font_weight: inherited_font_style.font_weight, - inherited_font_size: inherited_font_style.font_size, - inherited_text_decorations_in_effect: - inherited_style.get_inheritedtext()._servo_text_decorations_in_effect, - // To be overridden by applicable declarations: - font_size: inherited_font_style.font_size, - root_font_size: inherited_style.root_font_size, - display: longhands::display::get_initial_value(), - color: inherited_style.get_color().color, - text_decoration: longhands::text_decoration::get_initial_value(), - positioned: false, - floated: false, - border_top_present: false, - border_right_present: false, - border_bottom_present: false, - border_left_present: false, - outline_style_present: false, - } - }; - - // This assumes that the computed and specified values have the same Rust type. - macro_rules! get_specified( - ($style_struct_getter: ident, $property: ident, $declared_value: expr, $error_reporter: expr) => { - concat_idents!(substitute_variables_, $property)( - $declared_value, &custom_properties, |value| match *value { - DeclaredValue::Value(specified_value) => specified_value, - DeclaredValue::Initial => longhands::$property::get_initial_value(), - DeclaredValue::Inherit => { - inherited_style.$style_struct_getter().$property.clone() - } - DeclaredValue::WithVariables { .. } => unreachable!() - }, &mut $error_reporter - ) - }; - ); - - // Initialize `context` - // Declarations blocks are already stored in increasing precedence order. - for sub_list in applicable_declarations { - use values::specified::{LengthOrPercentage, Percentage}; - // Declarations are stored in reverse source order, we want them in forward order here. - for declaration in sub_list.declarations.iter().rev() { - match *declaration { - PropertyDeclaration::FontSize(ref value) => { - context.font_size = substitute_variables_font_size( - value, &custom_properties, |value| match *value { - DeclaredValue::Value(ref specified_value) => { - match specified_value.0 { - LengthOrPercentage::Length(Length::FontRelative(value)) => { - value.to_computed_value(context.inherited_font_size, - context.root_font_size) - } - LengthOrPercentage::Length(Length::ServoCharacterWidth(value)) => { - value.to_computed_value(context.inherited_font_size) - } - LengthOrPercentage::Length(l) => { - l.to_computed_value(&context) - } - LengthOrPercentage::Percentage(Percentage(value)) => { - context.inherited_font_size.scale_by(value) - } - LengthOrPercentage::Calc(calc) => { - let calc = calc.to_computed_value(&context); - calc.length() + context.inherited_font_size.scale_by(calc.percentage()) - } - } - } - DeclaredValue::Initial => longhands::font_size::get_initial_value(), - DeclaredValue::Inherit => context.inherited_font_size, - DeclaredValue::WithVariables { .. } => unreachable!(), - }, &mut error_reporter - ); - } - PropertyDeclaration::Color(ref value) => { - context.color = substitute_variables_color( - value, &custom_properties, |value| match *value { - DeclaredValue::Value(ref specified_value) => { - specified_value.parsed - } - DeclaredValue::Initial => longhands::color::get_initial_value(), - DeclaredValue::Inherit => inherited_style.get_color().color.clone(), - DeclaredValue::WithVariables { .. } => unreachable!(), - }, &mut error_reporter - ); - } - PropertyDeclaration::Display(ref value) => { - context.display = get_specified!(get_box, display, value, error_reporter); - } - PropertyDeclaration::Position(ref value) => { - context.positioned = match get_specified!(get_box, position, value, error_reporter) { - longhands::position::SpecifiedValue::absolute | - longhands::position::SpecifiedValue::fixed => true, - _ => false, - } - } - PropertyDeclaration::Float(ref value) => { - context.floated = get_specified!(get_box, float, value, error_reporter) - != longhands::float::SpecifiedValue::none; - } - PropertyDeclaration::TextDecoration(ref value) => { - context.text_decoration = get_specified!(get_text, text_decoration, value, error_reporter); - } - PropertyDeclaration::OutlineStyle(ref value) => { - context.outline_style_present = - match get_specified!(get_outline, outline_style, value, error_reporter) { - BorderStyle::none => false, - _ => true, - }; - } - % for side in ["top", "right", "bottom", "left"]: - PropertyDeclaration::Border${side.capitalize()}Style(ref value) => { - context.border_${side}_present = - match get_specified!(get_border, border_${side}_style, value, error_reporter) { - BorderStyle::none | BorderStyle::hidden => false, - _ => true, - }; - } - % endfor - _ => {} - } - } - } - - match (cached_style, parent_style) { - (Some(cached_style), Some(parent_style)) => { - return (cascade_with_cached_declarations(applicable_declarations, + if let (Some(cached_style), Some(parent_style)) = (cached_style, parent_style) { + let style = cascade_with_cached_declarations(viewport_size, + applicable_declarations, shareable, parent_style, cached_style, custom_properties, - &context, - error_reporter), false) - } - (_, _) => {} + error_reporter); + return (style, false) } - // Set computed values, overwriting earlier declarations for the same property. - let mut style = ComputedValues { - % for style_struct in STYLE_STRUCTS: - ${style_struct.ident}: - % if style_struct.inherited: - inherited_style - % else: - initial_values - % endif - .${style_struct.ident}.clone(), - % endfor - custom_properties: custom_properties, - shareable: shareable, - writing_mode: WritingMode::empty(), - root_font_size: context.root_font_size, + let mut context = computed::Context { + is_root_element: is_root_element, + viewport_size: viewport_size, + inherited_style: inherited_style, + style: ComputedValues { + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: + % if style_struct.inherited: + inherited_style + % else: + initial_values + % endif + .${style_struct.ident}.clone(), + % endfor + custom_properties: custom_properties, + shareable: shareable, + writing_mode: WritingMode::empty(), + root_font_size: inherited_style.root_font_size, + }, }; + + // Set computed values, overwriting earlier declarations for the same property. let mut cacheable = true; let mut seen = PropertyBitField::new(); // Declaration blocks are stored in increasing precedence order, we want them in decreasing @@ -6761,26 +6610,83 @@ pub fn cascade(viewport_size: Size2D<Au>, // of compiled code! To improve i-cache behavior, we outline the individual functions and use // virtual dispatch instead. CASCADE_PROPERTY.with(|cascade_property| { - for sub_list in applicable_declarations.iter().rev() { - // Declarations are already stored in reverse order. - for declaration in sub_list.declarations.iter() { - if let PropertyDeclaration::Custom(..) = *declaration { - continue + % for category_to_cascade_now in ["early", "other"]: + for sub_list in applicable_declarations.iter().rev() { + // Declarations are already stored in reverse order. + for declaration in sub_list.declarations.iter() { + if let PropertyDeclaration::Custom(..) = *declaration { + continue + } + // The computed value of some properties depends on the (sometimes computed) + // value of *other* properties. + // So we classify properties into "early" and "other", + // such that the only dependencies can be from "other" to "early". + // We iterate applicable_declarations twice, first cascading "early" properties + // then "other". + // Unfortunately, it’s not easy to check that this classification is correct. + let is_early_property = matches!(*declaration, + PropertyDeclaration::FontSize(_) | + PropertyDeclaration::Color(_) | + PropertyDeclaration::Position(_) | + PropertyDeclaration::Float(_) | + PropertyDeclaration::TextDecoration(_) + ); + if + % if category_to_cascade_now == "early": + ! + % endif + is_early_property + { + continue + } + let discriminant = unsafe { + intrinsics::discriminant_value(declaration) as usize + }; + (cascade_property[discriminant].unwrap())(declaration, + inherited_style, + &mut context, + &mut seen, + &mut cacheable, + &mut error_reporter); } - let discriminant = unsafe { - intrinsics::discriminant_value(declaration) as usize - }; - (cascade_property[discriminant].unwrap())(declaration, - &mut style, - inherited_style, - &context, - &mut seen, - &mut cacheable, - &mut error_reporter); } - } + % endfor }); + let mut style = context.style; + + let positioned = matches!(style.box_.position, + longhands::position::SpecifiedValue::absolute | + longhands::position::SpecifiedValue::fixed); + let floated = style.box_.float != longhands::float::SpecifiedValue::none; + if positioned || floated || is_root_element { + use computed_values::display::T; + + let specified_display = style.box_.display; + let computed_display = match specified_display { + T::inline_table => { + Some(T::table) + } + T::inline | T::inline_block | + T::table_row_group | T::table_column | + T::table_column_group | T::table_header_group | + T::table_footer_group | T::table_row | T::table_cell | + T::table_caption => { + Some(T::block) + } + _ => None + }; + if let Some(computed_display) = computed_display { + let box_ = Arc::make_mut(&mut style.box_); + box_.display = computed_display; + box_._servo_display_for_hypothetical_box = if is_root_element { + computed_display + } else { + specified_display + }; + } + } + { use computed_values::overflow_x::T as overflow; use computed_values::overflow_y; @@ -6797,35 +6703,21 @@ pub fn cascade(viewport_size: Size2D<Au>, } // The initial value of border-*-width may be changed at computed value time. - { - let border = Arc::make_mut(&mut style.border); - % for side in ["top", "right", "bottom", "left"]: - // Like calling to_computed_value, which wouldn't type check. - if !context.border_${side}_present { - border.border_${side}_width = Au(0); - } - % endfor - } - - // The initial value of display may be changed at computed value time. - if !seen.get_display() { - let box_ = Arc::make_mut(&mut style.box_); - let computed_value = box_.display.to_computed_value(&context); - box_.display = computed_value; - box_._servo_display_for_hypothetical_box = - longhands::_servo_display_for_hypothetical_box::derive_from_display( - computed_value, - &context); - } + % for side in ["top", "right", "bottom", "left"]: + // Like calling to_computed_value, which wouldn't type check. + if style.border.border_${side}_style.none_or_hidden() && + style.border.border_${side}_width != Au(0) { + Arc::make_mut(&mut style.border).border_${side}_width = Au(0); + } + % endfor // The initial value of outline width may be changed at computed value time. - if !context.outline_style_present { - let outline = Arc::make_mut(&mut style.outline); - outline.outline_width = Au(0); + if style.outline.outline_style.none_or_hidden() && style.outline.outline_width != Au(0) { + Arc::make_mut(&mut style.outline).outline_width = Au(0); } if is_root_element { - style.root_font_size = context.font_size; + style.root_font_size = style.font.font_size; } if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || diff --git a/components/style/values.rs b/components/style/values.rs index ad176f550a4..e3e59856970 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -1377,6 +1377,12 @@ pub mod specified { "outset" => outset = 2, } + impl BorderStyle { + pub fn none_or_hidden(&self) -> bool { + matches!(*self, BorderStyle::none | BorderStyle::hidden) + } + } + /// A time in seconds according to CSS-VALUES § 6.2. #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, HeapSizeOf)] pub struct Time(pub CSSFloat); @@ -1431,7 +1437,7 @@ pub mod specified { pub mod computed { use app_units::Au; use euclid::size::Size2D; - use properties::longhands; + use properties::ComputedValues; use std::fmt; use super::AuExtensionMethods; use super::specified::AngleOrCorner; @@ -1440,26 +1446,14 @@ pub mod computed { pub use cssparser::Color as CSSColor; pub use super::specified::{Angle, BorderStyle, Time}; - pub struct Context { - pub inherited_font_weight: longhands::font_weight::computed_value::T, - pub inherited_font_size: longhands::font_size::computed_value::T, - pub inherited_text_decorations_in_effect: - longhands::_servo_text_decorations_in_effect::computed_value::T, - pub color: longhands::color::computed_value::T, - pub text_decoration: longhands::text_decoration::computed_value::T, - pub font_size: longhands::font_size::computed_value::T, - pub root_font_size: longhands::font_size::computed_value::T, - pub display: longhands::display::computed_value::T, - pub positioned: bool, - pub floated: bool, - pub border_top_present: bool, - pub border_right_present: bool, - pub border_bottom_present: bool, - pub border_left_present: bool, + pub struct Context<'a> { pub is_root_element: bool, pub viewport_size: Size2D<Au>, - pub outline_style_present: bool, - // TODO, as needed: viewport size, etc. + pub inherited_style: &'a ComputedValues, + + /// Values access through this need to be in the properties "computed early": + /// color, text-decoration, font-size, display, position, float, border-*-style, outline-style + pub style: ComputedValues, } pub trait ToComputedValue { @@ -1500,11 +1494,12 @@ pub mod computed { specified::Length::Absolute(length) => length, specified::Length::Calc(calc) => calc.to_computed_value(context).length(), specified::Length::FontRelative(length) => - length.to_computed_value(context.font_size, context.root_font_size), + length.to_computed_value(context.style.get_font().font_size, + context.style.root_font_size), specified::Length::ViewportPercentage(length) => length.to_computed_value(context.viewport_size), specified::Length::ServoCharacterWidth(length) => - length.to_computed_value(context.font_size) + length.to_computed_value(context.style.get_font().font_size) } } } @@ -1603,8 +1598,8 @@ pub mod computed { } for val in &[self.ch, self.em, self.ex, self.rem] { if let Some(val) = *val { - length = Some(length.unwrap_or(Au(0)) + - val.to_computed_value(context.font_size, context.root_font_size)); + length = Some(length.unwrap_or(Au(0)) + val.to_computed_value( + context.style.get_font().font_size, context.style.root_font_size)); } } diff --git a/components/style/viewport.rs b/components/style/viewport.rs index fddf03ca8fe..53c6d5bcbc2 100644 --- a/components/style/viewport.rs +++ b/components/style/viewport.rs @@ -8,7 +8,7 @@ use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; use parser::{ParserContext, log_css_error}; -use properties::longhands; +use properties::INITIAL_VALUES; use std::ascii::AsciiExt; use std::collections::hash_map::{Entry, HashMap}; use std::fmt; @@ -594,21 +594,8 @@ impl MaybeNew for ViewportConstraints { let context = Context { is_root_element: false, viewport_size: initial_viewport, - inherited_font_weight: longhands::font_weight::get_initial_value(), - inherited_font_size: longhands::font_size::get_initial_value(), - inherited_text_decorations_in_effect: longhands::_servo_text_decorations_in_effect::get_initial_value(), - font_size: longhands::font_size::get_initial_value(), - root_font_size: longhands::font_size::get_initial_value(), - display: longhands::display::get_initial_value(), - color: longhands::color::get_initial_value(), - text_decoration: longhands::text_decoration::get_initial_value(), - positioned: false, - floated: false, - border_top_present: false, - border_right_present: false, - border_bottom_present: false, - border_left_present: false, - outline_style_present: false, + inherited_style: &*INITIAL_VALUES, + style: INITIAL_VALUES.clone(), }; // DEVICE-ADAPT § 9.3 Resolving 'extend-to-zoom' |