Bug 1923763: Part 2 - Implement Anchor function resolution functions from Rust side. r=firefox-style-system-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D231256
This commit is contained in:
David Shin
2025-01-21 15:11:23 +00:00
parent 0360dacf7c
commit af77990161
4 changed files with 131 additions and 2 deletions

View File

@@ -5,6 +5,7 @@
//! Generic types for CSS values related to length.
use crate::parser::{Parse, ParserContext};
use crate::values::generics::box_::PositionProperty;
use crate::values::generics::Optional;
use crate::values::DashedIdent;
#[cfg(feature = "gecko")]
@@ -450,6 +451,26 @@ where
}
}
/// Result of resolving an anchor function.
pub enum AnchorResolutionResult<'a, LengthPercentage> {
/// Function resolved to a valid anchor.
Resolved(LengthPercentage),
/// Referenced anchor is invalid, but fallback is used.
Fallback(&'a LengthPercentage),
/// Referenced anchor is invalid.
Invalid,
}
impl<'a, LengthPercentage> AnchorResolutionResult<'a, LengthPercentage> {
/// Return result for an invalid anchor function, depending on if it has any fallback.
pub fn new_anchor_invalid(fallback: Option<&'a LengthPercentage>) -> Self {
if let Some(fb) = fallback {
return Self::Fallback(fb);
}
Self::Invalid
}
}
impl<LengthPercentage> GenericAnchorSizeFunction<LengthPercentage>
{
/// Parse the inner part of `anchor-size()`, after the parser has consumed "anchor-size(".
@@ -487,6 +508,19 @@ impl<LengthPercentage> GenericAnchorSizeFunction<LengthPercentage>
})
})
}
/// Resolve the anchor size function. On failure, return reference to fallback, if exists.
pub fn resolve<'a>(
&'a self,
position_property: PositionProperty,
) -> AnchorResolutionResult<'a, LengthPercentage> {
if !position_property.is_absolutely_positioned() {
return AnchorResolutionResult::new_anchor_invalid(self.fallback.as_ref());
}
// TODO(dshin): Do the actual anchor resolution here.
AnchorResolutionResult::new_anchor_invalid(self.fallback.as_ref())
}
}
/// Keyword values for the anchor size function.

View File

@@ -11,8 +11,10 @@ use style_traits::CssWriter;
use style_traits::SpecifiedValueInfo;
use style_traits::ToCss;
use crate::logical_geometry::PhysicalSide;
use crate::values::animated::ToAnimatedZero;
use crate::values::generics::length::GenericAnchorSizeFunction;
use crate::values::generics::box_::PositionProperty;
use crate::values::generics::length::{AnchorResolutionResult, GenericAnchorSizeFunction};
use crate::values::generics::ratio::Ratio;
use crate::values::generics::Optional;
use crate::values::DashedIdent;
@@ -375,6 +377,26 @@ where
}
}
impl<Percentage, LengthPercentage> GenericAnchorFunction<Percentage, LengthPercentage> {
/// Resolve the anchor function. On failure, return reference to fallback, if exists.
pub fn resolve<'a>(
&'a self,
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_side(side) {
return AnchorResolutionResult::new_anchor_invalid(self.fallback.as_ref());
}
// TODO(dshin): Do the actual anchor resolution here.
AnchorResolutionResult::new_anchor_invalid(self.fallback.as_ref())
}
}
/// Keyword values for the anchor positioning function.
#[derive(
Animate,
@@ -423,6 +445,22 @@ pub enum AnchorSideKeyword {
Center,
}
impl AnchorSideKeyword {
fn valid_for_side(&self, side: PhysicalSide) -> bool {
match self {
Self::Left | Self::Right => side == PhysicalSide::Left || side == PhysicalSide::Right,
Self::Top | Self::Bottom => side == PhysicalSide::Top || side == PhysicalSide::Bottom,
Self::Inside |
Self::Outside |
Self::Start |
Self::End |
Self::SelfStart |
Self::SelfEnd |
Self::Center => true,
}
}
}
/// Anchor side for the anchor positioning function.
#[derive(
Animate,
@@ -450,3 +488,13 @@ pub enum AnchorSide<P> {
/// Percentage value between the `start` and `end` sides.
Percentage(P),
}
impl<P> AnchorSide<P> {
/// Is this anchor side valid for a given side?
pub fn valid_for_side(&self, side: PhysicalSide) -> bool {
match self {
Self::Keyword(k) => k.valid_for_side(side),
Self::Percentage(_) => true,
}
}
}

View File

@@ -326,6 +326,7 @@ include = [
"AnchorSizeFunction",
"Margin",
"PositionProperty",
"PhysicalSide",
]
item_types = [
"enums",

View File

@@ -16,6 +16,7 @@ use selectors::matching::{ElementSelectorFlags, MatchingForInvalidation, Selecto
use selectors::{Element, OpaqueElement};
use servo_arc::{Arc, ArcBorrow};
use smallvec::SmallVec;
use style::values::generics::length::AnchorResolutionResult;
use std::collections::BTreeSet;
use std::fmt::Write;
use std::iter;
@@ -103,6 +104,7 @@ use style::invalidation::element::relative_selector::{
};
use style::invalidation::element::restyle_hints::RestyleHint;
use style::invalidation::stylesheets::RuleChangeKind;
use style::logical_geometry::PhysicalSide;
use style::media_queries::MediaList;
use style::parser::{Parse, ParserContext};
#[cfg(feature = "gecko_debug")]
@@ -149,7 +151,9 @@ use style::values::computed::effects::Filter;
use style::values::computed::font::{
FamilyName, FontFamily, FontFamilyList, FontStretch, FontStyle, FontWeight, GenericFontFamily,
};
use style::values::computed::{self, Context, ToComputedValue};
use style::values::computed::length::AnchorSizeFunction;
use style::values::computed::position::AnchorFunction;
use style::values::computed::{self, Context, PositionProperty, ToComputedValue};
use style::values::distance::ComputeSquaredDistance;
use style::values::generics::color::ColorMixFlags;
use style::values::generics::easing::BeforeFlag;
@@ -9735,3 +9739,45 @@ pub unsafe extern "C" fn Servo_CSSParser_NextToken(
return true;
}
/// Result of resolving an anchor positioning function.
#[repr(u8)]
pub enum AnchorPositioningFunctionResolution {
/// Anchor function invalid.
Invalid,
/// Anchor function resolved to a reference to fallback.
ResolvedReference(*const computed::LengthPercentage),
/// Anchor function resolved to a value.
Resolved(computed::LengthPercentage),
}
impl AnchorPositioningFunctionResolution {
fn new(result: AnchorResolutionResult<'_, computed::LengthPercentage>) -> Self {
match result {
AnchorResolutionResult::Resolved(l) => AnchorPositioningFunctionResolution::Resolved(l),
AnchorResolutionResult::Fallback(l) => {
AnchorPositioningFunctionResolution::ResolvedReference(l as *const _)
},
AnchorResolutionResult::Invalid => AnchorPositioningFunctionResolution::Invalid,
}
}
}
#[no_mangle]
pub extern "C" fn Servo_ResolveAnchorFunction(
func: &AnchorFunction,
side: PhysicalSide,
prop: PositionProperty,
out: &mut AnchorPositioningFunctionResolution,
) {
*out = AnchorPositioningFunctionResolution::new(func.resolve(side, prop));
}
#[no_mangle]
pub extern "C" fn Servo_ResolveAnchorSizeFunction(
func: &AnchorSizeFunction,
prop: PositionProperty,
out: &mut AnchorPositioningFunctionResolution,
) {
*out = AnchorPositioningFunctionResolution::new(func.resolve(prop));
}