mirror of
https://github.com/servo/servo.git
synced 2025-08-11 08:25:32 +01:00
Auto merge of #19757 - emilio:bye-custom-cascade, r=nox
style: Remove -servo-text-decorations-in-effect It is bogus, because it depends on the display property as it's cascaded, but the display property can change afterwards, for example, if we get blockified because we're the root element or a flex item. Replace it with a normal field instead. Also, it carries some weight, because it's the last property that uses this concept of "derived" property, and "custom cascade". So we can remove some code after this. Compute it after the cascade process in StyleAdjuster. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19757) <!-- Reviewable:end -->
This commit is contained in:
commit
f2036e7661
12 changed files with 176 additions and 226 deletions
|
@ -145,10 +145,10 @@ def arg_to_bool(arg):
|
|||
|
||||
|
||||
class Longhand(object):
|
||||
def __init__(self, style_struct, name, spec=None, animation_value_type=None, derived_from=None, keyword=None,
|
||||
predefined_type=None, custom_cascade=False, servo_pref=None, gecko_pref=None,
|
||||
def __init__(self, style_struct, name, spec=None, animation_value_type=None, keyword=None,
|
||||
predefined_type=None, servo_pref=None, gecko_pref=None,
|
||||
enabled_in="content", need_index=False,
|
||||
custom_cascade_function=None, gecko_ffi_name=None,
|
||||
gecko_ffi_name=None,
|
||||
allowed_in_keyframe_block=True, cast_type='u8',
|
||||
logical=False, alias=None, extra_prefixes=None, boxed=False,
|
||||
flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False,
|
||||
|
@ -164,8 +164,6 @@ class Longhand(object):
|
|||
self.style_struct = style_struct
|
||||
self.servo_pref = servo_pref
|
||||
self.gecko_pref = gecko_pref
|
||||
self.custom_cascade = custom_cascade
|
||||
self.custom_cascade_function = custom_cascade_function if custom_cascade else None
|
||||
# For enabled_in, the setup is as follows:
|
||||
# It needs to be one of the four values: ["", "ua", "chrome", "content"]
|
||||
# * "chrome" implies "ua", and implies that they're explicitly
|
||||
|
@ -177,7 +175,6 @@ class Longhand(object):
|
|||
self.enabled_in = enabled_in
|
||||
self.need_index = need_index
|
||||
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
|
||||
self.derived_from = (derived_from or "").split()
|
||||
self.cast_type = cast_type
|
||||
self.logical = arg_to_bool(logical)
|
||||
self.alias = alias.split() if alias else []
|
||||
|
@ -241,7 +238,6 @@ class Shorthand(object):
|
|||
self.spec = spec
|
||||
self.ident = to_rust_ident(name)
|
||||
self.camel_case = to_camel_case(self.ident)
|
||||
self.derived_from = None
|
||||
self.servo_pref = servo_pref
|
||||
self.gecko_pref = gecko_pref
|
||||
self.sub_properties = sub_properties
|
||||
|
@ -365,7 +361,6 @@ class PropertiesData(object):
|
|||
self.current_style_struct = None
|
||||
self.longhands = []
|
||||
self.longhands_by_name = {}
|
||||
self.derived_longhands = {}
|
||||
self.longhand_aliases = []
|
||||
self.shorthands = []
|
||||
self.shorthand_aliases = []
|
||||
|
@ -397,9 +392,6 @@ class PropertiesData(object):
|
|||
self.longhands.append(longhand)
|
||||
self.longhands_by_name[name] = longhand
|
||||
|
||||
for name in longhand.derived_from:
|
||||
self.derived_longhands.setdefault(name, []).append(longhand)
|
||||
|
||||
return longhand
|
||||
|
||||
def declare_shorthand(self, name, sub_properties, products="gecko servo", *args, **kwargs):
|
||||
|
|
|
@ -260,14 +260,12 @@
|
|||
%>
|
||||
/// ${property.spec}
|
||||
pub mod ${property.ident} {
|
||||
% if not property.derived_from:
|
||||
#[allow(unused_imports)]
|
||||
use cssparser::{Parser, BasicParseError, Token};
|
||||
#[allow(unused_imports)]
|
||||
use parser::{Parse, ParserContext};
|
||||
#[allow(unused_imports)]
|
||||
use properties::{UnparsedValue, ShorthandId};
|
||||
% endif
|
||||
#[allow(unused_imports)]
|
||||
use cssparser::{Parser, BasicParseError, Token};
|
||||
#[allow(unused_imports)]
|
||||
use parser::{Parse, ParserContext};
|
||||
#[allow(unused_imports)]
|
||||
use properties::{UnparsedValue, ShorthandId};
|
||||
#[allow(unused_imports)]
|
||||
use values::{Auto, Either, None_, Normal};
|
||||
#[allow(unused_imports)]
|
||||
|
@ -319,106 +317,95 @@
|
|||
Some(LonghandId::${property.camel_case});
|
||||
% endif
|
||||
|
||||
% if not property.derived_from:
|
||||
match value {
|
||||
DeclaredValue::Value(specified_value) => {
|
||||
% if property.ident in SYSTEM_FONT_LONGHANDS and product == "gecko":
|
||||
if let Some(sf) = specified_value.get_system() {
|
||||
longhands::system_font::resolve_system_font(sf, context);
|
||||
}
|
||||
% endif
|
||||
% if not property.style_struct.inherited and property.logical:
|
||||
context.rule_cache_conditions.borrow_mut()
|
||||
.set_writing_mode_dependency(context.builder.writing_mode);
|
||||
% endif
|
||||
% if property.is_vector:
|
||||
// In the case of a vector property we want to pass
|
||||
// down an iterator so that this can be computed
|
||||
// without allocation
|
||||
//
|
||||
// However, computing requires a context, but the
|
||||
// style struct being mutated is on the context. We
|
||||
// temporarily remove it, mutate it, and then put it
|
||||
// back. Vector longhands cannot touch their own
|
||||
// style struct whilst computing, else this will
|
||||
// panic.
|
||||
let mut s =
|
||||
context.builder.take_${data.current_style_struct.name_lower}();
|
||||
{
|
||||
let iter = specified_value.compute_iter(context);
|
||||
s.set_${property.ident}(iter);
|
||||
}
|
||||
context.builder.put_${data.current_style_struct.name_lower}(s);
|
||||
% else:
|
||||
% if property.boxed:
|
||||
let computed = (**specified_value).to_computed_value(context);
|
||||
% else:
|
||||
let computed = specified_value.to_computed_value(context);
|
||||
% endif
|
||||
% if property.ident == "font_size":
|
||||
specified::FontSize::cascade_specified_font_size(
|
||||
context,
|
||||
&specified_value,
|
||||
computed,
|
||||
);
|
||||
% else:
|
||||
context.builder.set_${property.ident}(computed)
|
||||
% endif
|
||||
% endif
|
||||
}
|
||||
DeclaredValue::WithVariables(_) => unreachable!(),
|
||||
DeclaredValue::CSSWideKeyword(keyword) => match keyword {
|
||||
% if not data.current_style_struct.inherited:
|
||||
CSSWideKeyword::Unset |
|
||||
% endif
|
||||
CSSWideKeyword::Initial => {
|
||||
% if property.ident == "font_size":
|
||||
computed::FontSize::cascade_initial_font_size(context);
|
||||
% else:
|
||||
context.builder.reset_${property.ident}();
|
||||
% endif
|
||||
},
|
||||
% if data.current_style_struct.inherited:
|
||||
CSSWideKeyword::Unset |
|
||||
% endif
|
||||
CSSWideKeyword::Inherit => {
|
||||
% if not property.style_struct.inherited:
|
||||
context.rule_cache_conditions.borrow_mut().set_uncacheable();
|
||||
% endif
|
||||
% if property.ident == "font_size":
|
||||
computed::FontSize::cascade_inherit_font_size(context);
|
||||
% else:
|
||||
context.builder.inherit_${property.ident}();
|
||||
% endif
|
||||
match value {
|
||||
DeclaredValue::Value(specified_value) => {
|
||||
% if property.ident in SYSTEM_FONT_LONGHANDS and product == "gecko":
|
||||
if let Some(sf) = specified_value.get_system() {
|
||||
longhands::system_font::resolve_system_font(sf, context);
|
||||
}
|
||||
% endif
|
||||
% if not property.style_struct.inherited and property.logical:
|
||||
context.rule_cache_conditions.borrow_mut()
|
||||
.set_writing_mode_dependency(context.builder.writing_mode);
|
||||
% endif
|
||||
% if property.is_vector:
|
||||
// In the case of a vector property we want to pass
|
||||
// down an iterator so that this can be computed
|
||||
// without allocation
|
||||
//
|
||||
// However, computing requires a context, but the
|
||||
// style struct being mutated is on the context. We
|
||||
// temporarily remove it, mutate it, and then put it
|
||||
// back. Vector longhands cannot touch their own
|
||||
// style struct whilst computing, else this will
|
||||
// panic.
|
||||
let mut s =
|
||||
context.builder.take_${data.current_style_struct.name_lower}();
|
||||
{
|
||||
let iter = specified_value.compute_iter(context);
|
||||
s.set_${property.ident}(iter);
|
||||
}
|
||||
context.builder.put_${data.current_style_struct.name_lower}(s);
|
||||
% else:
|
||||
% if property.boxed:
|
||||
let computed = (**specified_value).to_computed_value(context);
|
||||
% else:
|
||||
let computed = specified_value.to_computed_value(context);
|
||||
% endif
|
||||
% if property.ident == "font_size":
|
||||
specified::FontSize::cascade_specified_font_size(
|
||||
context,
|
||||
&specified_value,
|
||||
computed,
|
||||
);
|
||||
% else:
|
||||
context.builder.set_${property.ident}(computed)
|
||||
% endif
|
||||
% endif
|
||||
}
|
||||
DeclaredValue::WithVariables(_) => unreachable!(),
|
||||
DeclaredValue::CSSWideKeyword(keyword) => match keyword {
|
||||
% if not data.current_style_struct.inherited:
|
||||
CSSWideKeyword::Unset |
|
||||
% endif
|
||||
CSSWideKeyword::Initial => {
|
||||
% if property.ident == "font_size":
|
||||
computed::FontSize::cascade_initial_font_size(context);
|
||||
% else:
|
||||
context.builder.reset_${property.ident}();
|
||||
% endif
|
||||
},
|
||||
% if data.current_style_struct.inherited:
|
||||
CSSWideKeyword::Unset |
|
||||
% endif
|
||||
CSSWideKeyword::Inherit => {
|
||||
% if not property.style_struct.inherited:
|
||||
context.rule_cache_conditions.borrow_mut().set_uncacheable();
|
||||
% endif
|
||||
% if property.ident == "font_size":
|
||||
computed::FontSize::cascade_inherit_font_size(context);
|
||||
% else:
|
||||
context.builder.inherit_${property.ident}();
|
||||
% endif
|
||||
}
|
||||
}
|
||||
|
||||
% if property.custom_cascade and property.custom_cascade_function:
|
||||
${property.custom_cascade_function}(declaration, context);
|
||||
% elif property.custom_cascade:
|
||||
cascade_property_custom(declaration, context);
|
||||
% endif
|
||||
% else:
|
||||
// Do not allow stylesheets to set derived properties.
|
||||
% endif
|
||||
}
|
||||
% if not property.derived_from:
|
||||
pub fn parse_declared<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<PropertyDeclaration, ParseError<'i>> {
|
||||
% if property.allow_quirks:
|
||||
parse_quirky(context, input, specified::AllowQuirks::Yes)
|
||||
% else:
|
||||
parse(context, input)
|
||||
% endif
|
||||
% if property.boxed:
|
||||
.map(Box::new)
|
||||
% endif
|
||||
.map(PropertyDeclaration::${property.camel_case})
|
||||
}
|
||||
% endif
|
||||
}
|
||||
|
||||
pub fn parse_declared<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<PropertyDeclaration, ParseError<'i>> {
|
||||
% if property.allow_quirks:
|
||||
parse_quirky(context, input, specified::AllowQuirks::Yes)
|
||||
% else:
|
||||
parse(context, input)
|
||||
% endif
|
||||
% if property.boxed:
|
||||
.map(Box::new)
|
||||
% endif
|
||||
.map(PropertyDeclaration::${property.camel_case})
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::Display::inline()",
|
||||
animation_value_type="discrete",
|
||||
needs_context=False,
|
||||
custom_cascade= product == 'servo',
|
||||
custom_cascade_function="specified::Display::cascade_property_custom",
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-display/#propdef-display",
|
||||
)}
|
||||
|
|
|
@ -132,68 +132,6 @@ ${helpers.predefined_type("word-spacing",
|
|||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing")}
|
||||
|
||||
<%helpers:longhand name="-servo-text-decorations-in-effect"
|
||||
derived_from="display text-decoration"
|
||||
products="servo"
|
||||
animation_value_type="none"
|
||||
spec="Nonstandard (Internal property used by Servo)">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)]
|
||||
pub struct SpecifiedValue {
|
||||
pub underline: bool,
|
||||
pub overline: bool,
|
||||
pub line_through: bool,
|
||||
}
|
||||
|
||||
trivial_to_computed_value!(SpecifiedValue);
|
||||
|
||||
pub mod computed_value {
|
||||
pub type T = super::SpecifiedValue;
|
||||
}
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
// Web compat doesn't matter here.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
SpecifiedValue::default()
|
||||
}
|
||||
|
||||
fn derive(context: &Context) -> computed_value::T {
|
||||
// Start with no declarations if this is an atomic inline-level box; otherwise, start with the
|
||||
// declarations in effect and add in the text decorations that this block specifies.
|
||||
let mut result = match context.style().get_box().clone_display() {
|
||||
super::display::computed_value::T::InlineBlock |
|
||||
super::display::computed_value::T::InlineTable => get_initial_value(),
|
||||
_ => context.builder.get_parent_inheritedtext().clone__servo_text_decorations_in_effect()
|
||||
};
|
||||
|
||||
result.underline |= context.style().get_text().has_underline();
|
||||
result.overline |= context.style().get_text().has_overline();
|
||||
result.line_through |= context.style().get_text().has_line_through();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn derive_from_text_decoration(context: &mut Context) {
|
||||
let derived = derive(context);
|
||||
context.builder.set__servo_text_decorations_in_effect(derived);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn derive_from_display(context: &mut Context) {
|
||||
let derived = derive(context);
|
||||
context.builder.set__servo_text_decorations_in_effect(derived);
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:single_keyword_computed name="white-space"
|
||||
values="normal pre nowrap pre-wrap pre-line"
|
||||
extra_gecko_values="-moz-pre-space"
|
||||
|
|
|
@ -29,8 +29,6 @@ ${helpers.predefined_type("text-decoration-line",
|
|||
"TextDecorationLine",
|
||||
"specified::TextDecorationLine::none()",
|
||||
initial_specified_value="specified::TextDecorationLine::none()",
|
||||
custom_cascade= product == 'servo',
|
||||
custom_cascade_function="specified::TextDecorationLine::cascade_property_custom",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line")}
|
||||
|
|
|
@ -570,13 +570,7 @@ impl LonghandId {
|
|||
match *self {
|
||||
% for property in data.longhands:
|
||||
LonghandId::${property.camel_case} => {
|
||||
% if not property.derived_from:
|
||||
longhands::${property.ident}::parse_declared(context, input)
|
||||
% else:
|
||||
Err(input.new_custom_error(
|
||||
StyleParseErrorKind::UnknownProperty("${property.ident}".into())
|
||||
))
|
||||
% endif
|
||||
longhands::${property.ident}::parse_declared(context, input)
|
||||
}
|
||||
% endfor
|
||||
}
|
||||
|
@ -1454,10 +1448,8 @@ impl ToCss for PropertyDeclaration {
|
|||
{
|
||||
match *self {
|
||||
% for property in data.longhands:
|
||||
% if not property.derived_from:
|
||||
PropertyDeclaration::${property.camel_case}(ref value) =>
|
||||
value.to_css(dest),
|
||||
% endif
|
||||
PropertyDeclaration::${property.camel_case}(ref value) =>
|
||||
value.to_css(dest),
|
||||
% endfor
|
||||
PropertyDeclaration::CSSWideKeyword(_, keyword) => keyword.to_css(dest),
|
||||
PropertyDeclaration::WithVariables(_, ref with_variables) => {
|
||||
|
@ -1474,9 +1466,6 @@ impl ToCss for PropertyDeclaration {
|
|||
Ok(())
|
||||
},
|
||||
PropertyDeclaration::Custom(_, ref value) => value.borrow().to_css(dest),
|
||||
% if any(property.derived_from for property in data.longhands):
|
||||
_ => Err(fmt::Error),
|
||||
% endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1859,6 +1848,13 @@ pub mod style_structs {
|
|||
/// The ${longhand.name} computed value.
|
||||
pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
|
||||
% endfor
|
||||
% if style_struct.name == "InheritedText":
|
||||
/// The "used" text-decorations that apply to this box.
|
||||
///
|
||||
/// FIXME(emilio): This is technically a box-tree concept, and
|
||||
/// would be nice to move away from style.
|
||||
pub text_decorations_in_effect: ::values::computed::text::TextDecorationsInEffect,
|
||||
% endif
|
||||
% if style_struct.name == "Font":
|
||||
/// The font hash, used for font caching.
|
||||
pub hash: u64,
|
||||
|
@ -1870,9 +1866,8 @@ pub mod style_structs {
|
|||
% endif
|
||||
}
|
||||
% if style_struct.name == "Font":
|
||||
|
||||
impl PartialEq for ${style_struct.name} {
|
||||
fn eq(&self, other: &${style_struct.name}) -> bool {
|
||||
impl PartialEq for Font {
|
||||
fn eq(&self, other: &Font) -> bool {
|
||||
self.hash == other.hash
|
||||
% for longhand in style_struct.longhands:
|
||||
&& self.${longhand.ident} == other.${longhand.ident}
|
||||
|
@ -3074,6 +3069,9 @@ mod lazy_static_module {
|
|||
% for longhand in style_struct.longhands:
|
||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
||||
% endfor
|
||||
% if style_struct.name == "InheritedText":
|
||||
text_decorations_in_effect: ::values::computed::text::TextDecorationsInEffect::default(),
|
||||
% endif
|
||||
% if style_struct.name == "Font":
|
||||
hash: 0,
|
||||
% endif
|
||||
|
@ -3644,7 +3642,7 @@ macro_rules! css_properties_accessors {
|
|||
$macro_name! {
|
||||
% for kind, props in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
|
||||
% for property in props:
|
||||
% if not property.derived_from and property.enabled_in_content():
|
||||
% if property.enabled_in_content():
|
||||
% for name in [property.name] + property.alias:
|
||||
% if '-' in name:
|
||||
[${to_rust_ident(name).capitalize()}, Set${to_rust_ident(name).capitalize()},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue