1use std::fmt::Write;
9
10use style_traits::CssWriter;
11use style_traits::SpecifiedValueInfo;
12use style_traits::ToCss;
13
14use crate::logical_geometry::PhysicalSide;
15use crate::values::animated::ToAnimatedZero;
16use crate::values::generics::box_::PositionProperty;
17use crate::values::generics::length::GenericAnchorSizeFunction;
18use crate::values::generics::ratio::Ratio;
19use crate::values::generics::Optional;
20use crate::values::DashedIdent;
21
22#[derive(
24 Animate,
25 Clone,
26 ComputeSquaredDistance,
27 Copy,
28 Debug,
29 Deserialize,
30 MallocSizeOf,
31 PartialEq,
32 Serialize,
33 SpecifiedValueInfo,
34 ToAnimatedValue,
35 ToAnimatedZero,
36 ToComputedValue,
37 ToResolvedValue,
38 ToShmem,
39 ToTyped,
40)]
41#[repr(C)]
42pub struct GenericPosition<H, V> {
43 pub horizontal: H,
45 pub vertical: V,
47}
48
49impl<H, V> PositionComponent for Position<H, V>
50where
51 H: PositionComponent,
52 V: PositionComponent,
53{
54 #[inline]
55 fn is_center(&self) -> bool {
56 self.horizontal.is_center() && self.vertical.is_center()
57 }
58}
59
60pub use self::GenericPosition as Position;
61
62impl<H, V> Position<H, V> {
63 pub fn new(horizontal: H, vertical: V) -> Self {
65 Self {
66 horizontal,
67 vertical,
68 }
69 }
70}
71
72pub trait PositionComponent {
74 fn is_center(&self) -> bool;
77}
78
79#[derive(
83 Animate,
84 Clone,
85 ComputeSquaredDistance,
86 Copy,
87 Debug,
88 Deserialize,
89 MallocSizeOf,
90 Parse,
91 PartialEq,
92 Serialize,
93 SpecifiedValueInfo,
94 ToAnimatedZero,
95 ToAnimatedValue,
96 ToComputedValue,
97 ToCss,
98 ToResolvedValue,
99 ToShmem,
100 ToTyped,
101)]
102#[repr(C, u8)]
103pub enum GenericPositionOrAuto<Pos> {
104 Position(Pos),
106 Auto,
108}
109
110pub use self::GenericPositionOrAuto as PositionOrAuto;
111
112impl<Pos> PositionOrAuto<Pos> {
113 #[inline]
115 pub fn auto() -> Self {
116 PositionOrAuto::Auto
117 }
118
119 #[inline]
121 pub fn is_auto(&self) -> bool {
122 matches!(self, PositionOrAuto::Auto)
123 }
124}
125
126#[derive(
128 Animate,
129 Clone,
130 ComputeSquaredDistance,
131 Copy,
132 Debug,
133 MallocSizeOf,
134 PartialEq,
135 Parse,
136 SpecifiedValueInfo,
137 ToAnimatedValue,
138 ToAnimatedZero,
139 ToComputedValue,
140 ToCss,
141 ToResolvedValue,
142 ToShmem,
143 ToTyped,
144)]
145#[repr(C, u8)]
146pub enum GenericZIndex<I> {
147 Integer(I),
149 Auto,
151}
152
153pub use self::GenericZIndex as ZIndex;
154
155impl<Integer> ZIndex<Integer> {
156 #[inline]
158 pub fn auto() -> Self {
159 ZIndex::Auto
160 }
161
162 #[inline]
164 pub fn is_auto(self) -> bool {
165 matches!(self, ZIndex::Auto)
166 }
167
168 #[inline]
170 pub fn integer_or(self, auto: Integer) -> Integer {
171 match self {
172 ZIndex::Integer(n) => n,
173 ZIndex::Auto => auto,
174 }
175 }
176}
177
178#[derive(
180 Animate,
181 Clone,
182 ComputeSquaredDistance,
183 Copy,
184 Debug,
185 MallocSizeOf,
186 PartialEq,
187 SpecifiedValueInfo,
188 ToAnimatedValue,
189 ToComputedValue,
190 ToCss,
191 ToResolvedValue,
192 ToShmem,
193)]
194#[repr(C, u8)]
195pub enum PreferredRatio<N> {
196 #[css(skip)]
198 None,
199 Ratio(
201 #[animation(field_bound)]
202 #[css(field_bound)]
203 #[distance(field_bound)]
204 Ratio<N>,
205 ),
206}
207
208#[derive(
210 Animate,
211 Clone,
212 ComputeSquaredDistance,
213 Copy,
214 Debug,
215 MallocSizeOf,
216 PartialEq,
217 SpecifiedValueInfo,
218 ToAnimatedValue,
219 ToComputedValue,
220 ToCss,
221 ToResolvedValue,
222 ToShmem,
223 ToTyped,
224)]
225#[repr(C)]
226pub struct GenericAspectRatio<N> {
227 #[animation(constant)]
229 #[css(represents_keyword)]
230 pub auto: bool,
231 #[animation(field_bound)]
233 #[css(field_bound)]
234 #[distance(field_bound)]
235 pub ratio: PreferredRatio<N>,
236}
237
238pub use self::GenericAspectRatio as AspectRatio;
239
240impl<N> AspectRatio<N> {
241 #[inline]
243 pub fn auto() -> Self {
244 AspectRatio {
245 auto: true,
246 ratio: PreferredRatio::None,
247 }
248 }
249}
250
251impl<N> ToAnimatedZero for AspectRatio<N> {
252 #[inline]
253 fn to_animated_zero(&self) -> Result<Self, ()> {
254 Err(())
255 }
256}
257
258#[derive(
267 Animate,
268 Clone,
269 ComputeSquaredDistance,
270 Debug,
271 MallocSizeOf,
272 PartialEq,
273 ToCss,
274 ToShmem,
275 ToAnimatedValue,
276 ToAnimatedZero,
277 ToComputedValue,
278 ToResolvedValue,
279 ToTyped,
280)]
281#[repr(C)]
282pub enum GenericInset<P, LP> {
283 LengthPercentage(LP),
285 Auto,
287 AnchorFunction(Box<GenericAnchorFunction<P, Self>>),
291 AnchorSizeFunction(Box<GenericAnchorSizeFunction<Self>>),
295 AnchorContainingCalcFunction(LP),
298}
299
300impl<P, LP> SpecifiedValueInfo for GenericInset<P, LP>
301where
302 LP: SpecifiedValueInfo,
303{
304 fn collect_completion_keywords(f: style_traits::KeywordsCollectFn) {
305 LP::collect_completion_keywords(f);
306 f(&["auto"]);
307 if static_prefs::pref!("layout.css.anchor-positioning.enabled") {
308 f(&["anchor", "anchor-size"]);
309 }
310 }
311}
312
313impl<P, LP> GenericInset<P, LP> {
314 #[inline]
316 pub fn auto() -> Self {
317 Self::Auto
318 }
319
320 #[inline]
322 #[cfg(feature = "servo")]
323 pub fn is_auto(&self) -> bool {
324 matches!(self, Self::Auto)
325 }
326}
327
328pub use self::GenericInset as Inset;
329
330#[derive(
335 Animate,
336 Clone,
337 ComputeSquaredDistance,
338 Debug,
339 MallocSizeOf,
340 PartialEq,
341 SpecifiedValueInfo,
342 ToShmem,
343 ToAnimatedValue,
344 ToAnimatedZero,
345 ToComputedValue,
346 ToResolvedValue,
347 Serialize,
348 Deserialize,
349)]
350#[repr(C)]
351pub struct GenericAnchorFunction<Percentage, Fallback> {
352 #[animation(constant)]
355 pub target_element: DashedIdent,
356 pub side: GenericAnchorSide<Percentage>,
359 pub fallback: Optional<Fallback>,
361}
362
363impl<Percentage, Fallback> ToCss for GenericAnchorFunction<Percentage, Fallback>
364where
365 Percentage: ToCss,
366 Fallback: ToCss,
367{
368 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> std::fmt::Result
369 where
370 W: Write,
371 {
372 dest.write_str("anchor(")?;
373 if !self.target_element.is_empty() {
374 self.target_element.to_css(dest)?;
375 dest.write_str(" ")?;
376 }
377 self.side.to_css(dest)?;
378 if let Some(f) = self.fallback.as_ref() {
379 dest.write_str(", ")?;
381 f.to_css(dest)?;
382 }
383 dest.write_str(")")
384 }
385}
386
387impl<Percentage, Fallback> GenericAnchorFunction<Percentage, Fallback> {
388 pub fn valid_for(&self, side: PhysicalSide, position_property: PositionProperty) -> bool {
390 position_property.is_absolutely_positioned() && self.side.valid_for(side)
391 }
392}
393
394#[derive(
396 Animate,
397 Clone,
398 ComputeSquaredDistance,
399 Copy,
400 Debug,
401 MallocSizeOf,
402 PartialEq,
403 SpecifiedValueInfo,
404 ToCss,
405 ToShmem,
406 Parse,
407 ToAnimatedValue,
408 ToAnimatedZero,
409 ToComputedValue,
410 ToResolvedValue,
411 Serialize,
412 Deserialize,
413)]
414#[repr(u8)]
415pub enum AnchorSideKeyword {
416 Inside,
418 Outside,
420 Top,
422 Left,
424 Right,
426 Bottom,
428 Start,
432 End,
434 SelfStart,
436 SelfEnd,
438 Center,
440}
441
442impl AnchorSideKeyword {
443 fn valid_for(&self, side: PhysicalSide) -> bool {
444 match self {
445 Self::Left | Self::Right => matches!(side, PhysicalSide::Left | PhysicalSide::Right),
446 Self::Top | Self::Bottom => matches!(side, PhysicalSide::Top | PhysicalSide::Bottom),
447 Self::Inside
448 | Self::Outside
449 | Self::Start
450 | Self::End
451 | Self::SelfStart
452 | Self::SelfEnd
453 | Self::Center => true,
454 }
455 }
456}
457
458#[derive(
460 Animate,
461 Clone,
462 ComputeSquaredDistance,
463 Copy,
464 Debug,
465 MallocSizeOf,
466 PartialEq,
467 Parse,
468 SpecifiedValueInfo,
469 ToCss,
470 ToShmem,
471 ToAnimatedValue,
472 ToAnimatedZero,
473 ToComputedValue,
474 ToResolvedValue,
475 Serialize,
476 Deserialize,
477)]
478#[repr(C)]
479pub enum GenericAnchorSide<P> {
480 Keyword(AnchorSideKeyword),
482 Percentage(P),
484}
485
486impl<P> GenericAnchorSide<P> {
487 pub fn valid_for(&self, side: PhysicalSide) -> bool {
489 match self {
490 Self::Keyword(k) => k.valid_for(side),
491 Self::Percentage(_) => true,
492 }
493 }
494}