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