style/values/computed/
position.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! CSS handling for the computed value of
6//! [`position`][position] values.
7//!
8//! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
9
10use crate::values::computed::{Integer, LengthPercentage, NonNegativeNumber, Percentage};
11use crate::values::generics::position::Position as GenericPosition;
12use crate::values::generics::position::PositionComponent as GenericPositionComponent;
13use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
14use crate::values::generics::position::ZIndex as GenericZIndex;
15use crate::values::generics::position::{
16    AnchorSideKeyword, GenericAnchorFunction, GenericAnchorSide,
17};
18use crate::values::generics::position::{AspectRatio as GenericAspectRatio, GenericInset};
19pub use crate::values::specified::position::{
20    AnchorName, AnchorScope, DashedIdentAndOrTryTactic, PositionAnchor, PositionArea,
21    PositionAreaKeyword, PositionTryFallbacks, PositionTryOrder, PositionVisibility,
22};
23pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow};
24use crate::Zero;
25use std::fmt::{self, Write};
26use style_traits::{CssWriter, ToCss};
27
28/// The computed value of a CSS `<position>`
29pub type Position = GenericPosition<HorizontalPosition, VerticalPosition>;
30
31/// The computed value of an `auto | <position>`
32pub type PositionOrAuto = GenericPositionOrAuto<Position>;
33
34/// The computed value of a CSS horizontal position.
35pub type HorizontalPosition = LengthPercentage;
36
37/// The computed value of a CSS vertical position.
38pub type VerticalPosition = LengthPercentage;
39
40/// The computed value of anchor side.
41pub type AnchorSide = GenericAnchorSide<Percentage>;
42
43impl AnchorSide {
44    /// Break down given anchor side into its equivalent keyword and percentage.
45    pub fn keyword_and_percentage(&self) -> (AnchorSideKeyword, Percentage) {
46        match self {
47            Self::Percentage(p) => (AnchorSideKeyword::Start, *p),
48            Self::Keyword(k) => {
49                if matches!(k, AnchorSideKeyword::Center) {
50                    (AnchorSideKeyword::Start, Percentage(0.5))
51                } else {
52                    (*k, Percentage::zero())
53                }
54            },
55        }
56    }
57}
58
59/// The computed value of an `anchor()` function.
60pub type AnchorFunction = GenericAnchorFunction<Percentage, Inset>;
61
62#[cfg(feature = "gecko")]
63use crate::{
64    gecko_bindings::structs::AnchorPosOffsetResolutionParams,
65    logical_geometry::PhysicalSide,
66    values::{computed::Length, DashedIdent},
67};
68
69impl AnchorFunction {
70    /// Resolve the anchor function with the given resolver. Returns `Err()` if no anchor is found.
71    #[cfg(feature = "gecko")]
72    pub fn resolve(
73        anchor_name: &DashedIdent,
74        anchor_side: &AnchorSide,
75        prop_side: PhysicalSide,
76        params: &AnchorPosOffsetResolutionParams,
77    ) -> Result<Length, ()> {
78        use crate::gecko_bindings::structs::Gecko_GetAnchorPosOffset;
79
80        let (keyword, percentage) = anchor_side.keyword_and_percentage();
81        let mut offset = Length::zero();
82        let valid = unsafe {
83            Gecko_GetAnchorPosOffset(
84                params,
85                anchor_name.0.as_ptr(),
86                prop_side as u8,
87                keyword as u8,
88                percentage.0,
89                &mut offset,
90            )
91        };
92
93        if !valid {
94            return Err(());
95        }
96
97        Ok(offset)
98    }
99}
100
101/// A computed type for `inset` properties.
102pub type Inset = GenericInset<Percentage, LengthPercentage>;
103
104impl Position {
105    /// `50% 50%`
106    #[inline]
107    pub fn center() -> Self {
108        Self::new(
109            LengthPercentage::new_percent(Percentage(0.5)),
110            LengthPercentage::new_percent(Percentage(0.5)),
111        )
112    }
113
114    /// `0% 0%`
115    #[inline]
116    pub fn zero() -> Self {
117        Self::new(LengthPercentage::zero(), LengthPercentage::zero())
118    }
119}
120
121impl ToCss for Position {
122    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
123    where
124        W: Write,
125    {
126        self.horizontal.to_css(dest)?;
127        dest.write_char(' ')?;
128        self.vertical.to_css(dest)
129    }
130}
131
132impl GenericPositionComponent for LengthPercentage {
133    fn is_center(&self) -> bool {
134        match self.to_percentage() {
135            Some(Percentage(per)) => per == 0.5,
136            _ => false,
137        }
138    }
139}
140
141/// A computed value for the `z-index` property.
142pub type ZIndex = GenericZIndex<Integer>;
143
144/// A computed value for the `aspect-ratio` property.
145pub type AspectRatio = GenericAspectRatio<NonNegativeNumber>;