style: Make content distribution parsing know the axis it's parsed for.

MozReview-Commit-ID: LMPXVtKU1mq
This commit is contained in:
Emilio Cobos Álvarez 2018-01-24 13:02:42 +01:00
parent 0aee33081f
commit 7497720081
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
6 changed files with 125 additions and 52 deletions

View file

@ -69,8 +69,8 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
animation_value_type="discrete")} animation_value_type="discrete")}
% else: % else:
${helpers.predefined_type(name="justify-content", ${helpers.predefined_type(name="justify-content",
type="ContentDistribution", type="JustifyContent",
initial_value="specified::ContentDistribution::normal()", initial_value="specified::JustifyContent(specified::ContentDistribution::normal())",
spec="https://drafts.csswg.org/css-align/#propdef-justify-content", spec="https://drafts.csswg.org/css-align/#propdef-justify-content",
extra_prefixes="webkit", extra_prefixes="webkit",
animation_value_type="discrete")} animation_value_type="discrete")}
@ -90,8 +90,8 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
animation_value_type="discrete")} animation_value_type="discrete")}
% else: % else:
${helpers.predefined_type(name="align-content", ${helpers.predefined_type(name="align-content",
type="ContentDistribution", type="AlignContent",
initial_value="specified::ContentDistribution::normal()", initial_value="specified::AlignContent(specified::ContentDistribution::normal())",
spec="https://drafts.csswg.org/css-align/#propdef-align-content", spec="https://drafts.csswg.org/css-align/#propdef-align-content",
extra_prefixes="webkit", extra_prefixes="webkit",
animation_value_type="discrete")} animation_value_type="discrete")}

View file

@ -615,33 +615,44 @@
<%helpers:shorthand name="place-content" sub_properties="align-content justify-content" <%helpers:shorthand name="place-content" sub_properties="align-content justify-content"
spec="https://drafts.csswg.org/css-align/#propdef-place-content" spec="https://drafts.csswg.org/css-align/#propdef-place-content"
products="gecko"> products="gecko">
use values::specified::align::{ContentDistribution, FallbackAllowed}; use values::specified::align::{AlignContent, JustifyContent, ContentDistribution, FallbackAllowed, AxisDirection};
pub fn parse_value<'i, 't>( pub fn parse_value<'i, 't>(
_: &ParserContext, _: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<Longhands, ParseError<'i>> { ) -> Result<Longhands, ParseError<'i>> {
let align = ContentDistribution::parse_with_fallback(input, FallbackAllowed::No)?; let align_content =
if align.has_extra_flags() { ContentDistribution::parse(
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); input,
} FallbackAllowed::No,
let justify = AxisDirection::Inline,
input.try(|input| ContentDistribution::parse_with_fallback(input, FallbackAllowed::No)) )?;
.unwrap_or(align);
if justify.has_extra_flags() { 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)); return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
} }
Ok(expanded! { Ok(expanded! {
align_content: align, align_content: AlignContent(align_content),
justify_content: justify, justify_content: JustifyContent(justify_content),
}) })
} }
impl<'a> ToCss for LonghandsToSerialize<'a> { impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
self.align_content.to_css(dest)?; 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(" ")?; dest.write_str(" ")?;
self.justify_content.to_css(dest)?; self.justify_content.to_css(dest)?;
} }

View file

@ -11,7 +11,7 @@ use style_traits::{CssWriter, ToCss};
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
use values::specified; 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. /// The computed value for the `justify-items` property.
/// ///

View file

@ -32,7 +32,7 @@ use super::specified;
pub use app_units::Au; pub use app_units::Au;
pub use properties::animated_properties::TransitionProperty; pub use properties::animated_properties::TransitionProperty;
#[cfg(feature = "gecko")] #[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::angle::Angle;
pub use self::background::{BackgroundSize, BackgroundRepeat}; pub use self::background::{BackgroundSize, BackgroundRepeat};
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};

View file

@ -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. /// Number of bits to shift a fallback alignment.
const ALIGN_ALL_SHIFT: u32 = structs::NS_STYLE_ALIGN_ALL_SHIFT; const ALIGN_ALL_SHIFT: u32 = structs::NS_STYLE_ALIGN_ALL_SHIFT;
/// Value of the `align-content` or `justify-content` property. /// An axis direction, either inline (for the `justify` properties) or block,
/// /// (for the `align` properties).
/// <https://drafts.csswg.org/css-align/#content-distribution> #[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] pub enum AxisDirection {
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] /// Block direction.
pub struct ContentDistribution { Block,
primary: AlignFlags, /// Inline direction.
fallback: AlignFlags, Inline,
} }
/// Whether fallback is allowed in align-content / justify-content parsing. /// Whether fallback is allowed in align-content / justify-content parsing.
@ -134,6 +134,16 @@ pub enum FallbackAllowed {
No, No,
} }
/// Shared value for the `align-content` and `justify-content` properties.
///
/// <https://drafts.csswg.org/css-align/#content-distribution>
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct ContentDistribution {
primary: AlignFlags,
fallback: AlignFlags,
}
impl ContentDistribution { impl ContentDistribution {
/// The initial value 'normal' /// The initial value 'normal'
#[inline] #[inline]
@ -155,6 +165,19 @@ impl ContentDistribution {
Self { primary, fallback } 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 /// The primary alignment
#[inline] #[inline]
pub fn primary(self) -> AlignFlags { pub fn primary(self) -> AlignFlags {
@ -176,9 +199,10 @@ impl ContentDistribution {
/// Parse a value for align-content / justify-content, optionally allowing /// Parse a value for align-content / justify-content, optionally allowing
/// fallback. /// fallback.
pub fn parse_with_fallback<'i, 't>( pub fn parse<'i, 't>(
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
fallback_allowed: FallbackAllowed, fallback_allowed: FallbackAllowed,
_axis: AxisDirection,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
// normal | <baseline-position> // normal | <baseline-position>
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) { 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.
///
/// <https://drafts.csswg.org/css-align/#propdef-align-content>
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
pub struct AlignContent(pub ContentDistribution);
impl Parse for ContentDistribution { impl Parse for AlignContent {
// normal | <baseline-position> | fn parse<'i, 't>(
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ] _: &ParserContext,
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { input: &mut Parser<'i, 't>,
Self::parse_with_fallback(input, FallbackAllowed::Yes) ) -> Result<Self, ParseError<'i>> {
Ok(AlignContent(ContentDistribution::parse(
input,
FallbackAllowed::Yes,
AxisDirection::Block,
)?))
}
}
#[cfg(feature = "gecko")]
impl From<u16> for AlignContent {
fn from(bits: u16) -> Self {
AlignContent(ContentDistribution::from_bits(bits))
}
}
#[cfg(feature = "gecko")]
impl From<AlignContent> for u16 {
fn from(v: AlignContent) -> u16 {
v.0.as_bits()
}
}
/// Value for the `justify-content` property.
///
/// <https://drafts.csswg.org/css-align/#propdef-align-content>
#[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<Self, ParseError<'i>> {
Ok(JustifyContent(ContentDistribution::parse(
input,
FallbackAllowed::Yes,
AxisDirection::Inline,
)?))
}
}
#[cfg(feature = "gecko")]
impl From<u16> for JustifyContent {
fn from(bits: u16) -> Self {
JustifyContent(ContentDistribution::from_bits(bits))
}
}
#[cfg(feature = "gecko")]
impl From<JustifyContent> for u16 {
fn from(v: JustifyContent) -> u16 {
v.0.as_bits()
} }
} }
@ -349,25 +430,6 @@ impl Parse for JustifyItems {
} }
} }
#[cfg(feature = "gecko")]
impl From<u16> 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<ContentDistribution> for u16 {
fn from(v: ContentDistribution) -> u16 {
v.primary().bits() as u16 |
((v.fallback().bits() as u16) << ALIGN_ALL_SHIFT)
}
}
// auto | normal | stretch | <baseline-position> // auto | normal | stretch | <baseline-position>
fn parse_auto_normal_stretch_baseline<'i, 't>( fn parse_auto_normal_stretch_baseline<'i, 't>(
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,

View file

@ -26,7 +26,7 @@ use values::specified::calc::CalcNode;
pub use properties::animated_properties::TransitionProperty; pub use properties::animated_properties::TransitionProperty;
pub use self::angle::Angle; pub use self::angle::Angle;
#[cfg(feature = "gecko")] #[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::background::{BackgroundRepeat, BackgroundSize};
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};