commit 4994fbf4b4d95946f81667c6218eaf3e91c90893
parent c4e294aaf9be3773f7b435174b035cc0715c8325
Author: Jonathan Kew <jkew@mozilla.com>
Date: Thu, 23 Oct 2025 10:40:24 +0000
Bug 1995253 - patch 1 - Add flip-x and flip-y keywords to position-try-fallbacks. r=layout-reviewers,firefox-style-system-reviewers,emilio
(Testcases added to WPT in following patch.)
Differential Revision: https://phabricator.services.mozilla.com/D269493
Diffstat:
4 files changed, 65 insertions(+), 18 deletions(-)
diff --git a/layout/base/AnchorPositioningUtils.cpp b/layout/base/AnchorPositioningUtils.cpp
@@ -651,6 +651,12 @@ static void ApplyFallbackTactic(
case StylePositionTryFallbacksTryTacticKeyword::FlipStart:
FlipStartsAndEnds(aPhysicalArea, aWM);
return;
+ case StylePositionTryFallbacksTryTacticKeyword::FlipX:
+ FlipInAxis(aPhysicalArea, PhysicalAxis::Horizontal);
+ return;
+ case StylePositionTryFallbacksTryTacticKeyword::FlipY:
+ FlipInAxis(aPhysicalArea, PhysicalAxis::Vertical);
+ return;
}
}
diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js
@@ -13430,6 +13430,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
"--foo",
"flip-block",
"flip-inline",
+ "flip-x",
+ "flip-y",
"flip-start",
"left",
"span-y-start",
@@ -13479,6 +13481,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
"--foo",
"flip-block",
"flip-inline",
+ "flip-x",
+ "flip-y",
"flip-start",
"left",
"span-y-start",
@@ -13489,6 +13493,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
"most-width --foo",
"most-width flip-block",
"most-width flip-inline",
+ "most-width flip-x",
+ "most-width flip-y",
"most-width flip-start",
"most-width left",
"most-width span-y-start",
@@ -13499,6 +13505,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
"most-height --foo",
"most-height flip-block",
"most-height flip-inline",
+ "most-height flip-x",
+ "most-height flip-y",
"most-height flip-start",
"most-height left",
"most-height span-y-start",
@@ -13509,6 +13517,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
"most-block-size --foo",
"most-block-size flip-block",
"most-block-size flip-inline",
+ "most-block-size flip-x",
+ "most-block-size flip-y",
"most-block-size flip-start",
"most-block-size left",
"most-block-size span-y-start",
@@ -13519,6 +13529,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
"most-inline-size --foo",
"most-inline-size flip-block",
"most-inline-size flip-inline",
+ "most-inline-size flip-x",
+ "most-inline-size flip-y",
"most-inline-size flip-start",
"most-inline-size left",
"most-inline-size span-y-start",
diff --git a/servo/components/style/style_adjuster.rs b/servo/components/style/style_adjuster.rs
@@ -935,20 +935,30 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
/// overkill for now.
fn adjust_for_try_tactic(&mut self, tactic: PositionTryFallbacksTryTactic) {
debug_assert!(!tactic.is_empty());
- let horizontal = self.style.writing_mode.is_horizontal();
+ // TODO: This is supposed to use the containing block's WM (bug 1995256).
+ let wm = self.style.writing_mode;
// TODO: Flip inset / margin / sizes percentages and anchor lookup sides as necessary.
for tactic in tactic.into_iter() {
+ use PositionTryFallbacksTryTacticKeyword::*;
match tactic {
- PositionTryFallbacksTryTacticKeyword::None => break,
- PositionTryFallbacksTryTacticKeyword::FlipBlock => {
+ None => break,
+ FlipBlock => {
self.flip_self_alignment(/* block = */ true);
- self.flip_insets_and_margins(!horizontal);
+ self.flip_insets_and_margins(/* horizontal = */ wm.is_vertical());
},
- PositionTryFallbacksTryTacticKeyword::FlipInline => {
+ FlipInline => {
self.flip_self_alignment(/* block = */ false);
- self.flip_insets_and_margins(horizontal);
+ self.flip_insets_and_margins(/* horizontal = */ wm.is_horizontal());
+ },
+ FlipX => {
+ self.flip_self_alignment(/* block = */ wm.is_vertical());
+ self.flip_insets_and_margins(/* horizontal = */ true);
+ },
+ FlipY => {
+ self.flip_self_alignment(/* block = */ wm.is_horizontal());
+ self.flip_insets_and_margins(/* horizontal = */ false);
},
- PositionTryFallbacksTryTacticKeyword::FlipStart => {
+ FlipStart => {
self.flip_start();
},
}
diff --git a/servo/components/style/values/specified/position.rs b/servo/components/style/values/specified/position.rs
@@ -524,6 +524,10 @@ pub enum PositionTryFallbacksTryTacticKeyword {
FlipInline,
/// Swap the values in the start properties.
FlipStart,
+ /// Swap the values in the X axis.
+ FlipX,
+ /// Swap the values in the Y axis.
+ FlipY,
}
impl PositionTryFallbacksTryTacticKeyword {
@@ -556,6 +560,8 @@ pub struct PositionTryFallbacksTryTactic(
pub PositionTryFallbacksTryTacticKeyword,
pub PositionTryFallbacksTryTacticKeyword,
pub PositionTryFallbacksTryTacticKeyword,
+ pub PositionTryFallbacksTryTacticKeyword,
+ pub PositionTryFallbacksTryTacticKeyword,
);
impl Parse for PositionTryFallbacksTryTactic {
@@ -563,17 +569,30 @@ impl Parse for PositionTryFallbacksTryTactic {
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- let first = PositionTryFallbacksTryTacticKeyword::parse(input)?;
- let second = input
- .try_parse(PositionTryFallbacksTryTacticKeyword::parse)
- .unwrap_or_default();
- let third = input
- .try_parse(PositionTryFallbacksTryTacticKeyword::parse)
- .unwrap_or_default();
- if first == second || first == third || (!second.is_none() && second == third) {
- return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ let kw = [
+ PositionTryFallbacksTryTacticKeyword::parse(input)?,
+ input
+ .try_parse(PositionTryFallbacksTryTacticKeyword::parse)
+ .unwrap_or_default(),
+ input
+ .try_parse(PositionTryFallbacksTryTacticKeyword::parse)
+ .unwrap_or_default(),
+ input
+ .try_parse(PositionTryFallbacksTryTacticKeyword::parse)
+ .unwrap_or_default(),
+ input
+ .try_parse(PositionTryFallbacksTryTacticKeyword::parse)
+ .unwrap_or_default(),
+ ];
+ for i in 0..kw.len() - 1 {
+ if kw[i].is_none() {
+ break;
+ }
+ if kw[i + 1..].contains(&kw[i]) {
+ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ }
}
- Ok(Self(first, second, third))
+ Ok(Self(kw[0], kw[1], kw[2], kw[3], kw[4]))
}
}
@@ -587,7 +606,7 @@ impl PositionTryFallbacksTryTactic {
/// Iterates over the fallbacks in order.
#[inline]
pub fn into_iter(&self) -> impl IntoIterator<Item = PositionTryFallbacksTryTacticKeyword> {
- [self.0, self.1, self.2]
+ [self.0, self.1, self.2, self.3, self.4]
}
}