diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 722faf11326..3da02412132 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -864,7 +864,8 @@ fn static_assert() { <% skip_position_longhands = " ".join(x.ident for x in SIDES + GRID_LINES) %> <%self:impl_trait style_struct_name="Position" skip_longhands="${skip_position_longhands} z-index box-sizing order align-content - justify-content align-self justify-self"> + justify-content align-self justify-self align-items + justify-items"> % for side in SIDES: <% impl_split_style_coord("%s" % side.ident, "mOffset", @@ -926,6 +927,24 @@ fn static_assert() { ${impl_simple_copy('justify_self', 'mJustifySelf')} + pub fn set_align_items(&mut self, v: longhands::align_items::computed_value::T) { + self.gecko.mAlignItems = v.0.bits() + } + + ${impl_simple_copy('align_items', 'mAlignItems')} + + pub fn set_justify_items(&mut self, v: longhands::justify_items::computed_value::T) { + self.gecko.mJustifyItems = v.0.bits() + } + + ${impl_simple_copy('justify_items', 'mJustifyItems')} + + pub fn clone_justify_items(&self) -> longhands::justify_items::computed_value::T { + use values::specified::align::{AlignFlags, JustifyItems}; + JustifyItems(AlignFlags::from_bits(self.gecko.mJustifyItems) + .expect("mJustifyItems contains valid flags")) + } + pub fn set_box_sizing(&mut self, v: longhands::box_sizing::computed_value::T) { use computed_values::box_sizing::T; use gecko_bindings::structs::StyleBoxSizing; diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index b169f74c396..186bf7c5ac4 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -99,22 +99,19 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse", animatable=False)} % endif -// https://drafts.csswg.org/css-flexbox/#propdef-align-items -// FIXME: This is a workaround for 'normal' value. We don't support the Gecko initial value 'normal' yet. -${helpers.single_keyword("align-items", "stretch flex-start flex-end center baseline" if product == "servo" - else "normal stretch flex-start flex-end center baseline", - need_clone=True, - extra_prefixes="webkit", - gecko_constant_prefix="NS_STYLE_ALIGN", - spec="https://drafts.csswg.org/css-flexbox/#align-items-property", - animatable=False)} - % if product == "servo": // FIXME: Update Servo to support the same Syntax as Gecko. ${helpers.single_keyword("align-content", "stretch flex-start flex-end center space-between space-around", extra_prefixes="webkit", spec="https://drafts.csswg.org/css-flexbox/#align-content-property", animatable=False)} + + ${helpers.single_keyword("align-items", + "stretch flex-start flex-end center baseline", + need_clone=True, + extra_prefixes="webkit", + spec="https://drafts.csswg.org/css-flexbox/#align-items-property", + animatable=False)} % else: ${helpers.predefined_type(name="align-content", type="AlignJustifyContent", @@ -122,6 +119,19 @@ ${helpers.single_keyword("align-items", "stretch flex-start flex-end center base spec="https://drafts.csswg.org/css-flexbox/#align-content-property", extra_prefixes="webkit", animatable=False)} + + ${helpers.predefined_type(name="align-items", + type="AlignItems", + initial_value="specified::AlignItems::normal()", + spec="https://drafts.csswg.org/css-align/#propdef-align-items", + extra_prefixes="webkit", + animatable=False)} + + ${helpers.predefined_type(name="justify-items", + type="JustifyItems", + initial_value="specified::JustifyItems::auto()", + spec="https://drafts.csswg.org/css-align/#propdef-justify-items", + animatable=False)} % endif // Flex item properties diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 3c22ab1a8bb..6df904b832b 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -17,7 +17,7 @@ pub use self::image::{AngleOrCorner, EndingShape as GradientShape, Gradient, Gra pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword}; pub use super::{Auto, Either, None_}; #[cfg(feature = "gecko")] -pub use super::specified::{AlignJustifyContent, AlignJustifySelf}; +pub use super::specified::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems}; pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone}; pub use super::specified::url::UrlExtraData; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto}; @@ -122,6 +122,32 @@ impl ToComputedValue for specified::CSSColor { } } +#[cfg(feature = "gecko")] +impl ToComputedValue for specified::JustifyItems { + type ComputedValue = JustifyItems; + + // https://drafts.csswg.org/css-align/#valdef-justify-items-auto + fn to_computed_value(&self, context: &Context) -> JustifyItems { + use values::specified::align; + // If the inherited value of `justify-items` includes the `legacy` keyword, `auto` computes + // to the inherited value. + if self.0 == align::ALIGN_AUTO { + let inherited = context.inherited_style.get_position().clone_justify_items(); + if inherited.0.contains(align::ALIGN_LEGACY) { + return inherited + } + } + return *self + } + + #[inline] + fn from_computed_value(computed: &JustifyItems) -> Self { + *computed + } +} + +#[cfg(feature = "gecko")] +impl ComputedValueAsSpecified for specified::AlignItems {} #[cfg(feature = "gecko")] impl ComputedValueAsSpecified for specified::AlignJustifyContent {} #[cfg(feature = "gecko")] diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 26291f219e6..0c79ff6dddc 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -9,6 +9,7 @@ use cssparser::Parser; use gecko_bindings::structs; use parser::{Parse, ParserContext}; +use std::ascii::AsciiExt; use std::fmt; use style_traits::ToCss; use values::HasViewportPercentage; @@ -238,6 +239,86 @@ impl Parse for AlignJustifySelf { } } +/// Value of the `align-items` property +/// +/// https://drafts.csswg.org/css-align/#self-alignment +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct AlignItems(pub AlignFlags); + +impl AlignItems { + /// The initial value 'normal' + #[inline] + pub fn normal() -> Self { + AlignItems(ALIGN_NORMAL) + } +} + +no_viewport_percentage!(AlignItems); + +impl ToCss for AlignItems { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.0.to_css(dest) + } +} + +impl Parse for AlignItems { + // normal | stretch | | + // [ ? && ] + fn parse(_: &ParserContext, input: &mut Parser) -> Result { + // normal | stretch | + if let Ok(value) = input.try(parse_normal_stretch_baseline) { + return Ok(AlignItems(value)) + } + // [ ? && ] + if let Ok(value) = input.try(parse_overflow_self_position) { + return Ok(AlignItems(value)) + } + Err(()) + } +} + +/// Value of the `justify-items` property +/// +/// https://drafts.csswg.org/css-align/#justify-items-property +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct JustifyItems(pub AlignFlags); + +impl JustifyItems { + /// The initial value 'auto' + #[inline] + pub fn auto() -> Self { + JustifyItems(ALIGN_AUTO) + } +} + +no_viewport_percentage!(JustifyItems); + +impl ToCss for JustifyItems { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.0.to_css(dest) + } +} + +impl Parse for JustifyItems { + // auto | normal | stretch | | + // [ ? && ] + // [ legacy && [ left | right | center ] ] + fn parse(_: &ParserContext, input: &mut Parser) -> Result { + // auto | normal | stretch | + if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) { + return Ok(JustifyItems(value)) + } + // [ ? && ] + if let Ok(value) = input.try(parse_overflow_self_position) { + return Ok(JustifyItems(value)) + } + // [ legacy && [ left | right | center ] ] + if let Ok(value) = input.try(parse_legacy) { + return Ok(JustifyItems(value)) + } + Err(()) + } +} // auto | normal | stretch | fn parse_auto_normal_stretch_baseline(input: &mut Parser) -> Result { @@ -251,6 +332,17 @@ fn parse_auto_normal_stretch_baseline(input: &mut Parser) -> Result +fn parse_normal_stretch_baseline(input: &mut Parser) -> Result { + let ident = input.expect_ident()?; + match_ignore_ascii_case! { ident, + "normal" => Ok(ALIGN_NORMAL), + "stretch" => Ok(ALIGN_STRETCH), + "baseline" => Ok(ALIGN_BASELINE), + _ => Err(()) + } +} + // normal | fn parse_normal_or_baseline(input: &mut Parser) -> Result { let ident = input.expect_ident()?; @@ -350,3 +442,26 @@ fn parse_self_position(input: &mut Parser) -> Result { _ => Err(()) } } + +// [ legacy && [ left | right | center ] ] +fn parse_legacy(input: &mut Parser) -> Result { + let a = input.expect_ident()?; + let b = input.expect_ident()?; + if a.eq_ignore_ascii_case("legacy") { + match_ignore_ascii_case! { b, + "left" => Ok(ALIGN_LEGACY | ALIGN_LEFT), + "right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT), + "center" => Ok(ALIGN_LEGACY | ALIGN_CENTER), + _ => Err(()) + } + } else if b.eq_ignore_ascii_case("legacy") { + match_ignore_ascii_case! { a, + "left" => Ok(ALIGN_LEGACY | ALIGN_LEFT), + "right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT), + "center" => Ok(ALIGN_LEGACY | ALIGN_CENTER), + _ => Err(()) + } + } else { + Err(()) + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index e79d68b7777..f9634f3e6ad 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -21,7 +21,7 @@ use super::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use super::computed::Shadow as ComputedShadow; #[cfg(feature = "gecko")] -pub use self::align::{AlignJustifyContent, AlignJustifySelf}; +pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems}; pub use self::grid::GridLine; pub use self::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient}; pub use self::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};