commit ed620cdee7bb063499f54733c34230e437694c1a
parent a9a60b32dcc92e40f6460c8e28a1a072919588bc
Author: Jonathan Watt <jwatt@jwatt.org>
Date: Tue, 9 Dec 2025 17:22:27 +0000
Bug 2004161. Fix position-area default self-alignment. r=dshin,firefox-style-system-reviewers,layout-reviewers,emilio
https://drafts.csswg.org/css-anchor-position-1/#position-area-alignment
Differential Revision: https://phabricator.services.mozilla.com/D275625
Diffstat:
3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h
@@ -71,6 +71,12 @@ using PhysicalAxes = EnumSet<PhysicalAxis>;
static constexpr PhysicalAxes kPhysicalAxesBoth{PhysicalAxis::Vertical,
PhysicalAxis::Horizontal};
+inline StyleLogicalAxis ToStyleLogicalAxis(LogicalAxis aLogicalAxis) {
+ return StyleLogicalAxis(aLogicalAxis == LogicalAxis::Block
+ ? StyleLogicalAxis::Block
+ : StyleLogicalAxis::Inline);
+}
+
inline LogicalAxis GetOrthogonalAxis(LogicalAxis aAxis) {
return aAxis == LogicalAxis::Block ? LogicalAxis::Inline : LogicalAxis::Block;
}
@@ -474,6 +480,10 @@ class WritingMode {
mWritingMode = aComputedStyle->WritingMode();
}
+ inline StyleWritingMode ToStyleWritingMode() const {
+ return StyleWritingMode(GetBits());
+ }
+
/**
* This function performs fixup for elements with 'unicode-bidi: plaintext',
* where inline directionality is derived from the Unicode bidi categories
diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
@@ -2550,11 +2550,14 @@ nsContainerFrame::CSSAlignmentForAbsPosChildWithinContainingBlock(
: StyleAlignFlags::START;
alignment |= StyleAlignFlags::UNSAFE;
} else {
- auto keyword = aLogicalAxis == LogicalAxis::Inline
- ? aResolvedPositionArea.first
- : aResolvedPositionArea.second;
- // Use normal position-area alignment
- Servo_ResolvePositionAreaSelfAlignment(&keyword, &alignment);
+ // Use default position-area self-alignment:
+ // https://drafts.csswg.org/css-anchor-position-1/#position-area-alignment
+ const auto axis = ToStyleLogicalAxis(aLogicalAxis);
+ const auto cbSWM = cbWM.ToStyleWritingMode();
+ const auto selfWM =
+ aChildRI.mFrame->GetWritingMode().ToStyleWritingMode();
+ Servo_ResolvePositionAreaSelfAlignment(&aResolvedPositionArea, axis,
+ &cbSWM, &selfWM, &alignment);
}
}
diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs
@@ -106,7 +106,7 @@ use style::invalidation::element::relative_selector::{
};
use style::invalidation::element::restyle_hints::RestyleHint;
use style::invalidation::stylesheets::RuleChangeKind;
-use style::logical_geometry::{PhysicalAxis, PhysicalSide, WritingMode};
+use style::logical_geometry::{LogicalAxis, PhysicalAxis, PhysicalSide, WritingMode};
use style::media_queries::MediaList;
use style::parser::{Parse, ParserContext};
use style::properties::declaration_block::PropertyTypedValue;
@@ -165,7 +165,7 @@ use style::values::computed::length_percentage::{
};
use style::values::computed::position::{AnchorFunction, PositionArea};
use style::values::computed::{
- self, ContentVisibility, Context, PositionAreaKeyword, ToComputedValue,
+ self, ContentVisibility, Context, ToComputedValue,
};
use style::values::distance::{ComputeSquaredDistance, SquaredDistance};
use style::values::generics::color::ColorMixFlags;
@@ -10842,12 +10842,24 @@ pub extern "C" fn Servo_PhysicalizePositionArea(
*area = area.to_physical(*cb_wm, *self_wm);
}
+/// https://drafts.csswg.org/css-anchor-position-1/#position-area-alignment
#[no_mangle]
pub extern "C" fn Servo_ResolvePositionAreaSelfAlignment(
- area: &PositionAreaKeyword,
+ area: &PositionArea,
+ axis: LogicalAxis,
+ cb_wm: &WritingMode,
+ self_wm: &WritingMode,
out: &mut AlignFlags,
) {
- let Some(align) = area.to_self_alignment() else {
+ // As well as converting `area` and `axis` to the same form for comparison
+ // this also makes sure `area`'s second keyword explicit (not none).
+ let physical_area = area.to_physical(*cb_wm, *self_wm);
+ let physical_axis = axis.to_physical(*cb_wm);
+ let area_keyword = match physical_axis {
+ PhysicalAxis::Horizontal => physical_area.first,
+ PhysicalAxis::Vertical => physical_area.second,
+ };
+ let Some(align) = area_keyword.to_self_alignment() else {
debug_assert!(
false,
"ResolvePositionAreaSelfAlignment called on {:?}",