Auto merge of #14120 - Manishearth:logical, r=emilio

Support logical properties in style

Adds support for the logical block-end/inline-start/etc properties. These properties (like `border-block-end-color`) map to "physical" properties (e.g. `border-top-color`) depending on the writing mode.

Todo:

 - [x] Handle shorthands
 - [x] Make geckolib setters work
 - [x] Handle padding/offset logical properties
 - [x] Perhaps handle `-block-size`, `-inline-size` type logical properties?
 - [x] Tests?

This will overall add 16 new longhands and 4 new shorthands, taking a big bite out of the [remaining properties work](https://manishearth.github.io/css-properties-list/?stylo=hide&servo=hide&firefox=only&chrome=show&mdn=false&alexa=false)

f? @emilio @SimonSapin

<!-- 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/14120)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-11-11 15:41:08 -06:00 committed by GitHub
commit 4b9693cf81
10 changed files with 240 additions and 89 deletions

View file

@ -103,6 +103,39 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopWidth; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-width; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStartColor;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStartWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStartStyle;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEndColor;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEndWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEndStyle;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStartColor;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStartWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStartStyle;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEndColor;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEndWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEndStyle;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-start;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockStart;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-block-end;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBlockEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-start;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineStart;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-inline-end;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderInlineEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString content; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString content;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString color; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString color;
@ -242,6 +275,14 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-right; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginTop; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginTop;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-top; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-top;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-block-start;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginBlockStart;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-block-end;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginBlockEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-inline-start;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginInlineStart;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-inline-end;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginInlineEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBottom; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBottom;
@ -252,6 +293,14 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-right; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingTop; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingTop;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-top; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-top;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-block-start;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBlockStart;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-block-end;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBlockEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-inline-start;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingInlineStart;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-inline-end;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingInlineEnd;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineColor; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineColor;
@ -284,6 +333,18 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-width; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxWidth; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxWidth;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-width; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString block-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString blockSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString inline-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString inlineSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-block-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxBlockSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-inline-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxInlineSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-block-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString minBlockSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-inline-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString minInlineSize;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString zIndex; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString zIndex;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString z-index; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString z-index;

View file

@ -4,6 +4,15 @@
import re import re
PHYSICAL_SIDES = ["top", "left", "bottom", "right"]
LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
PHYSICAL_SIZES = ["width", "height"]
LOGICAL_SIZES = ["block-size", "inline-size"]
# bool is True when logical
ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [(side, True) for side in LOGICAL_SIDES]
ALL_SIZES = [(size, False) for size in PHYSICAL_SIZES] + [(size, True) for size in LOGICAL_SIZES]
def to_rust_ident(name): def to_rust_ident(name):
name = name.replace("-", "_") name = name.replace("-", "_")
@ -63,12 +72,19 @@ class Keyword(object):
return "as " + type_str if self.needs_cast() else "" return "as " + type_str if self.needs_cast() else ""
def arg_to_bool(arg):
if isinstance(arg, bool):
return arg
assert arg in ["True", "False"]
return arg == "True"
class Longhand(object): class Longhand(object):
def __init__(self, style_struct, name, animatable=None, derived_from=None, keyword=None, def __init__(self, style_struct, name, animatable=None, derived_from=None, keyword=None,
predefined_type=None, custom_cascade=False, experimental=False, internal=False, predefined_type=None, custom_cascade=False, experimental=False, internal=False,
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False, need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
allowed_in_keyframe_block=True, complex_color=False, cast_type='u8', allowed_in_keyframe_block=True, complex_color=False, cast_type='u8',
has_uncacheable_values=False): has_uncacheable_values=False, logical=False):
self.name = name self.name = name
self.keyword = keyword self.keyword = keyword
self.predefined_type = predefined_type self.predefined_type = predefined_type
@ -85,6 +101,7 @@ class Longhand(object):
self.derived_from = (derived_from or "").split() self.derived_from = (derived_from or "").split()
self.complex_color = complex_color self.complex_color = complex_color
self.cast_type = cast_type self.cast_type = cast_type
self.logical = arg_to_bool(logical)
# https://drafts.csswg.org/css-animations/#keyframes # https://drafts.csswg.org/css-animations/#keyframes
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property # > The <declaration-list> inside of <keyframe-block> accepts any CSS property
@ -97,12 +114,10 @@ class Longhand(object):
# really random. # really random.
if animatable is None: if animatable is None:
raise TypeError("animatable should be specified for " + name + ")") raise TypeError("animatable should be specified for " + name + ")")
if isinstance(animatable, bool): self.animatable = arg_to_bool(animatable)
self.animatable = animatable if self.logical:
else: # Logical properties don't animate separately
assert animatable == "True" or animatable == "False" self.animatable = False
self.animatable = animatable == "True"
# NB: Animatable implies clone because a property animation requires a # NB: Animatable implies clone because a property animation requires a
# copy of the computed value. # copy of the computed value.
# #

View file

@ -8,6 +8,7 @@
from data import to_rust_ident from data import to_rust_ident
from data import Keyword from data import Keyword
%> %>
<%namespace name="helpers" file="/helpers.mako.rs" />
use app_units::Au; use app_units::Au;
use custom_properties::ComputedValuesMap; use custom_properties::ComputedValuesMap;
@ -401,6 +402,10 @@ def set_gecko_property(ffi_name, expr):
% endif % endif
</%def> </%def>
<%def name="impl_logical(name, need_clone=False, **kwargs)">
${helpers.logical_setter(name, need_clone)}
</%def>
<%def name="impl_style_struct(style_struct)"> <%def name="impl_style_struct(style_struct)">
impl ${style_struct.gecko_struct_name} { impl ${style_struct.gecko_struct_name} {
#[allow(dead_code, unused_variables)] #[allow(dead_code, unused_variables)]
@ -496,7 +501,10 @@ impl Debug for ${style_struct.gecko_struct_name} {
need_clone=longhand.need_clone) need_clone=longhand.need_clone)
# get the method and pass additional keyword or type-specific arguments # get the method and pass additional keyword or type-specific arguments
if longhand.keyword: if longhand.logical:
method = impl_logical
args.update(name=longhand.name)
elif longhand.keyword:
method = impl_keyword method = impl_keyword
args.update(keyword=longhand.keyword) args.update(keyword=longhand.keyword)
if "font" in longhand.ident: if "font" in longhand.ident:
@ -510,7 +518,7 @@ impl Debug for ${style_struct.gecko_struct_name} {
picked_longhands, stub_longhands = [], [] picked_longhands, stub_longhands = [], []
for x in longhands: for x in longhands:
if (x.keyword or x.predefined_type in predefined_types) and x.name not in force_stub: if (x.keyword or x.predefined_type in predefined_types or x.logical) and x.name not in force_stub:
picked_longhands.append(x) picked_longhands.append(x)
else: else:
stub_longhands.append(x) stub_longhands.append(x)

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%! from data import Keyword, to_rust_ident, to_camel_case %> <%! from data import Keyword, to_rust_ident, to_camel_case, LOGICAL_SIDES, PHYSICAL_SIDES, LOGICAL_SIZES %>
<%def name="longhand(name, **kwargs)"> <%def name="longhand(name, **kwargs)">
<%call expr="raw_longhand(name, **kwargs)"> <%call expr="raw_longhand(name, **kwargs)">
@ -221,15 +221,19 @@
cascade_info.on_cascade_property(&declaration, cascade_info.on_cascade_property(&declaration,
&value); &value);
} }
% if property.logical:
let wm = context.style.writing_mode;
% endif
<% maybe_wm = ", wm" if property.logical else "" %>
match *value { match *value {
DeclaredValue::Value(ref specified_value) => { DeclaredValue::Value(ref specified_value) => {
let computed = specified_value.to_computed_value(context); let computed = specified_value.to_computed_value(context);
% if property.has_uncacheable_values: % if property.has_uncacheable_values:
context.mutate_style().mutate_${data.current_style_struct.name_lower}() context.mutate_style().mutate_${data.current_style_struct.name_lower}()
.set_${property.ident}(computed, cacheable); .set_${property.ident}(computed, cacheable ${maybe_wm});
% else: % else:
context.mutate_style().mutate_${data.current_style_struct.name_lower}() context.mutate_style().mutate_${data.current_style_struct.name_lower}()
.set_${property.ident}(computed); .set_${property.ident}(computed ${maybe_wm});
% endif % endif
} }
DeclaredValue::WithVariables { .. } => unreachable!(), DeclaredValue::WithVariables { .. } => unreachable!(),
@ -239,7 +243,7 @@
let initial_struct = ComputedValues::initial_values() let initial_struct = ComputedValues::initial_values()
.get_${data.current_style_struct.name_lower}(); .get_${data.current_style_struct.name_lower}();
context.mutate_style().mutate_${data.current_style_struct.name_lower}() context.mutate_style().mutate_${data.current_style_struct.name_lower}()
.copy_${property.ident}_from(initial_struct); .copy_${property.ident}_from(initial_struct ${maybe_wm});
}, },
DeclaredValue::Inherit => { DeclaredValue::Inherit => {
// This is a bit slow, but this is rare so it shouldn't // This is a bit slow, but this is rare so it shouldn't
@ -250,7 +254,7 @@
let inherited_struct = let inherited_struct =
inherited_style.get_${data.current_style_struct.name_lower}(); inherited_style.get_${data.current_style_struct.name_lower}();
context.mutate_style().mutate_${data.current_style_struct.name_lower}() context.mutate_style().mutate_${data.current_style_struct.name_lower}()
.copy_${property.ident}_from(inherited_struct); .copy_${property.ident}_from(inherited_struct ${maybe_wm});
} }
} }
}, error_reporter); }, error_reporter);
@ -607,3 +611,69 @@
} }
</%self:shorthand> </%self:shorthand>
</%def> </%def>
<%def name="logical_setter_helper(name)">
<%
side = None
size = None
maybe_side = [s for s in LOGICAL_SIDES if s in name]
maybe_size = [s for s in LOGICAL_SIZES if s in name]
if len(maybe_side) == 1:
side = maybe_side[0]
elif len(maybe_size) == 1:
size = maybe_size[0]
%>
% if side is not None:
use logical_geometry::PhysicalSide;
match wm.${to_rust_ident(side)}_physical_side() {
% for phy_side in PHYSICAL_SIDES:
PhysicalSide::${phy_side.title()} => {
${caller.inner(physical_ident=to_rust_ident(name.replace(side, phy_side)))}
}
% endfor
}
% elif size is not None:
<%
# (horizontal, vertical)
physical_size = ("height", "width")
if size == "inline-size":
physical_size = ("width", "height")
%>
if wm.is_vertical() {
${caller.inner(physical_ident=to_rust_ident(name.replace(size, physical_size[1])))}
} else {
${caller.inner(physical_ident=to_rust_ident(name.replace(size, physical_size[0])))}
}
% else:
<% raise Exception("Don't know what to do with logical property %s" % name) %>
% endif
</%def>
<%def name="logical_setter(name, need_clone=False)">
pub fn set_${to_rust_ident(name)}(&mut self,
v: longhands::${to_rust_ident(name)}::computed_value::T,
wm: WritingMode) {
<%self:logical_setter_helper name="${name}">
<%def name="inner(physical_ident)">
self.set_${physical_ident}(v)
</%def>
</%self:logical_setter_helper>
}
pub fn copy_${to_rust_ident(name)}_from(&mut self, other: &Self, wm: WritingMode) {
<%self:logical_setter_helper name="${name}">
<%def name="inner(physical_ident)">
self.copy_${physical_ident}_from(other)
</%def>
</%self:logical_setter_helper>
}
% if need_clone:
pub fn clone_${to_rust_ident(name)}(&self, wm: WritingMode)
-> longhands::${to_rust_ident(name)}::computed_value::T {
<%self:logical_setter_helper name="${name}">
<%def name="inner(physical_ident)">
self.clone_${physical_ident}()
</%def>
</%self:logical_setter_helper>
}
% endif
</%def>

View file

@ -3,26 +3,26 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %> <% from data import Method, PHYSICAL_SIDES, ALL_SIDES %>
<% data.new_style_struct("Border", inherited=False, <% data.new_style_struct("Border", inherited=False,
additional_methods=[Method("border_" + side + "_has_nonzero_width", additional_methods=[Method("border_" + side + "_has_nonzero_width",
"bool") for side in ["top", "right", "bottom", "left"]]) %> "bool") for side in ["top", "right", "bottom", "left"]]) %>
% for side in ["top", "right", "bottom", "left"]: % for side in ALL_SIDES:
${helpers.predefined_type("border-%s-color" % side, "CSSColor", ${helpers.predefined_type("border-%s-color" % side[0], "CSSColor",
"::cssparser::Color::CurrentColor", "::cssparser::Color::CurrentColor",
animatable=True)} animatable=True, logical = side[1])}
% endfor % endfor
% for side in ["top", "right", "bottom", "left"]: % for side in ALL_SIDES:
${helpers.predefined_type("border-%s-style" % side, "BorderStyle", ${helpers.predefined_type("border-%s-style" % side[0], "BorderStyle",
"specified::BorderStyle::none", "specified::BorderStyle::none",
need_clone=True, animatable=False)} need_clone=True, animatable=False, logical = side[1])}
% endfor % endfor
% for side in ["top", "right", "bottom", "left"]: % for side in ALL_SIDES:
<%helpers:longhand name="border-${side}-width" animatable="True"> <%helpers:longhand name="border-${side[0]}-width" animatable="True" logical="${side[1]}">
use app_units::Au; use app_units::Au;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;

View file

@ -3,11 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import ALL_SIDES %>
<% data.new_style_struct("Margin", inherited=False) %> <% data.new_style_struct("Margin", inherited=False) %>
% for side in ["top", "right", "bottom", "left"]: % for side in ALL_SIDES:
${helpers.predefined_type("margin-" + side, "LengthOrPercentageOrAuto", ${helpers.predefined_type("margin-%s" % side[0], "LengthOrPercentageOrAuto",
"computed::LengthOrPercentageOrAuto::Length(Au(0))", "computed::LengthOrPercentageOrAuto::Length(Au(0))",
animatable=True)} animatable=True, logical = side[1])}
% endfor % endfor

View file

@ -3,12 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import ALL_SIDES %>
<% data.new_style_struct("Padding", inherited=False) %> <% data.new_style_struct("Padding", inherited=False) %>
% for side in ["top", "right", "bottom", "left"]: % for side in ALL_SIDES:
${helpers.predefined_type("padding-" + side, "LengthOrPercentage", ${helpers.predefined_type("padding-%s" % side[0], "LengthOrPercentage",
"computed::LengthOrPercentage::Length(Au(0))", "computed::LengthOrPercentage::Length(Au(0))",
"parse_non_negative", "parse_non_negative",
animatable=True)} animatable=True,
logical = side[1])}
% endfor % endfor

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import ALL_SIZES %>
<% data.new_style_struct("Position", inherited=False) %> <% data.new_style_struct("Position", inherited=False) %>
@ -133,41 +134,28 @@ ${helpers.predefined_type("flex-basis",
"computed::LengthOrPercentageOrAutoOrContent::Auto", "computed::LengthOrPercentageOrAutoOrContent::Auto",
animatable=False)} animatable=False)}
${helpers.predefined_type("width", % for (size, logical) in ALL_SIZES:
"LengthOrPercentageOrAuto", // width, height, block-size, inline-size
"computed::LengthOrPercentageOrAuto::Auto", ${helpers.predefined_type("%s" % size,
"parse_non_negative", "LengthOrPercentageOrAuto",
animatable=True)} "computed::LengthOrPercentageOrAuto::Auto",
"parse_non_negative",
animatable=True, logical = logical)}
${helpers.predefined_type("height", // min-width, min-height, min-block-size, min-inline-size
"LengthOrPercentageOrAuto", ${helpers.predefined_type("min-%s" % size,
"computed::LengthOrPercentageOrAuto::Auto", "LengthOrPercentage",
"parse_non_negative", "computed::LengthOrPercentage::Length(Au(0))",
animatable=True)} "parse_non_negative",
animatable=True, logical = logical)}
${helpers.predefined_type("min-width", // max-width, max-height, max-block-size, max-inline-size
"LengthOrPercentage", ${helpers.predefined_type("max-%s" % size,
"computed::LengthOrPercentage::Length(Au(0))", "LengthOrPercentageOrNone",
"parse_non_negative", "computed::LengthOrPercentageOrNone::None",
animatable=True)} "parse_non_negative",
animatable=True, logical = logical)}
${helpers.predefined_type("max-width", % endfor
"LengthOrPercentageOrNone",
"computed::LengthOrPercentageOrNone::None",
"parse_non_negative",
animatable=True)}
${helpers.predefined_type("min-height",
"LengthOrPercentage",
"computed::LengthOrPercentage::Length(Au(0))",
"parse_non_negative",
animatable=True)}
${helpers.predefined_type("max-height",
"LengthOrPercentageOrNone",
"computed::LengthOrPercentageOrNone::None",
"parse_non_negative",
animatable=True)}
${helpers.single_keyword("box-sizing", ${helpers.single_keyword("box-sizing",
"content-box border-box", "content-box border-box",

View file

@ -894,6 +894,7 @@ pub mod style_structs {
use fnv::FnvHasher; use fnv::FnvHasher;
use super::longhands; use super::longhands;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use logical_geometry::WritingMode;
% for style_struct in data.active_style_structs(): % for style_struct in data.active_style_structs():
% if style_struct.name == "Font": % if style_struct.name == "Font":
@ -924,24 +925,27 @@ pub mod style_structs {
impl ${style_struct.name} { impl ${style_struct.name} {
% for longhand in style_struct.longhands: % for longhand in style_struct.longhands:
#[allow(non_snake_case)] % if longhand.logical:
#[inline] ${helpers.logical_setter(name=longhand.name)}
pub fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) { % else:
self.${longhand.ident} = v;
}
#[allow(non_snake_case)]
#[inline]
pub fn copy_${longhand.ident}_from(&mut self, other: &Self) {
self.${longhand.ident} = other.${longhand.ident}.clone();
}
% if longhand.need_clone:
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[inline] #[inline]
pub fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T { pub fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) {
self.${longhand.ident}.clone() self.${longhand.ident} = v;
} }
#[allow(non_snake_case)]
#[inline]
pub fn copy_${longhand.ident}_from(&mut self, other: &Self) {
self.${longhand.ident} = other.${longhand.ident}.clone();
}
% if longhand.need_clone:
#[allow(non_snake_case)]
#[inline]
pub fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
self.${longhand.ident}.clone()
}
% endif
% endif % endif
% if longhand.need_index: % if longhand.need_index:
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn ${longhand.ident}_count(&self) -> usize { pub fn ${longhand.ident}_count(&self) -> usize {
@ -1562,7 +1566,9 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
PropertyDeclaration::Position(_) | PropertyDeclaration::Position(_) |
PropertyDeclaration::Float(_) | PropertyDeclaration::Float(_) |
PropertyDeclaration::TextDecoration${'' if product == 'servo' else 'Line'}(_) | PropertyDeclaration::TextDecoration${'' if product == 'servo' else 'Line'}(_) |
PropertyDeclaration::WritingMode(_) PropertyDeclaration::WritingMode(_) |
PropertyDeclaration::Direction(_) |
PropertyDeclaration::TextOrientation(_)
); );
if if
% if category_to_cascade_now == "early": % if category_to_cascade_now == "early":
@ -1582,6 +1588,10 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
&mut cascade_info, &mut cascade_info,
&mut error_reporter); &mut error_reporter);
} }
% if category_to_cascade_now == "early":
let mode = get_writing_mode(context.style.get_inheritedbox());
context.style.set_writing_mode(mode);
% endif
% endfor % endfor
}); });
@ -1688,8 +1698,6 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
style.mutate_font().compute_font_hash(); style.mutate_font().compute_font_hash();
} }
let mode = get_writing_mode(style.get_inheritedbox());
style.set_writing_mode(mode);
style style
} }

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" /> <%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import to_rust_ident %> <% from data import to_rust_ident, ALL_SIDES %>
${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse")} ${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse")}
${helpers.four_sides_shorthand("border-style", "border-%s-style", ${helpers.four_sides_shorthand("border-style", "border-%s-style",
@ -83,7 +83,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
if any { Ok((color, style, width)) } else { Err(()) } if any { Ok((color, style, width)) } else { Err(()) }
} }
% for side in ["top", "right", "bottom", "left"]: % for side in map(lambda x: x[0], ALL_SIDES):
<%helpers:shorthand name="border-${side}" sub_properties="${' '.join( <%helpers:shorthand name="border-${side}" sub_properties="${' '.join(
'border-%s-%s' % (side, prop) 'border-%s-%s' % (side, prop)
for prop in ['color', 'style', 'width'] for prop in ['color', 'style', 'width']
@ -92,9 +92,9 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> { pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
let (color, style, width) = try!(super::parse_border(context, input)); let (color, style, width) = try!(super::parse_border(context, input));
Ok(Longhands { Ok(Longhands {
border_${side}_color: color, border_${to_rust_ident(side)}_color: color,
border_${side}_style: style, border_${to_rust_ident(side)}_style: style,
border_${side}_width: width border_${to_rust_ident(side)}_width: width
}) })
} }
@ -102,9 +102,9 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
super::serialize_directional_border( super::serialize_directional_border(
dest, dest,
self.border_${side}_width, self.border_${to_rust_ident(side)}_width,
self.border_${side}_style, self.border_${to_rust_ident(side)}_style,
self.border_${side}_color self.border_${to_rust_ident(side)}_color
) )
} }
} }