style: Separate out style structs into inherited and initial structs.

This doesn't make much of a difference in performance, but will be
necessary for style struct sharing.
This commit is contained in:
Patrick Walton 2014-02-07 10:28:22 -08:00
parent 6b89cbf3c5
commit 758f5ba755
6 changed files with 251 additions and 175 deletions

View file

@ -719,7 +719,7 @@ impl Flow for BlockFlow {
let style = box_.style();
// The text alignment of a block flow is the text alignment of its box's style.
self.base.flags_info.flags.set_text_align(style.Text.text_align);
self.base.flags_info.flags.set_text_align(style.InheritedText.text_align);
box_.assign_width(remaining_width);
// Can compute padding here since we know containing block width.

View file

@ -781,11 +781,11 @@ impl Box {
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
/// node.
pub fn text_align(&self) -> text_align::T {
self.style().Text.text_align
self.style().InheritedText.text_align
}
pub fn line_height(&self) -> line_height::T {
self.style().Box.line_height
self.style().InheritedBox.line_height
}
pub fn vertical_align(&self) -> vertical_align::T {
@ -793,7 +793,7 @@ impl Box {
}
pub fn white_space(&self) -> white_space::T {
self.style().Text.white_space
self.style().InheritedText.white_space
}
/// Returns the text decoration of this box, according to the style of the nearest ancestor
@ -1029,7 +1029,7 @@ impl Box {
box_bounds, absolute_box_bounds, self.debug_str());
debug!("Box::build_display_list: dirty={}, offset={}", *dirty, offset);
if self.style().Box.visibility != visibility::visible {
if self.style().InheritedBox.visibility != visibility::visible {
return;
}

View file

@ -730,7 +730,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
//
// If you implement other values for this property, you will almost certainly
// want to update this check.
match self.style().get().Text.white_space {
match self.style().get().InheritedText.white_space {
white_space::normal => true,
_ => false,
}

View file

@ -134,7 +134,7 @@ pub fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> RestyleDama
Padding.padding_top, Padding.padding_right, Padding.padding_bottom, Padding.padding_left,
Box.position, Box.width, Box.height, Box.float, Box.display,
Font.font_family, Font.font_size, Font.font_style, Font.font_weight,
Text.text_align, Text.text_decoration, Box.line_height ]);
InheritedText.text_align, Text.text_decoration, InheritedBox.line_height ]);
// FIXME: test somehow that we checked every CSS property

View file

@ -169,21 +169,24 @@ pub mod computed {
pub struct Context {
current_color: cssparser::RGBA,
parent_font_size: Au,
font_size: Au,
font_weight: longhands::font_weight::computed_value::T,
position: longhands::position::SpecifiedValue,
float: longhands::float::SpecifiedValue,
is_root_element: bool,
has_border_top: bool,
has_border_right: bool,
has_border_bottom: bool,
has_border_left: bool,
border_top_style: longhands::border_top_style::computed_value::T,
border_right_style: longhands::border_top_style::computed_value::T,
border_bottom_style: longhands::border_top_style::computed_value::T,
border_left_style: longhands::border_top_style::computed_value::T,
// TODO, as needed: root font size, viewport size, etc.
}
pub fn compute_Au(value: specified::Length, context: &Context) -> Au {
#[inline]
pub fn compute_Au(value: specified::Length, context: &Context, em_is_parent: bool) -> Au {
match value {
specified::Au_(value) => value,
specified::Em(value) if em_is_parent => context.parent_font_size.scale_by(value),
specified::Em(value) => context.font_size.scale_by(value),
specified::Ex(value) => {
let x_height = 0.5; // TODO: find that from the font
@ -200,7 +203,7 @@ pub mod computed {
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
-> LengthOrPercentage {
match value {
specified::LP_Length(value) => LP_Length(compute_Au(value, context)),
specified::LP_Length(value) => LP_Length(compute_Au(value, context, false)),
specified::LP_Percentage(value) => LP_Percentage(value),
}
}
@ -214,7 +217,7 @@ pub mod computed {
pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto,
context: &Context) -> LengthOrPercentageOrAuto {
match value {
specified::LPA_Length(value) => LPA_Length(compute_Au(value, context)),
specified::LPA_Length(value) => LPA_Length(compute_Au(value, context, false)),
specified::LPA_Percentage(value) => LPA_Percentage(value),
specified::LPA_Auto => LPA_Auto,
}
@ -229,7 +232,7 @@ pub mod computed {
pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone,
context: &Context) -> LengthOrPercentageOrNone {
match value {
specified::LPN_Length(value) => LPN_Length(compute_Au(value, context)),
specified::LPN_Length(value) => LPN_Length(compute_Au(value, context, false)),
specified::LPN_Percentage(value) => LPN_Percentage(value),
specified::LPN_None => LPN_None,
}

View file

@ -25,43 +25,61 @@ def to_rust_ident(name):
return name
class Longhand(object):
def __init__(self, name, is_inherited):
def __init__(self, name, priority):
self.name = name
self.ident = to_rust_ident(name)
self.is_inherited = is_inherited
self.style_struct = THIS_STYLE_STRUCT
self.priority = priority
class Shorthand(object):
def __init__(self, name, sub_properties):
def __init__(self, name, priority, sub_properties):
self.name = name
self.ident = to_rust_ident(name)
self.sub_properties = [LONGHANDS_BY_NAME[s] for s in sub_properties]
self.priority = priority
LONGHANDS_PER_STYLE_STRUCT = []
THIS_STYLE_STRUCT_LONGHANDS = None
class StyleStruct(object):
def __init__(self, name, inherited):
self.name = name
self.longhands = []
self.inherited = inherited
STYLE_STRUCTS = []
THIS_STYLE_STRUCT = None
LONGHANDS = []
LONGHANDS_BY_NAME = {}
SHORTHANDS = []
def new_style_struct(name):
longhands = []
LONGHANDS_PER_STYLE_STRUCT.append((name, longhands))
global THIS_STYLE_STRUCT_LONGHANDS
THIS_STYLE_STRUCT_LONGHANDS = longhands
def new_style_struct(name, is_inherited):
global THIS_STYLE_STRUCT
style_struct = StyleStruct(name, is_inherited)
STYLE_STRUCTS.append(style_struct)
THIS_STYLE_STRUCT = style_struct
return ""
def switch_to_style_struct(name):
global THIS_STYLE_STRUCT
for style_struct in STYLE_STRUCTS:
if style_struct.name == name:
THIS_STYLE_STRUCT = style_struct
return ""
fail()
%>
pub mod longhands {
pub use super::*;
pub use std;
pub fn computed_as_specified<T>(value: T, _context: &computed::Context) -> T { value }
pub fn computed_as_specified<T>(value: T, _context: &mut computed::Context) -> T {
value
}
<%def name="raw_longhand(name, inherited=False, no_super=False)">
<%def name="raw_longhand(name, priority='Normal', no_super=False)">
<%
property = Longhand(name, inherited)
THIS_STYLE_STRUCT_LONGHANDS.append(property)
property = Longhand(name, priority)
THIS_STYLE_STRUCT.longhands.append(property)
LONGHANDS.append(property)
LONGHANDS_BY_NAME[name] = property
%>
@ -76,15 +94,15 @@ pub mod longhands {
match CSSWideKeyword::parse(input) {
Some(Some(keyword)) => Some(CSSWideKeyword(keyword)),
Some(None) => Some(CSSWideKeyword(${
"Inherit" if inherited else "Initial"})),
"Inherit" if THIS_STYLE_STRUCT.inherited else "Initial"})),
None => parse_specified(input),
}
}
}
</%def>
<%def name="longhand(name, inherited=False, no_super=False)">
<%self:raw_longhand name="${name}" inherited="${inherited}">
<%def name="longhand(name, priority='Normal', no_super=False)">
<%self:raw_longhand name="${name}" priority="${priority}">
${caller.body()}
pub fn parse_specified(input: &[ComponentValue])
-> Option<DeclaredValue<SpecifiedValue>> {
@ -93,8 +111,8 @@ pub mod longhands {
</%self:raw_longhand>
</%def>
<%def name="single_component_value(name, inherited=False)">
<%self:longhand name="${name}" inherited="${inherited}">
<%def name="single_component_value(name, priority='Normal')">
<%self:longhand name="${name}" priority="${priority}">
${caller.body()}
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
one_component_value(input).and_then(from_component_value)
@ -102,8 +120,8 @@ pub mod longhands {
</%self:longhand>
</%def>
<%def name="single_keyword_computed(name, values, inherited=False)">
<%self:single_component_value name="${name}" inherited="${inherited}">
<%def name="single_keyword_computed(name, values, priority='Normal')">
<%self:single_component_value name="${name}" priority="${priority}">
${caller.body()}
pub mod computed_value {
#[deriving(Eq, Clone, FromPrimitive)]
@ -130,15 +148,15 @@ pub mod longhands {
</%self:single_component_value>
</%def>
<%def name="single_keyword(name, values, inherited=False)">
<%self:single_keyword_computed name="${name}" values="${values}" inherited="${inherited}">
<%def name="single_keyword(name, values, priority='Normal')">
<%self:single_keyword_computed name="${name}" values="${values}" priority="${priority}">
// The computed value is the same as the specified value.
pub use to_computed_value = super::computed_as_specified;
</%self:single_keyword_computed>
</%def>
<%def name="predefined_type(name, type, initial_value, parse_method='parse', inherited=False)">
<%self:single_component_value name="${name}" inherited="${inherited}">
<%def name="predefined_type(name, type, initial_value, parse_method='parse')">
<%self:single_component_value name="${name}">
pub use to_computed_value = super::super::common_types::computed::compute_${type};
pub type SpecifiedValue = specified::${type};
pub mod computed_value {
@ -154,14 +172,14 @@ pub mod longhands {
// CSS 2.1, Section 8 - Box model
${new_style_struct("Margin")}
${new_style_struct("Margin", False)}
% for side in ["top", "right", "bottom", "left"]:
${predefined_type("margin-" + side, "LengthOrPercentageOrAuto",
"computed::LPA_Length(Au(0))")}
% endfor
${new_style_struct("Padding")}
${new_style_struct("Padding", False)}
% for side in ["top", "right", "bottom", "left"]:
${predefined_type("padding-" + side, "LengthOrPercentage",
@ -169,17 +187,33 @@ pub mod longhands {
"parse_non_negative")}
% endfor
${new_style_struct("Border")}
${new_style_struct("Border", False)}
% for side in ["top", "right", "bottom", "left"]:
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
% endfor
// double groove ridge insed outset
${single_keyword("border-top-style", "none solid dotted dashed hidden")}
<%self:single_keyword_computed name="border-top-style"
values="none solid dotted dashed hidden"
priority="High">
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
-> computed_value::T {
context.border_top_style = value;
value
}
</%self:single_keyword_computed>
% for side in ["right", "bottom", "left"]:
<%self:longhand name="border-${side}-style", no_super="True">
pub use super::border_top_style::*;
<%self:longhand name="border-${side}-style", no_super="True", priority="High">
pub use super::border_top_style::get_initial_value;
pub use super::border_top_style::parse;
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
-> computed_value::T {
context.border_${side}_style = value;
value
}
pub type SpecifiedValue = super::border_top_style::SpecifiedValue;
pub mod computed_value {
pub type T = super::super::border_top_style::computed_value::T;
@ -204,6 +238,7 @@ pub mod longhands {
}
% for side in ["top", "right", "bottom", "left"]:
<%self:longhand name="border-${side}-width">
use super::super::border_is_present;
pub type SpecifiedValue = specified::Length;
pub mod computed_value {
use super::super::Au;
@ -215,15 +250,18 @@ pub mod longhands {
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
one_component_value(input).and_then(parse_border_width)
}
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
-> computed_value::T {
if context.has_border_${side} { computed::compute_Au(value, context) }
else { Au(0) }
if !border_is_present(context.border_${side}_style) {
Au(0)
} else {
computed::compute_Au(value, context, false)
}
}
</%self:longhand>
% endfor
${new_style_struct("PositionOffsets")}
${new_style_struct("PositionOffsets", False)}
% for side in ["top", "right", "bottom", "left"]:
${predefined_type(side, "LengthOrPercentageOrAuto",
@ -232,7 +270,7 @@ pub mod longhands {
// CSS 2.1, Section 9 - Visual formatting model
${new_style_struct("Box")}
${new_style_struct("Box", False)}
// TODO: don't parse values we don't support
<%self:single_keyword_computed name="display"
@ -286,8 +324,9 @@ pub mod longhands {
"computed::LPN_None",
"parse_non_negative")}
${new_style_struct("InheritedBox", True)}
<%self:single_component_value name="line-height" inherited="True">
<%self:single_component_value name="line-height">
#[deriving(Clone)]
pub enum SpecifiedValue {
SpecifiedNormal,
@ -324,12 +363,14 @@ pub mod longhands {
-> computed_value::T {
match value {
SpecifiedNormal => Normal,
SpecifiedLength(value) => Length(computed::compute_Au(value, context)),
SpecifiedLength(value) => Length(computed::compute_Au(value, context, false)),
SpecifiedNumber(value) => Number(value),
}
}
</%self:single_component_value>
${switch_to_style_struct("Box")}
<%self:single_component_value name="vertical-align">
<% vertical_align_keywords = (
"baseline sub super top text-top middle bottom text-bottom".split()) %>
@ -387,14 +428,18 @@ pub mod longhands {
// CSS 2.1, Section 11 - Visual effects
${single_keyword("overflow", "visible hidden", inherited=False)} // TODO: scroll auto
${single_keyword("overflow", "visible hidden")} // TODO: scroll auto
${switch_to_style_struct("InheritedBox")}
// TODO: collapse. Well, do tables first.
${single_keyword("visibility", "visible hidden", inherited=True)}
${single_keyword("visibility", "visible hidden")}
// CSS 2.1, Section 12 - Generated content, automatic numbering, and lists
<%self:longhand name="content" inherited="False">
${switch_to_style_struct("Box")}
<%self:longhand name="content">
pub use to_computed_value = super::computed_as_specified;
pub mod computed_value {
#[deriving(Eq, Clone)]
@ -437,15 +482,15 @@ pub mod longhands {
// CSS 2.1, Section 14 - Colors and Backgrounds
${new_style_struct("Background")}
${new_style_struct("Background", False)}
${predefined_type("background-color", "CSSColor",
"RGBA(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}
${new_style_struct("Color")}
${new_style_struct("Color", True)}
<%self:raw_longhand name="color" inherited="True">
<%self:raw_longhand name="color">
pub use to_computed_value = super::computed_as_specified;
pub type SpecifiedValue = RGBA;
pub mod computed_value {
@ -465,9 +510,9 @@ pub mod longhands {
// CSS 2.1, Section 15 - Fonts
${new_style_struct("Font")}
${new_style_struct("Font", True)}
<%self:longhand name="font-family" inherited="True">
<%self:longhand name="font-family">
pub use to_computed_value = super::computed_as_specified;
pub mod computed_value {
#[deriving(Eq, Clone)]
@ -545,10 +590,10 @@ pub mod longhands {
</%self:longhand>
${single_keyword("font-style", "normal italic oblique", inherited=True)}
${single_keyword("font-variant", "normal", inherited=True)} // Add small-caps when supported
${single_keyword("font-style", "normal italic oblique")}
${single_keyword("font-variant", "normal")} // Add small-caps when supported
<%self:single_component_value name="font-weight" inherited="True">
<%self:single_component_value name="font-weight" priority="High">
#[deriving(Clone)]
pub enum SpecifiedValue {
Bolder,
@ -603,9 +648,9 @@ pub mod longhands {
}
}
#[inline] pub fn get_initial_value() -> computed_value::T { Weight400 } // normal
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
-> computed_value::T {
match value {
let result = match value {
% for weight in range(100, 901, 100):
SpecifiedWeight${weight} => Weight${weight},
% endfor
@ -631,17 +676,25 @@ pub mod longhands {
Weight800 => Weight700,
Weight900 => Weight700,
},
}
};
context.font_weight = result;
result
}
</%self:single_component_value>
<%self:single_component_value name="font-size" inherited="True">
<%self:single_component_value name="font-size" priority="High">
pub use to_computed_value = super::super::common_types::computed::compute_Au;
pub type SpecifiedValue = specified::Length; // Percentages are the same as em.
pub mod computed_value {
use super::super::Au;
pub type T = Au;
}
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
-> computed_value::T {
let result = computed::compute_Au(value, context, true);
context.font_size = result;
result
}
#[inline] pub fn get_initial_value() -> computed_value::T {
Au::from_px(16) // medium
}
@ -659,10 +712,12 @@ pub mod longhands {
// CSS 2.1, Section 16 - Text
${new_style_struct("Text")}
${new_style_struct("InheritedText", True)}
// TODO: initial value should be 'start' (CSS Text Level 3, direction-dependent.)
${single_keyword("text-align", "left right center justify", inherited=True)}
${single_keyword("text-align", "left right center justify")}
${new_style_struct("Text", False)}
<%self:longhand name="text-decoration">
pub use to_computed_value = super::computed_as_specified;
@ -709,7 +764,9 @@ pub mod longhands {
}
</%self:longhand>
${single_keyword("white-space", "normal pre", inherited=True)}
${switch_to_style_struct("InheritedText")}
${single_keyword("white-space", "normal pre")}
// CSS 2.1, Section 17 - Tables
@ -721,9 +778,9 @@ pub mod shorthands {
pub use super::*;
pub use super::longhands::*;
<%def name="shorthand(name, sub_properties)">
<%def name="shorthand(name, sub_properties, priority='Normal')">
<%
shorthand = Shorthand(name, sub_properties.split())
shorthand = Shorthand(name, priority, sub_properties.split())
SHORTHANDS.append(shorthand)
%>
pub mod ${shorthand.ident} {
@ -1029,7 +1086,7 @@ impl PropertyDeclaration {
% for sub_property in shorthand.sub_properties:
result_list.push(${sub_property.ident}_declaration(
CSSWideKeyword(${
"Inherit" if sub_property.is_inherited else "Initial"})
"Inherit" if sub_property.style_struct.inherited else "Initial"})
));
% endfor
},
@ -1057,10 +1114,10 @@ impl PropertyDeclaration {
pub mod style_structs {
use super::longhands;
% for name, longhands in LONGHANDS_PER_STYLE_STRUCT:
% for style_struct in STYLE_STRUCTS:
#[deriving(Eq, Clone)]
pub struct ${name} {
% for longhand in longhands:
pub struct ${style_struct.name} {
% for longhand in style_struct.longhands:
${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
% endfor
}
@ -1069,8 +1126,8 @@ pub mod style_structs {
#[deriving(Eq, Clone)]
pub struct ComputedValues {
% for name, longhands in LONGHANDS_PER_STYLE_STRUCT:
${name}: style_structs::${name},
% for style_struct in STYLE_STRUCTS:
${style_struct.name}: style_structs::${style_struct.name},
% endfor
}
@ -1090,111 +1147,127 @@ impl ComputedValues {
}
}
#[inline]
fn get_initial_values() -> ComputedValues {
ComputedValues {
% for style_struct, longhands in LONGHANDS_PER_STYLE_STRUCT:
${style_struct}: style_structs::${style_struct} {
% for longhand in longhands:
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
% endfor
},
% endfor
/// Creates a new cascade context.
fn new_cascade_context(style_Color: &style_structs::Color,
style_Font: &style_structs::Font,
style_Box: &style_structs::Box,
is_root_element: bool)
-> computed::Context {
computed::Context {
current_color: style_Color.color,
parent_font_size: style_Font.font_size,
font_size: style_Font.font_size,
font_weight: style_Font.font_weight,
position: style_Box.position,
float: style_Box.float,
is_root_element: is_root_element,
border_top_style: longhands::border_top_style::get_initial_value(),
border_right_style: longhands::border_top_style::get_initial_value(),
border_bottom_style: longhands::border_top_style::get_initial_value(),
border_left_style: longhands::border_top_style::get_initial_value(),
}
}
fn border_is_present(border_style: longhands::border_top_style::computed_value::T) -> bool {
match border_style {
longhands::border_top_style::hidden | longhands::border_top_style::none => false,
_ => true
}
}
// Most specific/important declarations last
/// Performs the CSS cascade, computing new styles for an element from its parent style and
/// optionally a cached related style. The arguments are:
///
/// * `applicable_declarations`: The list of CSS rules that matched.
///
/// * `parent_style`: The parent style, if applicable; if `None`, this is the root node.
///
/// Returns the computed values.
pub fn cascade(applicable_declarations: &[Arc<~[PropertyDeclaration]>],
parent_style: Option< &ComputedValues >)
-> ComputedValues {
let initial_keep_alive;
let (parent_style, is_root_element) = match parent_style {
Some(s) => (s, false),
let is_root_element;
% for style_struct in STYLE_STRUCTS:
let mut style_${style_struct.name};
% endfor
match parent_style {
Some(parent_style) => {
is_root_element = false;
% for style_struct in STYLE_STRUCTS:
% if style_struct.inherited:
style_${style_struct.name} = parent_style.${style_struct.name}.clone();
% else:
style_${style_struct.name} = style_structs::${style_struct.name} {
% for longhand in style_struct.longhands:
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
% endfor
};
%endif
% endfor
}
None => {
initial_keep_alive = ~get_initial_values();
(&*initial_keep_alive, true)
}
};
struct AllDeclaredValues {
% for property in LONGHANDS:
${property.ident}: DeclaredValue<longhands::${property.ident}::SpecifiedValue>,
% endfor
}
let mut specified = AllDeclaredValues {
% for property in LONGHANDS:
${property.ident}: CSSWideKeyword(${
"Inherit" if property.is_inherited else "Initial"}),
is_root_element = true;
% for style_struct in STYLE_STRUCTS:
style_${style_struct.name} = style_structs::${style_struct.name} {
% for longhand in style_struct.longhands:
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
% endfor
};
% endfor
}
}
let mut context = new_cascade_context(&style_Color, &style_Font, &style_Box, is_root_element);
<%def name="apply(priority)">
for sub_list in applicable_declarations.iter() {
for declaration in sub_list.get().iter() {
match declaration {
% for property in LONGHANDS:
&${property.ident}_declaration(ref value) => {
% for style_struct in STYLE_STRUCTS:
% for property in style_struct.longhands:
% if property.priority == priority:
&${property.ident}_declaration(SpecifiedValue(ref value)) => {
// Overwrite earlier declarations.
// TODO: can we avoid a copy?
specified.${property.ident} = (*value).clone()
style_${style_struct.name}.${property.ident} =
longhands::${property.ident}::to_computed_value(
(*value).clone(),
&mut context)
}
% endfor
&${property.ident}_declaration(CSSWideKeyword(Inherit)) => {
// This is a bit slow, but this is rare so it shouldn't matter.
match parent_style {
None => {
style_${style_struct.name}.${property.ident} =
longhands::${property.ident}::get_initial_value()
}
Some(ref parent_style) => {
style_${style_struct.name}.${property.ident} =
parent_style.${style_struct.name}
.${property.ident}
.clone()
}
}
}
// This assumes that the computed and specified values have the same Rust type.
macro_rules! get_specified(
($style_struct: ident, $property: ident) => {
match specified.$property {
SpecifiedValue(value) => value,
CSSWideKeyword(Initial) => longhands::$property::get_initial_value(),
CSSWideKeyword(Inherit) => parent_style.$style_struct.$property.clone(),
&${property.ident}_declaration(CSSWideKeyword(Initial)) => {
style_${style_struct.name}.${property.ident} =
longhands::${property.ident}::get_initial_value()
}
};
)
macro_rules! has_border(
($property: ident) => {
match get_specified!(Border, $property) {
longhands::border_top_style::none
| longhands::border_top_style::hidden => false,
_ => true,
}
};
)
let context = &mut computed::Context {
current_color: get_specified!(Color, color),
font_size: parent_style.Font.font_size,
font_weight: parent_style.Font.font_weight,
position: get_specified!(Box, position),
float: get_specified!(Box, float),
is_root_element: is_root_element,
has_border_top: has_border!(border_top_style),
has_border_right: has_border!(border_right_style),
has_border_bottom: has_border!(border_bottom_style),
has_border_left: has_border!(border_left_style),
};
macro_rules! get_computed(
($style_struct: ident, $property: ident) => {
match specified.$property {
SpecifiedValue(ref value)
// TODO: avoid a copy?
=> longhands::$property::to_computed_value(value.clone(), context),
CSSWideKeyword(Initial) => longhands::$property::get_initial_value(),
CSSWideKeyword(Inherit) => parent_style.$style_struct.$property.clone(),
}
};
)
context.font_size = get_computed!(Font, font_size);
ComputedValues {
% for style_struct, longhands in LONGHANDS_PER_STYLE_STRUCT:
${style_struct}: style_structs::${style_struct} {
% for longhand in longhands:
${longhand.ident}:
% if longhand.ident == 'font_size':
context.font_size,
% else:
get_computed!(${style_struct}, ${longhand.ident}),
% endif
% endfor
},
% endfor
_ => {}
}
}
}
</%def>
${apply("High")}
${apply("Normal")}
ComputedValues {
% for style_struct in STYLE_STRUCTS:
${style_struct.name}: style_${style_struct.name},
% endfor
}
}