commit 0b924e8dc732131e6068b76d0beba7e3f676b127 parent b0c5a2223b93f7d631914423d166290ddb77a3ff Author: Emilio Cobos Álvarez <emilio@crisal.io> Date: Thu, 16 Oct 2025 16:42:33 +0000 Bug 1994696 - Make alignment properties on different axes share types to the extent possible. r=layout-reviewers,firefox-style-system-reviewers,dshin For bug 1994673 we need to cascade AlignSelf as JustifySelf and vice versa. This is a lot easier if the types are shared. For justify-items we can't right now because of the `legacy` shenanigans, which really sucks. I'll try to find a solution for that. Maybe we should just clobber the legacy value. Differential Revision: https://phabricator.services.mozilla.com/D268866 Diffstat:
16 files changed, 172 insertions(+), 314 deletions(-)
diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp @@ -1399,7 +1399,7 @@ nsFlexContainerFrame::UsedAlignSelfAndFlagsForItem( // Note: we don't need to call nsLayoutUtils::GetStyleFrame(aFlexItem) because // the table wrapper frame inherits 'align-self' property from the table // frame. - StyleAlignSelf usedAlignSelf = + StyleSelfAlignment usedAlignSelf = aFlexItem->StylePosition()->UsedAlignSelf(Style()); if (MOZ_LIKELY(usedAlignSelf._0 == StyleAlignFlags::NORMAL)) { // For flex items, 'align-self:normal' behaves as 'align-self:stretch'. diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp @@ -7126,7 +7126,7 @@ LogicalSize nsIFrame::ComputeAbsolutePosAutoSize( const auto boxSizingAdjust = stylePos->mBoxSizing == StyleBoxSizing::Border ? aBorderPadding : LogicalSize(aWM); - auto shouldStretch = [](StyleSelfAlignment aAlignment, const nsIFrame* aFrame, + auto shouldStretch = [](StyleAlignFlags aAlignment, const nsIFrame* aFrame, bool aStartIsAuto, bool aEndIsAuto) { if (aStartIsAuto || aEndIsAuto) { // Note(dshin, bug 1930427): This is not part of the current spec [1]; @@ -7140,13 +7140,13 @@ LogicalSize nsIFrame::ComputeAbsolutePosAutoSize( return false; } // Don't care about flag bits for auto-sizing. - aAlignment &= ~StyleSelfAlignment::FLAG_BITS; + aAlignment &= ~StyleAlignFlags::FLAG_BITS; - if (aAlignment == StyleSelfAlignment::STRETCH) { + if (aAlignment == StyleAlignFlags::STRETCH) { return true; } - if (aAlignment == StyleSelfAlignment::NORMAL) { + if (aAlignment == StyleAlignFlags::NORMAL) { // Some replaced elements behave as semi-replaced elements - we want them // to stretch (See bug 1740580). return !aFrame->HasReplacedSizing() && !aFrame->IsTableWrapperFrame(); @@ -7161,15 +7161,15 @@ LogicalSize nsIFrame::ComputeAbsolutePosAutoSize( // Self alignment properties translate `auto` to normal for this purpose. // https://drafts.csswg.org/css-align-3/#valdef-justify-self-auto const auto inlineAlignSelf = parentWM.IsOrthogonalTo(aWM) - ? stylePos->UsedAlignSelf(nullptr)._0 - : stylePos->UsedJustifySelf(nullptr)._0; + ? stylePos->UsedAlignSelf(nullptr) + : stylePos->UsedJustifySelf(nullptr); const auto blockAlignSelf = parentWM.IsOrthogonalTo(aWM) - ? stylePos->UsedJustifySelf(nullptr)._0 - : stylePos->UsedAlignSelf(nullptr)._0; + ? stylePos->UsedJustifySelf(nullptr) + : stylePos->UsedAlignSelf(nullptr); const auto iShouldStretch = shouldStretch( - inlineAlignSelf, this, iStartOffsetIsAuto, iEndOffsetIsAuto); - const auto bShouldStretch = - shouldStretch(blockAlignSelf, this, bStartOffsetIsAuto, bEndOffsetIsAuto); + inlineAlignSelf._0, this, iStartOffsetIsAuto, iEndOffsetIsAuto); + const auto bShouldStretch = shouldStretch( + blockAlignSelf._0, this, bStartOffsetIsAuto, bEndOffsetIsAuto); const auto iSizeIsAuto = styleISize->IsAuto(); // Note(dshin, bug 1789477): `auto` in the context of abs-element uses // stretch-fit sizing, given specific alignment conditions [1]. Effectively, diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml @@ -578,11 +578,9 @@ cbindgen-types = [ { gecko = "StyleSymbolsType", servo = "crate::counter_style::SymbolsType" }, { gecko = "StyleCounterStyle", servo = "crate::counter_style::CounterStyle" }, { gecko = "StyleComputedJustifyItems", servo = "crate::values::computed::align::ComputedJustifyItems" }, - { gecko = "StyleAlignItems", servo = "crate::values::computed::AlignItems" }, - { gecko = "StyleJustifySelf", servo = "crate::values::computed::JustifySelf" }, - { gecko = "StyleAlignSelf", servo = "crate::values::computed::AlignSelf" }, - { gecko = "StyleAlignContent", servo = "crate::values::computed::align::AlignContent" }, - { gecko = "StyleJustifyContent", servo = "crate::values::computed::align::JustifyContent" }, + { gecko = "StyleItemPlacement", servo = "crate::values::computed::ItemPlacement" }, + { gecko = "StyleContentDistribution", servo = "crate::values::computed::ContentDistribution" }, + { gecko = "StyleSelfAlignment", servo = "crate::values::computed::SelfAlignment" }, { gecko = "StyleComputedValueFlags", servo = "crate::computed_value_flags::ComputedValueFlags" }, { gecko = "StyleImage", servo = "crate::values::computed::Image" }, { gecko = "StyleShapeOutside", servo = "crate::values::computed::basic_shape::ShapeOutside" }, diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp @@ -1335,7 +1335,7 @@ const StyleContainIntrinsicSize& nsStylePosition::ContainIntrinsicISize( return aWM.IsVertical() ? mContainIntrinsicHeight : mContainIntrinsicWidth; } -StyleAlignSelf nsStylePosition::UsedAlignSelf( +StyleSelfAlignment nsStylePosition::UsedAlignSelf( const ComputedStyle* aParent) const { if (mAlignSelf._0 != StyleAlignFlags::AUTO) { return mAlignSelf; @@ -1349,14 +1349,14 @@ StyleAlignSelf nsStylePosition::UsedAlignSelf( return {StyleAlignFlags::NORMAL}; } -StyleJustifySelf nsStylePosition::UsedJustifySelf( +StyleSelfAlignment nsStylePosition::UsedJustifySelf( const ComputedStyle* aParent) const { if (mJustifySelf._0 != StyleAlignFlags::AUTO) { return mJustifySelf; } if (MOZ_LIKELY(aParent)) { const auto& inheritedJustifyItems = - aParent->StylePosition()->mJustifyItems.computed; + aParent->StylePosition()->mJustifyItems.computed._0; return {inheritedJustifyItems._0 & ~StyleAlignFlags::LEGACY}; } return {StyleAlignFlags::NORMAL}; diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h @@ -934,8 +934,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition { using LogicalAxis = mozilla::LogicalAxis; using StyleImplicitGridTracks = mozilla::StyleImplicitGridTracks; using ComputedStyle = mozilla::ComputedStyle; - using StyleAlignSelf = mozilla::StyleAlignSelf; - using StyleJustifySelf = mozilla::StyleJustifySelf; + using StyleSelfAlignment = mozilla::StyleSelfAlignment; nsChangeHint CalcDifference(const nsStylePosition& aNewData, const ComputedStyle& aOldStyle) const; @@ -973,13 +972,13 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition { * Return the used value for 'align-self' given our parent ComputedStyle * (or null for the root). */ - StyleAlignSelf UsedAlignSelf(const ComputedStyle*) const; + StyleSelfAlignment UsedAlignSelf(const ComputedStyle*) const; /** * Return the used value for 'justify-self' given our parent ComputedStyle * aParent (or null for the root). */ - StyleJustifySelf UsedJustifySelf(const ComputedStyle*) const; + StyleSelfAlignment UsedJustifySelf(const ComputedStyle*) const; /** * Return the used value for 'justify/align-self' in aAxis given our parent @@ -1020,12 +1019,12 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition { mozilla::StyleGridAutoFlow mGridAutoFlow; mozilla::StyleMasonryAutoFlow mMasonryAutoFlow; - mozilla::StyleAlignContent mAlignContent; - mozilla::StyleAlignItems mAlignItems; - mozilla::StyleAlignSelf mAlignSelf; - mozilla::StyleJustifyContent mJustifyContent; + mozilla::StyleContentDistribution mAlignContent; + mozilla::StyleItemPlacement mAlignItems; + mozilla::StyleSelfAlignment mAlignSelf; + mozilla::StyleContentDistribution mJustifyContent; mozilla::StyleComputedJustifyItems mJustifyItems; - mozilla::StyleJustifySelf mJustifySelf; + mozilla::StyleSelfAlignment mJustifySelf; mozilla::StyleFlexDirection mFlexDirection; mozilla::StyleFlexWrap mFlexWrap; mozilla::StyleObjectFit mObjectFit; diff --git a/servo/components/style/matching.rs b/servo/components/style/matching.rs @@ -868,9 +868,9 @@ trait PrivateMatchMethods: TElement { let new_justify_items = new_values.get_position().clone_justify_items(); let was_legacy_justify_items = - old_justify_items.computed.0.contains(AlignFlags::LEGACY); + old_justify_items.computed.contains(AlignFlags::LEGACY); - let is_legacy_justify_items = new_justify_items.computed.0.contains(AlignFlags::LEGACY); + let is_legacy_justify_items = new_justify_items.computed.contains(AlignFlags::LEGACY); if is_legacy_justify_items != was_legacy_justify_items { return ChildRestyleRequirement::MustCascadeChildren; diff --git a/servo/components/style/properties/data.py b/servo/components/style/properties/data.py @@ -568,9 +568,6 @@ class Longhand(Property): return False if self.predefined_type: return self.predefined_type in { - "AlignContent", - "AlignItems", - "AlignSelf", "Appearance", "AnimationComposition", "AnimationDirection", @@ -611,9 +608,10 @@ class Longhand(Property): "PositionArea", "PositionAreaKeyword", "PositionProperty", - "JustifyContent", + "ContentDistribution", + "ItemPlacement", + "SelfAlignment", "JustifyItems", - "JustifySelf", "LineBreak", "LineClamp", "MasonryAutoFlow", diff --git a/servo/components/style/properties/gecko.mako.rs b/servo/components/style/properties/gecko.mako.rs @@ -617,7 +617,7 @@ fn static_assert() { <%self:impl_trait style_struct_name="Position"> pub fn set_computed_justify_items(&mut self, v: values::specified::JustifyItems) { - debug_assert_ne!(v.0, crate::values::specified::align::AlignFlags::LEGACY); + debug_assert_ne!(v, values::specified::JustifyItems::legacy()); self.mJustifyItems.computed = v; } </%self:impl_trait> diff --git a/servo/components/style/properties/longhands/position.mako.rs b/servo/components/style/properties/longhands/position.mako.rs @@ -76,9 +76,10 @@ ${helpers.single_keyword( ${helpers.predefined_type( "justify-content", - "JustifyContent", - "specified::JustifyContent(specified::ContentDistribution::normal())", + "ContentDistribution", + "specified::ContentDistribution::normal()", engines="gecko servo", + parse_method="parse_inline", spec="https://drafts.csswg.org/css-align/#propdef-justify-content", extra_prefixes="webkit", animation_type="discrete", @@ -88,8 +89,9 @@ ${helpers.predefined_type( ${helpers.predefined_type( "align-content", - "AlignContent", - "specified::AlignContent(specified::ContentDistribution::normal())", + "ContentDistribution", + "specified::ContentDistribution::normal()", + parse_method="parse_block", engines="gecko servo", spec="https://drafts.csswg.org/css-align/#propdef-align-content", extra_prefixes="webkit", @@ -100,9 +102,10 @@ ${helpers.predefined_type( ${helpers.predefined_type( "align-items", - "AlignItems", - "specified::AlignItems::normal()", + "ItemPlacement", + "specified::ItemPlacement::normal()", engines="gecko servo", + parse_method="parse_block", spec="https://drafts.csswg.org/css-align/#propdef-align-items", extra_prefixes="webkit", animation_type="discrete", @@ -146,9 +149,10 @@ ${helpers.predefined_type( // https://drafts.csswg.org/css-align/#align-self-property ${helpers.predefined_type( "align-self", - "AlignSelf", - "specified::AlignSelf(specified::SelfAlignment::auto())", + "SelfAlignment", + "specified::SelfAlignment::auto()", engines="gecko servo", + parse_method="parse_block", spec="https://drafts.csswg.org/css-align/#align-self-property", extra_prefixes="webkit", animation_type="discrete", @@ -157,8 +161,9 @@ ${helpers.predefined_type( )} ${helpers.predefined_type( "justify-self", - "JustifySelf", - "specified::JustifySelf(specified::SelfAlignment::auto())", + "SelfAlignment", + "specified::SelfAlignment::auto()", + parse_method="parse_inline", engines="gecko servo", spec="https://drafts.csswg.org/css-align/#justify-self-property", animation_type="discrete", diff --git a/servo/components/style/properties/shorthands/position.mako.rs b/servo/components/style/properties/shorthands/position.mako.rs @@ -723,18 +723,14 @@ sub_properties="align-content justify-content" spec="https://drafts.csswg.org/css-align/#propdef-place-content" > - use crate::values::specified::align::{AlignContent, JustifyContent, ContentDistribution, AxisDirection}; + use crate::values::specified::align::ContentDistribution; pub fn parse_value<'i, 't>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Longhands, ParseError<'i>> { - let align_content = - ContentDistribution::parse(input, AxisDirection::Block)?; - - let justify_content = input.try_parse(|input| { - ContentDistribution::parse(input, AxisDirection::Inline) - }); + let align_content = ContentDistribution::parse_block(context, input)?; + let justify_content = input.try_parse(|input| ContentDistribution::parse_inline(context, input)); let justify_content = match justify_content { Ok(v) => v, @@ -755,15 +751,15 @@ }; Ok(expanded! { - align_content: AlignContent(align_content), - justify_content: JustifyContent(justify_content), + align_content: align_content, + justify_content: justify_content, }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { self.align_content.to_css(dest)?; - if self.align_content.0 != self.justify_content.0 { + if self.align_content != self.justify_content { dest.write_char(' ')?; self.justify_content.to_css(dest)?; } @@ -779,14 +775,14 @@ spec="https://drafts.csswg.org/css-align/#place-self-property" rule_types_allowed="Style PositionTry" > - use crate::values::specified::align::{AlignSelf, JustifySelf, SelfAlignment, AxisDirection}; + use crate::values::specified::align::SelfAlignment; pub fn parse_value<'i, 't>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Longhands, ParseError<'i>> { - let align = SelfAlignment::parse(input, AxisDirection::Block)?; - let justify = input.try_parse(|input| SelfAlignment::parse(input, AxisDirection::Inline)); + let align = SelfAlignment::parse_block(context, input)?; + let justify = input.try_parse(|input| SelfAlignment::parse_inline(context, input)); let justify = match justify { Ok(v) => v, @@ -797,14 +793,14 @@ }; Ok(expanded! { - align_self: AlignSelf(align), - justify_self: JustifySelf(justify), + align_self: align, + justify_self: justify, }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { self.align_self.to_css(dest)?; - if self.align_self.0 != self.justify_self.0 { + if self.align_self != self.justify_self { dest.write_char(' ')?; self.justify_self.to_css(dest)?; } @@ -819,38 +815,30 @@ sub_properties="align-items justify-items" spec="https://drafts.csswg.org/css-align/#place-items-property" > - use crate::values::specified::align::{AlignItems, JustifyItems}; - use crate::parser::Parse; - - impl From<AlignItems> for JustifyItems { - fn from(align: AlignItems) -> JustifyItems { - JustifyItems(align.0) - } - } + use crate::values::specified::align::{ItemPlacement, JustifyItems}; pub fn parse_value<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Longhands, ParseError<'i>> { - let align = AlignItems::parse(context, input)?; + let align = ItemPlacement::parse_block(context, input)?; let justify = - input.try_parse(|input| JustifyItems::parse(context, input)) - .unwrap_or_else(|_| JustifyItems::from(align)); + input.try_parse(|input| ItemPlacement::parse_inline(context, input)) + .unwrap_or_else(|_| align.clone()); Ok(expanded! { align_items: align, - justify_items: justify, + justify_items: JustifyItems(justify), }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { self.align_items.to_css(dest)?; - if self.align_items.0 != self.justify_items.0 { + if *self.align_items != self.justify_items.0 { dest.write_char(' ')?; self.justify_items.to_css(dest)?; } - Ok(()) } } diff --git a/servo/components/style/style_adjuster.rs b/servo/components/style/style_adjuster.rs @@ -794,17 +794,13 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { fn adjust_for_justify_items(&mut self) { use crate::values::specified::align; let justify_items = self.style.get_position().clone_justify_items(); - if justify_items.specified.0 != align::AlignFlags::LEGACY { + if justify_items.specified != align::JustifyItems::legacy() { return; } let parent_justify_items = self.style.get_parent_position().clone_justify_items(); - if !parent_justify_items - .computed - .0 - .contains(align::AlignFlags::LEGACY) - { + if !parent_justify_items.computed.contains(align::AlignFlags::LEGACY) { return; } diff --git a/servo/components/style/values/computed/align.rs b/servo/components/style/values/computed/align.rs @@ -9,10 +9,7 @@ use crate::values::computed::{Context, ToComputedValue}; use crate::values::specified; -pub use super::specified::{ - AlignContent, AlignItems, ContentDistribution, JustifyContent, SelfAlignment, -}; -pub use super::specified::{AlignSelf, JustifySelf}; +pub use super::specified::{ContentDistribution, ItemPlacement, SelfAlignment}; /// The computed value for the `justify-items` property. /// @@ -67,7 +64,7 @@ impl ToComputedValue for specified::JustifyItems { fn to_computed_value(&self, _context: &Context) -> JustifyItems { use crate::values::specified::align; let specified = *self; - let computed = if self.0 != align::AlignFlags::LEGACY { + let computed = if (self.0).0 != align::AlignFlags::LEGACY { *self } else { // If the inherited value of `justify-items` includes the diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs @@ -37,8 +37,7 @@ use std::cmp; use std::f32; use std::ops::{Add, Sub}; -pub use self::align::{AlignContent, AlignItems, JustifyContent, JustifyItems, SelfAlignment}; -pub use self::align::{AlignSelf, JustifySelf}; +pub use self::align::{SelfAlignment, ContentDistribution, ItemPlacement, JustifyItems}; pub use self::angle::Angle; pub use self::animation::{ AnimationComposition, AnimationDirection, AnimationDuration, AnimationFillMode, diff --git a/servo/components/style/values/specified/align.rs b/servo/components/style/values/specified/align.rs @@ -145,6 +145,7 @@ pub enum AxisDirection { /// Shared value for the `align-content` and `justify-content` properties. /// /// <https://drafts.csswg.org/css-align/#content-distribution> +/// <https://drafts.csswg.org/css-align/#propdef-align-content> #[derive( Clone, Copy, @@ -156,6 +157,7 @@ pub enum AxisDirection { ToCss, ToResolvedValue, ToShmem, + ToTyped, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(C)] @@ -198,8 +200,23 @@ impl ContentDistribution { self.primary } - /// Parse a value for align-content / justify-content. - pub fn parse<'i, 't>( + /// Parse a value for align-content + pub fn parse_block<'i>( + _: &ParserContext, + input: &mut Parser<'i, '_>, + ) -> Result<Self, ParseError<'i>> { + Self::parse(input, AxisDirection::Block) + } + + /// Parse a value for justify-content + pub fn parse_inline<'i>( + _: &ParserContext, + input: &mut Parser<'i, '_>, + ) -> Result<Self, ParseError<'i>> { + Self::parse(input, AxisDirection::Inline) + } + + fn parse<'i, 't>( input: &mut Parser<'i, 't>, axis: AxisDirection, ) -> Result<Self, ParseError<'i>> { @@ -245,106 +262,28 @@ impl ContentDistribution { content_position | overflow_position, )) } +} - fn list_keywords(f: KeywordsCollectFn, axis: AxisDirection) { +impl SpecifiedValueInfo for ContentDistribution { + fn collect_completion_keywords(f: KeywordsCollectFn) { f(&["normal"]); - if axis == AxisDirection::Block { - list_baseline_keywords(f); - } + list_baseline_keywords(f); // block-axis only list_content_distribution_keywords(f); list_overflow_position_keywords(f); f(&["start", "end", "flex-start", "flex-end", "center"]); - if axis == AxisDirection::Inline { - f(&["left", "right"]); - } - } -} - -/// Value for the `align-content` property. -/// -/// <https://drafts.csswg.org/css-align/#propdef-align-content> -#[derive( - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - PartialEq, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, - ToTyped, -)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[repr(transparent)] -pub struct AlignContent(pub ContentDistribution); - -impl Parse for AlignContent { - fn parse<'i, 't>( - _: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - // NOTE Please also update `impl SpecifiedValueInfo` below when - // this function is updated. - Ok(AlignContent(ContentDistribution::parse( - input, - AxisDirection::Block, - )?)) - } -} - -impl SpecifiedValueInfo for AlignContent { - fn collect_completion_keywords(f: KeywordsCollectFn) { - ContentDistribution::list_keywords(f, AxisDirection::Block); + f(&["left", "right"]); // inline-axis only } } -/// Value for the `justify-content` property. +/// The specified value of the {align,justify}-self properties. /// -/// <https://drafts.csswg.org/css-align/#propdef-justify-content> -#[derive( - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - PartialEq, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, - ToTyped, -)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[repr(transparent)] -pub struct JustifyContent(pub ContentDistribution); - -impl Parse for JustifyContent { - fn parse<'i, 't>( - _: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - // NOTE Please also update `impl SpecifiedValueInfo` below when - // this function is updated. - Ok(JustifyContent(ContentDistribution::parse( - input, - AxisDirection::Inline, - )?)) - } -} - -impl SpecifiedValueInfo for JustifyContent { - fn collect_completion_keywords(f: KeywordsCollectFn) { - ContentDistribution::list_keywords(f, AxisDirection::Inline); - } -} - /// <https://drafts.csswg.org/css-align/#self-alignment> +/// <https://drafts.csswg.org/css-align/#propdef-align-self> #[derive( Clone, Copy, Debug, + Deref, Eq, MallocSizeOf, PartialEq, @@ -352,9 +291,10 @@ impl SpecifiedValueInfo for JustifyContent { ToCss, ToResolvedValue, ToShmem, + ToTyped, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[repr(transparent)] +#[repr(C)] pub struct SelfAlignment(pub AlignFlags); impl SelfAlignment { @@ -374,8 +314,24 @@ impl SelfAlignment { } } - /// Parse a self-alignment value on one of the axis. - pub fn parse<'i, 't>( + /// Parse self-alignment on the block axis (for align-self) + pub fn parse_block<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + Self::parse(input, AxisDirection::Block) + } + + /// Parse self-alignment on the block axis (for align-self) + pub fn parse_inline<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + Self::parse(input, AxisDirection::Inline) + } + + /// Parse a self-alignment value on one of the axes. + fn parse<'i, 't>( input: &mut Parser<'i, 't>, axis: AxisDirection, ) -> Result<Self, ParseError<'i>> { @@ -411,53 +367,23 @@ impl SelfAlignment { } } -/// The specified value of the align-self property. -/// -/// <https://drafts.csswg.org/css-align/#propdef-align-self> -#[derive( - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - PartialEq, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, - ToTyped, -)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[repr(C)] -pub struct AlignSelf(pub SelfAlignment); - -impl Parse for AlignSelf { - fn parse<'i, 't>( - _: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - // NOTE Please also update `impl SpecifiedValueInfo` below when - // this function is updated. - Ok(AlignSelf(SelfAlignment::parse( - input, - AxisDirection::Block, - )?)) - } -} - -impl SpecifiedValueInfo for AlignSelf { +impl SpecifiedValueInfo for SelfAlignment { fn collect_completion_keywords(f: KeywordsCollectFn) { - SelfAlignment::list_keywords(f, AxisDirection::Block); + // TODO: This technically lists left/right for align-self. Not amazing but also not sure + // worth fixing here, could be special-cased on the caller. + Self::list_keywords(f, AxisDirection::Block); } } -/// The specified value of the justify-self property. +/// Value of the `align-items` and `justify-items` properties /// -/// <https://drafts.csswg.org/css-align/#propdef-justify-self> +/// <https://drafts.csswg.org/css-align/#propdef-align-items> +/// <https://drafts.csswg.org/css-align/#propdef-justify-items> #[derive( Clone, Copy, Debug, + Deref, Eq, MallocSizeOf, PartialEq, @@ -469,85 +395,67 @@ impl SpecifiedValueInfo for AlignSelf { )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(C)] -pub struct JustifySelf(pub SelfAlignment); +pub struct ItemPlacement(pub AlignFlags); -impl Parse for JustifySelf { - fn parse<'i, 't>( - _: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - // NOTE Please also update `impl SpecifiedValueInfo` below when - // this function is updated. - Ok(JustifySelf(SelfAlignment::parse( - input, - AxisDirection::Inline, - )?)) +impl ItemPlacement { + /// The value 'normal' + #[inline] + pub fn normal() -> Self { + Self(AlignFlags::NORMAL) } } -impl SpecifiedValueInfo for JustifySelf { - fn collect_completion_keywords(f: KeywordsCollectFn) { - SelfAlignment::list_keywords(f, AxisDirection::Inline); +impl ItemPlacement { + /// Parse a value for align-items + pub fn parse_block<'i>( + _: &ParserContext, + input: &mut Parser<'i, '_>, + ) -> Result<Self, ParseError<'i>> { + Self::parse(input, AxisDirection::Block) } -} -/// Value of the `align-items` property -/// -/// <https://drafts.csswg.org/css-align/#propdef-align-items> -#[derive( - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - PartialEq, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, - ToTyped, -)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[repr(C)] -pub struct AlignItems(pub AlignFlags); - -impl AlignItems { - /// The initial value 'normal' - #[inline] - pub fn normal() -> Self { - AlignItems(AlignFlags::NORMAL) + /// Parse a value for justify-items + pub fn parse_inline<'i>( + _: &ParserContext, + input: &mut Parser<'i, '_>, + ) -> Result<Self, ParseError<'i>> { + Self::parse(input, AxisDirection::Inline) } -} -impl Parse for AlignItems { - // normal | stretch | <baseline-position> | - // <overflow-position>? <self-position> fn parse<'i, 't>( - _: &ParserContext, input: &mut Parser<'i, 't>, + axis: AxisDirection, ) -> Result<Self, ParseError<'i>> { // NOTE Please also update `impl SpecifiedValueInfo` below when // this function is updated. // <baseline-position> if let Ok(baseline) = input.try_parse(parse_baseline) { - return Ok(AlignItems(baseline)); + return Ok(Self(baseline)); } // normal | stretch if let Ok(value) = input.try_parse(parse_normal_stretch) { - return Ok(AlignItems(value)); + return Ok(Self(value)); } + + if axis == AxisDirection::Inline { + // legacy | [ legacy && [ left | right | center ] ] + if let Ok(value) = input.try_parse(parse_legacy) { + return Ok(Self(value)); + } + } + // <overflow-position>? <self-position> let overflow = input .try_parse(parse_overflow_position) .unwrap_or(AlignFlags::empty()); - let self_position = parse_self_position(input, AxisDirection::Block)?; - Ok(AlignItems(self_position | overflow)) + let self_position = parse_self_position(input, axis)?; + Ok(ItemPlacement(self_position | overflow)) } } -impl SpecifiedValueInfo for AlignItems { +impl SpecifiedValueInfo for ItemPlacement { fn collect_completion_keywords(f: KeywordsCollectFn) { list_baseline_keywords(f); list_normal_stretch(f); @@ -560,68 +468,39 @@ impl SpecifiedValueInfo for AlignItems { /// /// <https://drafts.csswg.org/css-align/#justify-items-property> #[derive( - Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem, ToTyped, + Clone, Copy, Debug, Deref, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem, ToTyped, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(C)] -pub struct JustifyItems(pub AlignFlags); +pub struct JustifyItems(pub ItemPlacement); impl JustifyItems { /// The initial value 'legacy' #[inline] pub fn legacy() -> Self { - JustifyItems(AlignFlags::LEGACY) + Self(ItemPlacement(AlignFlags::LEGACY)) } /// The value 'normal' #[inline] pub fn normal() -> Self { - JustifyItems(AlignFlags::NORMAL) + Self(ItemPlacement::normal()) } } impl Parse for JustifyItems { fn parse<'i, 't>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - // NOTE Please also update `impl SpecifiedValueInfo` below when - // this function is updated. - - // <baseline-position> - // - // It's weird that this accepts <baseline-position>, but not - // justify-content... - if let Ok(baseline) = input.try_parse(parse_baseline) { - return Ok(JustifyItems(baseline)); - } - - // normal | stretch - if let Ok(value) = input.try_parse(parse_normal_stretch) { - return Ok(JustifyItems(value)); - } - - // legacy | [ legacy && [ left | right | center ] ] - if let Ok(value) = input.try_parse(parse_legacy) { - return Ok(JustifyItems(value)); - } - - // <overflow-position>? <self-position> - let overflow = input - .try_parse(parse_overflow_position) - .unwrap_or(AlignFlags::empty()); - let self_position = parse_self_position(input, AxisDirection::Inline)?; - Ok(JustifyItems(overflow | self_position)) + ItemPlacement::parse_inline(context, input).map(Self) } } impl SpecifiedValueInfo for JustifyItems { fn collect_completion_keywords(f: KeywordsCollectFn) { - list_baseline_keywords(f); - list_normal_stretch(f); - list_legacy_keywords(f); - list_overflow_position_keywords(f); - list_self_position_keywords(f, AxisDirection::Inline); + ItemPlacement::collect_completion_keywords(f); + list_legacy_keywords(f); // Inline axis only } } diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs @@ -25,8 +25,7 @@ use std::ops::Add; use style_traits::values::specified::AllowedNumericType; use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss}; -pub use self::align::{AlignContent, AlignItems, AlignSelf, ContentDistribution}; -pub use self::align::{JustifyContent, JustifyItems, JustifySelf, SelfAlignment}; +pub use self::align::{ContentDistribution, ItemPlacement, SelfAlignment, JustifyItems}; pub use self::angle::{AllowUnitlessZeroAngle, Angle}; pub use self::animation::{ AnimationComposition, AnimationDirection, AnimationDuration, AnimationFillMode, diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml @@ -284,9 +284,9 @@ include = [ "WritingModeProperty", "Content", "ContentItem", - "AlignSelf", - "JustifySelf", - "AlignItems", + "ContentDistribution", + "SelfAlignment", + "ItemPlacement", "ComputedJustifyItems", "AlignContent", "JustifyContent",