aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-11-07 14:34:22 -0800
committerManish Goregaokar <manishsmail@gmail.com>2016-11-11 11:55:57 -0800
commite34eb13d6583249e2d159cfeece2c5f12fe465ad (patch)
treeaf8abe077fbeccbb5e0097f2972a4ccf9f8c1e71 /components
parentf1c3e97fb47b6fbe1d82ebb30a38ab7afd4fe0b8 (diff)
downloadservo-e34eb13d6583249e2d159cfeece2c5f12fe465ad.tar.gz
servo-e34eb13d6583249e2d159cfeece2c5f12fe465ad.zip
Support logical properties
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/webidls/CSSStyleDeclaration.webidl25
-rw-r--r--components/style/properties/data.py25
-rw-r--r--components/style/properties/gecko.mako.rs12
-rw-r--r--components/style/properties/helpers.mako.rs64
-rw-r--r--components/style/properties/longhand/border.mako.rs18
-rw-r--r--components/style/properties/properties.mako.rs42
6 files changed, 146 insertions, 40 deletions
diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl
index c64ecd119c7..a8cd456c41d 100644
--- a/components/script/dom/webidls/CSSStyleDeclaration.webidl
+++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl
@@ -103,6 +103,31 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopWidth;
[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 content;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString color;
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index 8ef12fd6cd4..f8ad6e83283 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -4,6 +4,11 @@
import re
+PHYSICAL_SIDES = ["top", "left", "bottom", "right"]
+LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
+# bool is True when logical
+ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [(side, True) for side in LOGICAL_SIDES]
+
def to_rust_ident(name):
name = name.replace("-", "_")
@@ -63,12 +68,19 @@ class Keyword(object):
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):
def __init__(self, style_struct, name, animatable=None, derived_from=None, keyword=None,
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,
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.keyword = keyword
self.predefined_type = predefined_type
@@ -85,6 +97,7 @@ class Longhand(object):
self.derived_from = (derived_from or "").split()
self.complex_color = complex_color
self.cast_type = cast_type
+ self.logical = arg_to_bool(logical)
# https://drafts.csswg.org/css-animations/#keyframes
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property
@@ -97,12 +110,10 @@ class Longhand(object):
# really random.
if animatable is None:
raise TypeError("animatable should be specified for " + name + ")")
- if isinstance(animatable, bool):
- self.animatable = animatable
- else:
- assert animatable == "True" or animatable == "False"
- self.animatable = animatable == "True"
-
+ self.animatable = arg_to_bool(animatable)
+ if self.logical:
+ # Logical properties don't animate separately
+ self.animatable = False
# NB: Animatable implies clone because a property animation requires a
# copy of the computed value.
#
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index cead90fc571..4e3db27ac12 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -8,6 +8,7 @@
from data import to_rust_ident
from data import Keyword
%>
+<%namespace name="helpers" file="/helpers.mako.rs" />
use app_units::Au;
use custom_properties::ComputedValuesMap;
@@ -400,6 +401,10 @@ def set_gecko_property(ffi_name, expr):
% endif
</%def>
+<%def name="impl_logical(name, need_clone=False, **kwargs)">
+ ${helpers.logical_setter(name, need_clone)}
+</%def>
+
<%def name="impl_style_struct(style_struct)">
impl ${style_struct.gecko_struct_name} {
#[allow(dead_code, unused_variables)]
@@ -495,7 +500,10 @@ impl Debug for ${style_struct.gecko_struct_name} {
need_clone=longhand.need_clone)
# 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
args.update(keyword=longhand.keyword)
if "font" in longhand.ident:
@@ -509,7 +517,7 @@ impl Debug for ${style_struct.gecko_struct_name} {
picked_longhands, stub_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)
else:
stub_longhands.append(x)
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index fe7bac7efe9..d022e2c310f 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -2,7 +2,7 @@
* 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/. */
-<%! from data import Keyword, to_rust_ident, to_camel_case %>
+<%! from data import Keyword, to_rust_ident, to_camel_case, LOGICAL_SIDES, PHYSICAL_SIDES %>
<%def name="longhand(name, **kwargs)">
<%call expr="raw_longhand(name, **kwargs)">
@@ -221,15 +221,19 @@
cascade_info.on_cascade_property(&declaration,
&value);
}
+ % if property.logical:
+ let wm = context.style.writing_mode;
+ % endif
+ <% maybe_wm = ", wm" if property.logical else "" %>
match *value {
DeclaredValue::Value(ref specified_value) => {
let computed = specified_value.to_computed_value(context);
% if property.has_uncacheable_values:
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
- .set_${property.ident}(computed, cacheable);
+ .set_${property.ident}(computed, cacheable ${maybe_wm});
% else:
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
- .set_${property.ident}(computed);
+ .set_${property.ident}(computed ${maybe_wm});
% endif
}
DeclaredValue::WithVariables { .. } => unreachable!(),
@@ -239,7 +243,7 @@
let initial_struct = ComputedValues::initial_values()
.get_${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 => {
// This is a bit slow, but this is rare so it shouldn't
@@ -250,7 +254,7 @@
let inherited_struct =
inherited_style.get_${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);
@@ -607,3 +611,53 @@
}
</%self:shorthand>
</%def>
+
+<%def name="logical_setter_helper(name)">
+ <%
+ side = None
+ maybe_side = [side for side in LOGICAL_SIDES if side in name]
+ if len(maybe_side) == 1:
+ side = maybe_side[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(side_ident=to_rust_ident(name.replace(side, phy_side)))}
+ }
+ % endfor
+ }
+ % 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(side_ident)">
+ self.set_${side_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(side_ident)">
+ self.copy_${side_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(side_ident)">
+ self.clone_${side_ident}()
+ </%def>
+ </%self:logical_setter_helper>
+ }
+ % endif
+</%def>
diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs
index b0b8d0701ad..1c6819d7062 100644
--- a/components/style/properties/longhand/border.mako.rs
+++ b/components/style/properties/longhand/border.mako.rs
@@ -3,26 +3,26 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%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,
additional_methods=[Method("border_" + side + "_has_nonzero_width",
"bool") for side in ["top", "right", "bottom", "left"]]) %>
-% for side in ["top", "right", "bottom", "left"]:
- ${helpers.predefined_type("border-%s-color" % side, "CSSColor",
+% for side in ALL_SIDES:
+ ${helpers.predefined_type("border-%s-color" % side[0], "CSSColor",
"::cssparser::Color::CurrentColor",
- animatable=True)}
+ animatable=True, logical = side[1])}
% endfor
-% for side in ["top", "right", "bottom", "left"]:
- ${helpers.predefined_type("border-%s-style" % side, "BorderStyle",
+% for side in ALL_SIDES:
+ ${helpers.predefined_type("border-%s-style" % side[0], "BorderStyle",
"specified::BorderStyle::none",
- need_clone=True, animatable=False)}
+ need_clone=True, animatable=False, logical = side[1])}
% endfor
-% for side in ["top", "right", "bottom", "left"]:
- <%helpers:longhand name="border-${side}-width" animatable="True">
+% for side in ALL_SIDES:
+ <%helpers:longhand name="border-${side[0]}-width" animatable="True" logical="${side[1]}">
use app_units::Au;
use std::fmt;
use style_traits::ToCss;
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index ca72c0c38aa..1823159fec6 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -893,6 +893,7 @@ pub mod style_structs {
use fnv::FnvHasher;
use super::longhands;
use std::hash::{Hash, Hasher};
+ use logical_geometry::WritingMode;
% for style_struct in data.active_style_structs():
% if style_struct.name == "Font":
@@ -923,24 +924,27 @@ pub mod style_structs {
impl ${style_struct.name} {
% for longhand in style_struct.longhands:
- #[allow(non_snake_case)]
- #[inline]
- pub fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) {
- 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:
+ % if longhand.logical:
+ ${helpers.logical_setter(name=longhand.name)}
+ % else:
#[allow(non_snake_case)]
#[inline]
- pub fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
- self.${longhand.ident}.clone()
+ pub fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) {
+ 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
-
% if longhand.need_index:
#[allow(non_snake_case)]
pub fn ${longhand.ident}_count(&self) -> usize {
@@ -1560,7 +1564,9 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
PropertyDeclaration::Position(_) |
PropertyDeclaration::Float(_) |
PropertyDeclaration::TextDecoration${'' if product == 'servo' else 'Line'}(_) |
- PropertyDeclaration::WritingMode(_)
+ PropertyDeclaration::WritingMode(_) |
+ PropertyDeclaration::Direction(_) |
+ PropertyDeclaration::TextOrientation(_)
);
if
% if category_to_cascade_now == "early":
@@ -1580,6 +1586,10 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
&mut cascade_info,
&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
});
@@ -1686,8 +1696,6 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
style.mutate_font().compute_font_hash();
}
- let mode = get_writing_mode(style.get_inheritedbox());
- style.set_writing_mode(mode);
style
}