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)]
40#[repr(C)]
41pub struct GenericPosition<H, V> {
42 pub horizontal: H,
44 pub vertical: V,
46}
47
48impl<H, V> PositionComponent for Position<H, V>
49where
50 H: PositionComponent,
51 V: PositionComponent,
52{
53 #[inline]
54 fn is_center(&self) -> bool {
55 self.horizontal.is_center() && self.vertical.is_center()
56 }
57}
58
59pub use self::GenericPosition as Position;
60
61impl<H, V> Position<H, V> {
62 pub fn new(horizontal: H, vertical: V) -> Self {
64 Self {
65 horizontal,
66 vertical,
67 }
68 }
69}
70
71pub trait PositionComponent {
73 fn is_center(&self) -> bool;
76}
77
78#[derive(
82 Animate,
83 Clone,
84 ComputeSquaredDistance,
85 Copy,
86 Debug,
87 Deserialize,
88 MallocSizeOf,
89 Parse,
90 PartialEq,
91 Serialize,
92 SpecifiedValueInfo,
93 ToAnimatedZero,
94 ToAnimatedValue,
95 ToComputedValue,
96 ToCss,
97 ToResolvedValue,
98 ToShmem,
99)]
100#[repr(C, u8)]
101pub enum GenericPositionOrAuto<Pos> {
102 Position(Pos),
104 Auto,
106}
107
108pub use self::GenericPositionOrAuto as PositionOrAuto;
109
110impl<Pos> PositionOrAuto<Pos> {
111 #[inline]
113 pub fn auto() -> Self {
114 PositionOrAuto::Auto
115 }
116
117 #[inline]
119 pub fn is_auto(&self) -> bool {
120 matches!(self, PositionOrAuto::Auto)
121 }
122}
123
124#[derive(
126 Animate,
127 Clone,
128 ComputeSquaredDistance,
129 Copy,
130 Debug,
131 MallocSizeOf,
132 PartialEq,
133 Parse,
134 SpecifiedValueInfo,
135 ToAnimatedValue,
136 ToAnimatedZero,
137 ToComputedValue,
138 ToCss,
139 ToResolvedValue,
140 ToShmem,
141)]
142#[repr(C, u8)]
143pub enum GenericZIndex<I> {
144 Integer(I),
146 Auto,
148}
149
150pub use self::GenericZIndex as ZIndex;
151
152impl<Integer> ZIndex<Integer> {
153 #[inline]
155 pub fn auto() -> Self {
156 ZIndex::Auto
157 }
158
159 #[inline]
161 pub fn is_auto(self) -> bool {
162 matches!(self, ZIndex::Auto)
163 }
164
165 #[inline]
167 pub fn integer_or(self, auto: Integer) -> Integer {
168 match self {
169 ZIndex::Integer(n) => n,
170 ZIndex::Auto => auto,
171 }
172 }
173}
174
175#[derive(
177 Animate,
178 Clone,
179 ComputeSquaredDistance,
180 Copy,
181 Debug,
182 MallocSizeOf,
183 PartialEq,
184 SpecifiedValueInfo,
185 ToAnimatedValue,
186 ToComputedValue,
187 ToCss,
188 ToResolvedValue,
189 ToShmem,
190)]
191#[repr(C, u8)]
192pub enum PreferredRatio<N> {
193 #[css(skip)]
195 None,
196 Ratio(
198 #[animation(field_bound)]
199 #[css(field_bound)]
200 #[distance(field_bound)]
201 Ratio<N>,
202 ),
203}
204
205#[derive(
207 Animate,
208 Clone,
209 ComputeSquaredDistance,
210 Copy,
211 Debug,
212 MallocSizeOf,
213 PartialEq,
214 SpecifiedValueInfo,
215 ToAnimatedValue,
216 ToComputedValue,
217 ToCss,
218 ToResolvedValue,
219 ToShmem,
220)]
221#[repr(C)]
222pub struct GenericAspectRatio<N> {
223 #[animation(constant)]
225 #[css(represents_keyword)]
226 pub auto: bool,
227 #[animation(field_bound)]
229 #[css(field_bound)]
230 #[distance(field_bound)]
231 pub ratio: PreferredRatio<N>,
232}
233
234pub use self::GenericAspectRatio as AspectRatio;
235
236impl<N> AspectRatio<N> {
237 #[inline]
239 pub fn auto() -> Self {
240 AspectRatio {
241 auto: true,
242 ratio: PreferredRatio::None,
243 }
244 }
245}
246
247impl<N> ToAnimatedZero for AspectRatio<N> {
248 #[inline]
249 fn to_animated_zero(&self) -> Result<Self, ()> {
250 Err(())
251 }
252}
253
254#[derive(
263 Animate,
264 Clone,
265 ComputeSquaredDistance,
266 Debug,
267 MallocSizeOf,
268 PartialEq,
269 ToCss,
270 ToShmem,
271 ToAnimatedValue,
272 ToAnimatedZero,
273 ToComputedValue,
274 ToResolvedValue,
275)]
276#[repr(C)]
277pub enum GenericInset<P, LP> {
278 LengthPercentage(LP),
280 Auto,
282 AnchorFunction(
286 #[animation(field_bound)]
287 #[distance(field_bound)]
288 Box<GenericAnchorFunction<P, LP>>,
289 ),
290 AnchorSizeFunction(
294 #[animation(field_bound)]
295 #[distance(field_bound)]
296 Box<GenericAnchorSizeFunction<LP>>,
297 ),
298 AnchorContainingCalcFunction(LP),
301}
302
303impl<P, LP> SpecifiedValueInfo for GenericInset<P, LP>
304where
305 LP: SpecifiedValueInfo,
306{
307 fn collect_completion_keywords(f: style_traits::KeywordsCollectFn) {
308 LP::collect_completion_keywords(f);
309 f(&["auto"]);
310 if static_prefs::pref!("layout.css.anchor-positioning.enabled") {
311 f(&["anchor", "anchor-size"]);
312 }
313 }
314}
315
316impl<P, LP> GenericInset<P, LP> {
317 #[inline]
319 pub fn auto() -> Self {
320 Self::Auto
321 }
322
323 #[inline]
325 #[cfg(feature = "servo")]
326 pub fn is_auto(&self) -> bool {
327 matches!(self, Self::Auto)
328 }
329}
330
331pub use self::GenericInset as Inset;
332
333#[derive(
338 Animate,
339 Clone,
340 ComputeSquaredDistance,
341 Debug,
342 MallocSizeOf,
343 PartialEq,
344 SpecifiedValueInfo,
345 ToShmem,
346 ToAnimatedValue,
347 ToAnimatedZero,
348 ToComputedValue,
349 ToResolvedValue,
350 Serialize,
351 Deserialize,
352)]
353#[repr(C)]
354pub struct GenericAnchorFunction<Percentage, LengthPercentage> {
355 #[animation(constant)]
358 pub target_element: DashedIdent,
359 pub side: GenericAnchorSide<Percentage>,
362 pub fallback: Optional<LengthPercentage>,
364}
365
366impl<Percentage, LengthPercentage> ToCss for GenericAnchorFunction<Percentage, LengthPercentage>
367where
368 Percentage: ToCss,
369 LengthPercentage: ToCss,
370{
371 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> std::fmt::Result
372 where
373 W: Write,
374 {
375 dest.write_str("anchor(")?;
376 if !self.target_element.is_empty() {
377 self.target_element.to_css(dest)?;
378 dest.write_str(" ")?;
379 }
380 self.side.to_css(dest)?;
381 if let Some(f) = self.fallback.as_ref() {
382 dest.write_str(", ")?;
384 f.to_css(dest)?;
385 }
386 dest.write_str(")")
387 }
388}
389
390impl<Percentage, LengthPercentage> GenericAnchorFunction<Percentage, LengthPercentage> {
391 pub fn valid_for(
393 &self,
394 side: PhysicalSide,
395 position_property: PositionProperty,
396 ) -> bool {
397 position_property.is_absolutely_positioned() && self.side.valid_for(side)
398 }
399}
400
401#[derive(
403 Animate,
404 Clone,
405 ComputeSquaredDistance,
406 Copy,
407 Debug,
408 MallocSizeOf,
409 PartialEq,
410 SpecifiedValueInfo,
411 ToCss,
412 ToShmem,
413 Parse,
414 ToAnimatedValue,
415 ToAnimatedZero,
416 ToComputedValue,
417 ToResolvedValue,
418 Serialize,
419 Deserialize,
420)]
421#[repr(u8)]
422pub enum AnchorSideKeyword {
423 Inside,
425 Outside,
427 Top,
429 Left,
431 Right,
433 Bottom,
435 Start,
439 End,
441 SelfStart,
443 SelfEnd,
445 Center,
447}
448
449impl AnchorSideKeyword {
450 fn valid_for(&self, side: PhysicalSide) -> bool {
451 match self {
452 Self::Left | Self::Right => matches!(side, PhysicalSide::Left | PhysicalSide::Right),
453 Self::Top | Self::Bottom => matches!(side, PhysicalSide::Top | PhysicalSide::Bottom),
454 Self::Inside |
455 Self::Outside |
456 Self::Start |
457 Self::End |
458 Self::SelfStart |
459 Self::SelfEnd |
460 Self::Center => true,
461 }
462 }
463}
464
465#[derive(
467 Animate,
468 Clone,
469 ComputeSquaredDistance,
470 Copy,
471 Debug,
472 MallocSizeOf,
473 PartialEq,
474 Parse,
475 SpecifiedValueInfo,
476 ToCss,
477 ToShmem,
478 ToAnimatedValue,
479 ToAnimatedZero,
480 ToComputedValue,
481 ToResolvedValue,
482 Serialize,
483 Deserialize,
484)]
485#[repr(C)]
486pub enum GenericAnchorSide<P> {
487 Keyword(AnchorSideKeyword),
489 Percentage(P),
491}
492
493impl<P> GenericAnchorSide<P> {
494 pub fn valid_for(&self, side: PhysicalSide) -> bool {
496 match self {
497 Self::Keyword(k) => k.valid_for(side),
498 Self::Percentage(_) => true,
499 }
500 }
501}