aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2016-03-09 00:33:01 +0100
committerSimon Sapin <simon.sapin@exyr.org>2016-03-18 17:09:16 +0100
commit529164e4a5b0fcca67d5a1fa31f17f87c038eadd (patch)
tree4d4db27a18480f46ff0d0ae5e968817d0324624b
parentbab28e507090b06272bc9f85627ebaa5cdeddd62 (diff)
downloadservo-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.rs492
-rw-r--r--components/style/values.rs41
-rw-r--r--components/style/viewport.rs19
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'