1use super::prelude::*;
2
3#[derive(IntoCursor, Parse, Peek, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
6#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.types.angle"))]
7#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
8pub enum Angle {
9 #[atom(CssAtomSet::Grad)]
10 Grad(T![Dimension]),
11 #[atom(CssAtomSet::Rad)]
12 Rad(T![Dimension]),
13 #[atom(CssAtomSet::Turn)]
14 Turn(T![Dimension]),
15 #[atom(CssAtomSet::Deg)]
16 Deg(T![Dimension]),
17}
18
19impl From<Angle> for f32 {
20 fn from(val: Angle) -> Self {
21 match val {
22 Angle::Grad(f) => f.into(),
23 Angle::Rad(f) => f.into(),
24 Angle::Turn(f) => f.into(),
25 Angle::Deg(f) => f.into(),
26 }
27 }
28}
29
30impl ToNumberValue for Angle {
31 fn to_number_value(&self) -> Option<f32> {
32 Some((*self).into())
33 }
34}
35
36impl Angle {
37 const DEG_GRAD: f32 = 0.9;
38 const DEG_RAD: f32 = 57.295_78;
39 const DEG_TURN: f32 = 360.0;
40
41 pub fn as_degrees(&self) -> f32 {
42 match self {
43 Self::Grad(d) => Into::<f32>::into(*d) * Self::DEG_GRAD,
44 Self::Rad(d) => Into::<f32>::into(*d) * Self::DEG_RAD,
45 Self::Turn(d) => Into::<f32>::into(*d) * Self::DEG_TURN,
46 Self::Deg(d) => (*d).into(),
47 }
48 }
49}
50
51#[derive(IntoCursor, Parse, Peek, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
53#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(children))]
54pub enum AngleOrZero {
55 Angle(Angle),
56 #[cfg_attr(feature = "visitable", visit(skip))]
57 Zero(#[in_range(0.0..=0.0)] T![Number]),
58}
59
60#[derive(IntoCursor, Parse, Peek, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
62#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(children))]
63pub enum AngleOrNumber {
64 Angle(Angle),
65 #[cfg_attr(feature = "visitable", visit(skip))]
66 Number(T![Number]),
67}
68
69impl From<AngleOrZero> for f32 {
70 fn from(val: AngleOrZero) -> Self {
71 match val {
72 AngleOrZero::Angle(f) => f.into(),
73 AngleOrZero::Zero(f) => f.into(),
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::CssAtomSet;
82 use css_parse::assert_parse;
83
84 #[test]
85 fn size_test() {
86 assert_eq!(std::mem::size_of::<Angle>(), 16);
87 }
88
89 #[test]
90 fn test_writes() {
91 assert_parse!(CssAtomSet::ATOMS, Angle, "0grad");
92 assert_parse!(CssAtomSet::ATOMS, Angle, "0deg");
93 assert_parse!(CssAtomSet::ATOMS, AngleOrZero, "0", AngleOrZero::Zero(_));
94 }
95}