Bug 1964122: Work with side, not axis, when resolving anchor() r=firefox-style-system-reviewers,emilio
Previously, we mapped left: anchor(left); to "Resolve anchor(left) with in horizontal axis" - However, this doesn't work for two reasons: 1. `left: anchor(left)` and `right: anchor(left)` have to return 2 different values to produce the identical result 2. We need side data for `left: anchor(inside)` and `right: anchor(outside)` Differential Revision: https://phabricator.services.mozilla.com/D247663
This commit is contained in:
committed by
dshin@mozilla.com
parent
b7d69dd476
commit
1a41596bbf
@@ -1273,17 +1273,21 @@ inline gfx::Point StyleCoordinatePair<LengthPercentage>::ToGfxPoint(
|
||||
y.ResolveToCSSPixels(aBasis->Height()));
|
||||
}
|
||||
|
||||
inline StylePhysicalAxis GetStylePhysicalAxis(mozilla::Side aSide) {
|
||||
return aSide == mozilla::Side::eSideTop || aSide == mozilla::Side::eSideBottom
|
||||
? StylePhysicalAxis::Vertical
|
||||
: StylePhysicalAxis::Horizontal;
|
||||
}
|
||||
|
||||
inline StylePhysicalAxis ToStylePhysicalAxis(PhysicalAxis aAxis) {
|
||||
// TODO(dhsin): Should look into merging these two values...
|
||||
// Assert for this casting lives in `nsStyleStruct.cpp` since
|
||||
// `PhysicalAxis` is a forward decl here.
|
||||
return static_cast<StylePhysicalAxis>(static_cast<uint8_t>(aAxis));
|
||||
inline StylePhysicalSide ToStylePhysicalSide(mozilla::Side aSide) {
|
||||
// TODO(dshin): Should look into merging these two types...
|
||||
static_assert(static_cast<uint8_t>(mozilla::Side::eSideLeft) ==
|
||||
static_cast<uint8_t>(StylePhysicalSide::Left),
|
||||
"Left side doesn't match");
|
||||
static_assert(static_cast<uint8_t>(mozilla::Side::eSideRight) ==
|
||||
static_cast<uint8_t>(StylePhysicalSide::Right),
|
||||
"Left side doesn't match");
|
||||
static_assert(static_cast<uint8_t>(mozilla::Side::eSideTop) ==
|
||||
static_cast<uint8_t>(StylePhysicalSide::Top),
|
||||
"Left side doesn't match");
|
||||
static_assert(static_cast<uint8_t>(mozilla::Side::eSideBottom) ==
|
||||
static_cast<uint8_t>(StylePhysicalSide::Bottom),
|
||||
"Left side doesn't match");
|
||||
return static_cast<StylePhysicalSide>(static_cast<uint8_t>(aSide));
|
||||
}
|
||||
|
||||
#define DEFINE_LENGTH_PERCENTAGE_CTOR(ty_) \
|
||||
|
||||
@@ -1363,14 +1363,8 @@ StyleJustifySelf nsStylePosition::UsedJustifySelf(
|
||||
}
|
||||
|
||||
AnchorResolvedInset AnchorResolvedInsetHelper::ResolveAnchor(
|
||||
const mozilla::StyleInset& aValue, mozilla::StylePhysicalAxis aAxis,
|
||||
mozilla::StylePositionProperty aPosition) {
|
||||
static_assert(static_cast<uint8_t>(mozilla::PhysicalAxis::Vertical) ==
|
||||
static_cast<uint8_t>(StylePhysicalAxis::Vertical),
|
||||
"Vertical axis doesn't match");
|
||||
static_assert(static_cast<uint8_t>(mozilla::PhysicalAxis::Horizontal) ==
|
||||
static_cast<uint8_t>(StylePhysicalAxis::Horizontal),
|
||||
"Horizontal axis doesn't match");
|
||||
const StyleInset& aValue, StylePhysicalSide aSide,
|
||||
StylePositionProperty aPosition) {
|
||||
MOZ_ASSERT(aValue.HasAnchorPositioningFunction(),
|
||||
"Calling anchor resolution without using it?");
|
||||
switch (aValue.tag) {
|
||||
@@ -1378,7 +1372,7 @@ AnchorResolvedInset AnchorResolvedInsetHelper::ResolveAnchor(
|
||||
const auto& lp = aValue.AsAnchorContainingCalcFunction();
|
||||
const auto& c = lp.AsCalc();
|
||||
auto result = StyleCalcAnchorPositioningFunctionResolution::Invalid();
|
||||
Servo_ResolveAnchorFunctionsInCalcPercentage(&c, &aAxis, aPosition,
|
||||
Servo_ResolveAnchorFunctionsInCalcPercentage(&c, &aSide, aPosition,
|
||||
&result);
|
||||
if (result.IsInvalid()) {
|
||||
return Auto();
|
||||
@@ -1387,7 +1381,7 @@ AnchorResolvedInset AnchorResolvedInsetHelper::ResolveAnchor(
|
||||
}
|
||||
case StyleInset::Tag::AnchorFunction: {
|
||||
auto resolved = StyleAnchorPositioningFunctionResolution::Invalid();
|
||||
Servo_ResolveAnchorFunction(&*aValue.AsAnchorFunction(), aAxis, aPosition,
|
||||
Servo_ResolveAnchorFunction(&*aValue.AsAnchorFunction(), aSide, aPosition,
|
||||
&resolved);
|
||||
if (resolved.IsInvalid()) {
|
||||
return Auto();
|
||||
|
||||
@@ -749,12 +749,12 @@ struct AnchorResolvedInsetHelper {
|
||||
}
|
||||
|
||||
static AnchorResolvedInset FromUnresolved(
|
||||
const mozilla::StyleInset& aValue, mozilla::StylePhysicalAxis aAxis,
|
||||
const mozilla::StyleInset& aValue, mozilla::Side aSide,
|
||||
mozilla::StylePositionProperty aPosition) {
|
||||
if (!aValue.HasAnchorPositioningFunction()) {
|
||||
return AnchorResolvedInset::NonOwning(&aValue);
|
||||
}
|
||||
return ResolveAnchor(aValue, aAxis, aPosition);
|
||||
return ResolveAnchor(aValue, mozilla::ToStylePhysicalSide(aSide), aPosition);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -763,7 +763,7 @@ struct AnchorResolvedInsetHelper {
|
||||
}
|
||||
|
||||
static AnchorResolvedInset ResolveAnchor(
|
||||
const mozilla::StyleInset& aValue, mozilla::StylePhysicalAxis aAxis,
|
||||
const mozilla::StyleInset& aValue, mozilla::StylePhysicalSide aSide,
|
||||
mozilla::StylePositionProperty aPosition);
|
||||
};
|
||||
|
||||
@@ -1014,7 +1014,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
|
||||
AnchorResolvedInset GetAnchorResolvedInset(
|
||||
mozilla::Side aSide, mozilla::StylePositionProperty aPosition) const {
|
||||
return AnchorResolvedInsetHelper::FromUnresolved(
|
||||
mOffset.Get(aSide), GetStylePhysicalAxis(aSide), aPosition);
|
||||
mOffset.Get(aSide), aSide, aPosition);
|
||||
}
|
||||
inline AnchorResolvedInset GetAnchorResolvedInset(
|
||||
mozilla::LogicalSide aSide, WritingMode aWM,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
use super::{Context, Length, Percentage, PositionProperty, ToComputedValue};
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::gecko_bindings::structs::GeckoFontMetrics;
|
||||
use crate::logical_geometry::PhysicalAxis;
|
||||
use crate::logical_geometry::PhysicalSide;
|
||||
use crate::values::animated::{Animate, Context as AnimatedContext, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use crate::values::generics::calc::{CalcUnits, PositivePercentageBasis};
|
||||
@@ -915,10 +915,10 @@ fn resolve_anchor_functions(
|
||||
) -> Result<Option<CalcNode>, ()> {
|
||||
let resolution = match node {
|
||||
CalcNode::Anchor(f) => {
|
||||
let axis = info.axis.expect("Unexpected anchor()");
|
||||
let side = info.side.expect("Unexpected anchor()");
|
||||
// Invalid use of `anchor()` (i.e. Outside of inset properties) should've been
|
||||
// caught at parse time.
|
||||
f.resolve(axis, info.position_property)
|
||||
f.resolve(side, info.position_property)
|
||||
},
|
||||
CalcNode::AnchorSize(f) => f.resolve(info.position_property),
|
||||
_ => return Ok(None),
|
||||
@@ -938,14 +938,13 @@ fn resolve_anchor_functions(
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CalcAnchorFunctionResolutionInfo {
|
||||
/// Which axis we're resolving anchor functions for.
|
||||
/// Which side we're resolving anchor functions for.
|
||||
/// This is only relevant for `anchor()`, which requires
|
||||
/// the property using the function to be in the same axis
|
||||
/// as the specified side [1]. `None` if we aren't expecting
|
||||
/// `anchor()`, like in size properties, where only `anchor-size()`
|
||||
/// is allowed.
|
||||
/// the property using the function to be in the side[1].
|
||||
/// `None` if we aren't expecting `anchor()`, like in size
|
||||
/// properties, where only `anchor-size()` is allowed.
|
||||
/// [1]: https://drafts.csswg.org/css-anchor-position-1/#anchor-valid
|
||||
pub axis: Option<PhysicalAxis>,
|
||||
pub side: Option<PhysicalSide>,
|
||||
/// `position` property of the box for which this style is being resolved.
|
||||
pub position_property: PositionProperty,
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use style_traits::CssWriter;
|
||||
use style_traits::SpecifiedValueInfo;
|
||||
use style_traits::ToCss;
|
||||
|
||||
use crate::logical_geometry::PhysicalAxis;
|
||||
use crate::logical_geometry::PhysicalSide;
|
||||
use crate::values::animated::ToAnimatedZero;
|
||||
use crate::values::generics::box_::PositionProperty;
|
||||
use crate::values::generics::length::{AnchorResolutionResult, GenericAnchorSizeFunction};
|
||||
@@ -391,14 +391,14 @@ impl<Percentage, LengthPercentage> GenericAnchorFunction<Percentage, LengthPerce
|
||||
/// Resolve the anchor function. On failure, return reference to fallback, if exists.
|
||||
pub fn resolve<'a>(
|
||||
&'a self,
|
||||
axis: PhysicalAxis,
|
||||
side: PhysicalSide,
|
||||
position_property: PositionProperty,
|
||||
) -> AnchorResolutionResult<'a, LengthPercentage> {
|
||||
if !position_property.is_absolutely_positioned() {
|
||||
return AnchorResolutionResult::new_anchor_invalid(self.fallback.as_ref());
|
||||
}
|
||||
|
||||
if !self.side.valid_for_axis(axis) {
|
||||
if !self.side.valid_for(side) {
|
||||
return AnchorResolutionResult::new_anchor_invalid(self.fallback.as_ref());
|
||||
}
|
||||
|
||||
@@ -456,10 +456,10 @@ pub enum AnchorSideKeyword {
|
||||
}
|
||||
|
||||
impl AnchorSideKeyword {
|
||||
fn valid_for_axis(&self, axis: PhysicalAxis) -> bool {
|
||||
fn valid_for(&self, side: PhysicalSide) -> bool {
|
||||
match self {
|
||||
Self::Left | Self::Right => axis == PhysicalAxis::Horizontal,
|
||||
Self::Top | Self::Bottom => axis == PhysicalAxis::Vertical,
|
||||
Self::Left | Self::Right => matches!(side, PhysicalSide::Left | PhysicalSide::Right),
|
||||
Self::Top | Self::Bottom => matches!(side, PhysicalSide::Top | PhysicalSide::Bottom),
|
||||
Self::Inside |
|
||||
Self::Outside |
|
||||
Self::Start |
|
||||
@@ -500,10 +500,10 @@ pub enum AnchorSide<P> {
|
||||
}
|
||||
|
||||
impl<P> AnchorSide<P> {
|
||||
/// Is this anchor side valid for a given axis?
|
||||
pub fn valid_for_axis(&self, axis: PhysicalAxis) -> bool {
|
||||
/// Is this anchor side valid for a given side?
|
||||
pub fn valid_for(&self, side: PhysicalSide) -> bool {
|
||||
match self {
|
||||
Self::Keyword(k) => k.valid_for_axis(axis),
|
||||
Self::Keyword(k) => k.valid_for(side),
|
||||
Self::Percentage(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,6 +331,7 @@ include = [
|
||||
"Margin",
|
||||
"PositionProperty",
|
||||
"PhysicalAxis",
|
||||
"PhysicalSide",
|
||||
"QueryFontMetricsFlags",
|
||||
]
|
||||
item_types = [
|
||||
|
||||
@@ -103,7 +103,7 @@ use style::invalidation::element::relative_selector::{
|
||||
};
|
||||
use style::invalidation::element::restyle_hints::RestyleHint;
|
||||
use style::invalidation::stylesheets::RuleChangeKind;
|
||||
use style::logical_geometry::PhysicalAxis;
|
||||
use style::logical_geometry::PhysicalSide;
|
||||
use style::media_queries::MediaList;
|
||||
use style::parser::{Parse, ParserContext};
|
||||
#[cfg(feature = "gecko_debug")]
|
||||
@@ -8447,12 +8447,12 @@ pub enum CalcAnchorPositioningFunctionResolution {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ResolveAnchorFunctionsInCalcPercentage(
|
||||
calc: &computed::length_percentage::CalcLengthPercentage,
|
||||
axis: Option<&PhysicalAxis>,
|
||||
side: Option<&PhysicalSide>,
|
||||
position_property: PositionProperty,
|
||||
out: &mut CalcAnchorPositioningFunctionResolution,
|
||||
) {
|
||||
let resolved = calc.resolve_anchor(CalcAnchorFunctionResolutionInfo {
|
||||
axis: axis.copied(),
|
||||
side: side.copied(),
|
||||
position_property,
|
||||
});
|
||||
|
||||
@@ -9869,11 +9869,11 @@ impl AnchorPositioningFunctionResolution {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ResolveAnchorFunction(
|
||||
func: &AnchorFunction,
|
||||
axis: PhysicalAxis,
|
||||
side: PhysicalSide,
|
||||
prop: PositionProperty,
|
||||
out: &mut AnchorPositioningFunctionResolution,
|
||||
) {
|
||||
*out = AnchorPositioningFunctionResolution::new(func.resolve(axis, prop));
|
||||
*out = AnchorPositioningFunctionResolution::new(func.resolve(side, prop));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
Reference in New Issue
Block a user