diff options
author | Manish Goregaokar <manishsmail@gmail.com> | 2016-11-07 14:34:22 -0800 |
---|---|---|
committer | Manish Goregaokar <manishsmail@gmail.com> | 2016-11-11 11:55:57 -0800 |
commit | e34eb13d6583249e2d159cfeece2c5f12fe465ad (patch) | |
tree | af8abe077fbeccbb5e0097f2972a4ccf9f8c1e71 /components | |
parent | f1c3e97fb47b6fbe1d82ebb30a38ab7afd4fe0b8 (diff) | |
download | servo-e34eb13d6583249e2d159cfeece2c5f12fe465ad.tar.gz servo-e34eb13d6583249e2d159cfeece2c5f12fe465ad.zip |
Support logical properties
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/webidls/CSSStyleDeclaration.webidl | 25 | ||||
-rw-r--r-- | components/style/properties/data.py | 25 | ||||
-rw-r--r-- | components/style/properties/gecko.mako.rs | 12 | ||||
-rw-r--r-- | components/style/properties/helpers.mako.rs | 64 | ||||
-rw-r--r-- | components/style/properties/longhand/border.mako.rs | 18 | ||||
-rw-r--r-- | components/style/properties/properties.mako.rs | 42 |
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 } |