Skip to content

Commit 276ed42

Browse files
committed
Improve properties.mako.rs file structure, take 2
This is a new attempt of servo#10586, after Simon Sapin's great cleanups in servo#10749 has landed. I have adjusted the changes to the new structure that was introduced, and also only done a few of the longhand ones. Will certainly continue on this as soon as we have a basic agreement that this style is reasonable.
1 parent 3bfa4cc commit 276ed42

File tree

10 files changed

+358
-305
lines changed

10 files changed

+358
-305
lines changed

components/style/properties/build.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
sys.path.insert(0, os.path.join(BASE, "Mako-0.9.1.zip"))
1111

1212
from mako import exceptions
13+
from mako.lookup import TemplateLookup
1314
from mako.template import Template
1415

1516
import data
@@ -43,10 +44,19 @@ def abort(message):
4344

4445
def render(filename, **context):
4546
try:
47+
# Workaround the fact that we can have a different working directory when called, and Mako includes will fail
48+
# miserably if we don't give it proper instructions in the TemplateLookup.
49+
if os.getcwd().endswith("components/style"):
50+
properties_path = "properties"
51+
else:
52+
properties_path = "components/style/properties"
53+
54+
lookup = TemplateLookup(directories=[properties_path])
4655
template = Template(open(filename, "rb").read(),
56+
filename=filename,
4757
input_encoding="utf8",
48-
strict_undefined=True,
49-
filename=filename)
58+
lookup=lookup,
59+
strict_undefined=True)
5060
# Uncomment to debug generated Python code:
5161
# write("/tmp", "mako_%s.py" % os.path.basename(filename), template.code)
5262
return template.render(**context).encode("utf8")

components/style/properties/data.py

+7
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ def switch_to_style_struct(self, name):
134134
return
135135
raise Exception("Failed to find the struct named " + name)
136136

137+
def new_method(self, name, return_type):
138+
return Method(name, return_type)
139+
137140
def declare_longhand(self, name, products="gecko servo", **kwargs):
138141
products = products.split()
139142
if self.product not in products:
@@ -154,3 +157,7 @@ def declare_shorthand(self, name, sub_properties, *args, **kwargs):
154157
shorthand = Shorthand(name, sub_properties, *args, **kwargs)
155158
self.shorthands.append(shorthand)
156159
return shorthand
160+
161+
# Wrapper for the module-level method, since some scopes can only access the stuff in the PropertiesData class.
162+
def to_rust_ident(self, name):
163+
return to_rust_ident(name)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
<%page args="data, helpers" />
6+
7+
<% data.new_style_struct("Border", inherited=False, gecko_ffi_name="nsStyleBorder",
8+
additional_methods=[data.new_method("border_" + side + "_is_none_or_hidden_and_has_nonzero_width",
9+
"bool") for side in ["top", "right", "bottom", "left"]]) %>
10+
11+
% for side in ["top", "right", "bottom", "left"]:
12+
${helpers.predefined_type("border-%s-color" % side, "CSSColor", "::cssparser::Color::CurrentColor")}
13+
% endfor
14+
15+
% for side in ["top", "right", "bottom", "left"]:
16+
${helpers.predefined_type("border-%s-style" % side, "BorderStyle", "specified::BorderStyle::none")}
17+
% endfor
18+
19+
% for side in ["top", "right", "bottom", "left"]:
20+
<%helpers:longhand name="border-${side}-width">
21+
use app_units::Au;
22+
use cssparser::ToCss;
23+
use std::fmt;
24+
25+
impl ToCss for SpecifiedValue {
26+
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
27+
self.0.to_css(dest)
28+
}
29+
}
30+
31+
#[inline]
32+
pub fn parse(_context: &ParserContext, input: &mut Parser)
33+
-> Result<SpecifiedValue, ()> {
34+
specified::parse_border_width(input).map(SpecifiedValue)
35+
}
36+
#[derive(Debug, Clone, PartialEq, HeapSizeOf)]
37+
pub struct SpecifiedValue(pub specified::Length);
38+
pub mod computed_value {
39+
use app_units::Au;
40+
pub type T = Au;
41+
}
42+
#[inline] pub fn get_initial_value() -> computed_value::T {
43+
Au::from_px(3) // medium
44+
}
45+
46+
impl ToComputedValue for SpecifiedValue {
47+
type ComputedValue = computed_value::T;
48+
49+
#[inline]
50+
fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
51+
self.0.to_computed_value(context)
52+
}
53+
}
54+
</%helpers:longhand>
55+
% endfor
56+
57+
// FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage>
58+
% for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]:
59+
${helpers.predefined_type("border-" + corner + "-radius", "BorderRadiusSize",
60+
"computed::BorderRadiusSize::zero()",
61+
"parse")}
62+
% endfor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
<%page args="data, helpers" />
6+
7+
<% data.new_style_struct("Box", inherited=False, gecko_ffi_name="nsStyleDisplay",
8+
additional_methods=[data.new_method("clone_display",
9+
"longhands::display::computed_value::T"),
10+
data.new_method("clone_position",
11+
"longhands::position::computed_value::T"),
12+
data.new_method("is_floated", "bool"),
13+
data.new_method("overflow_x_is_visible", "bool"),
14+
data.new_method("overflow_y_is_visible", "bool"),
15+
data.new_method("transition_count", "usize")]) %>
16+
17+
// TODO(SimonSapin): don't parse `inline-table`, since we don't support it
18+
<%helpers:longhand name="display" custom_cascade="${product == 'servo'}">
19+
<%
20+
values = """inline block inline-block
21+
table inline-table table-row-group table-header-group table-footer-group
22+
table-row table-column-group table-column table-cell table-caption
23+
list-item flex
24+
none
25+
""".split()
26+
experimental_values = set("flex".split())
27+
%>
28+
pub use self::computed_value::T as SpecifiedValue;
29+
use values::computed::{Context, ComputedValueAsSpecified};
30+
31+
pub mod computed_value {
32+
#[allow(non_camel_case_types)]
33+
#[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug, HeapSizeOf)]
34+
#[derive(Deserialize, Serialize)]
35+
pub enum T {
36+
% for value in values:
37+
${data.to_rust_ident(value)},
38+
% endfor
39+
}
40+
41+
impl ::cssparser::ToCss for T {
42+
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
43+
where W: ::std::fmt::Write {
44+
match *self {
45+
% for value in values:
46+
T::${data.to_rust_ident(value)} => dest.write_str("${value}"),
47+
% endfor
48+
}
49+
}
50+
}
51+
}
52+
#[inline] pub fn get_initial_value() -> computed_value::T {
53+
computed_value::T::${data.to_rust_ident(values[0])}
54+
}
55+
pub fn parse(_context: &ParserContext, input: &mut Parser)
56+
-> Result<SpecifiedValue, ()> {
57+
match_ignore_ascii_case! { try!(input.expect_ident()),
58+
% for value in values:
59+
"${value}" => {
60+
% if value in experimental_values:
61+
if !::util::prefs::get_pref("layout.${value}.enabled")
62+
.as_boolean().unwrap_or(false) {
63+
return Err(())
64+
}
65+
% endif
66+
Ok(computed_value::T::${data.to_rust_ident(value)})
67+
},
68+
% endfor
69+
_ => Err(())
70+
}
71+
}
72+
73+
impl ComputedValueAsSpecified for SpecifiedValue {}
74+
75+
% if product == "servo":
76+
fn cascade_property_custom<C: ComputedValues>(
77+
_declaration: &PropertyDeclaration,
78+
_inherited_style: &C,
79+
context: &mut computed::Context<C>,
80+
_seen: &mut PropertyBitField,
81+
_cacheable: &mut bool,
82+
_error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
83+
longhands::_servo_display_for_hypothetical_box::derive_from_display(context);
84+
longhands::_servo_text_decorations_in_effect::derive_from_display(context);
85+
}
86+
% endif
87+
88+
</%helpers:longhand>
89+
90+
${helpers.single_keyword("position", "static absolute relative fixed", extra_gecko_values="sticky")}
91+
92+
<%helpers:single_keyword_computed name="float" values="none left right" gecko_ffi_name="mFloats">
93+
impl ToComputedValue for SpecifiedValue {
94+
type ComputedValue = computed_value::T;
95+
96+
#[inline]
97+
fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
98+
let positioned = matches!(context.style().get_box().clone_position(),
99+
longhands::position::SpecifiedValue::absolute |
100+
longhands::position::SpecifiedValue::fixed);
101+
if positioned {
102+
SpecifiedValue::none
103+
} else {
104+
*self
105+
}
106+
}
107+
}
108+
109+
</%helpers:single_keyword_computed>
110+
111+
${helpers.single_keyword("clear", "none left right both", gecko_ffi_name="mBreakType")}
112+
113+
<%helpers:longhand name="-servo-display-for-hypothetical-box" derived_from="display" products="servo">
114+
pub use super::display::{SpecifiedValue, get_initial_value};
115+
pub use super::display::{parse};
116+
117+
pub mod computed_value {
118+
pub type T = super::SpecifiedValue;
119+
}
120+
121+
#[inline]
122+
pub fn derive_from_display<Cx: TContext>(context: &mut Cx) {
123+
let d = context.style().get_box().clone_display();
124+
context.mutate_style().mutate_box().set__servo_display_for_hypothetical_box(d);
125+
}
126+
127+
</%helpers:longhand>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
<%page args="data, helpers" />
6+
7+
<% data.new_style_struct("Margin", inherited=False, gecko_ffi_name="nsStyleMargin") %>
8+
9+
% for side in ["top", "right", "bottom", "left"]:
10+
${helpers.predefined_type("margin-" + side, "LengthOrPercentageOrAuto",
11+
"computed::LengthOrPercentageOrAuto::Length(Au(0))")}
12+
% endfor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
<%page args="data, helpers" />
6+
7+
<% data.new_style_struct("Outline", inherited=False, gecko_ffi_name="nsStyleOutline",
8+
additional_methods=[data.new_method("outline_is_none_or_hidden_and_has_nonzero_width", "bool")]) %>
9+
10+
// TODO(pcwalton): `invert`
11+
${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::CurrentColor")}
12+
13+
<%helpers:longhand name="outline-style">
14+
pub use values::specified::BorderStyle as SpecifiedValue;
15+
pub fn get_initial_value() -> SpecifiedValue { SpecifiedValue::none }
16+
pub mod computed_value {
17+
pub use values::specified::BorderStyle as T;
18+
}
19+
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
20+
match SpecifiedValue::parse(input) {
21+
Ok(SpecifiedValue::hidden) => Err(()),
22+
result => result
23+
}
24+
}
25+
</%helpers:longhand>
26+
27+
<%helpers:longhand name="outline-width">
28+
use app_units::Au;
29+
use cssparser::ToCss;
30+
use std::fmt;
31+
use values::AuExtensionMethods;
32+
33+
impl ToCss for SpecifiedValue {
34+
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
35+
self.0.to_css(dest)
36+
}
37+
}
38+
39+
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
40+
specified::parse_border_width(input).map(SpecifiedValue)
41+
}
42+
#[derive(Debug, Clone, PartialEq, HeapSizeOf)]
43+
pub struct SpecifiedValue(pub specified::Length);
44+
pub mod computed_value {
45+
use app_units::Au;
46+
pub type T = Au;
47+
}
48+
pub use super::border_top_width::get_initial_value;
49+
impl ToComputedValue for SpecifiedValue {
50+
type ComputedValue = computed_value::T;
51+
52+
#[inline]
53+
fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
54+
self.0.to_computed_value(context)
55+
}
56+
}
57+
</%helpers:longhand>
58+
59+
${helpers.predefined_type("outline-offset", "Length", "Au(0)")}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
<%page args="data, helpers" />
6+
7+
<% data.new_style_struct("Padding", inherited=False, gecko_ffi_name="nsStylePadding") %>
8+
9+
% for side in ["top", "right", "bottom", "left"]:
10+
${helpers.predefined_type("padding-" + side, "LengthOrPercentage",
11+
"computed::LengthOrPercentage::Length(Au(0))",
12+
"parse_non_negative")}
13+
% endfor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
<%page args="data, helpers" />
6+
7+
<% data.new_style_struct("Position", inherited=False, gecko_ffi_name="nsStylePosition") %>
8+
9+
% for side in ["top", "right", "bottom", "left"]:
10+
${helpers.predefined_type(side, "LengthOrPercentageOrAuto",
11+
"computed::LengthOrPercentageOrAuto::Auto")}
12+
% endfor
13+
14+
<%helpers:longhand name="z-index">
15+
use values::computed::ComputedValueAsSpecified;
16+
17+
impl ComputedValueAsSpecified for SpecifiedValue {}
18+
pub type SpecifiedValue = computed_value::T;
19+
pub mod computed_value {
20+
use cssparser::ToCss;
21+
use std::fmt;
22+
23+
#[derive(PartialEq, Clone, Eq, Copy, Debug, HeapSizeOf)]
24+
pub enum T {
25+
Auto,
26+
Number(i32),
27+
}
28+
29+
impl ToCss for T {
30+
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
31+
match *self {
32+
T::Auto => dest.write_str("auto"),
33+
T::Number(number) => write!(dest, "{}", number),
34+
}
35+
}
36+
}
37+
38+
impl T {
39+
pub fn number_or_zero(self) -> i32 {
40+
match self {
41+
T::Auto => 0,
42+
T::Number(value) => value,
43+
}
44+
}
45+
}
46+
}
47+
#[inline]
48+
pub fn get_initial_value() -> computed_value::T {
49+
computed_value::T::Auto
50+
}
51+
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
52+
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
53+
Ok(computed_value::T::Auto)
54+
} else {
55+
specified::parse_integer(input).map(computed_value::T::Number)
56+
}
57+
}
58+
</%helpers:longhand>

0 commit comments

Comments
 (0)