mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
Auto merge of #6364 - pcwalton:debloat-cascade, r=SimonSapin
layout: Outline the individual property cascading functions to reduce I-cache footprint. Reduces the size of `properties::cascade` from over 100K of code to under 5K. Due to the improved I-cache utilization, improves ARM scaling on 4 cores by 15%. r? @SimonSapin (feel free to punt to someone else if you like) <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6364) <!-- Reviewable:end -->
This commit is contained in:
commit
6386addb01
2 changed files with 205 additions and 111 deletions
|
@ -22,8 +22,10 @@ fn main() {
|
|||
.env("PYTHONPATH", &mako)
|
||||
.env("TEMPLATE", &template)
|
||||
.arg("-c")
|
||||
.arg("from os import environ; from mako.template import Template;\
|
||||
print(Template(filename=environ['TEMPLATE']).render())")
|
||||
.arg("from os import environ; from mako.template import Template; \
|
||||
from mako import exceptions; \n\
|
||||
try:\n print(Template(filename=environ['TEMPLATE']).render());\n\
|
||||
except:\n print exceptions.html_error_template().render()")
|
||||
.stderr(Stdio::inherit())
|
||||
.output()
|
||||
.unwrap();
|
||||
|
|
|
@ -10,6 +10,8 @@ use std::default::Default;
|
|||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::intrinsics;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use util::logical_geometry::{LogicalMargin, PhysicalSide, WritingMode};
|
||||
|
@ -44,12 +46,13 @@ def to_camel_case(ident):
|
|||
return re.sub("_([a-z])", lambda m: m.group(1).upper(), ident.strip("_").capitalize())
|
||||
|
||||
class Longhand(object):
|
||||
def __init__(self, name, derived_from=None, experimental=False):
|
||||
def __init__(self, name, derived_from=None, custom_cascade=False, experimental=False):
|
||||
self.name = name
|
||||
self.ident = to_rust_ident(name)
|
||||
self.camel_case = to_camel_case(self.ident)
|
||||
self.style_struct = THIS_STYLE_STRUCT
|
||||
self.experimental = experimental
|
||||
self.custom_cascade = custom_cascade
|
||||
if derived_from is None:
|
||||
self.derived_from = None
|
||||
else:
|
||||
|
@ -98,12 +101,15 @@ def switch_to_style_struct(name):
|
|||
|
||||
pub mod longhands {
|
||||
|
||||
<%def name="raw_longhand(name, derived_from=None, experimental=False)">
|
||||
<%def name="raw_longhand(name, derived_from=None, custom_cascade=False, experimental=False)">
|
||||
<%
|
||||
if derived_from is not None:
|
||||
derived_from = derived_from.split()
|
||||
|
||||
property = Longhand(name, derived_from=derived_from, experimental=experimental)
|
||||
property = Longhand(name,
|
||||
derived_from=derived_from,
|
||||
custom_cascade=custom_cascade,
|
||||
experimental=experimental)
|
||||
THIS_STYLE_STRUCT.longhands.append(property)
|
||||
LONGHANDS.append(property)
|
||||
LONGHANDS_BY_NAME[name] = property
|
||||
|
@ -113,14 +119,69 @@ pub mod longhands {
|
|||
DERIVED_LONGHANDS.setdefault(name, []).append(property)
|
||||
%>
|
||||
pub mod ${property.ident} {
|
||||
#![allow(unused_imports)]
|
||||
% if derived_from is None:
|
||||
use cssparser::Parser;
|
||||
use parser::ParserContext;
|
||||
use properties::{CSSWideKeyword, DeclaredValue};
|
||||
% endif
|
||||
#[allow(unused_imports)]
|
||||
use properties::longhands;
|
||||
use properties::property_bit_field::PropertyBitField;
|
||||
use properties::{ComputedValues, PropertyDeclaration};
|
||||
use values::computed::ToComputedValue;
|
||||
use values::{computed, specified};
|
||||
use std::sync::Arc;
|
||||
${caller.body()}
|
||||
#[allow(unused_variables)]
|
||||
pub fn cascade_property(declaration: &PropertyDeclaration,
|
||||
style: &mut ComputedValues,
|
||||
inherited_style: &ComputedValues,
|
||||
context: &computed::Context,
|
||||
seen: &mut PropertyBitField,
|
||||
cacheable: &mut bool) {
|
||||
let declared_value = match *declaration {
|
||||
PropertyDeclaration::${property.camel_case}(ref declared_value) => {
|
||||
declared_value
|
||||
}
|
||||
_ => panic!("entered the wrong cascade_property() implementation"),
|
||||
};
|
||||
% if property.derived_from is None:
|
||||
if seen.get_${property.ident}() {
|
||||
return
|
||||
}
|
||||
seen.set_${property.ident}();
|
||||
let computed_value = match *declared_value {
|
||||
DeclaredValue::SpecifiedValue(ref specified_value) => {
|
||||
specified_value.to_computed_value(&context)
|
||||
}
|
||||
DeclaredValue::Initial => get_initial_value(),
|
||||
DeclaredValue::Inherit => {
|
||||
// This is a bit slow, but this is rare so it shouldn't
|
||||
// matter.
|
||||
//
|
||||
// FIXME: is it still?
|
||||
*cacheable = false;
|
||||
inherited_style.${THIS_STYLE_STRUCT.ident}
|
||||
.${property.ident}
|
||||
.clone()
|
||||
}
|
||||
};
|
||||
Arc::make_unique(&mut style.${THIS_STYLE_STRUCT.ident}).${property.ident} =
|
||||
computed_value;
|
||||
|
||||
% if custom_cascade:
|
||||
cascade_property_custom(&computed_value,
|
||||
declaration,
|
||||
style,
|
||||
inherited_style,
|
||||
context,
|
||||
seen,
|
||||
cacheable);
|
||||
% endif
|
||||
% else:
|
||||
// Do not allow stylesheets to set derived properties.
|
||||
% endif
|
||||
}
|
||||
% if derived_from is None:
|
||||
pub fn parse_declared(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<DeclaredValue<SpecifiedValue>, ()> {
|
||||
|
@ -136,9 +197,9 @@ pub mod longhands {
|
|||
}
|
||||
</%def>
|
||||
|
||||
<%def name="longhand(name, derived_from=None, experimental=False)">
|
||||
<%def name="longhand(name, derived_from=None, custom_cascade=False, experimental=False)">
|
||||
<%self:raw_longhand name="${name}" derived_from="${derived_from}"
|
||||
experimental="${experimental}">
|
||||
custom_cascade="${custom_cascade}" experimental="${experimental}">
|
||||
${caller.body()}
|
||||
% if derived_from is None:
|
||||
pub fn parse_specified(context: &ParserContext, input: &mut Parser)
|
||||
|
@ -149,8 +210,9 @@ pub mod longhands {
|
|||
</%self:raw_longhand>
|
||||
</%def>
|
||||
|
||||
<%def name="single_keyword_computed(name, values, experimental=False)">
|
||||
<%self:longhand name="${name}" experimental="${experimental}">
|
||||
<%def name="single_keyword_computed(name, values, custom_cascade=False, experimental=False)">
|
||||
<%self:longhand name="${name}" custom_cascade="${custom_cascade}"
|
||||
experimental="${experimental}">
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
${caller.body()}
|
||||
pub mod computed_value {
|
||||
|
@ -225,7 +287,7 @@ pub mod longhands {
|
|||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
<%self:longhand name="border-${side}-width">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use util::geometry::Au;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
@ -293,7 +355,7 @@ pub mod longhands {
|
|||
</%self:longhand>
|
||||
|
||||
<%self:longhand name="outline-width">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use util::geometry::Au;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
@ -343,12 +405,13 @@ pub mod longhands {
|
|||
|
||||
// TODO(SimonSapin): don't parse `inline-table`, since we don't support it
|
||||
<%self:single_keyword_computed name="display"
|
||||
custom_cascade="True"
|
||||
values="inline block inline-block
|
||||
table inline-table table-row-group table-header-group table-footer-group
|
||||
table-row table-column-group table-column table-cell table-caption
|
||||
list-item
|
||||
none">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
@ -375,6 +438,22 @@ pub mod longhands {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cascade_property_custom(computed_value: &computed_value::T,
|
||||
declaration: &PropertyDeclaration,
|
||||
style: &mut ComputedValues,
|
||||
inherited_style: &ComputedValues,
|
||||
context: &computed::Context,
|
||||
seen: &mut PropertyBitField,
|
||||
cacheable: &mut bool) {
|
||||
Arc::make_unique(&mut style.box_)._servo_display_for_hypothetical_box =
|
||||
longhands::_servo_display_for_hypothetical_box::derive_from_display(
|
||||
*computed_value,
|
||||
&context);
|
||||
Arc::make_unique(&mut style.inheritedtext)._servo_text_decorations_in_effect =
|
||||
longhands::_servo_text_decorations_in_effect::derive_from_display(*computed_value,
|
||||
&context);
|
||||
}
|
||||
</%self:single_keyword_computed>
|
||||
|
||||
${single_keyword("position", "static absolute relative fixed")}
|
||||
|
@ -456,7 +535,7 @@ pub mod longhands {
|
|||
"computed::LengthOrPercentageOrAuto::Auto",
|
||||
"parse_non_negative")}
|
||||
<%self:longhand name="height">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -512,7 +591,7 @@ pub mod longhands {
|
|||
${switch_to_style_struct("InheritedBox")}
|
||||
|
||||
<%self:longhand name="line-height">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use values::CSSFloat;
|
||||
|
@ -602,7 +681,7 @@ pub mod longhands {
|
|||
${switch_to_style_struct("Box")}
|
||||
|
||||
<%self:longhand name="vertical-align">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -705,7 +784,7 @@ pub mod longhands {
|
|||
|
||||
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
|
||||
<%self:single_keyword_computed name="overflow-x" values="visible hidden scroll auto">
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
pub fn compute_with_other_overflow_direction(value: SpecifiedValue,
|
||||
other_direction: SpecifiedValue)
|
||||
|
@ -734,7 +813,7 @@ pub mod longhands {
|
|||
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
|
||||
<%self:longhand name="overflow-y">
|
||||
use super::overflow_x;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
@ -967,7 +1046,7 @@ pub mod longhands {
|
|||
use url::Url;
|
||||
use cssparser::{ToCss, Token};
|
||||
use std::fmt;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum SpecifiedValue {
|
||||
|
@ -1164,7 +1243,7 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="background-image">
|
||||
use values::specified::Image;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -1212,7 +1291,7 @@ pub mod longhands {
|
|||
<%self:longhand name="background-position">
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
pub mod computed_value {
|
||||
use values::computed::LengthOrPercentage;
|
||||
|
@ -1326,7 +1405,7 @@ pub mod longhands {
|
|||
use cssparser::{ToCss, Token};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
pub mod computed_value {
|
||||
use values::computed::LengthOrPercentageOrAuto;
|
||||
|
@ -1445,7 +1524,7 @@ pub mod longhands {
|
|||
<%self:raw_longhand name="color">
|
||||
use cssparser::{Color, RGBA};
|
||||
use values::specified::{CSSColor, CSSRGBA};
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
@ -1573,7 +1652,7 @@ pub mod longhands {
|
|||
<%self:longhand name="font-weight">
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Copy)]
|
||||
pub enum SpecifiedValue {
|
||||
|
@ -1691,7 +1770,7 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="font-size">
|
||||
use util::geometry::Au;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -1809,7 +1888,7 @@ pub mod longhands {
|
|||
</%self:longhand>
|
||||
|
||||
<%self:longhand name="letter-spacing">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -1860,7 +1939,7 @@ pub mod longhands {
|
|||
</%self:longhand>
|
||||
|
||||
<%self:longhand name="word-spacing">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -1926,7 +2005,7 @@ pub mod longhands {
|
|||
|
||||
${new_style_struct("Text", is_inherited=False)}
|
||||
|
||||
<%self:longhand name="text-decoration">
|
||||
<%self:longhand name="text-decoration" custom_cascade="True">
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
|
@ -2000,6 +2079,19 @@ pub mod longhands {
|
|||
}
|
||||
if !empty { Ok(result) } else { Err(()) }
|
||||
}
|
||||
|
||||
fn cascade_property_custom(computed_value: &computed_value::T,
|
||||
declaration: &PropertyDeclaration,
|
||||
style: &mut ComputedValues,
|
||||
inherited_style: &ComputedValues,
|
||||
context: &computed::Context,
|
||||
seen: &mut PropertyBitField,
|
||||
cacheable: &mut bool) {
|
||||
Arc::make_unique(&mut style.inheritedtext)._servo_text_decorations_in_effect =
|
||||
longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(
|
||||
*computed_value,
|
||||
&context);
|
||||
}
|
||||
</%self:longhand>
|
||||
|
||||
${switch_to_style_struct("InheritedText")}
|
||||
|
@ -2103,7 +2195,7 @@ pub mod longhands {
|
|||
${single_keyword("caption-side", "top bottom")}
|
||||
|
||||
<%self:longhand name="border-spacing">
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
@ -2257,7 +2349,7 @@ pub mod longhands {
|
|||
${new_style_struct("Column", is_inherited=False)}
|
||||
|
||||
<%self:longhand name="column-width" experimental="True">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -2308,7 +2400,7 @@ pub mod longhands {
|
|||
</%self:longhand>
|
||||
|
||||
<%self:longhand name="column-count" experimental="True">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -2363,7 +2455,7 @@ pub mod longhands {
|
|||
</%self:longhand>
|
||||
|
||||
<%self:longhand name="column-gap" experimental="True">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -2418,7 +2510,7 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="opacity">
|
||||
use values::CSSFloat;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -2461,7 +2553,7 @@ pub mod longhands {
|
|||
<%self:longhand name="box-shadow">
|
||||
use cssparser::{self, ToCss};
|
||||
use std::fmt;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct SpecifiedValue(Vec<SpecifiedBoxShadow>);
|
||||
|
@ -2647,7 +2739,7 @@ pub mod longhands {
|
|||
|
||||
// NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2.
|
||||
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
pub mod computed_value {
|
||||
use util::geometry::Au;
|
||||
|
@ -2768,7 +2860,7 @@ pub mod longhands {
|
|||
use cssparser::{self, ToCss};
|
||||
use std::fmt;
|
||||
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct SpecifiedValue(Vec<SpecifiedTextShadow>);
|
||||
|
@ -2931,7 +3023,6 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="filter">
|
||||
//pub use self::computed_value::T as SpecifiedValue;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::specified::{Angle, Length};
|
||||
use values::CSSFloat;
|
||||
use cssparser::ToCss;
|
||||
|
@ -3121,7 +3212,7 @@ pub mod longhands {
|
|||
|
||||
<%self:longhand name="transform">
|
||||
use values::CSSFloat;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
|
@ -3498,7 +3589,7 @@ pub mod longhands {
|
|||
${single_keyword("transform-style", "auto flat preserve-3d")}
|
||||
|
||||
<%self:longhand name="transform-origin">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use values::specified::{Length, LengthOrPercentage};
|
||||
|
||||
use cssparser::ToCss;
|
||||
|
@ -3637,7 +3728,7 @@ pub mod longhands {
|
|||
"computed::LengthOrNone::None")}
|
||||
|
||||
<%self:longhand name="perspective-origin">
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
use values::specified::LengthOrPercentage;
|
||||
|
||||
use cssparser::ToCss;
|
||||
|
@ -3760,7 +3851,7 @@ pub mod longhands {
|
|||
saturation color luminosity""")}
|
||||
|
||||
<%self:longhand name="image-rendering">
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
pub mod computed_value {
|
||||
use cssparser::ToCss;
|
||||
|
@ -3883,7 +3974,7 @@ pub mod longhands {
|
|||
// TODO(pcwalton): Multiple transitions.
|
||||
<%self:longhand name="transition-timing-function">
|
||||
use self::computed_value::{StartEnd, TransitionTimingFunction};
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::Context;
|
||||
|
||||
use euclid::point::Point2D;
|
||||
|
||||
|
@ -4080,7 +4171,7 @@ pub mod longhands {
|
|||
// TODO(pcwalton): Lots more properties.
|
||||
<%self:longhand name="transition-property">
|
||||
use self::computed_value::TransitionProperty;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
use values::computed::Context;
|
||||
|
||||
pub use self::computed_value::SingleComputedValue as SingleSpecifiedValue;
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
|
@ -5621,7 +5712,7 @@ fn cascade_with_cached_declarations(
|
|||
% endif
|
||||
% for derived in DERIVED_LONGHANDS[property.name]:
|
||||
Arc::make_unique(&mut style_${derived.style_struct.ident})
|
||||
.${derived.ident} =
|
||||
.${derived.ident} =
|
||||
longhands::${derived.ident}
|
||||
::derive_from_${property.ident}(
|
||||
computed_value,
|
||||
|
@ -5655,6 +5746,34 @@ fn cascade_with_cached_declarations(
|
|||
}
|
||||
}
|
||||
|
||||
type CascadePropertyFn = extern "Rust" fn(declaration: &PropertyDeclaration,
|
||||
style: &mut ComputedValues,
|
||||
inherited_style: &ComputedValues,
|
||||
context: &computed::Context,
|
||||
seen: &mut PropertyBitField,
|
||||
cacheable: &mut bool);
|
||||
|
||||
// This is a thread-local rather than a lazy static to avoid atomic operations when cascading
|
||||
// properties.
|
||||
thread_local!(static CASCADE_PROPERTY: Vec<Option<CascadePropertyFn>> = {
|
||||
let mut result: Vec<Option<CascadePropertyFn>> = Vec::new();
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
% for property in style_struct.longhands:
|
||||
let discriminant;
|
||||
unsafe {
|
||||
let variant = PropertyDeclaration::${property.camel_case}(intrinsics::uninit());
|
||||
discriminant = intrinsics::discriminant_value(&variant) as usize;
|
||||
mem::forget(variant);
|
||||
}
|
||||
while result.len() < discriminant + 1 {
|
||||
result.push(None)
|
||||
}
|
||||
result[discriminant] = Some(longhands::${property.ident}::cascade_property);
|
||||
% endfor
|
||||
% endfor
|
||||
result
|
||||
});
|
||||
|
||||
/// Performs the CSS cascade, computing new styles for an element from its parent style and
|
||||
/// optionally a cached related style. The arguments are:
|
||||
///
|
||||
|
@ -5813,75 +5932,48 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
|||
}
|
||||
|
||||
// Set computed values, overwriting earlier declarations for the same property.
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
let mut style_${style_struct.ident} =
|
||||
% if style_struct.inherited:
|
||||
inherited_style
|
||||
% else:
|
||||
initial_values
|
||||
% endif
|
||||
.${style_struct.ident}.clone();
|
||||
% endfor
|
||||
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
|
||||
shareable: false,
|
||||
writing_mode: WritingMode::empty(),
|
||||
root_font_size: context.root_font_size,
|
||||
};
|
||||
let mut cacheable = true;
|
||||
let mut seen = PropertyBitField::new();
|
||||
// Declaration blocks are stored in increasing precedence order,
|
||||
// we want them in decreasing order here.
|
||||
for sub_list in applicable_declarations.iter().rev() {
|
||||
// Declarations are already stored in reverse order.
|
||||
for declaration in sub_list.declarations.iter() {
|
||||
match *declaration {
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
% for property in style_struct.longhands:
|
||||
% if property.derived_from is None:
|
||||
PropertyDeclaration::${property.camel_case}(ref declared_value) => {
|
||||
if seen.get_${property.ident}() {
|
||||
continue
|
||||
}
|
||||
seen.set_${property.ident}();
|
||||
let computed_value = match *declared_value {
|
||||
DeclaredValue::SpecifiedValue(ref specified_value)
|
||||
=> specified_value.to_computed_value(&context),
|
||||
DeclaredValue::Initial
|
||||
=> longhands::${property.ident}::get_initial_value(),
|
||||
DeclaredValue::Inherit => {
|
||||
// This is a bit slow, but this is rare so it shouldn't
|
||||
// matter.
|
||||
//
|
||||
// FIXME: is it still?
|
||||
cacheable = false;
|
||||
inherited_style.${style_struct.ident}
|
||||
.${property.ident}
|
||||
.clone()
|
||||
}
|
||||
};
|
||||
Arc::make_unique(&mut style_${style_struct.ident})
|
||||
.${property.ident} = computed_value;
|
||||
|
||||
% if property.name in DERIVED_LONGHANDS:
|
||||
% for derived in DERIVED_LONGHANDS[property.name]:
|
||||
Arc::make_unique(&mut style_${derived.style_struct.ident})
|
||||
.${derived.ident} =
|
||||
longhands::${derived.ident}
|
||||
::derive_from_${property.ident}(
|
||||
computed_value,
|
||||
&context);
|
||||
% endfor
|
||||
% endif
|
||||
}
|
||||
% else:
|
||||
PropertyDeclaration::${property.camel_case}(_) => {
|
||||
// Do not allow stylesheets to set derived properties.
|
||||
}
|
||||
% endif
|
||||
% endfor
|
||||
% endfor
|
||||
// Declaration blocks are stored in increasing precedence order, we want them in decreasing
|
||||
// order here.
|
||||
//
|
||||
// We could (and used to) use a pattern match here, but that bloats this function to over 100K
|
||||
// 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() {
|
||||
let discriminant = unsafe {
|
||||
intrinsics::discriminant_value(declaration) as usize
|
||||
};
|
||||
(cascade_property[discriminant].unwrap())(declaration,
|
||||
&mut style,
|
||||
inherited_style,
|
||||
&context,
|
||||
&mut seen,
|
||||
&mut cacheable);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// The initial value of border-*-width may be changed at computed value time.
|
||||
{
|
||||
let border = Arc::make_unique(&mut style_border);
|
||||
let border = Arc::make_unique(&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 {
|
||||
|
@ -5892,13 +5984,13 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
|||
|
||||
// The initial value of display may be changed at computed value time.
|
||||
if !seen.get_display() {
|
||||
let box_ = Arc::make_unique(&mut style_box_);
|
||||
let box_ = Arc::make_unique(&mut style.box_);
|
||||
box_.display = box_.display.to_computed_value(&context);
|
||||
}
|
||||
|
||||
// The initial value of outline width may be changed at computed value time.
|
||||
if !context.outline_style_present {
|
||||
let outline = Arc::make_unique(&mut style_outline);
|
||||
let outline = Arc::make_unique(&mut style.outline);
|
||||
outline.outline_width = Au(0);
|
||||
}
|
||||
|
||||
|
@ -5908,13 +6000,13 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
|||
|
||||
if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() ||
|
||||
seen.get_font_family() {
|
||||
compute_font_hash(&mut *Arc::make_unique(&mut style_font))
|
||||
compute_font_hash(&mut *Arc::make_unique(&mut style.font))
|
||||
}
|
||||
|
||||
(ComputedValues {
|
||||
writing_mode: get_writing_mode(&*style_inheritedbox),
|
||||
writing_mode: get_writing_mode(&*style.inheritedbox),
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
${style_struct.ident}: style_${style_struct.ident},
|
||||
${style_struct.ident}: style.${style_struct.ident},
|
||||
% endfor
|
||||
shareable: shareable,
|
||||
root_font_size: context.root_font_size,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue