From 0aee33081fe4e8e10b3b53f0d114b9bb1c71a7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 24 Jan 2018 18:13:53 +0100 Subject: [PATCH 1/6] style: Serialize before other align bits. Otherwise the serialisation wouldn't roundtrip with the new syntax, which fixes the position of . Also make Servo and Gecko agree on whether to serialize "unsafe". Bug: 1430817 MozReview-Commit-ID: L3GSMk5pZ3F --- components/style/values/specified/align.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 584a24b61fb..460037925bd 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -75,7 +75,14 @@ impl ToCss for AlignFlags { where W: Write, { - let s = match *self & !AlignFlags::FLAG_BITS { + match *self & AlignFlags::FLAG_BITS { + AlignFlags::LEGACY => dest.write_str("legacy ")?, + AlignFlags::SAFE => dest.write_str("safe ")?, + // Don't serialize "unsafe", since it's the default. + _ => {} + } + + dest.write_str(match *self & !AlignFlags::FLAG_BITS { AlignFlags::AUTO => "auto", AlignFlags::NORMAL => "normal", AlignFlags::START => "start", @@ -94,16 +101,7 @@ impl ToCss for AlignFlags { AlignFlags::SPACE_AROUND => "space-around", AlignFlags::SPACE_EVENLY => "space-evenly", _ => unreachable!() - }; - dest.write_str(s)?; - - match *self & AlignFlags::FLAG_BITS { - AlignFlags::LEGACY => { dest.write_str(" legacy")?; } - AlignFlags::SAFE => { dest.write_str(" safe")?; } - AlignFlags::UNSAFE => { dest.write_str(" unsafe")?; } - _ => {} - } - Ok(()) + }) } } From 7497720081698df7c6513eeac8d127a5eaa8c409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 24 Jan 2018 13:02:42 +0100 Subject: [PATCH 2/6] style: Make content distribution parsing know the axis it's parsed for. MozReview-Commit-ID: LMPXVtKU1mq --- .../properties/longhand/position.mako.rs | 8 +- .../properties/shorthand/position.mako.rs | 35 +++-- components/style/values/computed/align.rs | 2 +- components/style/values/computed/mod.rs | 2 +- components/style/values/specified/align.rs | 128 +++++++++++++----- components/style/values/specified/mod.rs | 2 +- 6 files changed, 125 insertions(+), 52 deletions(-) diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 013b93b2640..b2d87302ad5 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -69,8 +69,8 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse", animation_value_type="discrete")} % else: ${helpers.predefined_type(name="justify-content", - type="ContentDistribution", - initial_value="specified::ContentDistribution::normal()", + type="JustifyContent", + initial_value="specified::JustifyContent(specified::ContentDistribution::normal())", spec="https://drafts.csswg.org/css-align/#propdef-justify-content", extra_prefixes="webkit", animation_value_type="discrete")} @@ -90,8 +90,8 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse", animation_value_type="discrete")} % else: ${helpers.predefined_type(name="align-content", - type="ContentDistribution", - initial_value="specified::ContentDistribution::normal()", + type="AlignContent", + initial_value="specified::AlignContent(specified::ContentDistribution::normal())", spec="https://drafts.csswg.org/css-align/#propdef-align-content", extra_prefixes="webkit", animation_value_type="discrete")} diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 8775eed5c2c..06549a71891 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -615,33 +615,44 @@ <%helpers:shorthand name="place-content" sub_properties="align-content justify-content" spec="https://drafts.csswg.org/css-align/#propdef-place-content" products="gecko"> - use values::specified::align::{ContentDistribution, FallbackAllowed}; + use values::specified::align::{AlignContent, JustifyContent, ContentDistribution, FallbackAllowed, AxisDirection}; pub fn parse_value<'i, 't>( _: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - let align = ContentDistribution::parse_with_fallback(input, FallbackAllowed::No)?; - if align.has_extra_flags() { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } - let justify = - input.try(|input| ContentDistribution::parse_with_fallback(input, FallbackAllowed::No)) - .unwrap_or(align); - if justify.has_extra_flags() { + let align_content = + ContentDistribution::parse( + input, + FallbackAllowed::No, + AxisDirection::Inline, + )?; + + let justify_content = input.try(|input| { + ContentDistribution::parse( + input, + FallbackAllowed::No, + AxisDirection::Block, + ) + }).unwrap_or(align_content); + + // NOTE(emilio): align-content parsing is more restrictive than + // justify-content parsing, so no need to do any extra check here for + // that. + if align_content.has_extra_flags() || justify_content.has_extra_flags() { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } Ok(expanded! { - align_content: align, - justify_content: justify, + align_content: AlignContent(align_content), + justify_content: JustifyContent(justify_content), }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { self.align_content.to_css(dest)?; - if self.align_content != self.justify_content { + if self.align_content.0 != self.justify_content.0 { dest.write_str(" ")?; self.justify_content.to_css(dest)?; } diff --git a/components/style/values/computed/align.rs b/components/style/values/computed/align.rs index c7bf6a30c6b..836ef93f857 100644 --- a/components/style/values/computed/align.rs +++ b/components/style/values/computed/align.rs @@ -11,7 +11,7 @@ use style_traits::{CssWriter, ToCss}; use values::computed::{Context, ToComputedValue}; use values::specified; -pub use super::specified::{AlignItems, ContentDistribution, SelfAlignment}; +pub use super::specified::{AlignContent, JustifyContent, AlignItems, SelfAlignment}; /// The computed value for the `justify-items` property. /// diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 7600d23a9d1..f2fef4f26a5 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -32,7 +32,7 @@ use super::specified; pub use app_units::Au; pub use properties::animated_properties::TransitionProperty; #[cfg(feature = "gecko")] -pub use self::align::{AlignItems, ContentDistribution, SelfAlignment, JustifyItems}; +pub use self::align::{AlignItems, AlignContent, JustifyContent, SelfAlignment, JustifyItems}; pub use self::angle::Angle; pub use self::background::{BackgroundSize, BackgroundRepeat}; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 460037925bd..e0faf23f864 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -110,14 +110,14 @@ const ALIGN_ALL_BITS: u16 = structs::NS_STYLE_ALIGN_ALL_BITS as u16; /// Number of bits to shift a fallback alignment. const ALIGN_ALL_SHIFT: u32 = structs::NS_STYLE_ALIGN_ALL_SHIFT; -/// Value of the `align-content` or `justify-content` property. -/// -/// -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -pub struct ContentDistribution { - primary: AlignFlags, - fallback: AlignFlags, +/// An axis direction, either inline (for the `justify` properties) or block, +/// (for the `align` properties). +#[derive(Clone, Copy, PartialEq)] +pub enum AxisDirection { + /// Block direction. + Block, + /// Inline direction. + Inline, } /// Whether fallback is allowed in align-content / justify-content parsing. @@ -134,6 +134,16 @@ pub enum FallbackAllowed { No, } +/// Shared value for the `align-content` and `justify-content` properties. +/// +/// +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +pub struct ContentDistribution { + primary: AlignFlags, + fallback: AlignFlags, +} + impl ContentDistribution { /// The initial value 'normal' #[inline] @@ -155,6 +165,19 @@ impl ContentDistribution { Self { primary, fallback } } + fn from_bits(bits: u16) -> Self { + let primary = + AlignFlags::from_bits_truncate((bits & ALIGN_ALL_BITS) as u8); + let fallback = + AlignFlags::from_bits_truncate((bits >> ALIGN_ALL_SHIFT) as u8); + Self::with_fallback(primary, fallback) + } + + fn as_bits(&self) -> u16 { + self.primary.bits() as u16 | + ((self.fallback.bits() as u16) << ALIGN_ALL_SHIFT) + } + /// The primary alignment #[inline] pub fn primary(self) -> AlignFlags { @@ -176,9 +199,10 @@ impl ContentDistribution { /// Parse a value for align-content / justify-content, optionally allowing /// fallback. - pub fn parse_with_fallback<'i, 't>( + pub fn parse<'i, 't>( input: &mut Parser<'i, 't>, fallback_allowed: FallbackAllowed, + _axis: AxisDirection, ) -> Result> { // normal | if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) { @@ -224,12 +248,69 @@ impl ToCss for ContentDistribution { } } +/// Value for the `align-content` property. +/// +/// +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub struct AlignContent(pub ContentDistribution); -impl Parse for ContentDistribution { - // normal | | - // [ || [ ? && ] ] - fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - Self::parse_with_fallback(input, FallbackAllowed::Yes) +impl Parse for AlignContent { + fn parse<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Ok(AlignContent(ContentDistribution::parse( + input, + FallbackAllowed::Yes, + AxisDirection::Block, + )?)) + } +} + +#[cfg(feature = "gecko")] +impl From for AlignContent { + fn from(bits: u16) -> Self { + AlignContent(ContentDistribution::from_bits(bits)) + } +} + +#[cfg(feature = "gecko")] +impl From for u16 { + fn from(v: AlignContent) -> u16 { + v.0.as_bits() + } +} + +/// Value for the `justify-content` property. +/// +/// +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub struct JustifyContent(pub ContentDistribution); + +impl Parse for JustifyContent { + fn parse<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Ok(JustifyContent(ContentDistribution::parse( + input, + FallbackAllowed::Yes, + AxisDirection::Inline, + )?)) + } +} + +#[cfg(feature = "gecko")] +impl From for JustifyContent { + fn from(bits: u16) -> Self { + JustifyContent(ContentDistribution::from_bits(bits)) + } +} + +#[cfg(feature = "gecko")] +impl From for u16 { + fn from(v: JustifyContent) -> u16 { + v.0.as_bits() } } @@ -349,25 +430,6 @@ impl Parse for JustifyItems { } } -#[cfg(feature = "gecko")] -impl From for ContentDistribution { - fn from(bits: u16) -> ContentDistribution { - let primary = - AlignFlags::from_bits_truncate((bits & ALIGN_ALL_BITS) as u8); - let fallback = - AlignFlags::from_bits_truncate((bits >> ALIGN_ALL_SHIFT) as u8); - ContentDistribution::with_fallback(primary, fallback) - } -} - -#[cfg(feature = "gecko")] -impl From for u16 { - fn from(v: ContentDistribution) -> u16 { - v.primary().bits() as u16 | - ((v.fallback().bits() as u16) << ALIGN_ALL_SHIFT) - } -} - // auto | normal | stretch | fn parse_auto_normal_stretch_baseline<'i, 't>( input: &mut Parser<'i, 't>, diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 2a9e05f7e75..1eb206de418 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -26,7 +26,7 @@ use values::specified::calc::CalcNode; pub use properties::animated_properties::TransitionProperty; pub use self::angle::Angle; #[cfg(feature = "gecko")] -pub use self::align::{AlignItems, ContentDistribution, SelfAlignment, JustifyItems}; +pub use self::align::{AlignContent, JustifyContent, AlignItems, ContentDistribution, SelfAlignment, JustifyItems}; pub use self::background::{BackgroundRepeat, BackgroundSize}; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing}; From fd47a93b9c3330b6e5f1385bc2342a277f58041d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 24 Jan 2018 13:23:19 +0100 Subject: [PATCH 3/6] style: Restrict and depending on the axis in content distribution properties. This fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1430817, and updates us to the current version of the css-align spec. MozReview-Commit-ID: LtBcdqYJeK --- .../properties/shorthand/position.mako.rs | 16 +++- components/style/values/specified/align.rs | 74 +++++++++++-------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 06549a71891..bb6af5d29fe 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -634,11 +634,19 @@ FallbackAllowed::No, AxisDirection::Block, ) - }).unwrap_or(align_content); + }); + + let justify_content = match justify_content { + Ok(v) => v, + Err(err) => { + if !align_content.is_valid_on_both_axes() { + return Err(err); + } + + align_content + } + }; - // NOTE(emilio): align-content parsing is more restrictive than - // justify-content parsing, so no need to do any extra check here for - // that. if align_content.has_extra_flags() || justify_content.has_extra_flags() { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index e0faf23f864..03957399b7e 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -178,6 +178,23 @@ impl ContentDistribution { ((self.fallback.bits() as u16) << ALIGN_ALL_SHIFT) } + /// Returns whether this value is valid for both axis directions. + pub fn is_valid_on_both_axes(&self) -> bool { + if self.primary.intersects(AlignFlags::BASELINE | AlignFlags::LAST_BASELINE) || + self.fallback.intersects(AlignFlags::BASELINE | AlignFlags::LAST_BASELINE) { + // is only allowed on the block axis. + return false; + } + + if self.primary.intersects(AlignFlags::LEFT | AlignFlags::RIGHT) || + self.fallback.intersects(AlignFlags::LEFT | AlignFlags::RIGHT) { + // left | right are only allowed on the inline axis. + return false; + } + + true + } + /// The primary alignment #[inline] pub fn primary(self) -> AlignFlags { @@ -202,17 +219,24 @@ impl ContentDistribution { pub fn parse<'i, 't>( input: &mut Parser<'i, 't>, fallback_allowed: FallbackAllowed, - _axis: AxisDirection, + axis: AxisDirection, ) -> Result> { - // normal | - if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) { - return Ok(ContentDistribution::new(value)) + // Try to parse normal first + if input.try(|i| i.expect_ident_matching("normal")).is_ok() { + return Ok(ContentDistribution::normal()); + } + + // Parse , but only on the block axis. + if axis == AxisDirection::Block { + if let Ok(value) = input.try(parse_baseline) { + return Ok(ContentDistribution::new(value)); + } } // followed by optional <*-position> if let Ok(value) = input.try(|input| parse_content_distribution(input)) { if fallback_allowed == FallbackAllowed::Yes { - if let Ok(fallback) = input.try(|input| parse_overflow_content_position(input)) { + if let Ok(fallback) = input.try(|input| parse_overflow_content_position(input, axis)) { return Ok(ContentDistribution::with_fallback(value, fallback)) } } @@ -220,7 +244,7 @@ impl ContentDistribution { } // <*-position> followed by optional - let fallback = parse_overflow_content_position(input)?; + let fallback = parse_overflow_content_position(input, axis)?; if fallback_allowed == FallbackAllowed::Yes { if let Ok(value) = input.try(|input| parse_content_distribution(input)) { return Ok(ContentDistribution::with_fallback(value, fallback)) @@ -335,7 +359,6 @@ impl SelfAlignment { } } - impl Parse for SelfAlignment { // auto | normal | stretch | | // [ ? && ] @@ -457,19 +480,8 @@ fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result -fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - if let Ok(baseline) = input.try(parse_baseline) { - return Ok(baseline); - } - - input.expect_ident_matching("normal")?; - Ok(AlignFlags::NORMAL) -} - // fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - // FIXME: remove clone() when lifetimes are non-lexical try_match_ident_ignore_ascii_case! { input, "baseline" => Ok(AlignFlags::BASELINE), "first" => { @@ -494,33 +506,37 @@ fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result? && ] -fn parse_overflow_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { +fn parse_overflow_content_position<'i, 't>( + input: &mut Parser<'i, 't>, + axis: AxisDirection, +) -> Result> { // followed by optional - if let Ok(mut content) = input.try(parse_content_position) { + if let Ok(mut content) = input.try(|input| parse_content_position(input, axis)) { if let Ok(overflow) = input.try(parse_overflow_position) { content |= overflow; } return Ok(content) } + // followed by required - if let Ok(overflow) = parse_overflow_position(input) { - if let Ok(content) = parse_content_position(input) { - return Ok(overflow | content) - } - } - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + let overflow = parse_overflow_position(input)?; + let content = parse_content_position(input, axis)?; + Ok(overflow | content) } // -fn parse_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { +fn parse_content_position<'i, 't>( + input: &mut Parser<'i, 't>, + axis: AxisDirection, +) -> Result> { try_match_ident_ignore_ascii_case! { input, "start" => Ok(AlignFlags::START), "end" => Ok(AlignFlags::END), "flex-start" => Ok(AlignFlags::FLEX_START), "flex-end" => Ok(AlignFlags::FLEX_END), "center" => Ok(AlignFlags::CENTER), - "left" => Ok(AlignFlags::LEFT), - "right" => Ok(AlignFlags::RIGHT), + "left" if axis == AxisDirection::Inline => Ok(AlignFlags::LEFT), + "right" if axis == AxisDirection::Inline => Ok(AlignFlags::RIGHT), } } From 4c773a1424c489e858e916c254cb5edc9266a817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 24 Jan 2018 17:02:08 +0100 Subject: [PATCH 4/6] style: Fix the position of the in content distribution shorthands, and remove fallback. MozReview-Commit-ID: 4rPICzZ5gMn --- .../properties/shorthand/position.mako.rs | 14 +-- components/style/values/specified/align.rs | 119 +++++------------- 2 files changed, 34 insertions(+), 99 deletions(-) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index bb6af5d29fe..1ea97f7dd89 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -615,25 +615,17 @@ <%helpers:shorthand name="place-content" sub_properties="align-content justify-content" spec="https://drafts.csswg.org/css-align/#propdef-place-content" products="gecko"> - use values::specified::align::{AlignContent, JustifyContent, ContentDistribution, FallbackAllowed, AxisDirection}; + use values::specified::align::{AlignContent, JustifyContent, ContentDistribution, AxisDirection}; pub fn parse_value<'i, 't>( _: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { let align_content = - ContentDistribution::parse( - input, - FallbackAllowed::No, - AxisDirection::Inline, - )?; + ContentDistribution::parse(input, AxisDirection::Block)?; let justify_content = input.try(|input| { - ContentDistribution::parse( - input, - FallbackAllowed::No, - AxisDirection::Block, - ) + ContentDistribution::parse(input, AxisDirection::Inline) }); let justify_content = match justify_content { diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 03957399b7e..0f261fc8a81 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -105,11 +105,6 @@ impl ToCss for AlignFlags { } } -/// Mask for a single AlignFlags value. -const ALIGN_ALL_BITS: u16 = structs::NS_STYLE_ALIGN_ALL_BITS as u16; -/// Number of bits to shift a fallback alignment. -const ALIGN_ALL_SHIFT: u32 = structs::NS_STYLE_ALIGN_ALL_SHIFT; - /// An axis direction, either inline (for the `justify` properties) or block, /// (for the `align` properties). #[derive(Clone, Copy, PartialEq)] @@ -120,28 +115,15 @@ pub enum AxisDirection { Inline, } -/// Whether fallback is allowed in align-content / justify-content parsing. -/// -/// This is used for the place-content shorthand, until the resolutions from [1] -/// are specified. -/// -/// [1]: https://github.com/w3c/csswg-drafts/issues/1002 -#[derive(Clone, Copy, PartialEq)] -pub enum FallbackAllowed { - /// Allow fallback alignment. - Yes, - /// Don't allow fallback alignment. - No, -} - /// Shared value for the `align-content` and `justify-content` properties. /// /// -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] pub struct ContentDistribution { primary: AlignFlags, - fallback: AlignFlags, + // FIXME(https://github.com/w3c/csswg-drafts/issues/1002): This will need to + // accept fallback alignment, eventually. } impl ContentDistribution { @@ -151,43 +133,30 @@ impl ContentDistribution { Self::new(AlignFlags::NORMAL) } - /// Construct a value with no fallback. + /// The initial value 'normal' #[inline] - pub fn new(flags: AlignFlags) -> Self { - Self::with_fallback(flags, AlignFlags::empty()) - } - - /// Construct a value including a fallback alignment. - /// - /// - #[inline] - pub fn with_fallback(primary: AlignFlags, fallback: AlignFlags) -> Self { - Self { primary, fallback } + pub fn new(primary: AlignFlags) -> Self { + Self { primary } } fn from_bits(bits: u16) -> Self { - let primary = - AlignFlags::from_bits_truncate((bits & ALIGN_ALL_BITS) as u8); - let fallback = - AlignFlags::from_bits_truncate((bits >> ALIGN_ALL_SHIFT) as u8); - Self::with_fallback(primary, fallback) + Self { + primary: AlignFlags::from_bits_truncate(bits as u8) + } } fn as_bits(&self) -> u16 { - self.primary.bits() as u16 | - ((self.fallback.bits() as u16) << ALIGN_ALL_SHIFT) + self.primary.bits() as u16 } /// Returns whether this value is valid for both axis directions. pub fn is_valid_on_both_axes(&self) -> bool { - if self.primary.intersects(AlignFlags::BASELINE | AlignFlags::LAST_BASELINE) || - self.fallback.intersects(AlignFlags::BASELINE | AlignFlags::LAST_BASELINE) { + if self.primary.intersects(AlignFlags::BASELINE | AlignFlags::LAST_BASELINE) { // is only allowed on the block axis. return false; } - if self.primary.intersects(AlignFlags::LEFT | AlignFlags::RIGHT) || - self.fallback.intersects(AlignFlags::LEFT | AlignFlags::RIGHT) { + if self.primary.intersects(AlignFlags::LEFT | AlignFlags::RIGHT) { // left | right are only allowed on the inline axis. return false; } @@ -201,24 +170,15 @@ impl ContentDistribution { self.primary } - /// The fallback alignment - #[inline] - pub fn fallback(self) -> AlignFlags { - self.fallback - } - /// Whether this value has extra flags. #[inline] pub fn has_extra_flags(self) -> bool { - self.primary().intersects(AlignFlags::FLAG_BITS) || - self.fallback().intersects(AlignFlags::FLAG_BITS) + self.primary().intersects(AlignFlags::FLAG_BITS) } - /// Parse a value for align-content / justify-content, optionally allowing - /// fallback. + /// Parse a value for align-content / justify-content. pub fn parse<'i, 't>( input: &mut Parser<'i, 't>, - fallback_allowed: FallbackAllowed, axis: AxisDirection, ) -> Result> { // Try to parse normal first @@ -233,42 +193,27 @@ impl ContentDistribution { } } - // followed by optional <*-position> - if let Ok(value) = input.try(|input| parse_content_distribution(input)) { - if fallback_allowed == FallbackAllowed::Yes { - if let Ok(fallback) = input.try(|input| parse_overflow_content_position(input, axis)) { - return Ok(ContentDistribution::with_fallback(value, fallback)) - } - } - return Ok(ContentDistribution::new(value)) + // + if let Ok(value) = input.try(parse_content_distribution) { + return Ok(ContentDistribution::new(value)); } - // <*-position> followed by optional - let fallback = parse_overflow_content_position(input, axis)?; - if fallback_allowed == FallbackAllowed::Yes { - if let Ok(value) = input.try(|input| parse_content_distribution(input)) { - return Ok(ContentDistribution::with_fallback(value, fallback)) - } - } + // ? + let overflow_position = + input.try(parse_overflow_position) + .unwrap_or(AlignFlags::empty()); - Ok(ContentDistribution::new(fallback)) - } -} + let content_position = try_match_ident_ignore_ascii_case! { input, + "start" => AlignFlags::START, + "end" => AlignFlags::END, + "flex-start" => AlignFlags::FLEX_START, + "flex-end" => AlignFlags::FLEX_END, + "center" => AlignFlags::CENTER, + "left" if axis == AxisDirection::Inline => AlignFlags::LEFT, + "right" if axis == AxisDirection::Inline => AlignFlags::RIGHT, + }; -impl ToCss for ContentDistribution { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - self.primary().to_css(dest)?; - match self.fallback() { - AlignFlags::AUTO => {} - fallback => { - dest.write_str(" ")?; - fallback.to_css(dest)?; - } - } - Ok(()) + Ok(ContentDistribution::new(content_position | overflow_position)) } } @@ -285,7 +230,6 @@ impl Parse for AlignContent { ) -> Result> { Ok(AlignContent(ContentDistribution::parse( input, - FallbackAllowed::Yes, AxisDirection::Block, )?)) } @@ -318,7 +262,6 @@ impl Parse for JustifyContent { ) -> Result> { Ok(JustifyContent(ContentDistribution::parse( input, - FallbackAllowed::Yes, AxisDirection::Inline, )?)) } From 8d7a3f4f3d4a93830d7c5b3010a35e5fc5455375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 24 Jan 2018 17:02:57 +0100 Subject: [PATCH 5/6] style: Update align-self / justify-self to the spec too. MozReview-Commit-ID: 8JKF5ucCbYm --- .../properties/longhand/position.mako.rs | 8 +- .../properties/shorthand/position.mako.rs | 42 +-- components/style/values/computed/align.rs | 1 + components/style/values/computed/mod.rs | 2 + components/style/values/specified/align.rs | 270 ++++++++++-------- components/style/values/specified/mod.rs | 2 + 6 files changed, 192 insertions(+), 133 deletions(-) diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index b2d87302ad5..1dc697bd201 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -138,15 +138,15 @@ ${helpers.predefined_type("flex-shrink", "NonNegativeNumber", animation_value_type="discrete")} % else: ${helpers.predefined_type(name="align-self", - type="SelfAlignment", - initial_value="specified::SelfAlignment::auto()", + type="AlignSelf", + initial_value="specified::AlignSelf(specified::SelfAlignment::auto())", spec="https://drafts.csswg.org/css-align/#align-self-property", extra_prefixes="webkit", animation_value_type="discrete")} ${helpers.predefined_type(name="justify-self", - type="SelfAlignment", - initial_value="specified::SelfAlignment::auto()", + type="JustifySelf", + initial_value="specified::JustifySelf(specified::SelfAlignment::auto())", spec="https://drafts.csswg.org/css-align/#justify-self-property", animation_value_type="discrete")} diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 1ea97f7dd89..340fdaddbce 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -664,35 +664,43 @@ <%helpers:shorthand name="place-self" sub_properties="align-self justify-self" spec="https://drafts.csswg.org/css-align/#place-self-property" products="gecko"> - use values::specified::align::SelfAlignment; - use parser::Parse; + use values::specified::align::{AlignSelf, JustifySelf, SelfAlignment, AxisDirection}; - pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - let align = SelfAlignment::parse(context, input)?; - if align.has_extra_flags() { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } - let justify = input.try(|input| SelfAlignment::parse(context, input)).unwrap_or(align.clone()); - if justify.has_extra_flags() { + pub fn parse_value<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let align = SelfAlignment::parse(input, AxisDirection::Block)?; + let justify = input.try(|input| SelfAlignment::parse(input, AxisDirection::Inline)); + + let justify = match justify { + Ok(v) => v, + Err(err) => { + if !align.is_valid_on_both_axes() { + return Err(err); + } + align + } + }; + + if justify.has_extra_flags() || align.has_extra_flags() { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } Ok(expanded! { - align_self: align, - justify_self: justify, + align_self: AlignSelf(align), + justify_self: JustifySelf(justify), }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { - if self.align_self == self.justify_self { - self.align_self.to_css(dest) - } else { - self.align_self.to_css(dest)?; + self.align_self.to_css(dest)?; + if self.align_self.0 != self.justify_self.0 { dest.write_str(" ")?; - self.justify_self.to_css(dest) + self.justify_self.to_css(dest)?; } + Ok(()) } } diff --git a/components/style/values/computed/align.rs b/components/style/values/computed/align.rs index 836ef93f857..02a93ee6f5d 100644 --- a/components/style/values/computed/align.rs +++ b/components/style/values/computed/align.rs @@ -12,6 +12,7 @@ use values::computed::{Context, ToComputedValue}; use values::specified; pub use super::specified::{AlignContent, JustifyContent, AlignItems, SelfAlignment}; +pub use super::specified::{AlignSelf, JustifySelf}; /// The computed value for the `justify-items` property. /// diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index f2fef4f26a5..4156e784c9e 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -33,6 +33,8 @@ pub use app_units::Au; pub use properties::animated_properties::TransitionProperty; #[cfg(feature = "gecko")] pub use self::align::{AlignItems, AlignContent, JustifyContent, SelfAlignment, JustifyItems}; +#[cfg(feature = "gecko")] +pub use self::align::{AlignSelf, JustifySelf}; pub use self::angle::Angle; pub use self::background::{BackgroundSize, BackgroundRepeat}; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 0f261fc8a81..8223928046e 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -18,8 +18,7 @@ bitflags! { /// Constants shared by multiple CSS Box Alignment properties /// /// These constants match Gecko's `NS_STYLE_ALIGN_*` constants. - #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] - #[derive(ToComputedValue)] + #[derive(MallocSizeOf, ToComputedValue)] pub struct AlignFlags: u8 { // Enumeration stored in the lower 5 bits: /// 'auto' @@ -151,12 +150,16 @@ impl ContentDistribution { /// Returns whether this value is valid for both axis directions. pub fn is_valid_on_both_axes(&self) -> bool { - if self.primary.intersects(AlignFlags::BASELINE | AlignFlags::LAST_BASELINE) { + if self.primary.contains(AlignFlags::BASELINE) || + self.primary.contains(AlignFlags::LAST_BASELINE) + { // is only allowed on the block axis. return false; } - if self.primary.intersects(AlignFlags::LEFT | AlignFlags::RIGHT) { + if self.primary.contains(AlignFlags::LEFT) || + self.primary.contains(AlignFlags::RIGHT) + { // left | right are only allowed on the inline axis. return false; } @@ -281,11 +284,8 @@ impl From for u16 { } } -/// Value of the `align-self` or `justify-self` property. -/// /// -#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Copy, Debug, Eq, PartialEq, ToComputedValue, ToCss)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] pub struct SelfAlignment(pub AlignFlags); impl SelfAlignment { @@ -295,31 +295,109 @@ impl SelfAlignment { SelfAlignment(AlignFlags::AUTO) } + /// Returns whether this value is valid for both axis directions. + pub fn is_valid_on_both_axes(&self) -> bool { + if self.0.contains(AlignFlags::BASELINE) || + self.0.contains(AlignFlags::LAST_BASELINE) + { + // is only allowed on the block axis. + return false; + } + + if self.0.contains(AlignFlags::LEFT) || + self.0.contains(AlignFlags::RIGHT) + { + // left | right are only allowed on the inline axis. + return false; + } + + true + } + /// Whether this value has extra flags. #[inline] pub fn has_extra_flags(self) -> bool { self.0.intersects(AlignFlags::FLAG_BITS) } -} -impl Parse for SelfAlignment { - // auto | normal | stretch | | - // [ ? && ] - fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - // auto | normal | stretch | - if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) { + /// Parse a self-alignment value on one of the axis. + pub fn parse<'i, 't>( + input: &mut Parser<'i, 't>, + axis: AxisDirection, + ) -> Result> { + // , only on the block axis. + if axis == AxisDirection::Block { + if let Ok(value) = input.try(parse_baseline) { + return Ok(SelfAlignment(value)); + } + } + + // auto | normal | stretch + if let Ok(value) = input.try(parse_auto_normal_stretch) { return Ok(SelfAlignment(value)) } - // [ ? && ] - Ok(SelfAlignment(parse_overflow_self_position(input)?)) + + // ? + let overflow_position = + input.try(parse_overflow_position) + .unwrap_or(AlignFlags::empty()); + let self_position = parse_self_position(input, axis)?; + Ok(SelfAlignment(overflow_position | self_position)) + } +} + +/// The specified value of the align-self property. +/// +/// +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub struct AlignSelf(pub SelfAlignment); + +impl Parse for AlignSelf { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + Ok(AlignSelf(SelfAlignment::parse(input, AxisDirection::Block)?)) + } +} + +impl From for AlignSelf { + fn from(bits: u8) -> Self { + AlignSelf(SelfAlignment(AlignFlags::from_bits_truncate(bits))) + } +} + +impl From for u8 { + fn from(align: AlignSelf) -> u8 { + (align.0).0.bits() + } +} + +/// The specified value of the justify-self property. +/// +/// +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub struct JustifySelf(pub SelfAlignment); + +impl Parse for JustifySelf { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + Ok(JustifySelf(SelfAlignment::parse(input, AxisDirection::Inline)?)) + } +} + +impl From for JustifySelf { + fn from(bits: u8) -> Self { + JustifySelf(SelfAlignment(AlignFlags::from_bits_truncate(bits))) + } +} + +impl From for u8 { + fn from(justify: JustifySelf) -> u8 { + (justify.0).0.bits() } } /// Value of the `align-items` property /// /// -#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Copy, Debug, Eq, PartialEq, ToComputedValue, ToCss)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] pub struct AlignItems(pub AlignFlags); impl AlignItems { @@ -339,22 +417,28 @@ impl AlignItems { impl Parse for AlignItems { // normal | stretch | | - // [ ? && ] + // ? fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - // normal | stretch | - if let Ok(value) = input.try(parse_normal_stretch_baseline) { + // + if let Ok(baseline) = input.try(parse_baseline) { + return Ok(AlignItems(baseline)); + } + + // normal | stretch + if let Ok(value) = input.try(parse_normal_stretch) { return Ok(AlignItems(value)) } - // [ ? && ] - Ok(AlignItems(parse_overflow_self_position(input)?)) + // ? + let overflow = input.try(parse_overflow_position).unwrap_or(AlignFlags::empty()); + let self_position = parse_self_position(input, AxisDirection::Block)?; + Ok(AlignItems(self_position | overflow)) } } /// Value of the `justify-items` property /// /// -#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)] pub struct JustifyItems(pub AlignFlags); impl JustifyItems { @@ -377,33 +461,49 @@ impl JustifyItems { } } - impl Parse for JustifyItems { - // auto | normal | stretch | | - // [ ? && ] - // [ legacy && [ left | right | center ] ] fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - // auto | normal | stretch | - if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) { + // + // + // It's weird that this accepts , but not the + // justify-self / justify-content properties... + if let Ok(baseline) = input.try(parse_baseline) { + return Ok(JustifyItems(baseline)); + } + + // auto | normal | stretch + // + // FIXME(emilio): auto is no longer a keyword in the current spec, and + // has been renamed to legacy, but that needs different changes because + // right now it's the initial value for both style systems, and has that + // weird behavior of "inheriting" into descendants. + // + // Fix this in both. + // + // See also: + // https://bugs.webkit.org/show_bug.cgi?id=172711 + // https://bugs.chromium.org/p/chromium/issues/detail?id=726148 + // + if let Ok(value) = input.try(parse_auto_normal_stretch) { return Ok(JustifyItems(value)) } - // [ legacy && [ left | right | center ] ] + + // [ legacy || [ left | right | center ] ] if let Ok(value) = input.try(parse_legacy) { return Ok(JustifyItems(value)) } - // [ ? && ] - Ok(JustifyItems(parse_overflow_self_position(input)?)) + + // ? + let overflow = input.try(parse_overflow_position).unwrap_or(AlignFlags::empty()); + let self_position = parse_self_position(input, AxisDirection::Inline)?; + Ok(JustifyItems(overflow | self_position)) } } -// auto | normal | stretch | -fn parse_auto_normal_stretch_baseline<'i, 't>( +// auto | normal | stretch +fn parse_auto_normal_stretch<'i, 't>( input: &mut Parser<'i, 't>, ) -> Result> { - if let Ok(baseline) = input.try(parse_baseline) { - return Ok(baseline); - } - try_match_ident_ignore_ascii_case! { input, "auto" => Ok(AlignFlags::AUTO), "normal" => Ok(AlignFlags::NORMAL), @@ -412,11 +512,7 @@ fn parse_auto_normal_stretch_baseline<'i, 't>( } // normal | stretch | -fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - if let Ok(baseline) = input.try(parse_baseline) { - return Ok(baseline); - } - +fn parse_normal_stretch<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { try_match_ident_ignore_ascii_case! { input, "normal" => Ok(AlignFlags::NORMAL), "stretch" => Ok(AlignFlags::STRETCH), @@ -448,41 +544,6 @@ fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result? && ] -fn parse_overflow_content_position<'i, 't>( - input: &mut Parser<'i, 't>, - axis: AxisDirection, -) -> Result> { - // followed by optional - if let Ok(mut content) = input.try(|input| parse_content_position(input, axis)) { - if let Ok(overflow) = input.try(parse_overflow_position) { - content |= overflow; - } - return Ok(content) - } - - // followed by required - let overflow = parse_overflow_position(input)?; - let content = parse_content_position(input, axis)?; - Ok(overflow | content) -} - -// -fn parse_content_position<'i, 't>( - input: &mut Parser<'i, 't>, - axis: AxisDirection, -) -> Result> { - try_match_ident_ignore_ascii_case! { input, - "start" => Ok(AlignFlags::START), - "end" => Ok(AlignFlags::END), - "flex-start" => Ok(AlignFlags::FLEX_START), - "flex-end" => Ok(AlignFlags::FLEX_END), - "center" => Ok(AlignFlags::CENTER), - "left" if axis == AxisDirection::Inline => Ok(AlignFlags::LEFT), - "right" if axis == AxisDirection::Inline => Ok(AlignFlags::RIGHT), - } -} - // fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { try_match_ident_ignore_ascii_case! { input, @@ -491,37 +552,22 @@ fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result? && ] -fn parse_overflow_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - // followed by optional - if let Ok(mut self_position) = input.try(parse_self_position) { - if let Ok(overflow) = input.try(parse_overflow_position) { - self_position |= overflow; - } - return Ok(self_position) - } - // followed by required - if let Ok(overflow) = parse_overflow_position(input) { - if let Ok(self_position) = parse_self_position(input) { - return Ok(overflow | self_position) - } - } - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) -} - -// -fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - try_match_ident_ignore_ascii_case! { input, - "start" => Ok(AlignFlags::START), - "end" => Ok(AlignFlags::END), - "flex-start" => Ok(AlignFlags::FLEX_START), - "flex-end" => Ok(AlignFlags::FLEX_END), - "center" => Ok(AlignFlags::CENTER), - "left" => Ok(AlignFlags::LEFT), - "right" => Ok(AlignFlags::RIGHT), - "self-start" => Ok(AlignFlags::SELF_START), - "self-end" => Ok(AlignFlags::SELF_END), - } +// | left | right in the inline axis. +fn parse_self_position<'i, 't>( + input: &mut Parser<'i, 't>, + axis: AxisDirection, +) -> Result> { + Ok(try_match_ident_ignore_ascii_case! { input, + "start" => AlignFlags::START, + "end" => AlignFlags::END, + "flex-start" => AlignFlags::FLEX_START, + "flex-end" => AlignFlags::FLEX_END, + "center" => AlignFlags::CENTER, + "self-start" => AlignFlags::SELF_START, + "self-end" => AlignFlags::SELF_END, + "left" if axis == AxisDirection::Inline => AlignFlags::LEFT, + "right" if axis == AxisDirection::Inline => AlignFlags::RIGHT, + }) } // [ legacy && [ left | right | center ] ] diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 1eb206de418..877580f799d 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -27,6 +27,8 @@ pub use properties::animated_properties::TransitionProperty; pub use self::angle::Angle; #[cfg(feature = "gecko")] pub use self::align::{AlignContent, JustifyContent, AlignItems, ContentDistribution, SelfAlignment, JustifyItems}; +#[cfg(feature = "gecko")] +pub use self::align::{AlignSelf, JustifySelf}; pub use self::background::{BackgroundRepeat, BackgroundSize}; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing}; From b7238c43cd6899cb1530f8ece8d6d3f3c17e154d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 29 Jan 2018 10:41:59 +0100 Subject: [PATCH 6/6] style: Properly compare the value of the alignment flags. What this did before happens to be ok for these constants, but it's not great, because it depends on their particular value. --- components/style/values/specified/align.rs | 46 +++++++++++----------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 8223928046e..9e8d49dfe00 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -69,6 +69,14 @@ bitflags! { } } +impl AlignFlags { + /// Returns the enumeration value stored in the lower 5 bits. + #[inline] + fn value(&self) -> Self { + *self & !AlignFlags::FLAG_BITS + } +} + impl ToCss for AlignFlags { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where @@ -81,7 +89,7 @@ impl ToCss for AlignFlags { _ => {} } - dest.write_str(match *self & !AlignFlags::FLAG_BITS { + dest.write_str(match self.value() { AlignFlags::AUTO => "auto", AlignFlags::NORMAL => "normal", AlignFlags::START => "start", @@ -150,21 +158,17 @@ impl ContentDistribution { /// Returns whether this value is valid for both axis directions. pub fn is_valid_on_both_axes(&self) -> bool { - if self.primary.contains(AlignFlags::BASELINE) || - self.primary.contains(AlignFlags::LAST_BASELINE) - { + match self.primary.value() { // is only allowed on the block axis. - return false; - } + AlignFlags::BASELINE | + AlignFlags::LAST_BASELINE => false, - if self.primary.contains(AlignFlags::LEFT) || - self.primary.contains(AlignFlags::RIGHT) - { // left | right are only allowed on the inline axis. - return false; - } + AlignFlags::LEFT | + AlignFlags::RIGHT => false, - true + _ => true, + } } /// The primary alignment @@ -297,21 +301,17 @@ impl SelfAlignment { /// Returns whether this value is valid for both axis directions. pub fn is_valid_on_both_axes(&self) -> bool { - if self.0.contains(AlignFlags::BASELINE) || - self.0.contains(AlignFlags::LAST_BASELINE) - { + match self.0.value() { // is only allowed on the block axis. - return false; - } + AlignFlags::BASELINE | + AlignFlags::LAST_BASELINE => false, - if self.0.contains(AlignFlags::LEFT) || - self.0.contains(AlignFlags::RIGHT) - { // left | right are only allowed on the inline axis. - return false; - } + AlignFlags::LEFT | + AlignFlags::RIGHT => false, - true + _ => true, + } } /// Whether this value has extra flags.